From 59bc9ba3105fc1c17c12b01676029d8803559b90 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Sat, 17 Sep 2022 02:08:16 +0800 Subject: [PATCH 001/102] Update build.sh --- build.sh | 69 +++++++++++++++----------------------------------------- 1 file changed, 18 insertions(+), 51 deletions(-) diff --git a/build.sh b/build.sh index e47fdea2..ef623019 100644 --- a/build.sh +++ b/build.sh @@ -1,7 +1,7 @@ #!/bin/sh # # Copyright (C) 2017 OVH OverTheBox -# Copyright (C) 2017-2022 Ycarus (Yannick Chabanois) for OpenMPTCProuter project +# Copyright (C) 2017-2020 Ycarus (Yannick Chabanois) for OpenMPTCProuter project # # This is free software, licensed under the GNU General Public License v3. # See /LICENSE for more information. @@ -42,7 +42,7 @@ SHORTCUT_FE=${SHORTCUT_FE:-no} #OMR_RELEASE=${OMR_RELEASE:-$(git describe --tags `git rev-list --tags --max-count=1` | sed 's/^\([0-9.]*\).*/\1/')} #OMR_RELEASE=${OMR_RELEASE:-$(git tag --sort=committerdate | tail -1)} OMR_RELEASE=${OMR_RELEASE:-$(git describe --tags `git rev-list --tags --max-count=1` | tail -1 | cut -d '-' -f1)} -OMR_REPO=${OMR_REPO:-http://$OMR_HOST:$OMR_PORT/release/$OMR_RELEASE-$OMR_KERNEL/$OMR_TARGET} +OMR_REPO=${OMR_REPO:-http://$OMR_HOST:$OMR_PORT/release/$OMR_RELEASE/$OMR_TARGET} OMR_FEED_URL="${OMR_FEED_URL:-https://github.com/suyuan168/openmptcprouter-feeds}" OMR_FEED_SRC="${OMR_FEED_SRC:-develop}" @@ -94,13 +94,13 @@ fi if [ "$OMR_OPENWRT" = "default" ]; then if [ "$OMR_KERNEL" = "5.4" ]; then # Use OpenWrt 21.02 for 5.4 kernel - _get_repo "$OMR_TARGET/${OMR_KERNEL}/source" https://github.com/openwrt/openwrt "cb6501435c3136c296e3477bc7f3b043e2a83a47" - _get_repo feeds/${OMR_KERNEL}/packages https://github.com/openwrt/packages "51077c1094a1e63d333d32b138b381296fd45276" - _get_repo feeds/${OMR_KERNEL}/luci https://github.com/openwrt/luci "bdaec14361fa44529a2da5996745d43fc79fd764" + _get_repo "$OMR_TARGET/${OMR_KERNEL}/source" https://github.com/openwrt/openwrt "ce92de8c8c90aa2a6281cbfb046fcf6498b78786" + _get_repo feeds/${OMR_KERNEL}/packages https://github.com/openwrt/packages "93aca6dfbe894217435e4623bc48489ab9695cd1" + _get_repo feeds/${OMR_KERNEL}/luci https://github.com/openwrt/luci "9139ad468599b586dbd7ca48fe5a149c95f28800" else - _get_repo "$OMR_TARGET/${OMR_KERNEL}/source" https://github.com/openwrt/openwrt "bae87942bcfb461d2882dd7e593b6aa2d75f63b1" - _get_repo feeds/${OMR_KERNEL}/packages https://github.com/openwrt/packages "2840abb0c049061618e4e32c5f59c20f7d081c67" - _get_repo feeds/${OMR_KERNEL}/luci https://github.com/openwrt/luci "46181e5ace8c5cf86e257d021b4e3e593f1a7f5e" + _get_repo "$OMR_TARGET/${OMR_KERNEL}/source" https://github.com/openwrt/openwrt "9d06e5a7735508d793c3a125f9f7d623671e29e4" + _get_repo feeds/${OMR_KERNEL}/packages https://github.com/openwrt/packages "b4043d92257505526a5b8ceac94f9f28f887abbd" + _get_repo feeds/${OMR_KERNEL}/luci https://github.com/openwrt/luci "111c551cdb8d14e8e5ef7c7a66ffdceb6d3cbb55" fi elif [ "$OMR_OPENWRT" = "master" ]; then _get_repo "$OMR_TARGET/${OMR_KERNEL}/source" https://github.com/openwrt/openwrt "master" @@ -133,25 +133,19 @@ fi rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/files" "$OMR_TARGET/${OMR_KERNEL}/source/tmp" #rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/mediatek/patches-4.14" #rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/mediatek/patches-5.4" -#rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/uboot-mediatek" -#rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/arm-trusted-firmware-mediatek" +rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/uboot-mediatek" +rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/arm-trusted-firmware-mediatek" rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/tools/firmware-utils" -if [ "$OMR_TARGET" != "rutx" ]; then - # There is many customization to support rutx and this seems to break other ipq40xx, so dirty workaround for now - mv "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx" "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx.old" - cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" - rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx" - mv "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx.old" "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx" -else - cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" -fi +cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" cat >> "$OMR_TARGET/${OMR_KERNEL}/source/package/base-files/files/etc/banner" <> "$OMR_TARGET/${OMR_KERNEL}/source/feeds.conf" fi -if [ "$OMR_DIST" = "openmptcprouter" ]; then - cat > "$OMR_TARGET/${OMR_KERNEL}/source/package/system/opkg/files/customfeeds.conf" <<-EOF - src/gz openwrt_luci http://packages.openmptcprouter.com/${OMR_RELEASE}/${OMR_REAL_TARGET}/luci - src/gz openwrt_packages http://packages.openmptcprouter.com/${OMR_RELEASE}/${OMR_REAL_TARGET}/packages - src/gz openwrt_base http://packages.openmptcprouter.com/${OMR_RELEASE}/${OMR_REAL_TARGET}/base - src/gz openwrt_routing http://packages.openmptcprouter.com/${OMR_RELEASE}/${OMR_REAL_TARGET}/routing - src/gz openwrt_telephony http://packages.openmptcprouter.com/${OMR_RELEASE}/${OMR_REAL_TARGET}/telephony - EOF -elif [ -n "$OMR_PACKAGES_URL" ]; then - cat > "$OMR_TARGET/${OMR_KERNEL}/source/package/system/opkg/files/customfeeds.conf" <<-EOF - src/gz openwrt_luci ${OMR_PACKAGES_URL}/${OMR_RELEASE}/${OMR_REAL_TARGET}/luci - src/gz openwrt_packages ${OMR_PACKAGES_URL}/${OMR_RELEASE}/${OMR_REAL_TARGET}/packages - src/gz openwrt_base ${OMR_PACKAGES_URL}/${OMR_RELEASE}/${OMR_REAL_TARGET}/base - src/gz openwrt_routing ${OMR_PACKAGES_URL}/${OMR_RELEASE}/${OMR_REAL_TARGET}/routing - src/gz openwrt_telephony ${OMR_PACKAGES_URL}/${OMR_RELEASE}/${OMR_REAL_TARGET}/telephony - EOF -else - cat > "$OMR_TARGET/${OMR_KERNEL}/source/package/system/opkg/files/customfeeds.conf" <<-EOF - src/gz openwrt_luci http://downloads.openwrt.org/snapshots/packages/${OMR_REAL_TARGET}/luci - src/gz openwrt_packages http://downloads.openwrt.org/snapshots/packages/${OMR_REAL_TARGET}/packages - src/gz openwrt_base http://downloads.openwrt.org/snapshots/packages/${OMR_REAL_TARGET}/base - src/gz openwrt_routing http://downloads.openwrt.org/snapshots/packages/${OMR_REAL_TARGET}/routing - src/gz openwrt_telephony http://downloads.openwrt.org/snapshots/packages/${OMR_REAL_TARGET}/telephony - EOF -fi + + + #cat > "$OMR_TARGET/${OMR_KERNEL}/source/package/system/opkg/files/customfeeds.conf" < Date: Sat, 17 Sep 2022 02:12:19 +0800 Subject: [PATCH 002/102] Update build.sh --- build.sh | 71 ++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 18 deletions(-) diff --git a/build.sh b/build.sh index ef623019..3e7c50ce 100644 --- a/build.sh +++ b/build.sh @@ -1,7 +1,7 @@ #!/bin/sh # # Copyright (C) 2017 OVH OverTheBox -# Copyright (C) 2017-2020 Ycarus (Yannick Chabanois) for OpenMPTCProuter project +# Copyright (C) 2017-2022 Ycarus (Yannick Chabanois) for OpenMPTCProuter project # # This is free software, licensed under the GNU General Public License v3. # See /LICENSE for more information. @@ -42,9 +42,9 @@ SHORTCUT_FE=${SHORTCUT_FE:-no} #OMR_RELEASE=${OMR_RELEASE:-$(git describe --tags `git rev-list --tags --max-count=1` | sed 's/^\([0-9.]*\).*/\1/')} #OMR_RELEASE=${OMR_RELEASE:-$(git tag --sort=committerdate | tail -1)} OMR_RELEASE=${OMR_RELEASE:-$(git describe --tags `git rev-list --tags --max-count=1` | tail -1 | cut -d '-' -f1)} -OMR_REPO=${OMR_REPO:-http://$OMR_HOST:$OMR_PORT/release/$OMR_RELEASE/$OMR_TARGET} +OMR_REPO=${OMR_REPO:-http://$OMR_HOST:$OMR_PORT/release/$OMR_RELEASE-$OMR_KERNEL/$OMR_TARGET} -OMR_FEED_URL="${OMR_FEED_URL:-https://github.com/suyuan168/openmptcprouter-feeds}" +OMR_FEED_URL="${OMR_FEED_URL:-https://github.com/ysurac/openmptcprouter-feeds}" OMR_FEED_SRC="${OMR_FEED_SRC:-develop}" CUSTOM_FEED_URL="${CUSTOM_FEED_URL}" @@ -94,13 +94,13 @@ fi if [ "$OMR_OPENWRT" = "default" ]; then if [ "$OMR_KERNEL" = "5.4" ]; then # Use OpenWrt 21.02 for 5.4 kernel - _get_repo "$OMR_TARGET/${OMR_KERNEL}/source" https://github.com/openwrt/openwrt "ce92de8c8c90aa2a6281cbfb046fcf6498b78786" - _get_repo feeds/${OMR_KERNEL}/packages https://github.com/openwrt/packages "93aca6dfbe894217435e4623bc48489ab9695cd1" - _get_repo feeds/${OMR_KERNEL}/luci https://github.com/openwrt/luci "9139ad468599b586dbd7ca48fe5a149c95f28800" + _get_repo "$OMR_TARGET/${OMR_KERNEL}/source" https://github.com/openwrt/openwrt "cb6501435c3136c296e3477bc7f3b043e2a83a47" + _get_repo feeds/${OMR_KERNEL}/packages https://github.com/openwrt/packages "51077c1094a1e63d333d32b138b381296fd45276" + _get_repo feeds/${OMR_KERNEL}/luci https://github.com/openwrt/luci "bdaec14361fa44529a2da5996745d43fc79fd764" else - _get_repo "$OMR_TARGET/${OMR_KERNEL}/source" https://github.com/openwrt/openwrt "9d06e5a7735508d793c3a125f9f7d623671e29e4" - _get_repo feeds/${OMR_KERNEL}/packages https://github.com/openwrt/packages "b4043d92257505526a5b8ceac94f9f28f887abbd" - _get_repo feeds/${OMR_KERNEL}/luci https://github.com/openwrt/luci "111c551cdb8d14e8e5ef7c7a66ffdceb6d3cbb55" + _get_repo "$OMR_TARGET/${OMR_KERNEL}/source" https://github.com/openwrt/openwrt "bae87942bcfb461d2882dd7e593b6aa2d75f63b1" + _get_repo feeds/${OMR_KERNEL}/packages https://github.com/openwrt/packages "2840abb0c049061618e4e32c5f59c20f7d081c67" + _get_repo feeds/${OMR_KERNEL}/luci https://github.com/openwrt/luci "46181e5ace8c5cf86e257d021b4e3e593f1a7f5e" fi elif [ "$OMR_OPENWRT" = "master" ]; then _get_repo "$OMR_TARGET/${OMR_KERNEL}/source" https://github.com/openwrt/openwrt "master" @@ -133,19 +133,27 @@ fi rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/files" "$OMR_TARGET/${OMR_KERNEL}/source/tmp" #rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/mediatek/patches-4.14" #rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/mediatek/patches-5.4" -rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/uboot-mediatek" -rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/arm-trusted-firmware-mediatek" +#rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/uboot-mediatek" +#rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/arm-trusted-firmware-mediatek" rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/tools/firmware-utils" -cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" +if [ "$OMR_TARGET" != "rutx" ]; then + # There is many customization to support rutx and this seems to break other ipq40xx, so dirty workaround for now + mv "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx" "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx.old" + cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" + rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx" + mv "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx.old" "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx" +else + cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" +fi cat >> "$OMR_TARGET/${OMR_KERNEL}/source/package/base-files/files/etc/banner" <> "$OMR_TARGET/${OMR_KERNEL}/source/feeds.conf" fi - - - +if [ "$OMR_DIST" = "openmptcprouter" ]; then + cat > "$OMR_TARGET/${OMR_KERNEL}/source/package/system/opkg/files/customfeeds.conf" <<-EOF + src/gz openwrt_luci http://packages.openmptcprouter.com/${OMR_RELEASE}/${OMR_REAL_TARGET}/luci + src/gz openwrt_packages http://packages.openmptcprouter.com/${OMR_RELEASE}/${OMR_REAL_TARGET}/packages + src/gz openwrt_base http://packages.openmptcprouter.com/${OMR_RELEASE}/${OMR_REAL_TARGET}/base + src/gz openwrt_routing http://packages.openmptcprouter.com/${OMR_RELEASE}/${OMR_REAL_TARGET}/routing + src/gz openwrt_telephony http://packages.openmptcprouter.com/${OMR_RELEASE}/${OMR_REAL_TARGET}/telephony + EOF +elif [ -n "$OMR_PACKAGES_URL" ]; then + cat > "$OMR_TARGET/${OMR_KERNEL}/source/package/system/opkg/files/customfeeds.conf" <<-EOF + src/gz openwrt_luci ${OMR_PACKAGES_URL}/${OMR_RELEASE}/${OMR_REAL_TARGET}/luci + src/gz openwrt_packages ${OMR_PACKAGES_URL}/${OMR_RELEASE}/${OMR_REAL_TARGET}/packages + src/gz openwrt_base ${OMR_PACKAGES_URL}/${OMR_RELEASE}/${OMR_REAL_TARGET}/base + src/gz openwrt_routing ${OMR_PACKAGES_URL}/${OMR_RELEASE}/${OMR_REAL_TARGET}/routing + src/gz openwrt_telephony ${OMR_PACKAGES_URL}/${OMR_RELEASE}/${OMR_REAL_TARGET}/telephony + EOF +else + cat > "$OMR_TARGET/${OMR_KERNEL}/source/package/system/opkg/files/customfeeds.conf" <<-EOF + src/gz openwrt_luci http://downloads.openwrt.org/snapshots/packages/${OMR_REAL_TARGET}/luci + src/gz openwrt_packages http://downloads.openwrt.org/snapshots/packages/${OMR_REAL_TARGET}/packages + src/gz openwrt_base http://downloads.openwrt.org/snapshots/packages/${OMR_REAL_TARGET}/base + src/gz openwrt_routing http://downloads.openwrt.org/snapshots/packages/${OMR_REAL_TARGET}/routing + src/gz openwrt_telephony http://downloads.openwrt.org/snapshots/packages/${OMR_REAL_TARGET}/telephony + EOF +fi #cat > "$OMR_TARGET/${OMR_KERNEL}/source/package/system/opkg/files/customfeeds.conf" < Date: Sat, 17 Sep 2022 02:13:54 +0800 Subject: [PATCH 003/102] Update build.sh --- build.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.sh b/build.sh index 3e7c50ce..7c22cc9b 100644 --- a/build.sh +++ b/build.sh @@ -44,7 +44,7 @@ SHORTCUT_FE=${SHORTCUT_FE:-no} OMR_RELEASE=${OMR_RELEASE:-$(git describe --tags `git rev-list --tags --max-count=1` | tail -1 | cut -d '-' -f1)} OMR_REPO=${OMR_REPO:-http://$OMR_HOST:$OMR_PORT/release/$OMR_RELEASE-$OMR_KERNEL/$OMR_TARGET} -OMR_FEED_URL="${OMR_FEED_URL:-https://github.com/ysurac/openmptcprouter-feeds}" +OMR_FEED_URL="${OMR_FEED_URL:-https://github.com/suyuan168/openmptcprouter-feeds}" OMR_FEED_SRC="${OMR_FEED_SRC:-develop}" CUSTOM_FEED_URL="${CUSTOM_FEED_URL}" @@ -153,7 +153,7 @@ cat >> "$OMR_TARGET/${OMR_KERNEL}/source/package/base-files/files/etc/banner" << TARGET: $OMR_TARGET ARCH: $OMR_REAL_TARGET - BUILD REPO: $(git config --get remote.origin.url) + BUILD DATE: $(date -u) ----------------------------------------------------- EOF From b9329052e4ed8752016e98986b30a6ed0176188d Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Sat, 17 Sep 2022 02:22:17 +0800 Subject: [PATCH 004/102] Update build.sh --- build.sh | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/build.sh b/build.sh index 7c22cc9b..2224e173 100644 --- a/build.sh +++ b/build.sh @@ -136,15 +136,9 @@ rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/files" "$OMR_TARGET/${OMR_KERNEL}/sourc #rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/uboot-mediatek" #rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/arm-trusted-firmware-mediatek" rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/tools/firmware-utils" -if [ "$OMR_TARGET" != "rutx" ]; then - # There is many customization to support rutx and this seems to break other ipq40xx, so dirty workaround for now - mv "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx" "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx.old" - cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" - rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx" - mv "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx.old" "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx" -else - cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" -fi + +cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" + cat >> "$OMR_TARGET/${OMR_KERNEL}/source/package/base-files/files/etc/banner" < Date: Sat, 17 Sep 2022 02:53:36 +0800 Subject: [PATCH 005/102] Update build.sh --- build.sh | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/build.sh b/build.sh index 2224e173..dce56d07 100644 --- a/build.sh +++ b/build.sh @@ -136,10 +136,7 @@ rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/files" "$OMR_TARGET/${OMR_KERNEL}/sourc #rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/uboot-mediatek" #rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/arm-trusted-firmware-mediatek" rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/tools/firmware-utils" - -cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" - - +-cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" cat >> "$OMR_TARGET/${OMR_KERNEL}/source/package/base-files/files/etc/banner" < Date: Sat, 17 Sep 2022 02:56:11 +0800 Subject: [PATCH 006/102] Update build.sh --- build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sh b/build.sh index dce56d07..5b24c5f6 100644 --- a/build.sh +++ b/build.sh @@ -136,7 +136,7 @@ rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/files" "$OMR_TARGET/${OMR_KERNEL}/sourc #rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/uboot-mediatek" #rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/arm-trusted-firmware-mediatek" rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/tools/firmware-utils" --cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" +cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" cat >> "$OMR_TARGET/${OMR_KERNEL}/source/package/base-files/files/etc/banner" < Date: Sun, 18 Sep 2022 12:32:01 +0800 Subject: [PATCH 007/102] Update qcom-ipq4019-z4019.dts --- .../files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts b/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts index 8e91989e..577e40ee 100755 --- a/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts +++ b/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts @@ -29,7 +29,7 @@ led-running = &power; led-upgrade = &power; serial0 = &blsp1_uart1; - serial1 = &blsp1_uart2; + }; chosen { @@ -280,11 +280,7 @@ status = "okay"; }; -&blsp1_uart2 { - pinctrl-0 = <&serial_1_pins>; - pinctrl-names = "default"; - status = "okay"; -}; + &tlmm { mdio_pins: mdio_pinmux { From bb8f4dc83b3ac7b97199efd623ea21a4f7db3b90 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Sun, 18 Sep 2022 14:01:03 +0800 Subject: [PATCH 008/102] Update build.sh --- build.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build.sh b/build.sh index 5b24c5f6..0832c500 100644 --- a/build.sh +++ b/build.sh @@ -74,6 +74,12 @@ elif [ "$OMR_TARGET" = "bpi-r2" ]; then OMR_REAL_TARGET="arm_cortex-a7_neon-vfpv4" elif [ "$OMR_TARGET" = "rutx" ]; then OMR_REAL_TARGET="arm_cortex-a7_neon-vfpv4" +elif [ "$OMR_TARGET" = "l1000" ]; then + OMR_REAL_TARGET="arm_cortex-a7_neon-vfpv4" +elif [ "$OMR_TARGET" = "zbt4019" ]; then + OMR_REAL_TARGET="arm_cortex-a7_neon-vfpv4" +elif [ "$OMR_TARGET" = "5gx3" ]; then + OMR_REAL_TARGET="arm_cortex-a7_neon-vfpv4" elif [ "$OMR_TARGET" = "bpi-r64" ]; then OMR_REAL_TARGET="aarch64_cortex-a53" elif [ "$OMR_TARGET" = "espressobin" ]; then From 949cf72ad854a47886de05ce048adf32193ab843 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Sun, 18 Sep 2022 14:05:20 +0800 Subject: [PATCH 009/102] fix arm --- config-5gx3 | 1 + config-l1000 | 1 + config-zbt4019 | 1 + 3 files changed, 3 insertions(+) diff --git a/config-5gx3 b/config-5gx3 index fa7bbd40..3b7960b0 100755 --- a/config-5gx3 +++ b/config-5gx3 @@ -2,6 +2,7 @@ # Automatically generated file; DO NOT EDIT. # OpenWrt Configuration # +CONFIG_KERNEL_ARM_MODULE_PLTS=y CONFIG_ARM_MODULE_PLTS=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_KERNEL_CC_OPTIMIZE_FOR_SIZE=y diff --git a/config-l1000 b/config-l1000 index 15ece074..59e5c947 100755 --- a/config-l1000 +++ b/config-l1000 @@ -2,6 +2,7 @@ # Automatically generated file; DO NOT EDIT. # OpenWrt Configuration # +CONFIG_KERNEL_ARM_MODULE_PLTS=y CONFIG_ARM_MODULE_PLTS=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_KERNEL_CC_OPTIMIZE_FOR_SIZE=y diff --git a/config-zbt4019 b/config-zbt4019 index a208be67..1ded6467 100755 --- a/config-zbt4019 +++ b/config-zbt4019 @@ -2,6 +2,7 @@ # Automatically generated file; DO NOT EDIT. # OpenWrt Configuration # +CONFIG_KERNEL_ARM_MODULE_PLTS=y CONFIG_ARM_MODULE_PLTS=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_KERNEL_CC_OPTIMIZE_FOR_SIZE=y From 8b6a0398950846cab9e208c3a9d8758b31f9811d Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Sun, 18 Sep 2022 14:13:49 +0800 Subject: [PATCH 010/102] Update config-5.4 --- root/target/linux/ipq40xx/config-5.4 | 39 +++++++++++----------------- 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/root/target/linux/ipq40xx/config-5.4 b/root/target/linux/ipq40xx/config-5.4 index cc171020..283b48b8 100644 --- a/root/target/linux/ipq40xx/config-5.4 +++ b/root/target/linux/ipq40xx/config-5.4 @@ -1,7 +1,4 @@ CONFIG_ALIGNMENT_TRAP=y -CONFIG_ARM_MODULE_PLTS=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_KERNEL_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_APQ_GCC_8084 is not set # CONFIG_APQ_MMCC_8084 is not set CONFIG_AR40XX_PHY=y @@ -50,12 +47,12 @@ CONFIG_BCH=y CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_MQ_PCI=y +CONFIG_BOOTCONFIG_PARTITION=y CONFIG_BOUNCE=y # CONFIG_CACHE_L2X0 is not set CONFIG_CLKDEV_LOOKUP=y CONFIG_CLKSRC_QCOM=y CONFIG_CLONE_BACKWARDS=y -CONFIG_CMDLINE_OVERRIDE=y CONFIG_COMMON_CLK=y CONFIG_COMMON_CLK_QCOM=y CONFIG_COMPAT_32BIT_TIME=y @@ -70,15 +67,14 @@ CONFIG_CPU_COPY_V6=y CONFIG_CPU_CP15=y CONFIG_CPU_CP15_MMU=y CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y # CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y CONFIG_CPU_FREQ_GOV_ATTR_SET=y CONFIG_CPU_FREQ_GOV_COMMON=y # CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set CONFIG_CPU_FREQ_GOV_ONDEMAND=y CONFIG_CPU_FREQ_GOV_PERFORMANCE=y # CONFIG_CPU_FREQ_GOV_POWERSAVE is not set -CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y # CONFIG_CPU_FREQ_GOV_USERSPACE is not set CONFIG_CPU_FREQ_STAT=y CONFIG_CPU_HAS_ASID=y @@ -135,11 +131,16 @@ CONFIG_CRYPTO_RNG=y CONFIG_CRYPTO_RNG2=y CONFIG_CRYPTO_RNG_DEFAULT=y CONFIG_CRYPTO_SEQIV=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA1_ARM=y +CONFIG_CRYPTO_SHA1_ARM_NEON=y CONFIG_CRYPTO_SHA256=y CONFIG_CRYPTO_SHA256_ARM=y +CONFIG_CRYPTO_SHA512_ARM=y CONFIG_CRYPTO_SIMD=y CONFIG_CRYPTO_XTS=y CONFIG_CRYPTO_ZSTD=y +CONFIG_CRYPTO_USER=y CONFIG_DCACHE_WORD_ACCESS=y CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" CONFIG_DEBUG_MISC=y @@ -187,7 +188,7 @@ CONFIG_GPIOLIB=y CONFIG_GPIOLIB_IRQCHIP=y CONFIG_GPIO_74X164=y CONFIG_GPIO_WATCHDOG=y -# CONFIG_GPIO_WATCHDOG_ARCH_INITCALL is not set +CONFIG_GPIO_WATCHDOG_ARCH_INITCALL=y CONFIG_HANDLE_DOMAIN_IRQ=y CONFIG_HARDEN_BRANCH_PREDICTOR=y CONFIG_HARDIRQS_SW_RESEND=y @@ -201,6 +202,8 @@ CONFIG_HWSPINLOCK=y CONFIG_HWSPINLOCK_QCOM=y CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_OPTEE=y +CONFIG_HZ=100 +CONFIG_HZ_100=y CONFIG_HZ_FIXED=0 CONFIG_I2C=y CONFIG_I2C_BOARDINFO=y @@ -348,25 +351,13 @@ CONFIG_PINCTRL_MSM=y # CONFIG_PINCTRL_SDM660 is not set # CONFIG_PINCTRL_SDM845 is not set # CONFIG_PINCTRL_SM8150 is not set +CONFIG_PLUGIN_HOSTCC="g++" CONFIG_PM_OPP=y CONFIG_POWER_RESET=y CONFIG_POWER_RESET_MSM=y CONFIG_POWER_SUPPLY=y CONFIG_PPS=y CONFIG_PRINTK_TIME=y -CONFIG_PSTORE=y -# CONFIG_PSTORE_842_COMPRESS is not set -CONFIG_PSTORE_COMPRESS=y -CONFIG_PSTORE_COMPRESS_DEFAULT="deflate" -# CONFIG_PSTORE_CONSOLE is not set -CONFIG_PSTORE_DEFLATE_COMPRESS=y -CONFIG_PSTORE_DEFLATE_COMPRESS_DEFAULT=y -# CONFIG_PSTORE_LZ4HC_COMPRESS is not set -# CONFIG_PSTORE_LZ4_COMPRESS is not set -# CONFIG_PSTORE_LZO_COMPRESS is not set -# CONFIG_PSTORE_PMSG is not set -CONFIG_PSTORE_RAM=y -# CONFIG_PSTORE_ZSTD_COMPRESS is not set CONFIG_PTP_1588_CLOCK=y CONFIG_QCA807X_PHY=y CONFIG_QCOM_A53PLL=y @@ -399,9 +390,6 @@ CONFIG_RATIONAL=y CONFIG_RCU_CPU_STALL_TIMEOUT=21 CONFIG_RCU_NEED_SEGCBLIST=y CONFIG_RCU_STALL_COMMON=y -CONFIG_REED_SOLOMON=y -CONFIG_REED_SOLOMON_DEC8=y -CONFIG_REED_SOLOMON_ENC8=y CONFIG_REFCOUNT_FULL=y CONFIG_REGMAP=y CONFIG_REGMAP_I2C=y @@ -463,7 +451,10 @@ CONFIG_TIMER_PROBE=y CONFIG_TREE_RCU=y CONFIG_TREE_SRCU=y CONFIG_UBIFS_FS=y -# CONFIG_UCLAMP_TASK is not set +CONFIG_UBIFS_FS_ADVANCED_COMPR=y +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_ZLIB=y +CONFIG_UBIFS_FS_ZSTD=y CONFIG_UEVENT_HELPER_PATH="" CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" CONFIG_UNWINDER_ARM=y From 027f65ae78238f44b6e7725e11041bb93105e194 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Sun, 18 Sep 2022 14:18:18 +0800 Subject: [PATCH 011/102] fix --- config-5gx3 | 9 ++++----- config-l1000 | 9 ++++----- config-zbt4019 | 9 ++++----- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/config-5gx3 b/config-5gx3 index 3b7960b0..c2e3dbbc 100755 --- a/config-5gx3 +++ b/config-5gx3 @@ -2,12 +2,11 @@ # Automatically generated file; DO NOT EDIT. # OpenWrt Configuration # -CONFIG_KERNEL_ARM_MODULE_PLTS=y -CONFIG_ARM_MODULE_PLTS=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_KERNEL_ARM_MODULE_PLTS=y +CONFIG_TARGET_SQUASHFS_BLOCK_SIZE=64 +CONFIG_KERNEL_SWAP=y +CONFIG_PREINITOPT=y CONFIG_KERNEL_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_MODULES=y -CONFIG_HAVE_DOT_CONFIG=y # CONFIG_TARGET_sunxi is not set # CONFIG_TARGET_apm821xx is not set # CONFIG_TARGET_ath25 is not set diff --git a/config-l1000 b/config-l1000 index 59e5c947..610d899e 100755 --- a/config-l1000 +++ b/config-l1000 @@ -2,12 +2,11 @@ # Automatically generated file; DO NOT EDIT. # OpenWrt Configuration # -CONFIG_KERNEL_ARM_MODULE_PLTS=y -CONFIG_ARM_MODULE_PLTS=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_KERNEL_ARM_MODULE_PLTS=y +CONFIG_TARGET_SQUASHFS_BLOCK_SIZE=64 +CONFIG_KERNEL_SWAP=y +CONFIG_PREINITOPT=y CONFIG_KERNEL_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_MODULES=y -CONFIG_HAVE_DOT_CONFIG=y # CONFIG_TARGET_sunxi is not set # CONFIG_TARGET_apm821xx is not set # CONFIG_TARGET_ath25 is not set diff --git a/config-zbt4019 b/config-zbt4019 index 1ded6467..31752148 100755 --- a/config-zbt4019 +++ b/config-zbt4019 @@ -2,12 +2,11 @@ # Automatically generated file; DO NOT EDIT. # OpenWrt Configuration # -CONFIG_KERNEL_ARM_MODULE_PLTS=y -CONFIG_ARM_MODULE_PLTS=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_KERNEL_ARM_MODULE_PLTS=y +CONFIG_TARGET_SQUASHFS_BLOCK_SIZE=64 +CONFIG_KERNEL_SWAP=y +CONFIG_PREINITOPT=y CONFIG_KERNEL_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_MODULES=y -CONFIG_HAVE_DOT_CONFIG=y # CONFIG_TARGET_sunxi is not set # CONFIG_TARGET_apm821xx is not set # CONFIG_TARGET_ath25 is not set From 5a6e9cd7b95902065023e65847cd298b354a5942 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Sun, 18 Sep 2022 14:59:29 +0800 Subject: [PATCH 012/102] fix --- root/target/linux/generic/config-5.15 | 267 +++++++++++------- root/target/linux/generic/config-5.4 | 51 ++-- .../files/drivers/net/phy/b53/b53_common.c | 2 +- 3 files changed, 198 insertions(+), 122 deletions(-) diff --git a/root/target/linux/generic/config-5.15 b/root/target/linux/generic/config-5.15 index 27d1d8d2..f5a14233 100755 --- a/root/target/linux/generic/config-5.15 +++ b/root/target/linux/generic/config-5.15 @@ -22,8 +22,10 @@ CONFIG_64BIT_TIME=y # CONFIG_ACPI_CONFIGFS is not set # CONFIG_ACPI_CUSTOM_METHOD is not set # CONFIG_ACPI_EXTLOG is not set +# CONFIG_ACPI_FPDT is not set # CONFIG_ACPI_HED is not set # CONFIG_ACPI_NFIT is not set +# CONFIG_ACPI_PRMT is not set # CONFIG_ACPI_REDUCED_HARDWARE_ONLY is not set # CONFIG_ACPI_TABLE_UPGRADE is not set # CONFIG_ACPI_VIDEO is not set @@ -49,6 +51,7 @@ CONFIG_64BIT_TIME=y # CONFIG_AD5758 is not set # CONFIG_AD5761 is not set # CONFIG_AD5764 is not set +# CONFIG_AD5766 is not set # CONFIG_AD5770R is not set # CONFIG_AD5791 is not set # CONFIG_AD5933 is not set @@ -108,6 +111,7 @@ CONFIG_64BIT_TIME=y # CONFIG_ADM8211 is not set # CONFIG_ADT7316 is not set # CONFIG_ADUX1020 is not set +# CONFIG_ADV_SWBUTTON is not set CONFIG_ADVISE_SYSCALLS=y # CONFIG_ADXL345_I2C is not set # CONFIG_ADXL345_SPI is not set @@ -154,6 +158,8 @@ CONFIG_ALLOW_DEV_COREDUMP=y # CONFIG_AMD8111_ETH is not set # CONFIG_AMD_MEM_ENCRYPT is not set # CONFIG_AMD_PHY is not set +# CONFIG_AMD_PMC is not set +# CONFIG_AMD_SFH_HID is not set # CONFIG_AMD_XGBE is not set # CONFIG_AMD_XGBE_HAVE_ECC is not set # CONFIG_AMIGA_PARTITION is not set @@ -178,12 +184,14 @@ CONFIG_ANON_INODES=y # CONFIG_ARCH_ACTIONS is not set # CONFIG_ARCH_AGILEX is not set # CONFIG_ARCH_ALPINE is not set +# CONFIG_ARCH_APPLE is not set # CONFIG_ARCH_ARTPEC is not set # CONFIG_ARCH_ASPEED is not set # CONFIG_ARCH_AT91 is not set # CONFIG_ARCH_AXXIA is not set # CONFIG_ARCH_BCM is not set # CONFIG_ARCH_BCM2835 is not set +# CONFIG_ARCH_BCM4908 is not set # CONFIG_ARCH_BCM_21664 is not set # CONFIG_ARCH_BCM_23550 is not set # CONFIG_ARCH_BCM_281XX is not set @@ -313,6 +321,7 @@ CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8 # CONFIG_ARM64_BTI is not set # CONFIG_ARM64_CRYPTO is not set # CONFIG_ARM64_E0PD is not set +# CONFIG_ARM64_EPAN is not set # CONFIG_ARM64_ERRATUM_1024718 is not set # CONFIG_ARM64_ERRATUM_1319367 is not set # CONFIG_ARM64_ERRATUM_1463225 is not set @@ -330,12 +339,13 @@ CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8 # CONFIG_ARM64_ERRATUM_858921 is not set # CONFIG_ARM64_HW_AFDBM is not set # CONFIG_ARM64_LSE_ATOMICS is not set -# CONFIG_ARM64_MODULE_PLTS is not set +CONFIG_ARM64_MODULE_PLTS=y # CONFIG_ARM64_MTE is not set # CONFIG_ARM64_PAN is not set # CONFIG_ARM64_PMEM is not set # CONFIG_ARM64_PSEUDO_NMI is not set # CONFIG_ARM64_PTDUMP_DEBUGFS is not set +# CONFIG_ARM64_PTR_AUTH_KERNEL is not set # CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set # CONFIG_ARM64_RAS_EXTN is not set # CONFIG_ARM64_RELOC_TEST is not set @@ -386,19 +396,20 @@ CONFIG_ARM_DMA_MEM_BUFFERABLE=y # CONFIG_ARM_ERRATA_852423 is not set # CONFIG_ARM_ERRATA_857271 is not set # CONFIG_ARM_ERRATA_857272 is not set +# CONFIG_ARM_FFA_TRANSPORT is not set CONFIG_ARM_GIC_MAX_NR=1 # CONFIG_ARM_KIRKWOOD_CPUFREQ is not set # CONFIG_ARM_KPROBES_TEST is not set # CONFIG_ARM_LPAE is not set # CONFIG_ARM_MHU is not set -# CONFIG_ARM_MODULE_PLTS is not set +# CONFIG_ARM_MHU_V2 is not set +CONFIG_ARM_MODULE_PLTS=y # CONFIG_ARM_PATCH_PHYS_VIRT is not set # CONFIG_ARM_PSCI is not set # CONFIG_ARM_PSCI_CHECKER is not set # CONFIG_ARM_PSCI_CPUIDLE is not set # CONFIG_ARM_PTDUMP_DEBUGFS is not set # CONFIG_ARM_SBSA_WATCHDOG is not set -# CONFIG_ARM_SCMI_PROTOCOL is not set # CONFIG_ARM_SCPI_PROTOCOL is not set # CONFIG_ARM_SDE_INTERFACE is not set # CONFIG_ARM_SMCCC_SOC_ID is not set @@ -557,8 +568,8 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_BCM_IPROC_ADC is not set # CONFIG_BCM_KONA_USB2_PHY is not set # CONFIG_BCM_SBA_RAID is not set -# CONFIG_BCM_VK is not set # CONFIG_BDI_SWITCH is not set +# CONFIG_BCM_VK is not set # CONFIG_BE2ISCSI is not set # CONFIG_BE2NET is not set # CONFIG_BEFS_FS is not set @@ -673,6 +684,7 @@ CONFIG_BLOCK=y # CONFIG_BMC150_MAGN_SPI is not set # CONFIG_BME680 is not set # CONFIG_BMG160 is not set +# CONFIG_BMI088_ACCEL is not set # CONFIG_BMI160_I2C is not set # CONFIG_BMI160_SPI is not set # CONFIG_BMIPS_GENERIC is not set @@ -744,6 +756,7 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_BTRFS_FS_POSIX_ACL is not set # CONFIG_BTRFS_FS_REF_VERIFY is not set # CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set +# CONFIG_BT_AOSPEXT is not set # CONFIG_BT_ATH3K is not set # CONFIG_BT_BNEP is not set CONFIG_BT_BNEP_MC_FILTER=y @@ -784,6 +797,7 @@ CONFIG_BT_HCIUART_H4=y # CONFIG_BT_RFCOMM is not set CONFIG_BT_RFCOMM_TTY=y # CONFIG_BT_SELFTEST is not set +# CONFIG_BT_VIRTIO is not set CONFIG_BUG=y # CONFIG_BUG_ON_DATA_CORRUPTION is not set CONFIG_BUILDTIME_EXTABLE_SORT=y @@ -798,6 +812,7 @@ CONFIG_CACHE_L2X0_PMU=y # CONFIG_CAN_BCM is not set # CONFIG_CAN_DEBUG_DEVICES is not set # CONFIG_CAN_DEV is not set +# CONFIG_CAN_ETAS_ES58X is not set # CONFIG_CAN_GS_USB is not set # CONFIG_CAN_GW is not set # CONFIG_CAN_HI311X is not set @@ -894,13 +909,13 @@ CONFIG_CIFS_POSIX=y # CONFIG_CIFS_SMB2 is not set # CONFIG_CIFS_STATS is not set # CONFIG_CIFS_STATS2 is not set +# CONFIG_CIFS_SWN_UPCALL is not set # CONFIG_CIFS_WEAK_PW_HASH is not set CONFIG_CIFS_XATTR=y # CONFIG_CIO_DAC is not set CONFIG_CLANG_VERSION=0 # CONFIG_CLEANCACHE is not set # CONFIG_CLKSRC_VERSATILE is not set -# CONFIG_CLK_GFM_LPASS_SM8250 is not set # CONFIG_CLK_HSDK is not set # CONFIG_CLK_QORIQ is not set # CONFIG_CLK_SP810 is not set @@ -913,6 +928,7 @@ CONFIG_CLS_U32_MARK=y # CONFIG_CM3605 is not set # CONFIG_CM36651 is not set # CONFIG_CMA is not set +# CONFIG_CMA_SYSFS is not set CONFIG_CMDLINE="" # CONFIG_CMDLINE_BOOL is not set # CONFIG_CMDLINE_EXTEND is not set @@ -924,6 +940,7 @@ CONFIG_CMDLINE="" # CONFIG_CODE_PATCHING_SELFTEST is not set # CONFIG_COMEDI is not set # CONFIG_COMMON_CLK_AXI_CLKGEN is not set +# CONFIG_CLK_BCM2711_DVP 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 @@ -953,6 +970,7 @@ CONFIG_CMDLINE="" CONFIG_COMPACTION=y # CONFIG_COMPAL_LAPTOP is not set # CONFIG_COMPAT is not set +# CONFIG_COMPAT_32BIT_TIME is not set # CONFIG_COMPAT_BRK is not set # CONFIG_COMPILE_TEST is not set # CONFIG_CONFIGFS_FS is not set @@ -1017,8 +1035,8 @@ CONFIG_CROSS_COMPILE="" # CONFIG_CROSS_MEMORY_ATTACH is not set CONFIG_CRYPTO=y # CONFIG_CRYPTO_842 is not set -CONFIG_CRYPTO_ACOMP2=y # CONFIG_CRYPTO_ADIANTUM is not set +CONFIG_CRYPTO_ACOMP2=y CONFIG_CRYPTO_AEAD=y CONFIG_CRYPTO_AEAD2=y # CONFIG_CRYPTO_AEGIS128 is not set @@ -1100,6 +1118,7 @@ CONFIG_CRYPTO_CTR=y # CONFIG_CRYPTO_DEV_MXC_SCC is not set # CONFIG_CRYPTO_DEV_MXS_DCP is not set # CONFIG_CRYPTO_DEV_NITROX_CNN55XX is not set +# CONFIG_CRYPTO_DEV_QAT_4XXX is not set # CONFIG_CRYPTO_DEV_QAT_C3XXX is not set # CONFIG_CRYPTO_DEV_QAT_C3XXXVF is not set # CONFIG_CRYPTO_DEV_QAT_C62X is not set @@ -1119,7 +1138,6 @@ CONFIG_CRYPTO_CTR=y # CONFIG_CRYPTO_DRBG_MENU is not set # CONFIG_CRYPTO_ECB is not set # CONFIG_CRYPTO_ECDH is not set -# CONFIG_CRYPTO_ECDSA is not set # CONFIG_CRYPTO_ECHAINIV is not set # CONFIG_CRYPTO_ECRDSA is not set # CONFIG_CRYPTO_ESSIV is not set @@ -1137,9 +1155,9 @@ CONFIG_CRYPTO_HASH2=y # CONFIG_CRYPTO_HW is not set # CONFIG_CRYPTO_JITTERENTROPY is not set # CONFIG_CRYPTO_KEYWRAP is not set -# CONFIG_CRYPTO_KHAZAD is not set CONFIG_CRYPTO_KPP=y CONFIG_CRYPTO_KPP2=y +# CONFIG_CRYPTO_KHAZAD is not set CONFIG_CRYPTO_LIB_AES=y CONFIG_CRYPTO_LIB_ARC4=y # CONFIG_CRYPTO_LIB_BLAKE2S is not set @@ -1236,7 +1254,6 @@ CONFIG_CRYPTO_SKCIPHER2=y # CONFIG_CRYPTO_ZSTD is not set # CONFIG_CS5535_MFGPT is not set # CONFIG_CS89x0 is not set -# CONFIG_CS89x0_PLATFORM is not set # CONFIG_CSD_LOCK_WAIT_DEBUG is not set # CONFIG_CUSE is not set # CONFIG_CW1200 is not set @@ -1250,7 +1267,6 @@ CONFIG_CRYPTO_SKCIPHER2=y # CONFIG_CYPRESS_FIRMWARE is not set # CONFIG_DA280 is not set # CONFIG_DA311 is not set -# CONFIG_DAMON is not set # CONFIG_DAVICOM_PHY is not set # CONFIG_DAX is not set # CONFIG_DCB is not set @@ -1264,7 +1280,6 @@ CONFIG_CRYPTO_SKCIPHER2=y # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_EFI is not set # CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_32B is not set -# CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B is not set # CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set CONFIG_DEBUG_FS=y CONFIG_DEBUG_FS_ALLOW_ALL=y @@ -1277,13 +1292,9 @@ CONFIG_DEBUG_FS_ALLOW_ALL=y # CONFIG_DEBUG_INFO_BTF is not set # CONFIG_DEBUG_INFO_COMPRESSED is not set # CONFIG_DEBUG_INFO_DWARF4 is not set -# CONFIG_DEBUG_INFO_DWARF5 is not set -CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y CONFIG_DEBUG_INFO_REDUCED=y # CONFIG_DEBUG_INFO_SPLIT is not set -# CONFIG_DEBUG_IRQFLAGS is not set CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_KMAP_LOCAL is not set # CONFIG_DEBUG_KMEMLEAK is not set # CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_KOBJECT_RELEASE is not set @@ -1379,6 +1390,7 @@ CONFIG_DEVPORT=y # CONFIG_DLHL60D is not set # CONFIG_DLM is not set # CONFIG_DM9000 is not set +# CONFIG_DMABUF_DEBUG is not set # CONFIG_DMABUF_HEAPS is not set # CONFIG_DMABUF_MOVE_NOTIFY is not set # CONFIG_DMABUF_SELFTESTS is not set @@ -1395,7 +1407,6 @@ CONFIG_DMA_DECLARE_COHERENT=y # CONFIG_DMA_ENGINE is not set # CONFIG_DMA_FENCE_TRACE is not set # CONFIG_DMA_JZ4780 is not set -# CONFIG_DMA_MAP_BENCHMARK is not set CONFIG_DMA_NONCOHERENT_MMAP=y # CONFIG_DMA_NOOP_OPS is not set # CONFIG_DMA_PERNUMA_CMA is not set @@ -1446,7 +1457,9 @@ CONFIG_DQL=y # CONFIG_DRM_AMD_DC_DCN3_0 is not set # CONFIG_DRM_AMD_DC_HDCP is not set # CONFIG_DRM_AMD_DC_SI is not set +# CONFIG_DRM_AMD_SECURE_DISPLAY is not set # CONFIG_DRM_ANALOGIX_ANX6345 is not set +# CONFIG_DRM_ANALOGIX_ANX7625 is not set # CONFIG_DRM_ANALOGIX_ANX78XX is not set # CONFIG_DRM_ARCPGU is not set # CONFIG_DRM_ARMADA is not set @@ -1454,6 +1467,7 @@ CONFIG_DQL=y # CONFIG_DRM_BOCHS is not set # CONFIG_DRM_CDNS_DSI is not set # CONFIG_DRM_CDNS_MHDP8546 is not set +# CONFIG_DRM_CHIPONE_ICN6211 is not set # CONFIG_DRM_CHRONTEL_CH7033 is not set # CONFIG_DRM_CIRRUS_QEMU is not set # CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS is not set @@ -1471,6 +1485,7 @@ CONFIG_DQL=y # CONFIG_DRM_FSL_DCU is not set # CONFIG_DRM_GM12U320 is not set # CONFIG_DRM_GMA500 is not set +# CONFIG_DRM_GUD is not set # CONFIG_DRM_HDLCD is not set # CONFIG_DRM_HISI_HIBMC is not set # CONFIG_DRM_HISI_KIRIN is not set @@ -1480,12 +1495,16 @@ CONFIG_DQL=y # CONFIG_DRM_I2C_NXP_TDA998X is not set # CONFIG_DRM_I2C_SIL164 is not set # CONFIG_DRM_I915 is not set +# CONFIG_DRM_ITE_IT66121 is not set +DRM_I915_REQUEST_TIMEOUT=20000 # CONFIG_DRM_KOMEDA is not set # CONFIG_DRM_LEGACY is not set # CONFIG_DRM_LIB_RANDOM is not set # CONFIG_DRM_LIMA is not set # CONFIG_DRM_LOAD_EDID_FIRMWARE 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_LVDS_CODEC is not set # CONFIG_DRM_LVDS_ENCODER is not set # CONFIG_DRM_MALI_DISPLAY is not set @@ -1497,14 +1516,18 @@ CONFIG_DQL=y # CONFIG_DRM_NWL_MIPI_DSI is not set # CONFIG_DRM_NXP_PTN3460 is not set # CONFIG_DRM_OMAP is not set -# CONFIG_DRM_PANEL_ARM_VERSATILE is not set +# CONFIG_DRM_PANEL_ABT_Y030XX067A is not set # CONFIG_DRM_PANEL_ASUS_Z00T_TM5P5_NT35596 is not set +# CONFIG_DRM_PANEL_ARM_VERSATILE is not set # CONFIG_DRM_PANEL_BOE_HIMAX8279D is not set # CONFIG_DRM_PANEL_BOE_TV101WUM_NL6 is not set +# CONFIG_DRM_PANEL_DSI_CM is not set # CONFIG_DRM_PANEL_ELIDA_KD35T133 is not set -# CONFIG_DRM_PANEL_FEIXIN_K101_IM2BA02 is not set # CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D is not set +# CONFIG_DRM_PANEL_FEIXIN_K101_IM2BA02 is not set +# CONFIG_DRM_PANEL_KHADAS_TS050 is not set # CONFIG_DRM_PANEL_ILITEK_IL9322 is not set +# CONFIG_DRM_PANEL_ILITEK_ILI9806E is not set # CONFIG_DRM_PANEL_ILITEK_ILI9881C is not set # CONFIG_DRM_PANEL_INNOLUX_P079ZCA is not set # CONFIG_DRM_PANEL_JDI_LT070ME05000 is not set @@ -1515,8 +1538,10 @@ CONFIG_DQL=y # CONFIG_DRM_PANEL_LG_LG4573 is not set # CONFIG_DRM_PANEL_LVDS is not set # CONFIG_DRM_PANEL_MANTIX_MLAF057WE51 is not set +# CONFIG_DRM_PANEL_MIPI_DBI is not set # CONFIG_DRM_PANEL_NEC_NL8048HL11 is not set # CONFIG_DRM_PANEL_NOVATEK_NT35510 is not set +# CONFIG_DRM_PANEL_NOVATEK_NT36672A is not set # CONFIG_DRM_PANEL_NOVATEK_NT39016 is not set # CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO is not set # CONFIG_DRM_PANEL_ORISETECH_OTM8009A is not set @@ -1528,6 +1553,7 @@ CONFIG_DQL=y # CONFIG_DRM_PANEL_ROCKTECH_JH057N00900 is not set # CONFIG_DRM_PANEL_RONBO_RB070D30 is not set # CONFIG_DRM_PANEL_SAMSUNG_LD9040 is not set +# CONFIG_DRM_PANEL_SAMSUNG_SOFEF00 is not set # CONFIG_DRM_PANEL_SAMSUNG_S6D16D0 is not set # CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2 is not set # CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03 is not set @@ -1544,9 +1570,11 @@ CONFIG_DQL=y # CONFIG_DRM_PANEL_SITRONIX_ST7789V is not set # CONFIG_DRM_PANEL_SONY_ACX424AKP is not set # CONFIG_DRM_PANEL_SONY_ACX565AKM is not set +# CONFIG_DRM_PANEL_TDO_TL070WSH30 is not set # CONFIG_DRM_PANEL_TPO_TD028TTEC1 is not set # CONFIG_DRM_PANEL_TPO_TD043MTEA1 is not set # CONFIG_DRM_PANEL_TPO_TPG110 is not set +# CONFIG_DRM_PANEL_TPO_Y17P is not set # CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA is not set # CONFIG_DRM_PANEL_VISIONOX_RM69299 is not set # CONFIG_DRM_PANEL_XINPENG_XPP055C272 is not set @@ -1563,6 +1591,7 @@ CONFIG_DQL=y # CONFIG_DRM_SII9234 is not set # CONFIG_DRM_SIL_SII8620 is not set # CONFIG_DRM_SIMPLE_BRIDGE is not set +# CONFIG_DRM_SIMPLEDRM is not set # CONFIG_DRM_STI is not set # CONFIG_DRM_STM is not set # CONFIG_DRM_SUN4I is not set @@ -1573,6 +1602,7 @@ CONFIG_DQL=y # CONFIG_DRM_TI_SN65DSI86 is not set # CONFIG_DRM_TI_TFP410 is not set # CONFIG_DRM_TI_TPD12S015 is not set +# CONFIG_DRM_TI_SN65DSI83 is not set # CONFIG_DRM_TOSHIBA_TC358762 is not set # CONFIG_DRM_TOSHIBA_TC358764 is not set # CONFIG_DRM_TOSHIBA_TC358767 is not set @@ -1587,6 +1617,7 @@ CONFIG_DQL=y # CONFIG_DRM_VKMS is not set # CONFIG_DRM_VMWGFX is not set # CONFIG_DRM_XEN is not set +# CONFIG_DRM_XEN_FRONTEND is not set # CONFIG_DS1682 is not set # CONFIG_DS1803 is not set # CONFIG_DS4424 is not set @@ -1662,6 +1693,7 @@ CONFIG_DVB_MAX_ADAPTERS=16 # CONFIG_DVB_MT312 is not set # CONFIG_DVB_MT352 is not set # CONFIG_DVB_MXL5XX is not set +# CONFIG_DVB_MXL692 is not set # CONFIG_DVB_NET is not set # CONFIG_DVB_NXT200X is not set # CONFIG_DVB_NXT6000 is not set @@ -1729,7 +1761,6 @@ CONFIG_DVB_MAX_ADAPTERS=16 # CONFIG_DWMAC_DWC_QOS_ETH is not set # CONFIG_DWMAC_INTEL_PLAT is not set # CONFIG_DWMAC_IPQ806X is not set -# CONFIG_DWMAC_LOONGSON is not set # CONFIG_DWMAC_LPC18XX is not set # CONFIG_DWMAC_MESON is not set # CONFIG_DWMAC_ROCKCHIP is not set @@ -1790,7 +1821,7 @@ CONFIG_EPOLL=y # CONFIG_ET131X is not set CONFIG_ETHERNET=y # CONFIG_ETHOC is not set -CONFIG_ETHTOOL_NETLINK=y +# CONFIG_ETHTOOL_NETLINK is not set CONFIG_EVENTFD=y # CONFIG_EVM is not set # CONFIG_EXFAT_FS is not set @@ -1819,6 +1850,7 @@ CONFIG_EXT4_USE_FOR_EXT2=y # CONFIG_EXTCON_RT8973A is not set # CONFIG_EXTCON_SM5502 is not set # CONFIG_EXTCON_USB_GPIO is not set +# CONFIG_EXTCON_USBC_TUSB320 is not set CONFIG_EXTRA_FIRMWARE="" CONFIG_EXTRA_TARGETS="" # CONFIG_EXYNOS_ADC is not set @@ -2026,12 +2058,15 @@ CONFIG_FSNOTIFY=y # CONFIG_FUSION_SPI is not set CONFIG_FUTEX=y CONFIG_FUTEX_PI=y +# CONFIG_FW_CACHE is not set # CONFIG_FW_CFG_SYSFS is not set CONFIG_FW_LOADER=y # CONFIG_FW_LOADER_COMPRESS is not set CONFIG_FW_LOADER_USER_HELPER=y CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y # CONFIG_FXAS21002C is not set +# CONFIG_FXLS8962AF_I2C is not set +# CONFIG_FXLS8962AF_SPI is not set # CONFIG_FXOS8700_I2C is not set # CONFIG_FXOS8700_SPI is not set CONFIG_GACT_PROB=y @@ -2121,6 +2156,7 @@ CONFIG_GPIOLIB_FASTPATH_LIMIT=512 # CONFIG_GPIO_PCI_IDIO_16 is not set # CONFIG_GPIO_PISOSR is not set # CONFIG_GPIO_PL061 is not set +# CONFIG_GPIO_PWM is not set # CONFIG_GPIO_RCAR is not set # CONFIG_GPIO_RDC321X is not set # CONFIG_GPIO_SAMA5D2_PIOBU is not set @@ -2158,7 +2194,6 @@ CONFIG_HARDENED_USERCOPY=y # CONFIG_HARDENED_USERCOPY_PAGESPAN is not set CONFIG_HARDEN_EL2_VECTORS=y # CONFIG_HARDLOCKUP_DETECTOR is not set -# CONFIG_HAVE_ARM_ARCH_TIMER is not set # CONFIG_HCALL_STATS is not set # CONFIG_HDC100X is not set # CONFIG_HDC2010 is not set @@ -2178,7 +2213,6 @@ CONFIG_HARDEN_EL2_VECTORS=y # CONFIG_HFSPLUS_FS_POSIX_ACL is not set # CONFIG_HFS_FS is not set # CONFIG_HFS_FS_POSIX_ACL is not set -# CONFIG_HI6421V600_IRQ is not set # CONFIG_HI8435 is not set # CONFIG_HIBERNATION is not set # CONFIG_HID is not set @@ -2210,6 +2244,7 @@ CONFIG_HARDEN_EL2_VECTORS=y # CONFIG_HID_ELO is not set # CONFIG_HID_EMS_FF is not set # CONFIG_HID_EZKEY is not set +# CONFIG_HID_FT260 is not set # CONFIG_HID_GEMBIRD is not set # CONFIG_HID_GENERIC is not set # CONFIG_HID_GFRM is not set @@ -2248,6 +2283,7 @@ CONFIG_HARDEN_EL2_VECTORS=y # CONFIG_HID_PICOLCD is not set # CONFIG_HID_PID is not set # CONFIG_HID_PLANTRONICS is not set +# CONFIG_HID_PLAYSTATION is not set # CONFIG_HID_PRIMAX is not set # CONFIG_HID_PRODIKEYS is not set # CONFIG_HID_REDRAGON is not set @@ -2257,6 +2293,7 @@ CONFIG_HARDEN_EL2_VECTORS=y # CONFIG_HID_SAITEK is not set # CONFIG_HID_SAMSUNG is not set # CONFIG_HID_SENSOR_HUB is not set +# CONFIG_HID_SEMITEK is not set # CONFIG_HID_SMARTJOYPLUS is not set # CONFIG_HID_SONY is not set # CONFIG_HID_SPEEDLINK is not set @@ -2397,6 +2434,9 @@ CONFIG_HZ_100=y # CONFIG_I2C_GPIO_FAULT_INJECTOR is not set # CONFIG_I2C_HELPER_AUTO is not set # CONFIG_I2C_HID is not set +# CONFIG_I2C_HID_ACPI is not set +# CONFIG_I2C_HID_OF is not set +# CONFIG_I2C_HID_OF_GOODIX is not set # CONFIG_I2C_I801 is not set # CONFIG_I2C_IBM_IIC is not set # CONFIG_I2C_IMG is not set @@ -2448,7 +2488,6 @@ CONFIG_HZ_100=y # CONFIG_I2C_VERSATILE is not set # CONFIG_I2C_VIA is not set # CONFIG_I2C_VIAPRO is not set -# CONFIG_I2C_VIRTIO is not set # CONFIG_I2C_XILINX is not set # CONFIG_I3C is not set # CONFIG_I40E is not set @@ -2470,7 +2509,7 @@ CONFIG_HZ_100=y # CONFIG_ICP10100 is not set # CONFIG_ICPLUS_PHY is not set # CONFIG_ICS932S401 is not set -# CONFIG_ICST is not set +♯ CONFIG_ICST is not set # CONFIG_IDE is not set # CONFIG_IDEAPAD_LAPTOP is not set # CONFIG_IDE_GD is not set @@ -2506,6 +2545,7 @@ CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 # CONFIG_IIO_ST_ACCEL_3AXIS is not set # CONFIG_IIO_ST_GYRO_3AXIS is not set # CONFIG_IIO_ST_LSM6DSX is not set +# CONFIG_IIO_ST_LSM9DS0 is not set # CONFIG_IIO_ST_MAGN_3AXIS is not set # CONFIG_IIO_ST_PRESS is not set # CONFIG_IIO_SW_DEVICE is not set @@ -2579,6 +2619,7 @@ CONFIG_INOTIFY_USER=y # CONFIG_INPUT_BMA150 is not set # CONFIG_INPUT_CM109 is not set # CONFIG_INPUT_CMA3000 is not set +# CONFIG_INPUT_DA7280_HAPTICS is not set # CONFIG_INPUT_DRV260X_HAPTICS is not set # CONFIG_INPUT_DRV2665_HAPTICS is not set # CONFIG_INPUT_DRV2667_HAPTICS is not set @@ -2595,6 +2636,7 @@ CONFIG_INOTIFY_USER=y # CONFIG_INPUT_IDEAPAD_SLIDEBAR is not set # CONFIG_INPUT_IMS_PCU is not set # CONFIG_INPUT_IQS269A is not set +# CONFIG_INPUT_IQS626A is not set # CONFIG_INPUT_JOYDEV is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_KEYBOARD is not set @@ -2700,7 +2742,6 @@ CONFIG_IO_WQ=y # CONFIG_IPV6_FOU is not set # CONFIG_IPV6_FOU_TUNNEL is not set # CONFIG_IPV6_ILA is not set -# CONFIG_IPV6_IOAM6_LWTUNNEL is not set # CONFIG_IPV6_MIP6 is not set # CONFIG_IPV6_MROUTE is not set # CONFIG_IPV6_MROUTE_MULTIPLE_TABLES is not set @@ -2767,6 +2808,7 @@ CONFIG_IP_ROUTE_VERBOSE=y # CONFIG_IP_VS is not set # CONFIG_IP_VS_MH is not set CONFIG_IP_VS_MH_TAB_INDEX=10 +# CONFIG_IP_VS_TWOS is not set # CONFIG_IRDA is not set # CONFIG_IRQSOFF_TRACER is not set # CONFIG_IRQ_ALL_CPUS is not set @@ -2845,6 +2887,7 @@ CONFIG_JFFS2_SUMMARY=y # CONFIG_JFS_STATISTICS is not set # CONFIG_JME is not set CONFIG_JOLIET=y +# CONFIG_JOYSTICK_QWIIC is not set # CONFIG_JSA1212 is not set # CONFIG_JUMP_LABEL is not set # CONFIG_JZ4740_WDT is not set @@ -2914,7 +2957,6 @@ CONFIG_KERNFS=y # CONFIG_KGDB is not set # CONFIG_KMEMCHECK is not set # CONFIG_KMX61 is not set -# CONFIG_KPC2000 is not set # CONFIG_KPROBES is not set # CONFIG_KPROBES_SANITY_TEST is not set # CONFIG_KPROBE_EVENTS_ON_NOTRACE is not set @@ -2932,6 +2974,7 @@ CONFIG_KUSER_HELPERS=y # CONFIG_KVM_GUEST is not set # CONFIG_KVM_INTEL is not set # CONFIG_KVM_WERROR is not set +# CONFIG_KVM_XEN is not set # CONFIG_KXCJK1013 is not set # CONFIG_KXSD9 is not set # CONFIG_L2TP is not set @@ -3030,6 +3073,7 @@ CONFIG_LEDS_TRIGGER_TIMER=y # CONFIG_LEDS_TRIGGER_TRANSIENT is not set # CONFIG_LEDS_TRIGGER_TTY is not set # CONFIG_LEDS_TURRIS_OMNIA is not set +# CONFIG_LEDS_UBNT_LEDBAR is not set # CONFIG_LEDS_USER is not set # CONFIG_LED_TRIGGER_PHY is not set # CONFIG_LEGACY_PTYS is not set @@ -3052,7 +3096,6 @@ CONFIG_LINEAR_RANGES=y # CONFIG_LIQUIDIO is not set # CONFIG_LIQUIDIO_VF is not set # CONFIG_LIS3L02DQ is not set -# CONFIG_LITEX_LITEETH is not set # CONFIG_LITEX_SOC_CONTROLLER is not set # CONFIG_LKDTM is not set CONFIG_LLC=y @@ -3140,8 +3183,8 @@ CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE="" # CONFIG_MANAGER_SBS is not set # CONFIG_MANDATORY_FILE_LOCKING is not set # CONFIG_MANGLE_BOOTARGS is not set -# CONFIG_MARVELL_10G_PHY is not set # CONFIG_MARVELL_88X2222_PHY is not set +# CONFIG_MARVELL_10G_PHY is not set # CONFIG_MARVELL_PHY is not set # CONFIG_MAX1027 is not set # CONFIG_MAX11100 is not set @@ -3161,7 +3204,6 @@ CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE="" # CONFIG_MAX63XX_WATCHDOG is not set # CONFIG_MAX9611 is not set # CONFIG_MAXIM_THERMOCOUPLE is not set -# CONFIG_MAXLINEAR_GPHY is not set CONFIG_MAY_USE_DEVLINK=y # CONFIG_MB1232 is not set # CONFIG_MC3230 is not set @@ -3176,7 +3218,6 @@ CONFIG_MAY_USE_DEVLINK=y # CONFIG_MCP4725 is not set # CONFIG_MCP4922 is not set # CONFIG_MCPM is not set -# CONFIG_MCTP is not set # CONFIG_MD is not set # CONFIG_MDIO_BCM_UNIMAC is not set # CONFIG_MDIO_BITBANG is not set @@ -3193,7 +3234,6 @@ CONFIG_MAY_USE_DEVLINK=y # CONFIG_MDIO_OCTEON is not set # CONFIG_MDIO_THUNDER is not set # CONFIG_MDIO_XPCS is not set -# CONFIG_MDM_GCC_9607 is not set # CONFIG_MD_FAULTY is not set # CONFIG_MEDIATEK_GE_PHY is not set # CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set @@ -3294,8 +3334,8 @@ CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 # CONFIG_MFD_EXYNOS_LPASS is not set # CONFIG_MFD_GATEWORKS_GSC is not set # CONFIG_MFD_HI6421_PMIC is not set -# CONFIG_MFD_INTEL_M10_BMC is not set # CONFIG_MFD_INTEL_PMT is not set +# CONFIG_MFD_INTEL_M10_BMC is not set # CONFIG_MFD_INTEL_QUARK_I2C_GPIO is not set # CONFIG_MFD_IQS62X is not set # CONFIG_MFD_JANZ_CMODIO is not set @@ -3338,8 +3378,6 @@ CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 # CONFIG_MFD_ROHM_BD71828 is not set # CONFIG_MFD_ROHM_BD718XX is not set # CONFIG_MFD_ROHM_BD957XMUF is not set -# CONFIG_MFD_RSMU_I2C is not set -# CONFIG_MFD_RSMU_SPI is not set # CONFIG_MFD_RT4831 is not set # CONFIG_MFD_RT5033 is not set # CONFIG_MFD_RTSX_PCI is not set @@ -3429,6 +3467,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_MLX4_CORE is not set # CONFIG_MLX4_EN is not set # CONFIG_MLX5_CORE is not set +# CONFIG_MLX5_SF is not set # CONFIG_MLX90614 is not set # CONFIG_MLX90632 is not set # CONFIG_MLXFW is not set @@ -3492,20 +3531,20 @@ CONFIG_MMC_BLOCK_MINORS=8 CONFIG_MMU=y CONFIG_MMU_GATHER_RCU_TABLE_FREE=y CONFIG_MMU_GATHER_TABLE_FREE=y -CONFIG_MODPROBE_PATH="/sbin/modprobe" CONFIG_MODULES=y # CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS is not set # CONFIG_MODULE_COMPRESS is not set # CONFIG_MODULE_COMPRESS_GZIP is not set -CONFIG_MODULE_COMPRESS_NONE=y # CONFIG_MODULE_COMPRESS_XZ is not set # CONFIG_MODULE_COMPRESS_ZSTD is not set +CONFIG_MODULE_COMPRESS_NONE=y # CONFIG_MODULE_FORCE_LOAD is not set # CONFIG_MODULE_FORCE_UNLOAD is not set # CONFIG_MODULE_SIG is not set # CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_MODULE_STRIPPED=y CONFIG_MODULE_UNLOAD=y +CONFIG_MODPROBE_PATH="/sbin/modprobe" # CONFIG_MODVERSIONS is not set # CONFIG_MOST is not set # CONFIG_MOTORCOMM_PHY is not set @@ -3537,8 +3576,6 @@ CONFIG_MPTCP_IPV6=y CONFIG_MSDOS_PARTITION=y # CONFIG_MSI_BITMAP_SELFTEST is not set # CONFIG_MSI_LAPTOP is not set -# CONFIG_MSM_GCC_8953 is not set -# CONFIG_MSM_MMCC_8994 is not set # CONFIG_MST_IRQ is not set CONFIG_MTD=y # CONFIG_MTD_ABSENT is not set @@ -3564,6 +3601,7 @@ CONFIG_MTD_CFI_UTIL=y CONFIG_MTD_COMPLEX_MAPPINGS=y # CONFIG_MTD_DATAFLASH is not set # CONFIG_MTD_DOCG3 is not set +# CONFIG_MTD_NAND_ECC_MEDIATEK is not set CONFIG_MTD_GEN_PROBE=y # CONFIG_MTD_GPIO_ADDR is not set # CONFIG_MTD_HYPERBUS is not set @@ -3581,7 +3619,6 @@ CONFIG_MTD_MAP_BANK_WIDTH_2=y CONFIG_MTD_MAP_BANK_WIDTH_4=y # CONFIG_MTD_MAP_BANK_WIDTH_8 is not set # CONFIG_MTD_MCHP23K256 is not set -# CONFIG_MTD_MCHP48L640 is not set # CONFIG_MTD_MT81xx_NOR is not set # CONFIG_MTD_MTDRAM is not set # CONFIG_MTD_MYLOADER_PARTS is not set @@ -3619,7 +3656,6 @@ CONFIG_MTD_NAND_DENALI_SCRATCH_REG_ADDR=0xff108018 # CONFIG_MTD_NAND_GPMI_NAND is not set # CONFIG_MTD_NAND_HISI504 is not set CONFIG_MTD_NAND_IDS=y -# CONFIG_MTD_NAND_INTEL_LGM is not set # CONFIG_MTD_NAND_JZ4740 is not set # CONFIG_MTD_NAND_MPC5121_NFC is not set # CONFIG_MTD_NAND_MTK is not set @@ -3636,7 +3672,6 @@ CONFIG_MTD_NAND_IDS=y # CONFIG_MTD_NAND_PXA3xx is not set # CONFIG_MTD_NAND_RB4XX is not set # CONFIG_MTD_NAND_RB750 is not set -# CONFIG_MTD_NAND_RB91X is not set # CONFIG_MTD_NAND_RICOH is not set # CONFIG_MTD_NAND_S3C2410 is not set # CONFIG_MTD_NAND_SHARPSL is not set @@ -3677,9 +3712,6 @@ CONFIG_MTD_ROOTFS_ROOT_DEV=y # CONFIG_MTD_SPINAND_MT29F is not set # CONFIG_MTD_SPI_NAND is not set # CONFIG_MTD_SPI_NOR is not set -# CONFIG_MTD_SPI_NOR_SWP_DISABLE is not set -CONFIG_MTD_SPI_NOR_SWP_DISABLE_ON_VOLATILE=y -# CONFIG_MTD_SPI_NOR_SWP_KEEP is not set # CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set CONFIG_MTD_SPI_NOR_USE_4K_SECTORS_LIMIT=4096 CONFIG_MTD_SPLIT=y @@ -3744,6 +3776,7 @@ CONFIG_NETDEVICES=y # CONFIG_NETFILTER_NETLINK is not set # CONFIG_NETFILTER_NETLINK_ACCT is not set # CONFIG_NETFILTER_NETLINK_GLUE_CT is not set +# CONFIG_NETFILTER_NETLINK_HOOK is not set # CONFIG_NETFILTER_NETLINK_LOG is not set # CONFIG_NETFILTER_NETLINK_OSF is not set # CONFIG_NETFILTER_NETLINK_QUEUE is not set @@ -3819,6 +3852,7 @@ CONFIG_NETDEVICES=y # CONFIG_NETFILTER_XT_TARGET_TEE is not set # CONFIG_NETFILTER_XT_TARGET_TPROXY is not set # CONFIG_NETFILTER_XT_TARGET_TRACE is not set +# CONFIG_NETFS_STATS is not set # CONFIG_NETLABEL is not set # CONFIG_NETLINK_DIAG is not set # CONFIG_NETLINK_MMAP is not set @@ -3892,27 +3926,21 @@ CONFIG_NET_CORE=y # CONFIG_NET_DSA_TAG_8021Q is not set # CONFIG_NET_DSA_TAG_AR9331 is not set # CONFIG_NET_DSA_TAG_BRCM is not set -# CONFIG_NET_DSA_TAG_BRCM_LEGACY is not set # CONFIG_NET_DSA_TAG_BRCM_PREPEND is not set # CONFIG_NET_DSA_TAG_DSA is not set # CONFIG_NET_DSA_TAG_EDSA is not set # CONFIG_NET_DSA_TAG_GSWIP is not set -# CONFIG_NET_DSA_TAG_HELLCREEK is not set # CONFIG_NET_DSA_TAG_KSZ is not set # CONFIG_NET_DSA_TAG_LAN9303 is not set # CONFIG_NET_DSA_TAG_MTK is not set # CONFIG_NET_DSA_TAG_OCELOT is not set -# CONFIG_NET_DSA_TAG_OCELOT_8021Q is not set # CONFIG_NET_DSA_TAG_QCA is not set # CONFIG_NET_DSA_TAG_RTL4_A is not set # CONFIG_NET_DSA_TAG_SJA1105 is not set # CONFIG_NET_DSA_TAG_TRAILER is not set -# CONFIG_NET_DSA_TAG_XRS700X is not set # CONFIG_NET_DSA_VITESSE_VSC73XX is not set # CONFIG_NET_DSA_VITESSE_VSC73XX_PLATFORM is not set # CONFIG_NET_DSA_VITESSE_VSC73XX_SPI is not set -# CONFIG_NET_DSA_XRS700X_I2C is not set -# CONFIG_NET_DSA_XRS700X_MDIO is not set # CONFIG_NET_EMATCH is not set # CONFIG_NET_EMATCH_CANID is not set # CONFIG_NET_EMATCH_CMP is not set @@ -4023,13 +4051,12 @@ CONFIG_NET_VENDOR_HUAWEI=y CONFIG_NET_VENDOR_I825XX=y CONFIG_NET_VENDOR_IBM=y CONFIG_NET_VENDOR_INTEL=y -# CONFIG_NET_VENDOR_LITEX is not set CONFIG_NET_VENDOR_MARVELL=y CONFIG_NET_VENDOR_MELLANOX=y CONFIG_NET_VENDOR_MICREL=y CONFIG_NET_VENDOR_MICROCHIP=y CONFIG_NET_VENDOR_MICROSEMI=y -# CONFIG_NET_VENDOR_MICROSOFT is not set +CONFIG_NET_VENDOR_MICROSOFT=y CONFIG_NET_VENDOR_MYRI=y CONFIG_NET_VENDOR_NATSEMI=y CONFIG_NET_VENDOR_NETERION=y @@ -4095,6 +4122,7 @@ CONFIG_NFS_V3=y # CONFIG_NFT_FLOW_OFFLOAD is not set # CONFIG_NFT_OBJREF is not set # CONFIG_NFT_OSF is not set +# CONFIG_NFT_REJECT_NETDEV is not set # CONFIG_NFT_RT is not set # CONFIG_NFT_SET_BITMAP is not set # CONFIG_NFT_SOCKET is not set @@ -4137,6 +4165,7 @@ CONFIG_NF_CONNTRACK_PROCFS=y # CONFIG_NF_LOG_ARP is not set # CONFIG_NF_LOG_BRIDGE is not set # CONFIG_NF_LOG_IPV4 is not set +# CONFIG_NF_LOG_IPV6 is not set # CONFIG_NF_LOG_NETDEV is not set # CONFIG_NF_LOG_SYSLOG is not set # CONFIG_NF_NAT is not set @@ -4241,13 +4270,13 @@ CONFIG_NMI_LOG_BUF_SHIFT=13 # CONFIG_NO_HZ_IDLE is not set # CONFIG_NS83820 is not set # CONFIG_NTB is not set -# CONFIG_NTFS3_FS is not set # CONFIG_NTFS_DEBUG is not set # CONFIG_NTFS_FS is not set # CONFIG_NTFS_RW is not set # CONFIG_NTP_PPS is not set # CONFIG_NULL_TTY is not set # CONFIG_NUMA is not set +# CONFIG_NVIDIA_CARMEL_CNP_ERRATUM is not set # CONFIG_NVM is not set # CONFIG_NVMEM is not set # CONFIG_NVMEM_BCM_OCOTP is not set @@ -4406,7 +4435,6 @@ CONFIG_PCIE_BUS_DEFAULT=y # CONFIG_PCIE_IPROC is not set # CONFIG_PCIE_KIRIN is not set # CONFIG_PCIE_LAYERSCAPE_GEN4 is not set -# CONFIG_PCIE_MICROCHIP_HOST is not set # CONFIG_PCIE_PTM is not set # CONFIG_PCIE_XILINX is not set # CONFIG_PCIPCWATCHDOG is not set @@ -4426,6 +4454,7 @@ CONFIG_PCIE_BUS_DEFAULT=y # CONFIG_PCI_J721E_HOST is not set # CONFIG_PCI_LAYERSCAPE is not set # CONFIG_PCI_MESON is not set +# CONFIG_PCIE_MICROCHIP_HOST is not set # CONFIG_PCI_MSI is not set # CONFIG_PCI_PASID is not set # CONFIG_PCI_PF_STUB is not set @@ -4480,7 +4509,6 @@ CONFIG_PCI_SYSCALL=y # CONFIG_PHY_CADENCE_SALVO is not set # CONFIG_PHY_CADENCE_SIERRA is not set # CONFIG_PHY_CADENCE_TORRENT is not set -# CONFIG_PHY_CAN_TRANSCEIVER is not set # CONFIG_PHY_CPCAP_USB is not set # CONFIG_PHY_EXYNOS_DP_VIDEO is not set # CONFIG_PHY_EXYNOS_MIPI_VIDEO is not set @@ -4503,31 +4531,26 @@ CONFIG_PCI_SYSCALL=y # CONFIG_PID_NS is not set CONFIG_PINCONF=y # CONFIG_PINCTRL is not set +# CONFIG_PINCTRL_ALDERLAKE is not set # CONFIG_PINCTRL_AMD is not set # CONFIG_PINCTRL_AXP209 is not set # CONFIG_PINCTRL_CEDARFORK is not set +# CONFIG_PINCTRL_ELKHARTLAKE is not set # CONFIG_PINCTRL_EXYNOS is not set # CONFIG_PINCTRL_EXYNOS5440 is not set # CONFIG_PINCTRL_ICELAKE is not set # CONFIG_PINCTRL_INGENIC is not set -# CONFIG_PINCTRL_LPASS_LPI is not set +# CONFIG_PINCTRL_LAKEFIELD is not set # CONFIG_PINCTRL_MCP23S08 is not set -# CONFIG_PINCTRL_MDM9607 is not set # CONFIG_PINCTRL_MICROCHIP_SGPIO is not set -# CONFIG_PINCTRL_MSM8953 is not set # CONFIG_PINCTRL_MSM8X74 is not set # CONFIG_PINCTRL_MT6779 is not set # CONFIG_PINCTRL_MT8167 is not set # CONFIG_PINCTRL_MT8192 is not set # CONFIG_PINCTRL_MTK_V2 is not set # CONFIG_PINCTRL_OCELOT is not set -# CONFIG_PINCTRL_SC7280 is not set -# CONFIG_PINCTRL_SC8180X is not set -# CONFIG_PINCTRL_SDX55 is not set +# CONFIG_PINCTRL_PISTACHIO is not set CONFIG_PINCTRL_SINGLE=y -# CONFIG_PINCTRL_SM6115 is not set -# CONFIG_PINCTRL_SM6125 is not set -# CONFIG_PINCTRL_SM8350 is not set # CONFIG_PINCTRL_STMFX is not set # CONFIG_PINCTRL_SX150X is not set # CONFIG_PING is not set @@ -4612,7 +4635,6 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_PRIME_NUMBERS is not set CONFIG_PRINTK=y # CONFIG_PRINTK_CALLER is not set -# CONFIG_PRINTK_INDEX is not set CONFIG_PRINTK_NMI=y CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13 # CONFIG_PRINTK_TIME is not set @@ -4650,26 +4672,26 @@ CONFIG_PROC_SYSCTL=y # CONFIG_PUBLIC_KEY_ALGO_RSA is not set # CONFIG_PVPANIC is not set # CONFIG_PWM is not set +# CONFIG_PWM_ATMEL_TCB is not set # CONFIG_PWM_DEBUG is not set +# CONFIG_PWM_DWC is not set # CONFIG_PWM_FSL_FTM is not set # CONFIG_PWM_PCA9685 is not set +# CONFIG_PWM_RASPBERRYPI_POE is not set CONFIG_PWRSEQ_EMMC=y # CONFIG_PWRSEQ_SD8787 is not set CONFIG_PWRSEQ_SIMPLE=y # CONFIG_QCA7000 is not set # CONFIG_QCA7000_SPI is not set # CONFIG_QCA7000_UART is not set -# CONFIG_QCOM_A7PLL is not set +# CONFIG_QCOM_ADM is not set # CONFIG_QCOM_EMAC is not set # CONFIG_QCOM_FALKOR_ERRATUM_1003 is not set # CONFIG_QCOM_FALKOR_ERRATUM_1009 is not set # CONFIG_QCOM_FALKOR_ERRATUM_E1041 is not set -# CONFIG_QCOM_GPI_DMA is not set # CONFIG_QCOM_HIDMA is not set # CONFIG_QCOM_HIDMA_MGMT is not set -# CONFIG_QCOM_LMH is not set # CONFIG_QCOM_QDF2400_ERRATUM_0065 is not set -# CONFIG_QCOM_QMI_HELPERS is not set # CONFIG_QCOM_SPMI_ADC5 is not set # CONFIG_QCOM_SPMI_IADC is not set # CONFIG_QCOM_SPMI_TEMP_ALARM is not set @@ -4713,6 +4735,7 @@ CONFIG_PWRSEQ_SIMPLE=y # CONFIG_RALINK is not set # CONFIG_RANDOM32_SELFTEST is not set # CONFIG_RANDOMIZE_BASE is not set +# CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT is not set # CONFIG_RANDOM_TRUST_BOOTLOADER is not set # CONFIG_RANDOM_TRUST_CPU is not set # CONFIG_RAPIDIO is not set @@ -4723,13 +4746,15 @@ CONFIG_PWRSEQ_SIMPLE=y CONFIG_RCU_CPU_STALL_TIMEOUT=60 # CONFIG_RCU_EQS_DEBUG is not set # CONFIG_RCU_EXPEDITE_BOOT is not set -# CONFIG_RCU_EXPERT is not set +CONFIG_RCU_EXPERT=y +CONFIG_RCU_FANOUT=32 +CONFIG_RCU_FANOUT_LEAF=16 +# CONFIG_RCU_FAST_NO_HZ is not set CONFIG_RCU_KTHREAD_PRIO=0 -CONFIG_RCU_NEED_SEGCBLIST=y +# CONFIG_RCU_NOCB_CPU is not set # CONFIG_RCU_PERF_TEST is not set # CONFIG_RCU_REF_SCALE_TEST is not set # CONFIG_RCU_SCALE_TEST is not set -CONFIG_RCU_STALL_COMMON=y # CONFIG_RCU_STRICT_GRACE_PERIOD is not set # CONFIG_RCU_TORTURE_TEST is not set CONFIG_RCU_TORTURE_TEST_SLOW_INIT_DELAY=3 @@ -4791,7 +4816,6 @@ CONFIG_RCU_TORTURE_TEST_SLOW_INIT_DELAY=3 # CONFIG_REGULATOR_MP886X is not set # CONFIG_REGULATOR_MPQ7920 is not set # CONFIG_REGULATOR_MT6311 is not set -# CONFIG_REGULATOR_MT6315 is not set # CONFIG_REGULATOR_PCA9450 is not set # CONFIG_REGULATOR_PF8X00 is not set # CONFIG_REGULATOR_PFUZE100 is not set @@ -4804,8 +4828,6 @@ CONFIG_RCU_TORTURE_TEST_SLOW_INIT_DELAY=3 # CONFIG_REGULATOR_RT6160 is not set # CONFIG_REGULATOR_RT6245 is not set # CONFIG_REGULATOR_RTMV20 is not set -# CONFIG_REGULATOR_RTQ2134 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 @@ -4840,6 +4862,7 @@ CONFIG_REISERFS_FS_XATTR=y # CONFIG_RESET_LPC18XX is not set # CONFIG_RESET_MESON is not set # CONFIG_RESET_PISTACHIO is not set +# CONFIG_RESET_RASPBERRYPI is not set # CONFIG_RESET_SOCFPGA is not set # CONFIG_RESET_STM32 is not set # CONFIG_RESET_SUNXI is not set @@ -4863,6 +4886,7 @@ CONFIG_RFKILL=y # CONFIG_ROMFS_FS is not set # CONFIG_ROSE is not set # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPI_POE_POWER is not set # CONFIG_RPMSG_QCOM_GLINK_RPM is not set # CONFIG_RPMSG_VIRTIO is not set # CONFIG_RPR0521 is not set @@ -4902,7 +4926,6 @@ CONFIG_RTC_DRV_CMOS=y # CONFIG_RTC_DRV_FM3130 is not set # CONFIG_RTC_DRV_FTRTC010 is not set # CONFIG_RTC_DRV_GENERIC is not set -# CONFIG_RTC_DRV_GOLDFISH is not set # CONFIG_RTC_DRV_HID_SENSOR_TIME is not set # CONFIG_RTC_DRV_HYM8563 is not set # CONFIG_RTC_DRV_ISL12022 is not set @@ -5020,12 +5043,14 @@ CONFIG_SATA_MOBILE_LPM_POLICY=0 CONFIG_SBITMAP=y # CONFIG_SC92031 is not set # CONFIG_SCA3000 is not set +# CONFIG_SCA3300 is not set # CONFIG_SCACHE_DEBUGFS is not set # CONFIG_SCC is not set # CONFIG_SCD30_CORE is not set # CONFIG_SCF_TORTURE_TEST is not set # CONFIG_SCHEDSTATS is not set # CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SCHED_CORE is not set # CONFIG_SCHED_DEBUG is not set CONFIG_SCHED_HRTICK=y # CONFIG_SCHED_MC is not set @@ -5123,19 +5148,10 @@ CONFIG_SCSI_PROC_FS=y # CONFIG_SCSI_ULTRASTOR is not set # CONFIG_SCSI_VIRTIO is not set # CONFIG_SCSI_WD719X is not set -# CONFIG_SC_CAMCC_7180 is not set -# CONFIG_SC_DISPCC_7280 is not set -# CONFIG_SC_GCC_7280 is not set -# CONFIG_SC_GCC_8180X is not set -# CONFIG_SC_GPUCC_7280 is not set -# CONFIG_SC_VIDEOCC_7280 is not set # CONFIG_SCx200_ACB is not set # CONFIG_SDIO_UART is not set -# CONFIG_SDM_GPUCC_660 is not set -# CONFIG_SDM_MMCC_660 is not set # CONFIG_SDR_MAX2175 is not set # CONFIG_SDR_PLATFORM_DRIVERS is not set -# CONFIG_SDX_GCC_55 is not set # CONFIG_SD_ADC_MODULATOR is not set # CONFIG_SECCOMP is not set # CONFIG_SECCOMP_CACHE_DEBUG is not set @@ -5146,7 +5162,6 @@ CONFIG_SECTION_MISMATCH_WARN_ONLY=y CONFIG_SECURITY_DMESG_RESTRICT=y # CONFIG_SECURITY_LOADPIN is not set # CONFIG_SECURITY_LOCKDOWN_LSM is not set -# CONFIG_SECURITY_NETWORK_XFRM is not set # CONFIG_SECURITY_PATH is not set # CONFIG_SECURITY_SAFESETID is not set # CONFIG_SECURITY_SELINUX_AVC_STATS is not set @@ -5199,10 +5214,13 @@ CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_SENSORS_BEL_PFE is not set # CONFIG_SENSORS_BH1770 is not set # CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BPA_RS600 is not set # CONFIG_SENSORS_CORETEMP is not set # CONFIG_SENSORS_CORSAIR_CPRO is not set +# CONFIG_SENSORS_CORSAIR_PSU is not set # CONFIG_SENSORS_DELL_SMM is not set # CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_DPS920AB is not set # CONFIG_SENSORS_DRIVETEMP is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_DS620 is not set @@ -5215,6 +5233,7 @@ CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_SENSORS_F75375S is not set # CONFIG_SENSORS_FAM15H_POWER is not set # CONFIG_SENSORS_FSCHMD is not set +# CONFIG_SENSORS_FSP_3Y is not set # CONFIG_SENSORS_FTSTEUTATES is not set # CONFIG_SENSORS_G760A is not set # CONFIG_SENSORS_G762 is not set @@ -5237,6 +5256,7 @@ CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_SENSORS_INA3221 is not set # CONFIG_SENSORS_INSPUR_IPSPS is not set # CONFIG_SENSORS_IR35221 is not set +# CONFIG_SENSORS_IR36021 is not set # CONFIG_SENSORS_IR38064 is not set # CONFIG_SENSORS_IRPS5401 is not set # CONFIG_SENSORS_ISL29018 is not set @@ -5283,6 +5303,7 @@ CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_SENSORS_LTQ_CPUTEMP is not set # CONFIG_SENSORS_MAX1111 is not set # CONFIG_SENSORS_MAX127 is not set +# CONFIG_SENSORS_MAX15301 is not set # CONFIG_SENSORS_MAX16064 is not set # CONFIG_SENSORS_MAX16065 is not set # CONFIG_SENSORS_MAX1619 is not set @@ -5303,6 +5324,7 @@ CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_SENSORS_MAX6697 is not set # CONFIG_SENSORS_MAX8688 is not set # CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_MP2888 is not set # CONFIG_SENSORS_MP2975 is not set # CONFIG_SENSORS_MR75203 is not set # CONFIG_SENSORS_NCT6683 is not set @@ -5311,18 +5333,21 @@ CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_SENSORS_NCT7904 is not set # CONFIG_SENSORS_NPCM7XX is not set # CONFIG_SENSORS_NSA320 is not set +# CONFIG_SENSORS_NZXT_KRAKEN2 is not set # CONFIG_SENSORS_NTC_THERMISTOR is not set # CONFIG_SENSORS_OCC_P8_I2C is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set # CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_PIM4328 is not set +# CONFIG_SENSORS_PM6764TR is not set # CONFIG_SENSORS_PMBUS is not set # CONFIG_SENSORS_POWR1220 is not set # CONFIG_SENSORS_PWM_FAN is not set # CONFIG_SENSORS_PXE1610 is not set +# CONFIG_SENSORS_Q54SJ108A2 is not set # CONFIG_SENSORS_RM3100_I2C is not set # CONFIG_SENSORS_RM3100_SPI is not set -# CONFIG_SENSORS_SBRMI is not set # CONFIG_SENSORS_SBTSI is not set # CONFIG_SENSORS_SCH5627 is not set # CONFIG_SENSORS_SCH5636 is not set @@ -5337,6 +5362,7 @@ CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_SMSC47M1 is not set # CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_STPDDC60 is not set # CONFIG_SENSORS_STTS751 is not set # CONFIG_SENSORS_TC654 is not set # CONFIG_SENSORS_TC74 is not set @@ -5510,7 +5536,6 @@ CONFIG_SLUB_CPU_PARTIAL=y # CONFIG_SLUB_MEMCG_SYSFS_ON is not set # CONFIG_SLUB_STATS is not set # CONFIG_SMARTJOYPLUS_FF is not set -# CONFIG_SMB_SERVER is not set # CONFIG_SMC911X is not set # CONFIG_SMC9194 is not set # CONFIG_SMC91X is not set @@ -5520,12 +5545,7 @@ CONFIG_SLUB_CPU_PARTIAL=y # CONFIG_SMSC_PHY is not set # CONFIG_SMS_SDIO_DRV is not set # CONFIG_SMS_USB_DRV is not set -# CONFIG_SM_CAMCC_8250 is not set # CONFIG_SM_FTL is not set -# CONFIG_SM_GCC_6115 is not set -# CONFIG_SM_GCC_6125 is not set -# CONFIG_SM_GCC_6350 is not set -# CONFIG_SM_GCC_8350 is not set # CONFIG_SND is not set # CONFIG_SND_AC97_POWER_SAVE is not set # CONFIG_SND_AD1816A is not set @@ -5552,6 +5572,8 @@ CONFIG_SLUB_CPU_PARTIAL=y # CONFIG_SND_AZT2320 is not set # CONFIG_SND_AZT3328 is not set # CONFIG_SND_BCD2000 is not set +# CONFIG_SND_BCM2835 is not set +# CONFIG_SND_BCM2835_SOC_I2S is not set # CONFIG_SND_BCM63XX_I2S_WHISTLER is not set # CONFIG_SND_BT87X is not set # CONFIG_SND_CA0106 is not set @@ -5656,6 +5678,8 @@ CONFIG_SND_PROC_FS=y # CONFIG_SND_RAWMIDI is not set # CONFIG_SND_RAWMIDI_SEQ is not set # CONFIG_SND_RIPTIDE is not set +# CONFIG_SND_RPI_SIMPLE_SOUNDCARD is not set +# CONFIG_SND_RPI_WM8804_SOUNDCARD is not set # CONFIG_SND_RME32 is not set # CONFIG_SND_RME96 is not set # CONFIG_SND_RME9652 is not set @@ -5672,12 +5696,16 @@ CONFIG_SND_PROC_FS=y # CONFIG_SND_SIS7019 is not set # CONFIG_SND_SOC is not set # CONFIG_SND_SOC_AC97_CODEC is not set +# CONFIG_SND_SOC_ADAU1372_I2C is not set +# CONFIG_SND_SOC_ADAU1372_SPI is not set # CONFIG_SND_SOC_ADAU1701 is not set # CONFIG_SND_SOC_ADAU1761_I2C is not set # CONFIG_SND_SOC_ADAU1761_SPI is not set # CONFIG_SND_SOC_ADAU7002 is not set # CONFIG_SND_SOC_ADAU7118_HW is not set # CONFIG_SND_SOC_ADAU7118_I2C is not set +# CONFIG_SND_SOC_AD193X_SPI is not set +# CONFIG_SND_SOC_AD193X_I2C is not set # CONFIG_SND_SOC_AK4104 is not set # CONFIG_SND_SOC_AK4118 is not set # CONFIG_SND_SOC_AK4458 is not set @@ -5734,7 +5762,9 @@ CONFIG_SND_PROC_FS=y # CONFIG_SND_SOC_FSL_SAI is not set # CONFIG_SND_SOC_FSL_SPDIF is not set # CONFIG_SND_SOC_FSL_SSI is not set +# CONFIG_SND_SOC_FSL_XCVR is not set # CONFIG_SND_SOC_GTM601 is not set +# CONFIG_SND_SOC_I_SABRE_CODEC is not set # CONFIG_SND_SOC_ICS43432 is not set # CONFIG_SND_SOC_IMG is not set # CONFIG_SND_SOC_IMX_AUDMIX is not set @@ -5781,6 +5811,10 @@ CONFIG_SND_SOC_INTEL_SST_TOPLEVEL=y # CONFIG_SND_SOC_JZ4725B_CODEC is not set # CONFIG_SND_SOC_JZ4740_CODEC is not set # CONFIG_SND_SOC_JZ4770_CODEC is not set +# CONFIG_SND_SOC_LPASS_WSA_MACRO is not set +# CONFIG_SND_SOC_LPASS_VA_MACRO is not set +# CONFIG_SND_SOC_LPASS_RX_MACRO is not set +# CONFIG_SND_SOC_LPASS_TX_MACRO is not set # CONFIG_SND_SOC_MA120X0P is not set # CONFIG_SND_SOC_MAX9759 is not set # CONFIG_SND_SOC_MAX98088 is not set @@ -5805,6 +5839,7 @@ CONFIG_SND_SOC_INTEL_SST_TOPLEVEL=y # CONFIG_SND_SOC_MT8173 is not set # CONFIG_SND_SOC_MT8183 is not set # CONFIG_SND_SOC_MTK_BTCVSD is not set +# CONFIG_SND_SOC_NAU8315 is not set # CONFIG_SND_SOC_NAU8540 is not set # CONFIG_SND_SOC_NAU8810 is not set # CONFIG_SND_SOC_NAU8822 is not set @@ -5826,13 +5861,17 @@ CONFIG_SND_SOC_INTEL_SST_TOPLEVEL=y # CONFIG_SND_SOC_RK3328 is not set # CONFIG_SND_SOC_RT5616 is not set # CONFIG_SND_SOC_RT5631 is not set +# CONFIG_SND_SOC_RT5640 is not set +# CONFIG_SND_SOC_RT5659 is not set # CONFIG_SND_SOC_RT5677_SPI is not set # CONFIG_SND_SOC_SGTL5000 is not set # CONFIG_SND_SOC_SIMPLE_AMPLIFIER is not set +# CONFIG_SND_SOC_SIMPLE_MUX is not set # CONFIG_SND_SOC_SIRF_AUDIO_CODEC is not set # CONFIG_SND_SOC_SOF_TOPLEVEL is not set # CONFIG_SND_SOC_SPDIF is not set # CONFIG_SND_SOC_SSM2305 is not set +# CONFIG_SND_SOC_SSM2518 is not set # CONFIG_SND_SOC_SSM2602_I2C is not set # CONFIG_SND_SOC_SSM2602_SPI is not set # CONFIG_SND_SOC_SSM4567 is not set @@ -5849,6 +5888,7 @@ CONFIG_SND_SOC_INTEL_SST_TOPLEVEL=y # CONFIG_SND_SOC_TAS6424 is not set # CONFIG_SND_SOC_TDA7419 is not set # CONFIG_SND_SOC_TFA9879 is not set +# CONFIG_SND_SOC_TFA989X is not set # CONFIG_SND_SOC_TLV320ADCX140 is not set # CONFIG_SND_SOC_TLV320AIC23_I2C is not set # CONFIG_SND_SOC_TLV320AIC23_SPI is not set @@ -5856,6 +5896,8 @@ CONFIG_SND_SOC_INTEL_SST_TOPLEVEL=y # CONFIG_SND_SOC_TLV320AIC32X4_I2C is not set # CONFIG_SND_SOC_TLV320AIC32X4_SPI is not set # CONFIG_SND_SOC_TLV320AIC3X is not set +# CONFIG_SND_SOC_TLV320AIC3X_I2C is not set +# CONFIG_SND_SOC_TLV320AIC3X_SPI is not set # CONFIG_SND_SOC_TPA6130A2 is not set # CONFIG_SND_SOC_TS3A227E is not set # CONFIG_SND_SOC_TSCS42XX is not set @@ -5915,6 +5957,7 @@ CONFIG_SND_USB=y CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_VIA82XX is not set # CONFIG_SND_VIA82XX_MODEM is not set +# CONFIG_SND_VIRTIO is not set # CONFIG_SND_VIRTUOSO is not set # CONFIG_SND_VX222 is not set # CONFIG_SND_VXPOCKET is not set @@ -6006,6 +6049,8 @@ CONFIG_SND_X86=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_SPMI is not set # CONFIG_SPS30 is not set +# CONFIG_SPS30_I2C is not set +# CONFIG_SPS30_SERIAL is not set CONFIG_SQUASHFS=y # CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set # CONFIG_SQUASHFS_DECOMP_MULTI is not set @@ -6036,7 +6081,6 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_STACKPROTECTOR is not set # CONFIG_STACKPROTECTOR_STRONG is not set # CONFIG_STACKTRACE is not set -# CONFIG_STACKTRACE_BUILD_ID is not set CONFIG_STACKTRACE_SUPPORT=y # CONFIG_STACK_TRACER is not set # CONFIG_STACK_VALIDATION is not set @@ -6080,6 +6124,7 @@ CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES=y # CONFIG_SUNXI_SRAM is not set # CONFIG_SUN_PARTITION is not set # CONFIG_SURFACE_3_BUTTON is not set +# CONFIG_SURFACE_PLATFORMS is not set # CONFIG_SUSPEND is not set # CONFIG_SUSPEND_SKIP_SYNC is not set CONFIG_SWAP=y @@ -6121,6 +6166,7 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_TARGET_CORE is not set # CONFIG_TASKSTATS is not set # CONFIG_TASKS_RCU is not set +CONFIG_TASKS_TRACE_RCU_READ_MB=y # CONFIG_TASK_XACCT is not set # CONFIG_TC35815 is not set # CONFIG_TCG_ATMEL is not set @@ -6131,10 +6177,10 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_TCG_ST33_I2C is not set # CONFIG_TCG_TIS is not set # CONFIG_TCG_TIS_I2C_ATMEL is not set +# CONFIG_TCG_TIS_I2C_CR50 is not set # CONFIG_TCG_TIS_I2C_INFINEON is not set # CONFIG_TCG_TIS_I2C_NUVOTON is not set # CONFIG_TCG_TIS_SPI is not set -# CONFIG_TCG_TIS_I2C_CR50 is not set # CONFIG_TCG_TIS_ST33ZP24_I2C is not set # CONFIG_TCG_TIS_ST33ZP24_SPI is not set # CONFIG_TCG_TPM is not set @@ -6173,7 +6219,6 @@ CONFIG_TCP_CONG_CUBIC=y # CONFIG_TEST_BITOPS is not set # CONFIG_TEST_BLACKHOLE_DEV is not set # CONFIG_TEST_BPF is not set -# CONFIG_TEST_DIV64 is not set # CONFIG_TEST_FIRMWARE is not set # CONFIG_TEST_FREE_PAGES is not set # CONFIG_TEST_HASH is not set @@ -6191,7 +6236,6 @@ CONFIG_TCP_CONG_CUBIC=y # CONFIG_TEST_POWER is not set # CONFIG_TEST_PRINTF is not set # CONFIG_TEST_RHASHTABLE is not set -# CONFIG_TEST_SCANF is not set # CONFIG_TEST_SORT is not set # CONFIG_TEST_STACKINIT is not set # CONFIG_TEST_STATIC_KEYS is not set @@ -6257,6 +6301,7 @@ CONFIG_TINY_RCU=y # CONFIG_TI_ADC161S626 is not set # CONFIG_TI_ADS1015 is not set # CONFIG_TI_ADS124S08 is not set +# CONFIG_TI_ADS131E08 is not set # CONFIG_TI_ADS7950 is not set # CONFIG_TI_ADS8344 is not set # CONFIG_TI_ADS8688 is not set @@ -6275,11 +6320,13 @@ CONFIG_TINY_RCU=y # CONFIG_TI_ST is not set # CONFIG_TI_SYSCON_RESET is not set # CONFIG_TI_TLC4541 is not set +# CONFIG_TI_TSC2046 is not set # CONFIG_TLAN is not set # CONFIG_TLS is not set # CONFIG_TMD_HERMES is not set # CONFIG_TMP006 is not set # CONFIG_TMP007 is not set +# CONFIG_TMP117 is not set CONFIG_TMPFS=y # CONFIG_TMPFS_INODE64 is not set # CONFIG_TMPFS_POSIX_ACL is not set @@ -6330,7 +6377,9 @@ CONFIG_TMPFS_XATTR=y # CONFIG_TOUCHSCREEN_HP600 is not set # CONFIG_TOUCHSCREEN_HP7XX is not set # CONFIG_TOUCHSCREEN_HTCPEN is not set +# CONFIG_TOUCHSCREEN_HYCON_HY46XX is not set # CONFIG_TOUCHSCREEN_ILI210X is not set +# CONFIG_TOUCHSCREEN_ILITEK is not set # CONFIG_TOUCHSCREEN_IMX6UL_TSC is not set # CONFIG_TOUCHSCREEN_INEXIO is not set # CONFIG_TOUCHSCREEN_IPAQ_MICRO is not set @@ -6344,6 +6393,7 @@ CONFIG_TMPFS_XATTR=y # CONFIG_TOUCHSCREEN_MIGOR is not set # CONFIG_TOUCHSCREEN_MK712 is not set # CONFIG_TOUCHSCREEN_MMS114 is not set +# CONFIG_TOUCHSCREEN_MSG2638 is not set # CONFIG_TOUCHSCREEN_MTOUCH is not set # CONFIG_TOUCHSCREEN_MX25 is not set # CONFIG_TOUCHSCREEN_MXS_LRADC is not set @@ -6434,6 +6484,7 @@ CONFIG_TRAD_SIGNALS=y # CONFIG_TRUSTED_FOUNDATIONS is not set # CONFIG_TRUSTED_KEYS is not set # CONFIG_TSL2583 is not set +# CONFIG_TSL2591 is not set # CONFIG_TSL2772 is not set # CONFIG_TSL2x7x is not set # CONFIG_TSL4531 is not set @@ -6743,6 +6794,7 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y # CONFIG_USB_ROLE_SWITCH is not set # CONFIG_USB_RTL8150 is not set # CONFIG_USB_RTL8152 is not set +# CONFIG_USB_RTL8153_ECM is not set # CONFIG_USB_S2255 is not set # CONFIG_USB_SERIAL is not set # CONFIG_USB_SERIAL_AIRCABLE is not set @@ -6810,6 +6862,7 @@ CONFIG_USB_SERIAL_SAFE_PADDED=y # CONFIG_USB_SERIAL_WHITEHEAT is not set # CONFIG_USB_SERIAL_WISHBONE is not set # CONFIG_USB_SERIAL_XIRCOM is not set +# CONFIG_USB_SERIAL_XR is not set # CONFIG_USB_SERIAL_XSENS_MT is not set # CONFIG_USB_SEVSEG is not set # CONFIG_USB_SIERRA_NET is not set @@ -6919,6 +6972,7 @@ CONFIG_VHOST_MENU=y # CONFIG_VIDEO_BT866 is not set # CONFIG_VIDEO_CADENCE is not set # CONFIG_VIDEO_CAFE_CCIC is not set +# CONFIG_VIDEO_CCS is not set # CONFIG_VIDEO_CS3308 is not set # CONFIG_VIDEO_CS5345 is not set # CONFIG_VIDEO_CS53L32A is not set @@ -6948,9 +7002,8 @@ CONFIG_VHOST_MENU=y # CONFIG_VIDEO_IMX274 is not set # CONFIG_VIDEO_IMX290 is not set # CONFIG_VIDEO_IMX319 is not set +# CONFIG_VIDEO_IMX334 is not set # CONFIG_VIDEO_IMX355 is not set -# CONFIG_VIDEO_IMX477 is not set -# CONFIG_VIDEO_IRS1125 is not set # CONFIG_VIDEO_IR_I2C is not set # CONFIG_VIDEO_IVTV is not set # CONFIG_VIDEO_KS0127 is not set @@ -6974,6 +7027,7 @@ CONFIG_VHOST_MENU=y # CONFIG_VIDEO_MXB is not set # CONFIG_VIDEO_NOON010PC30 is not set # CONFIG_VIDEO_OMAP2_VOUT is not set +# CONFIG_VIDEO_OV02A10 is not set # CONFIG_VIDEO_OV13858 is not set # CONFIG_VIDEO_OV2640 is not set # CONFIG_VIDEO_OV2659 is not set @@ -6983,6 +7037,7 @@ CONFIG_VHOST_MENU=y # CONFIG_VIDEO_OV5640 is not set # CONFIG_VIDEO_OV5645 is not set # CONFIG_VIDEO_OV5647 is not set +# CONFIG_VIDEO_OV5648 is not set # CONFIG_VIDEO_OV5670 is not set # CONFIG_VIDEO_OV5675 is not set # CONFIG_VIDEO_OV5695 is not set @@ -6993,11 +7048,14 @@ CONFIG_VHOST_MENU=y # CONFIG_VIDEO_OV772X is not set # CONFIG_VIDEO_OV7740 is not set # CONFIG_VIDEO_OV8856 is not set +# CONFIG_VIDEO_OV8865 is not set # CONFIG_VIDEO_OV9281 is not set # CONFIG_VIDEO_OV9640 is not set # CONFIG_VIDEO_OV9650 is not set +# CONFIG_VIDEO_OV9734 is not set # CONFIG_VIDEO_PVRUSB2 is not set # CONFIG_VIDEO_RDACM20 is not set +# CONFIG_VIDEO_RDACM21 is not set # CONFIG_VIDEO_RJ54N1 is not set # CONFIG_VIDEO_S5C73M3 is not set # CONFIG_VIDEO_S5K4ECGX is not set @@ -7070,7 +7128,6 @@ CONFIG_VLAN_8021Q=y # CONFIG_VLAN_8021Q_GVRP is not set # CONFIG_VLAN_8021Q_MVRP is not set # CONFIG_VME_BUS is not set -# CONFIG_VMLINUX_MAP is not set # CONFIG_VMSPLIT_1G is not set # CONFIG_VMSPLIT_2G is not set # CONFIG_VMSPLIT_2G_OPT is not set @@ -7133,7 +7190,6 @@ CONFIG_WATCHDOG_OPEN_TIMEOUT=0 # CONFIG_WD80x3 is not set # CONFIG_WDAT_WDT is not set # CONFIG_WDTPCI is not set -# CONFIG_WERROR is not set CONFIG_WEXT_CORE=y CONFIG_WEXT_PRIV=y CONFIG_WEXT_PROC=y @@ -7143,6 +7199,7 @@ CONFIG_WILINK_PLATFORM_DATA=y # CONFIG_WIREGUARD is not set CONFIG_WIRELESS=y CONFIG_WIRELESS_EXT=y +# CONFIG_WIRELESS_HOTKEY is not set # CONFIG_WIRELESS_WDS is not set # CONFIG_WIZNET_W5100 is not set # CONFIG_WIZNET_W5300 is not set @@ -7180,6 +7237,7 @@ CONFIG_X86_SYSFB=y # CONFIG_XEN is not set # CONFIG_XEN_GRANT_DMA_ALLOC is not set # CONFIG_XEN_PVCALLS_FRONTEND is not set +CONFIG_XEN_PVHVM_GUEST=y CONFIG_XEN_SCRUB_PAGES_DEFAULT=y CONFIG_XFRM=y # CONFIG_XFRM_INTERFACE is not set @@ -7222,6 +7280,7 @@ CONFIG_XZ_DEC=y # CONFIG_XZ_DEC_TEST is not set # CONFIG_XZ_DEC_X86 is not set # CONFIG_YAM is not set +# CONFIG_YAMAHA_YAS530 is not set # CONFIG_YELLOWFIN is not set # CONFIG_YENTA is not set # CONFIG_YENTA_O2 is not set @@ -7232,7 +7291,6 @@ CONFIG_XZ_DEC=y # CONFIG_ZD1211RW is not set # CONFIG_ZD1211RW_DEBUG is not set # CONFIG_ZEROPLUS_FF is not set -# CONFIG_ZERO_CALL_USED_REGS is not set # CONFIG_ZIIRAVE_WATCHDOG is not set # CONFIG_ZISOFS is not set # CONFIG_ZLIB_DEFLATE is not set @@ -7242,10 +7300,11 @@ CONFIG_ZONE_DMA=y # CONFIG_ZPA2326 is not set # CONFIG_ZPOOL is not set # CONFIG_ZRAM is not set -# CONFIG_ZRAM_MEMORY_TRACKING is not set -# CONFIG_ZRAM_DEF_COMP_LZORLE is not set +ZRAM_DEF_COMP_LZORLE=y # CONFIG_ZRAM_DEF_COMP_ZSTD is not set +# CONFIG_ZRAM_DEF_COMP_LZ4 is not set # CONFIG_ZRAM_DEF_COMP_LZO is not set +# CONFIG_ZRAM_MEMORY_TRACKING is not set # CONFIG_ZSMALLOC is not set # CONFIG_ZX_TDM is not set # CONFIG_AD5110 is not set diff --git a/root/target/linux/generic/config-5.4 b/root/target/linux/generic/config-5.4 index d7a2b318..0c7f48dd 100755 --- a/root/target/linux/generic/config-5.4 +++ b/root/target/linux/generic/config-5.4 @@ -297,9 +297,6 @@ CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8 # CONFIG_ARM64_64K_PAGES is not set # CONFIG_ARM64_CRYPTO is not set # CONFIG_ARM64_ERRATUM_1024718 is not set -# CONFIG_ARM64_ERRATUM_1165522 is not set -# CONFIG_ARM64_ERRATUM_1286807 is not set -# CONFIG_ARM64_ERRATUM_1418040 is not set # CONFIG_ARM64_ERRATUM_1463225 is not set # CONFIG_ARM64_ERRATUM_1542419 is not set # CONFIG_ARM64_ERRATUM_819472 is not set @@ -311,6 +308,7 @@ CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8 # CONFIG_ARM64_ERRATUM_843419 is not set # CONFIG_ARM64_ERRATUM_845719 is not set # CONFIG_ARM64_ERRATUM_858921 is not set +# CONFIG_ARM64_ERRATUM_1542419 is not set # CONFIG_ARM64_HW_AFDBM is not set # CONFIG_ARM64_LSE_ATOMICS is not set CONFIG_ARM64_MODULE_PLTS=y @@ -469,11 +467,6 @@ CONFIG_ATM_CLIP_NO_ICMP=y # CONFIG_B43LEGACY is not set # CONFIG_B44 is not set # CONFIG_B53 is not set -# CONFIG_B53_MDIO_DRIVER is not set -# CONFIG_B53_MMAP_DRIVER is not set -# CONFIG_B53_SERDES is not set -# CONFIG_B53_SPI_DRIVER is not set -# CONFIG_B53_SRAB_DRIVER is not set # CONFIG_BACKLIGHT_ADP8860 is not set # CONFIG_BACKLIGHT_ADP8870 is not set # CONFIG_BACKLIGHT_APPLE is not set @@ -790,7 +783,6 @@ CONFIG_CARDBUS=y # CONFIG_CAVIUM_ERRATUM_30115 is not set # CONFIG_CAVIUM_OCTEON_SOC is not set # CONFIG_CAVIUM_PTP is not set -# CONFIG_CAVIUM_TX2_ERRATUM_219 is not set # CONFIG_CB710_CORE is not set # CONFIG_CC10001_ADC is not set # CONFIG_CCS811 is not set @@ -807,6 +799,12 @@ CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y # CONFIG_CFG80211 is not set # CONFIG_CFG80211_CERTIFICATION_ONUS is not set # CONFIG_CGROUPS is not set +# CONFIG_CGROUP_BPF is not set +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CGROUP_HUGETLB is not set +# CONFIG_CGROUP_NET_CLASSID is not set +# CONFIG_CGROUP_NET_PRIO is not set +# CONFIG_CGROUP_RDMA is not set # CONFIG_CHARGER_ADP5061 is not set # CONFIG_CHARGER_BQ2415X is not set # CONFIG_CHARGER_BQ24190 is not set @@ -848,11 +846,12 @@ CONFIG_CIFS_ALLOW_INSECURE_LEGACY=y # CONFIG_CIFS_NFSD_EXPORT is not set CONFIG_CIFS_POSIX=y # CONFIG_CIFS_SMB2 is not set -# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_STATS=y # CONFIG_CIFS_STATS2 is not set # CONFIG_CIFS_WEAK_PW_HASH is not set -CONFIG_CIFS_XATTR=y +# CONFIG_CIFS_XATTR is not set # CONFIG_CIO_DAC is not set +CONFIG_CLANG_VERSION=0 # CONFIG_CLEANCACHE is not set # CONFIG_CLKSRC_VERSATILE is not set # CONFIG_CLK_HSDK is not set @@ -902,6 +901,7 @@ CONFIG_COMPACTION=y # CONFIG_COMPAT_BRK is not set # CONFIG_COMPILE_TEST is not set # CONFIG_CONFIGFS_FS is not set +# CONFIG_CONFIG_KVM_AMD_SEV is not set # CONFIG_CONNECTOR is not set CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7 CONFIG_CONSOLE_LOGLEVEL_QUIET=4 @@ -1759,7 +1759,6 @@ CONFIG_FSNOTIFY=y # CONFIG_FTRACE_STARTUP_TEST is not set # CONFIG_FTR_FIXUP_SELFTEST is not set # CONFIG_FTWDT010_WATCHDOG is not set -# CONFIG_FUJITSU_ERRATUM_010001 is not set # CONFIG_FUJITSU_ES is not set # CONFIG_FUJITSU_LAPTOP is not set # CONFIG_FUJITSU_TABLET is not set @@ -2082,6 +2081,7 @@ CONFIG_HW_PERF_EVENTS=y # CONFIG_HW_RANDOM_GEODE is not set # CONFIG_HW_RANDOM_INTEL is not set # CONFIG_HW_RANDOM_IPROC_RNG200 is not set +# CONFIG_HW_RANDOM_MTK is not set # CONFIG_HW_RANDOM_OMAP is not set # CONFIG_HW_RANDOM_OMAP3_ROM is not set # CONFIG_HW_RANDOM_PPC4XX is not set @@ -2146,6 +2146,7 @@ CONFIG_HZ_100=y # CONFIG_I2C_JZ4780 is not set # CONFIG_I2C_MLXCPLD is not set # CONFIG_I2C_MPC is not set +# CONFIG_I2C_MT65XX is not set # CONFIG_I2C_MUX is not set # CONFIG_I2C_MUX_GPIO is not set # CONFIG_I2C_MUX_GPMUX is not set @@ -2460,6 +2461,7 @@ CONFIG_IPV6_NDISC_NODETYPE=y # CONFIG_IPV6_ROUTER_PREF is not set # CONFIG_IPV6_ROUTE_INFO is not set # CONFIG_IPV6_SEG6_HMAC is not set +# CONFIG_IPV6_SEG6_LWTUNNEL is not set # CONFIG_IPV6_SIT is not set # CONFIG_IPV6_SIT_6RD is not set # CONFIG_IPV6_TUNNEL is not set @@ -2632,6 +2634,7 @@ CONFIG_KERNFS=y # CONFIG_KEYBOARD_MAX7359 is not set # CONFIG_KEYBOARD_MCS is not set # CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_MTK_PMIC is not set # CONFIG_KEYBOARD_NEWTON is not set # CONFIG_KEYBOARD_OMAP4 is not set # CONFIG_KEYBOARD_OPENCORES is not set @@ -2762,6 +2765,7 @@ CONFIG_LEDS_TRIGGER_NETDEV=y # CONFIG_LEDS_TRIGGER_PATTERN is not set CONFIG_LEDS_TRIGGER_TIMER=y # CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_UBNT_LEDBAR is not set # CONFIG_LEDS_USER is not set # CONFIG_LED_TRIGGER_PHY is not set # CONFIG_LEGACY_PTYS is not set @@ -2836,7 +2840,6 @@ CONFIG_LZMA_DECOMPRESS=y # CONFIG_MAC80211_MESSAGE_TRACING is not set CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 # CONFIG_MACB is not set -# CONFIG_MACB_USE_HWSTAMP is not set # CONFIG_MACH_ASM9260 is not set # CONFIG_MACH_DECSTATION is not set # CONFIG_MACH_INGENIC is not set @@ -3260,6 +3263,7 @@ CONFIG_MTD_NAND_IDS=y # CONFIG_MTD_NAND_JZ4740 is not set # CONFIG_MTD_NAND_MPC5121_NFC is not set # CONFIG_MTD_NAND_MTK is not set +# CONFIG_MTD_NAND_MTK_BMT is not set # CONFIG_MTD_NAND_MXC is not set # CONFIG_MTD_NAND_MXIC is not set # CONFIG_MTD_NAND_NANDSIM is not set @@ -3284,6 +3288,7 @@ CONFIG_MTD_OF_PARTS=y # CONFIG_MTD_ONENAND is not set # CONFIG_MTD_OOPS is not set # CONFIG_MTD_OTP is not set +# CONFIG_MTD_PARSER_TRX is not set # CONFIG_MTD_PARTITIONED_MASTER is not set # CONFIG_MTD_PCI is not set # CONFIG_MTD_PCMCIA is not set @@ -3347,6 +3352,8 @@ CONFIG_MULTIUSER=y # CONFIG_MV643XX_ETH is not set # CONFIG_MVMDIO is not set # CONFIG_MVNETA_BM is not set +# CONFIG_MVSW61XX_PHY is not set +# CONFIG_MVSWITCH_PHY is not set # CONFIG_MV_XOR_V2 is not set # CONFIG_MWAVE is not set # CONFIG_MWL8K is not set @@ -3721,6 +3728,8 @@ CONFIG_NFS_V3=y # CONFIG_NF_CONNTRACK_EVENTS is not set # CONFIG_NF_CONNTRACK_FTP is not set # CONFIG_NF_CONNTRACK_H323 is not set +# CONFIG_NF_CONNTRACK_IPV4 is not set +# CONFIG_NF_CONNTRACK_IPV6 is not set # CONFIG_NF_CONNTRACK_IRC is not set # CONFIG_NF_CONNTRACK_LABELS is not set # CONFIG_NF_CONNTRACK_MARK is not set @@ -3747,14 +3756,17 @@ CONFIG_NF_CONNTRACK_PROCFS=y # CONFIG_NF_DUP_IPV4 is not set # CONFIG_NF_DUP_IPV6 is not set # CONFIG_NF_FLOW_TABLE is not set +# CONFIG_NF_FLOW_TABLE_HW is not set # CONFIG_NF_LOG_ARP is not set # CONFIG_NF_LOG_BRIDGE is not set # CONFIG_NF_LOG_IPV4 is not set +# CONFIG_NF_LOG_IPV6 is not set # CONFIG_NF_LOG_NETDEV is not set # CONFIG_NF_NAT is not set # CONFIG_NF_NAT_AMANDA is not set # CONFIG_NF_NAT_FTP is not set # CONFIG_NF_NAT_H323 is not set +# CONFIG_NF_NAT_IPV6 is not set # CONFIG_NF_NAT_IRC is not set CONFIG_NF_NAT_MASQUERADE_IPV4=y CONFIG_NF_NAT_MASQUERADE_IPV6=y @@ -4117,6 +4129,7 @@ CONFIG_PINMUX=y # CONFIG_PLATFORM_MHU is not set # CONFIG_PLAT_SPEAR is not set # CONFIG_PLIP is not set +CONFIG_PLUGIN_HOSTCC="" # CONFIG_PLX_HERMES is not set # CONFIG_PM is not set # CONFIG_PMBUS is not set @@ -4137,8 +4150,8 @@ CONFIG_POSIX_TIMERS=y # 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_LINKSTATION is not set # CONFIG_POWER_RESET_LTC2952 is not set +# CONFIG_POWER_RESET_MT6323 is not set # CONFIG_POWER_RESET_PIIX4_POWEROFF is not set # CONFIG_POWER_RESET_RESTART is not set # CONFIG_POWER_RESET_SYSCON is not set @@ -4512,6 +4525,7 @@ CONFIG_RTC_SYSTOHC_DEVICE="rtc0" # CONFIG_RTL8366_SMI_DEBUG_FS is not set # CONFIG_RTL8367B_PHY is not set # CONFIG_RTL8367_PHY is not set +# CONFIG_RTL8367S_GSW is not set # CONFIG_RTLLIB is not set # CONFIG_RTL_CARDS is not set # CONFIG_RTS5208 is not set @@ -4952,6 +4966,7 @@ CONFIG_SERIAL_EARLYCON=y # CONFIG_SG_POOL is not set # CONFIG_SG_SPLIT is not set CONFIG_SHMEM=y +# CONFIG_SHORTCUT_FE is not set # CONFIG_SHUFFLE_PAGE_ALLOCATOR is not set # CONFIG_SH_ETH is not set # CONFIG_SH_TIMER_CMT is not set @@ -5265,7 +5280,9 @@ CONFIG_SND_SOC_INTEL_SST_TOPLEVEL=y # CONFIG_SND_SOC_MT2701 is not set # CONFIG_SND_SOC_MT6351 is not set # CONFIG_SND_SOC_MT6358 is not set +# CONFIG_SND_SOC_MT6797 is not set # CONFIG_SND_SOC_MT8173 is not set +# CONFIG_SND_SOC_MT8183 is not set # CONFIG_SND_SOC_MTK_BTCVSD is not set # CONFIG_SND_SOC_NAU8540 is not set # CONFIG_SND_SOC_NAU8810 is not set @@ -5433,7 +5450,9 @@ CONFIG_SND_X86=y # CONFIG_SPI_MPC52xx is not set # CONFIG_SPI_MPC52xx_PSC is not set # CONFIG_SPI_MTK_QUADSPI is not set +# CONFIG_SPI_MTK_SNFI is not set # CONFIG_SPI_MXIC is not set +# CONFIG_SPI_MTK_NOR is not set # CONFIG_SPI_NXP_FLEXSPI is not set # CONFIG_SPI_OCTEON is not set # CONFIG_SPI_OC_TINY is not set @@ -5592,6 +5611,7 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_TCIC is not set CONFIG_TCP_CONG_ADVANCED=y # CONFIG_TCP_CONG_BBR is not set +# CONFIG_TCP_CONG_BBR2 is not set # CONFIG_TCP_CONG_BIC is not set # CONFIG_TCP_CONG_CDG is not set CONFIG_TCP_CONG_CUBIC=y @@ -5640,7 +5660,6 @@ CONFIG_TCP_CONG_CUBIC=y # CONFIG_TEST_STRING_HELPERS is not set # CONFIG_TEST_STRSCPY is not set # CONFIG_TEST_SYSCTL is not set -# CONFIG_TEST_UBSAN is not set # CONFIG_TEST_UDELAY is not set # CONFIG_TEST_USER_COPY is not set # CONFIG_TEST_UUID is not set @@ -6318,8 +6337,6 @@ CONFIG_VDSO=y # CONFIG_VIDEO_ADV_DEBUG is not set # CONFIG_VIDEO_AK881X is not set # CONFIG_VIDEO_ASPEED is not set -# CONFIG_VIDEO_ATMEL_ISC is not set -# CONFIG_VIDEO_ATMEL_ISI is not set # CONFIG_VIDEO_BT819 is not set # CONFIG_VIDEO_BT848 is not set # CONFIG_VIDEO_BT856 is not set diff --git a/root/target/linux/generic/files/drivers/net/phy/b53/b53_common.c b/root/target/linux/generic/files/drivers/net/phy/b53/b53_common.c index a6dab255..87d731ec 100755 --- a/root/target/linux/generic/files/drivers/net/phy/b53/b53_common.c +++ b/root/target/linux/generic/files/drivers/net/phy/b53/b53_common.c @@ -529,7 +529,7 @@ static int b53_configure_ports_of(struct b53_device *dev) po |= PORT_OVERRIDE_SPEED_2000M; else po |= GMII_PO_SPEED_2000M; - __attribute__((__fallthrough__)); + fallthrough; case 1000: po |= GMII_PO_SPEED_1000M; break; From 5a63ee9ed3c7bece372b7d7e78f3705dad89a027 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Sun, 18 Sep 2022 15:04:37 +0800 Subject: [PATCH 013/102] Update build.sh --- build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sh b/build.sh index 0832c500..f849d31f 100644 --- a/build.sh +++ b/build.sh @@ -705,4 +705,4 @@ fi echo "Building $OMR_DIST for the target $OMR_TARGET with kernel ${OMR_KERNEL}" make defconfig make IGNORE_ERRORS=m "$@" -echo "Done" \ No newline at end of file +echo "Done" From a1628957ffdfe810dbfaf271007d7400ef87e8d7 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Sun, 18 Sep 2022 15:12:26 +0800 Subject: [PATCH 014/102] Update .gitignore --- .gitignore | 9 --------- 1 file changed, 9 deletions(-) diff --git a/.gitignore b/.gitignore index 2d93d211..60bb3ca0 100755 --- a/.gitignore +++ b/.gitignore @@ -1,20 +1,11 @@ *.o .DS_Store .*.swp -/env -/dl -/.config -/.config.old -/bin /build_dir /staging_dir /tmp /logs -/feeds -/feeds.conf /files -/overlay -/package/feeds /package/openwrt-packages key-build* *.orig From 5db3025cd1fefdbba85408a412fb082ec8dba189 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Sun, 18 Sep 2022 22:32:47 +0800 Subject: [PATCH 015/102] Update qcom-ipq4019-z4019.dts --- .../arch/arm/boot/dts/qcom-ipq4019-z4019.dts | 98 +++++++++++-------- 1 file changed, 56 insertions(+), 42 deletions(-) diff --git a/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts b/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts index 577e40ee..e31df98b 100755 --- a/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts +++ b/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts @@ -122,11 +122,8 @@ leds { compatible = "gpio-leds"; - - power: power { - label = "green:power"; - gpios = <&tlmm 36 GPIO_ACTIVE_LOW>; - }; + pinctrl-0 = <&led_pins>; + pinctrl-names = "default"; wifi0 { label = "green:wlan0"; @@ -138,8 +135,8 @@ gpios = <&tlmm 42 GPIO_ACTIVE_LOW>; }; - 4g { - label = "green:4g"; + 4g1 { + label = "green:4g1"; gpios = <&tlmm 1 GPIO_ACTIVE_LOW>; }; @@ -153,27 +150,23 @@ gpios = <&tlmm 4 GPIO_ACTIVE_LOW>; }; - 4gpwr { - label = "green:4gpwr"; - gpios = <&tlmm 20 GPIO_ACTIVE_LOW>; + 4g1pwr { + label = "green:4g1pwr"; + gpios = <&tlmm 20 GPIO_ACTIVE_HIGH>; }; 4g2pwr { label = "green:4g2pwr"; - gpios = <&tlmm 8 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 8 GPIO_ACTIVE_HIGH>; }; 4g3pwr { label = "green:4g3pwr"; - gpios = <&tlmm 9 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 9 GPIO_ACTIVE_HIGH>; }; + }; - 4g2sim { - label = "green:4g2sim"; - gpios = <&tlmm 0 GPIO_ACTIVE_LOW>; - }; - - watchdog { + watchdog { compatible = "linux,wdt-gpio"; gpios = <&tlmm 11 GPIO_ACTIVE_LOW>; hw_algo = "toggle"; @@ -304,47 +297,68 @@ }; }; + led_pins: led_pins { + wifi1 { + pins = "gpio42"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; - power_4g_pinmux { - mux { + wifi2 { + pins = "gpio43"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + + 4g1 { + pins = "gpio1"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + + 4g2 { + pins = "gpio2"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + + 4g3 { + pins = "gpio4"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + + + power_4g1 { pins = "gpio20"; function = "gpio"; - drive-strength = <12>; - bias-pull-down; + drive-strength = <8>; + bias-pull-up; output-high; }; - }; - power_4g2_pinmux { - mux { + power_4g2 { pins = "gpio8"; function = "gpio"; - drive-strength = <12>; - bias-pull-down; + drive-strength = <8>; + bias-pull-up; output-high; }; - }; - power_4g3_pinmux { - mux { + power_4g3 { pins = "gpio9"; function = "gpio"; - drive-strength = <12>; - bias-pull-down; + drive-strength = <8>; + bias-pull-up; output-high; }; }; - power_sim_sw_pinmux { - mux { - pins = "gpio0"; - function = "gpio"; - drive-strength = <12>; - bias-disable; - output-low; - }; - }; - spi_0_pins: spi_0_pinmux { pinmux { function = "blsp_spi0"; From 6960831ae3b7115e5fd9ab6a7b816d0c1e2ac72e Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Mon, 19 Sep 2022 01:53:17 +0800 Subject: [PATCH 016/102] Revert "Update qcom-ipq4019-z4019.dts" This reverts commit 5db3025cd1fefdbba85408a412fb082ec8dba189. --- .../arch/arm/boot/dts/qcom-ipq4019-z4019.dts | 98 ++++++++----------- 1 file changed, 42 insertions(+), 56 deletions(-) diff --git a/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts b/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts index e31df98b..577e40ee 100755 --- a/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts +++ b/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts @@ -122,8 +122,11 @@ leds { compatible = "gpio-leds"; - pinctrl-0 = <&led_pins>; - pinctrl-names = "default"; + + power: power { + label = "green:power"; + gpios = <&tlmm 36 GPIO_ACTIVE_LOW>; + }; wifi0 { label = "green:wlan0"; @@ -135,8 +138,8 @@ gpios = <&tlmm 42 GPIO_ACTIVE_LOW>; }; - 4g1 { - label = "green:4g1"; + 4g { + label = "green:4g"; gpios = <&tlmm 1 GPIO_ACTIVE_LOW>; }; @@ -150,23 +153,27 @@ gpios = <&tlmm 4 GPIO_ACTIVE_LOW>; }; - 4g1pwr { - label = "green:4g1pwr"; - gpios = <&tlmm 20 GPIO_ACTIVE_HIGH>; + 4gpwr { + label = "green:4gpwr"; + gpios = <&tlmm 20 GPIO_ACTIVE_LOW>; }; 4g2pwr { label = "green:4g2pwr"; - gpios = <&tlmm 8 GPIO_ACTIVE_HIGH>; + gpios = <&tlmm 8 GPIO_ACTIVE_LOW>; }; 4g3pwr { label = "green:4g3pwr"; - gpios = <&tlmm 9 GPIO_ACTIVE_HIGH>; + gpios = <&tlmm 9 GPIO_ACTIVE_LOW>; }; - }; - watchdog { + 4g2sim { + label = "green:4g2sim"; + gpios = <&tlmm 0 GPIO_ACTIVE_LOW>; + }; + + watchdog { compatible = "linux,wdt-gpio"; gpios = <&tlmm 11 GPIO_ACTIVE_LOW>; hw_algo = "toggle"; @@ -297,68 +304,47 @@ }; }; - led_pins: led_pins { - wifi1 { - pins = "gpio42"; - function = "gpio"; - drive-strength = <8>; - bias-pull-up; - }; - wifi2 { - pins = "gpio43"; - function = "gpio"; - drive-strength = <8>; - bias-pull-up; - }; - - 4g1 { - pins = "gpio1"; - function = "gpio"; - drive-strength = <8>; - bias-pull-up; - }; - - 4g2 { - pins = "gpio2"; - function = "gpio"; - drive-strength = <8>; - bias-pull-up; - }; - - 4g3 { - pins = "gpio4"; - function = "gpio"; - drive-strength = <8>; - bias-pull-up; - }; - - - power_4g1 { + power_4g_pinmux { + mux { pins = "gpio20"; function = "gpio"; - drive-strength = <8>; - bias-pull-up; + drive-strength = <12>; + bias-pull-down; output-high; }; + }; - power_4g2 { + power_4g2_pinmux { + mux { pins = "gpio8"; function = "gpio"; - drive-strength = <8>; - bias-pull-up; + drive-strength = <12>; + bias-pull-down; output-high; }; + }; - power_4g3 { + power_4g3_pinmux { + mux { pins = "gpio9"; function = "gpio"; - drive-strength = <8>; - bias-pull-up; + drive-strength = <12>; + bias-pull-down; output-high; }; }; + power_sim_sw_pinmux { + mux { + pins = "gpio0"; + function = "gpio"; + drive-strength = <12>; + bias-disable; + output-low; + }; + }; + spi_0_pins: spi_0_pinmux { pinmux { function = "blsp_spi0"; From b8bcd6573a432576312186277841f472fee17463 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Mon, 19 Sep 2022 01:53:51 +0800 Subject: [PATCH 017/102] Revert "Revert "Update qcom-ipq4019-z4019.dts"" This reverts commit 6960831ae3b7115e5fd9ab6a7b816d0c1e2ac72e. --- .../arch/arm/boot/dts/qcom-ipq4019-z4019.dts | 98 +++++++++++-------- 1 file changed, 56 insertions(+), 42 deletions(-) diff --git a/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts b/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts index 577e40ee..e31df98b 100755 --- a/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts +++ b/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts @@ -122,11 +122,8 @@ leds { compatible = "gpio-leds"; - - power: power { - label = "green:power"; - gpios = <&tlmm 36 GPIO_ACTIVE_LOW>; - }; + pinctrl-0 = <&led_pins>; + pinctrl-names = "default"; wifi0 { label = "green:wlan0"; @@ -138,8 +135,8 @@ gpios = <&tlmm 42 GPIO_ACTIVE_LOW>; }; - 4g { - label = "green:4g"; + 4g1 { + label = "green:4g1"; gpios = <&tlmm 1 GPIO_ACTIVE_LOW>; }; @@ -153,27 +150,23 @@ gpios = <&tlmm 4 GPIO_ACTIVE_LOW>; }; - 4gpwr { - label = "green:4gpwr"; - gpios = <&tlmm 20 GPIO_ACTIVE_LOW>; + 4g1pwr { + label = "green:4g1pwr"; + gpios = <&tlmm 20 GPIO_ACTIVE_HIGH>; }; 4g2pwr { label = "green:4g2pwr"; - gpios = <&tlmm 8 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 8 GPIO_ACTIVE_HIGH>; }; 4g3pwr { label = "green:4g3pwr"; - gpios = <&tlmm 9 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 9 GPIO_ACTIVE_HIGH>; }; + }; - 4g2sim { - label = "green:4g2sim"; - gpios = <&tlmm 0 GPIO_ACTIVE_LOW>; - }; - - watchdog { + watchdog { compatible = "linux,wdt-gpio"; gpios = <&tlmm 11 GPIO_ACTIVE_LOW>; hw_algo = "toggle"; @@ -304,47 +297,68 @@ }; }; + led_pins: led_pins { + wifi1 { + pins = "gpio42"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; - power_4g_pinmux { - mux { + wifi2 { + pins = "gpio43"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + + 4g1 { + pins = "gpio1"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + + 4g2 { + pins = "gpio2"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + + 4g3 { + pins = "gpio4"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + + + power_4g1 { pins = "gpio20"; function = "gpio"; - drive-strength = <12>; - bias-pull-down; + drive-strength = <8>; + bias-pull-up; output-high; }; - }; - power_4g2_pinmux { - mux { + power_4g2 { pins = "gpio8"; function = "gpio"; - drive-strength = <12>; - bias-pull-down; + drive-strength = <8>; + bias-pull-up; output-high; }; - }; - power_4g3_pinmux { - mux { + power_4g3 { pins = "gpio9"; function = "gpio"; - drive-strength = <12>; - bias-pull-down; + drive-strength = <8>; + bias-pull-up; output-high; }; }; - power_sim_sw_pinmux { - mux { - pins = "gpio0"; - function = "gpio"; - drive-strength = <12>; - bias-disable; - output-low; - }; - }; - spi_0_pins: spi_0_pinmux { pinmux { function = "blsp_spi0"; From 11d183654da5d399651aa0b6a82b91da56d281c8 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Mon, 19 Sep 2022 01:56:26 +0800 Subject: [PATCH 018/102] Revert "Revert "Revert "Update qcom-ipq4019-z4019.dts""" This reverts commit b8bcd6573a432576312186277841f472fee17463. --- .../arch/arm/boot/dts/qcom-ipq4019-z4019.dts | 98 ++++++++----------- 1 file changed, 42 insertions(+), 56 deletions(-) diff --git a/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts b/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts index e31df98b..577e40ee 100755 --- a/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts +++ b/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts @@ -122,8 +122,11 @@ leds { compatible = "gpio-leds"; - pinctrl-0 = <&led_pins>; - pinctrl-names = "default"; + + power: power { + label = "green:power"; + gpios = <&tlmm 36 GPIO_ACTIVE_LOW>; + }; wifi0 { label = "green:wlan0"; @@ -135,8 +138,8 @@ gpios = <&tlmm 42 GPIO_ACTIVE_LOW>; }; - 4g1 { - label = "green:4g1"; + 4g { + label = "green:4g"; gpios = <&tlmm 1 GPIO_ACTIVE_LOW>; }; @@ -150,23 +153,27 @@ gpios = <&tlmm 4 GPIO_ACTIVE_LOW>; }; - 4g1pwr { - label = "green:4g1pwr"; - gpios = <&tlmm 20 GPIO_ACTIVE_HIGH>; + 4gpwr { + label = "green:4gpwr"; + gpios = <&tlmm 20 GPIO_ACTIVE_LOW>; }; 4g2pwr { label = "green:4g2pwr"; - gpios = <&tlmm 8 GPIO_ACTIVE_HIGH>; + gpios = <&tlmm 8 GPIO_ACTIVE_LOW>; }; 4g3pwr { label = "green:4g3pwr"; - gpios = <&tlmm 9 GPIO_ACTIVE_HIGH>; + gpios = <&tlmm 9 GPIO_ACTIVE_LOW>; }; - }; - watchdog { + 4g2sim { + label = "green:4g2sim"; + gpios = <&tlmm 0 GPIO_ACTIVE_LOW>; + }; + + watchdog { compatible = "linux,wdt-gpio"; gpios = <&tlmm 11 GPIO_ACTIVE_LOW>; hw_algo = "toggle"; @@ -297,68 +304,47 @@ }; }; - led_pins: led_pins { - wifi1 { - pins = "gpio42"; - function = "gpio"; - drive-strength = <8>; - bias-pull-up; - }; - wifi2 { - pins = "gpio43"; - function = "gpio"; - drive-strength = <8>; - bias-pull-up; - }; - - 4g1 { - pins = "gpio1"; - function = "gpio"; - drive-strength = <8>; - bias-pull-up; - }; - - 4g2 { - pins = "gpio2"; - function = "gpio"; - drive-strength = <8>; - bias-pull-up; - }; - - 4g3 { - pins = "gpio4"; - function = "gpio"; - drive-strength = <8>; - bias-pull-up; - }; - - - power_4g1 { + power_4g_pinmux { + mux { pins = "gpio20"; function = "gpio"; - drive-strength = <8>; - bias-pull-up; + drive-strength = <12>; + bias-pull-down; output-high; }; + }; - power_4g2 { + power_4g2_pinmux { + mux { pins = "gpio8"; function = "gpio"; - drive-strength = <8>; - bias-pull-up; + drive-strength = <12>; + bias-pull-down; output-high; }; + }; - power_4g3 { + power_4g3_pinmux { + mux { pins = "gpio9"; function = "gpio"; - drive-strength = <8>; - bias-pull-up; + drive-strength = <12>; + bias-pull-down; output-high; }; }; + power_sim_sw_pinmux { + mux { + pins = "gpio0"; + function = "gpio"; + drive-strength = <12>; + bias-disable; + output-low; + }; + }; + spi_0_pins: spi_0_pinmux { pinmux { function = "blsp_spi0"; From a1b99247c7b0885dd8e151d96cf06dbc1265c08a Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Mon, 19 Sep 2022 01:58:08 +0800 Subject: [PATCH 019/102] Revert "Revert "Revert "Revert "Update qcom-ipq4019-z4019.dts"""" This reverts commit 11d183654da5d399651aa0b6a82b91da56d281c8. --- .../arch/arm/boot/dts/qcom-ipq4019-z4019.dts | 98 +++++++++++-------- 1 file changed, 56 insertions(+), 42 deletions(-) diff --git a/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts b/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts index 577e40ee..e31df98b 100755 --- a/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts +++ b/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts @@ -122,11 +122,8 @@ leds { compatible = "gpio-leds"; - - power: power { - label = "green:power"; - gpios = <&tlmm 36 GPIO_ACTIVE_LOW>; - }; + pinctrl-0 = <&led_pins>; + pinctrl-names = "default"; wifi0 { label = "green:wlan0"; @@ -138,8 +135,8 @@ gpios = <&tlmm 42 GPIO_ACTIVE_LOW>; }; - 4g { - label = "green:4g"; + 4g1 { + label = "green:4g1"; gpios = <&tlmm 1 GPIO_ACTIVE_LOW>; }; @@ -153,27 +150,23 @@ gpios = <&tlmm 4 GPIO_ACTIVE_LOW>; }; - 4gpwr { - label = "green:4gpwr"; - gpios = <&tlmm 20 GPIO_ACTIVE_LOW>; + 4g1pwr { + label = "green:4g1pwr"; + gpios = <&tlmm 20 GPIO_ACTIVE_HIGH>; }; 4g2pwr { label = "green:4g2pwr"; - gpios = <&tlmm 8 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 8 GPIO_ACTIVE_HIGH>; }; 4g3pwr { label = "green:4g3pwr"; - gpios = <&tlmm 9 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 9 GPIO_ACTIVE_HIGH>; }; + }; - 4g2sim { - label = "green:4g2sim"; - gpios = <&tlmm 0 GPIO_ACTIVE_LOW>; - }; - - watchdog { + watchdog { compatible = "linux,wdt-gpio"; gpios = <&tlmm 11 GPIO_ACTIVE_LOW>; hw_algo = "toggle"; @@ -304,47 +297,68 @@ }; }; + led_pins: led_pins { + wifi1 { + pins = "gpio42"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; - power_4g_pinmux { - mux { + wifi2 { + pins = "gpio43"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + + 4g1 { + pins = "gpio1"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + + 4g2 { + pins = "gpio2"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + + 4g3 { + pins = "gpio4"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + + + power_4g1 { pins = "gpio20"; function = "gpio"; - drive-strength = <12>; - bias-pull-down; + drive-strength = <8>; + bias-pull-up; output-high; }; - }; - power_4g2_pinmux { - mux { + power_4g2 { pins = "gpio8"; function = "gpio"; - drive-strength = <12>; - bias-pull-down; + drive-strength = <8>; + bias-pull-up; output-high; }; - }; - power_4g3_pinmux { - mux { + power_4g3 { pins = "gpio9"; function = "gpio"; - drive-strength = <12>; - bias-pull-down; + drive-strength = <8>; + bias-pull-up; output-high; }; }; - power_sim_sw_pinmux { - mux { - pins = "gpio0"; - function = "gpio"; - drive-strength = <12>; - bias-disable; - output-low; - }; - }; - spi_0_pins: spi_0_pinmux { pinmux { function = "blsp_spi0"; From 8ffcde52ce6eef368aec94c2bce2753f7027e4bf Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Mon, 19 Sep 2022 02:05:10 +0800 Subject: [PATCH 020/102] Update qcom-ipq4019-z4019.dts --- .../ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts | 2 -- 1 file changed, 2 deletions(-) diff --git a/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts b/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts index e31df98b..da82273e 100755 --- a/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts +++ b/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts @@ -164,7 +164,6 @@ label = "green:4g3pwr"; gpios = <&tlmm 9 GPIO_ACTIVE_HIGH>; }; - }; watchdog { compatible = "linux,wdt-gpio"; @@ -333,7 +332,6 @@ bias-pull-up; }; - power_4g1 { pins = "gpio20"; function = "gpio"; From 3ba6b5ba93b0674bd26de624c1385da006f9705d Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Mon, 19 Sep 2022 03:01:30 +0800 Subject: [PATCH 021/102] Update qcom-ipq4019-z4019.dts --- .../files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts b/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts index da82273e..768115ef 100755 --- a/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts +++ b/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts @@ -13,7 +13,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * */ - #include "qcom-ipq4019.dtsi" #include #include @@ -165,7 +164,7 @@ gpios = <&tlmm 9 GPIO_ACTIVE_HIGH>; }; - watchdog { + watchdog { compatible = "linux,wdt-gpio"; gpios = <&tlmm 11 GPIO_ACTIVE_LOW>; hw_algo = "toggle"; @@ -272,8 +271,6 @@ status = "okay"; }; - - &tlmm { mdio_pins: mdio_pinmux { mux_1 { @@ -332,6 +329,7 @@ bias-pull-up; }; + power_4g1 { pins = "gpio20"; function = "gpio"; @@ -420,4 +418,4 @@ &wifi1 { status = "okay"; qcom,ath10k-calibration-variant = "ZBT-Z4019"; -}; +}; \ No newline at end of file From 0883f93fbb56acfe2ccaa6d73107973555d02906 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Mon, 19 Sep 2022 17:10:32 +0800 Subject: [PATCH 022/102] Update qcom-ipq4019-z4019.dts --- .../ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts b/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts index 768115ef..16158bea 100755 --- a/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts +++ b/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts @@ -123,6 +123,11 @@ compatible = "gpio-leds"; pinctrl-0 = <&led_pins>; pinctrl-names = "default"; + + power: power { + label = "green:power"; + gpios = <&tlmm 36 GPIO_ACTIVE_LOW>; + }; wifi0 { label = "green:wlan0"; From d623caa9a43aee224970a5f08d84d31d1777b94a Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Wed, 21 Sep 2022 22:26:30 +0800 Subject: [PATCH 023/102] fix --- config-5gx3 | 4 ++++ config-l1000 | 4 ++++ config-zbt4019 | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/config-5gx3 b/config-5gx3 index c2e3dbbc..a5a70b61 100755 --- a/config-5gx3 +++ b/config-5gx3 @@ -3,10 +3,14 @@ # OpenWrt Configuration # CONFIG_KERNEL_ARM_MODULE_PLTS=y +CONFIG_ARM_MODULE_PLTS=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_TARGET_SQUASHFS_BLOCK_SIZE=64 CONFIG_KERNEL_SWAP=y CONFIG_PREINITOPT=y CONFIG_KERNEL_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_MODULES=y +CONFIG_HAVE_DOT_CONFIG=y # CONFIG_TARGET_sunxi is not set # CONFIG_TARGET_apm821xx is not set # CONFIG_TARGET_ath25 is not set diff --git a/config-l1000 b/config-l1000 index 610d899e..4139a6e2 100755 --- a/config-l1000 +++ b/config-l1000 @@ -3,10 +3,14 @@ # OpenWrt Configuration # CONFIG_KERNEL_ARM_MODULE_PLTS=y +CONFIG_ARM_MODULE_PLTS=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_TARGET_SQUASHFS_BLOCK_SIZE=64 CONFIG_KERNEL_SWAP=y CONFIG_PREINITOPT=y CONFIG_KERNEL_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_MODULES=y +CONFIG_HAVE_DOT_CONFIG=y # CONFIG_TARGET_sunxi is not set # CONFIG_TARGET_apm821xx is not set # CONFIG_TARGET_ath25 is not set diff --git a/config-zbt4019 b/config-zbt4019 index 31752148..3d5ae2a1 100755 --- a/config-zbt4019 +++ b/config-zbt4019 @@ -3,10 +3,14 @@ # OpenWrt Configuration # CONFIG_KERNEL_ARM_MODULE_PLTS=y +CONFIG_ARM_MODULE_PLTS=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_TARGET_SQUASHFS_BLOCK_SIZE=64 CONFIG_KERNEL_SWAP=y CONFIG_PREINITOPT=y CONFIG_KERNEL_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_MODULES=y +CONFIG_HAVE_DOT_CONFIG=y # CONFIG_TARGET_sunxi is not set # CONFIG_TARGET_apm821xx is not set # CONFIG_TARGET_ath25 is not set From 543347a91df7a71ab5815bf4070aa4676949c798 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Wed, 21 Sep 2022 22:29:20 +0800 Subject: [PATCH 024/102] Update config-5.4 --- root/target/linux/ipq40xx/config-5.4 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/root/target/linux/ipq40xx/config-5.4 b/root/target/linux/ipq40xx/config-5.4 index 283b48b8..915bd0eb 100644 --- a/root/target/linux/ipq40xx/config-5.4 +++ b/root/target/linux/ipq40xx/config-5.4 @@ -1,4 +1,6 @@ CONFIG_ALIGNMENT_TRAP=y +CONFIG_ARM_MODULE_PLTS=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_APQ_GCC_8084 is not set # CONFIG_APQ_MMCC_8084 is not set CONFIG_AR40XX_PHY=y From 0af9fc9c3b5a01b8a78c8f6621c4b7db9e044ee3 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Tue, 27 Sep 2022 02:40:10 +0800 Subject: [PATCH 025/102] Delete 922-add-full-modems.patch --- .../hack-5.4/922-add-full-modems.patch | 100 ------------------ 1 file changed, 100 deletions(-) delete mode 100644 root/target/linux/generic/hack-5.4/922-add-full-modems.patch diff --git a/root/target/linux/generic/hack-5.4/922-add-full-modems.patch b/root/target/linux/generic/hack-5.4/922-add-full-modems.patch deleted file mode 100644 index 3bc891ca..00000000 --- a/root/target/linux/generic/hack-5.4/922-add-full-modems.patch +++ /dev/null @@ -1,100 +0,0 @@ -Index: linux-5.4.179/drivers/usb/serial/option.c -=================================================================== ---- linux-5.4.179.orig/drivers/usb/serial/option.c -+++ linux-5.4.179/drivers/usb/serial/option.c -@@ -566,6 +566,17 @@ static void option_instat_callback(struc - #define WETELECOM_PRODUCT_WMD300 0x6803 - - -+//david add Fibocom products -+#define FIBOCOM_VENDOR_ID 0x2cb7 -+#define FIBOCOM_PRODUCT_L71X 0x0001 -+#define FIBOCOM_USB_VENDOR_AND_INTERFACE_INFO(vend, cl, sc, pr) \ -+.match_flags = USB_DEVICE_ID_MATCH_INT_INFO \ -+| USB_DEVICE_ID_MATCH_VENDOR, \ -+.idVendor = (vend), \ -+.bInterfaceClass = (cl), \ -+.bInterfaceSubClass = (sc), \ -+.bInterfaceProtocol = (pr) -+ - /* Device flags */ - - /* Highest interface number which can be used with NCTRL() and RSVD() */ -@@ -585,6 +596,77 @@ static void option_instat_callback(struc - - - static const struct usb_device_id option_ids[] = { -+ { USB_DEVICE(0x2ecc, 0x3010) },/* td-tech 909s */ -+//fibocom L610 -+ { USB_DEVICE(0x1782, 0x4d11) , .driver_info = RSVD(4) }, -+ { USB_DEVICE(0x1782, 0x4d10) }, -+ {USB_DEVICE(0x2949, 0x7401), .driver_info = RSVD(1) }, -+ {USB_DEVICE(0x2949, 0x7402), .driver_info = RSVD(0) }, -+//add 5g quectel rm500q, foxconn T99W240T00, meige srm815 -+ { USB_DEVICE(0x2C7C, 0x0800) }, /* Quectel RG500Q/RM500Q/RG510Q/RM510Q */ -+ { USB_DEVICE(0x2C7C, 0x0900) }, /* Quectel RG500U RG200U */ -+ { USB_DEVICE(0x05C6, 0x90DB), .driver_info = RSVD(2)|RSVD(3)|RSVD(4)|RSVD(5) }, -+ { USB_DEVICE(0x05C6, 0x90D5), .driver_info = RSVD(2)|RSVD(3) }, -+ { USB_DEVICE(0x2dee, 0x4d22), .driver_info = RSVD(4)|RSVD(5) }, -+//add simcom a7600e -+ { USB_DEVICE(0x1e0e, 0x9011), .driver_info = RSVD(0)|RSVD(1) }, -+//add U9300 -+ { USB_DEVICE(0x1c9e, 0x9b3c), .driver_info = RSVD(4)|RSVD(5) }, -+//add ucloud m2 -+ { USB_DEVICE_AND_INTERFACE_INFO(0x1782, 0x5d22, 0xff, 0x00, 0x00), .driver_info = RSVD(3) }, -+//add yuge clm920 -+ { USB_DEVICE(0x1286, 0x4e3c), .driver_info = RSVD(0)|RSVD(1) }, -+//add nodecom nl660 -+ { USB_DEVICE(0x1508, 0x1001), .driver_info = RSVD(4)|RSVD(5) }, -+//add quectel product -+ { USB_DEVICE(0x05C6, 0x9090), .driver_info = RSVD(4)|RSVD(5) }, -+ { USB_DEVICE(0x05C6, 0x9003), .driver_info = RSVD(4)|RSVD(5) }, -+ { USB_DEVICE(0x05C6, 0X9215), .driver_info = RSVD(4)|RSVD(5) }, -+ { USB_DEVICE(0x2c7c, 0x0125), .driver_info = RSVD(4)|RSVD(5) }, -+ { USB_DEVICE(0x2c7c, 0x0121), .driver_info = RSVD(4)|RSVD(5) }, -+//add xin feng wei ye -+ { USB_DEVICE(0x5c6, 0x5012), .driver_info = RSVD(4)|RSVD(5) }, -+ { USB_DEVICE(0x5c6, 0x5013), .driver_info = RSVD(4)|RSVD(5) },//gobinet id -+//add em8000 -+ { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0x0532, 0xff, 0xff, 0xff), .driver_info = RSVD(6)|RSVD(7) }, -+//add end -+//add fibocom L71x -+ { FIBOCOM_USB_VENDOR_AND_INTERFACE_INFO(0x2cb7, 0xff, 0xff, 0xff) }, -+ { FIBOCOM_USB_VENDOR_AND_INTERFACE_INFO(0x2cb7, 0x0a, 0x00, 0xff) }, -+ { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0x0256, 0xff, 0xff, 0xff) }, -+ { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0x0579, 0xff, 0xff, 0xff), .driver_info = RSVD(0)|RSVD(1)|RSVD(5)|RSVD(6) }, -+//add end -+//add mu709s -+ { USB_DEVICE(0x12d1, 0x1c25) }, -+//add forege 630b -+ { USB_DEVICE(0x05c6, 0x9025) }, -+//add kuanyi BM806U -+ //{ USB_DEVICE(0x2020, 0x2033) }, -+ { USB_DEVICE_INTERFACE_CLASS(0x2020, 0x2033, 0xff), .driver_info = RSVD(4) }, -+//add forege 730 -+ { USB_DEVICE(0x05c6, 0xf601), .driver_info = RSVD(4)|RSVD(5) }, -+//add Meig slm790 -+ { USB_DEVICE(0x2dee,0x4d20), .driver_info = RSVD(0) }, -+ { USB_DEVICE(0x2dee,0x4d57), .driver_info = RSVD(0) |RSVD(1)}, -+//add end -+//add Quectel EC200T -+ { USB_DEVICE(0x2c7c, 0x6026) }, -+//add end -+//add Luat air720,air724 -+ { USB_DEVICE(0x1286,0x4e3d) }, -+ { USB_DEVICE(0x1782,0x4e00) }, -+//add end -+//add N720 and N720V5 -+ { USB_DEVICE(0x2949,0x8247), .driver_info = RSVD(4)|RSVD(5) }, -+ { USB_DEVICE(0x2949,0x8241), .driver_info = RSVD(0)}, -+ { USB_DEVICE(0x2949,0x8242), .driver_info = RSVD(0)}, -+ { USB_DEVICE(0x2949,0x8243), .driver_info = RSVD(0)}, -+ { USB_DEVICE(0x2949,0x8700) }, -+//add end -+//david add em7355 em7455(DELL 3P10Y) -+ { USB_DEVICE_INTERFACE_CLASS(0x1199, 0x9041, 0xff), .driver_info = RSVD(8)|RSVD(10)|RSVD(11) }, /* MC7305/MC7355 */ -+ { USB_DEVICE_INTERFACE_CLASS(0x413c, 0x81b6, 0xff), .driver_info = RSVD(8)|RSVD(10)|RSVD(11) }, /* EM7455 */ -+//add end - { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, - { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, - { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_LIGHT) }, From d2ed5b571f962a4a7d5b0725fa260e28be8addc2 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 4 Oct 2022 08:48:59 +0200 Subject: [PATCH 026/102] Fix RPI and R7800 compilation --- build.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build.sh b/build.sh index e19c73b5..03cf5218 100755 --- a/build.sh +++ b/build.sh @@ -453,6 +453,12 @@ if [ -f target/linux/mediatek/patches-5.4/0999-hnat.patch ]; then rm -f target/linux/mediatek/patches-5.4/0999-hnat.patch fi +if [ -f target/linux/bcm27xx/patches-5.15/950-0019-drm-vc4-select-PM.patch ]; then + rm -f target/linux/bcm27xx/patches-5.15/950-0019-drm-vc4-select-PM.patch +fi +if [ -f target/linux/ipq806x/patches-5.4/0063-2-tsens-support-configurable-interrupts.patch ]; then + rm -f target/linux/ipq806x/patches-5.4/0063-2-tsens-support-configurable-interrupts.patch +fi #if [ -f target/linux/ipq40xx/patches-5.4/100-GPIO-add-named-gpio-exports.patch ]; then # rm -f target/linux/ipq40xx/patches-5.4/100-GPIO-add-named-gpio-exports.patch #fi From 6ea0b8908aa4f86b57d7dfe16662f888f4a07b5e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 12 Oct 2022 19:34:50 +0200 Subject: [PATCH 027/102] Update MPTCP patch --- .../generic/hack-5.4/690-mptcp_v0.96.patch | 645 +++++++++++++++--- 1 file changed, 541 insertions(+), 104 deletions(-) diff --git a/root/target/linux/generic/hack-5.4/690-mptcp_v0.96.patch b/root/target/linux/generic/hack-5.4/690-mptcp_v0.96.patch index e5b44dd0..ec8783d1 100644 --- a/root/target/linux/generic/hack-5.4/690-mptcp_v0.96.patch +++ b/root/target/linux/generic/hack-5.4/690-mptcp_v0.96.patch @@ -1,5 +1,5 @@ diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt -index db9d53b879f8..3d859ac99b73 100644 +index 8f71a17ad544..da15fba4125c 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -2784,6 +2784,10 @@ @@ -50,7 +50,7 @@ index 535ee41ee421..9f82f93e6e77 100644 req = __skb_push(skb, sizeof(*req)); memset(req, 0, sizeof(*req)); diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h -index b04b5bd43f54..57e35d51db8c 100644 +index 680f71ecdc08..6a9dc0368f94 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -717,7 +717,7 @@ struct sk_buff { @@ -62,6 +62,18 @@ index b04b5bd43f54..57e35d51db8c 100644 union { struct { +diff --git a/include/linux/socket.h b/include/linux/socket.h +index a465c6a45d6f..3bfdbfb49c5a 100644 +--- a/include/linux/socket.h ++++ b/include/linux/socket.h +@@ -346,6 +346,7 @@ struct ucred { + #define SOL_KCM 281 + #define SOL_TLS 282 + #define SOL_XDP 283 ++#define SOL_MPTCP 284 + + /* IPX options */ + #define IPX_TYPE 1 diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 358deb4ff830..aebfedba9838 100644 --- a/include/linux/tcp.h @@ -287,10 +299,10 @@ index 58db7c69c146..1acaa5e45f15 100644 union { diff --git a/include/net/mptcp.h b/include/net/mptcp.h new file mode 100644 -index 000000000000..f2efa46027d0 +index 000000000000..d565634f760f --- /dev/null +++ b/include/net/mptcp.h -@@ -0,0 +1,1549 @@ +@@ -0,0 +1,1559 @@ +/* + * MPTCP implementation + * @@ -642,6 +654,9 @@ index 000000000000..f2efa46027d0 + u32 orig_window_clamp; + + struct tcp_info *master_info; ++ ++ u8 add_addr_signal; ++ u8 add_addr_accepted; +}; + +#define MPTCP_VERSION_0 0 @@ -1165,6 +1180,8 @@ index 000000000000..f2efa46027d0 +void mptcp_sub_close_wq(struct work_struct *work); +void mptcp_sub_close(struct sock *sk, unsigned long delay); +struct sock *mptcp_select_ack_sock(const struct sock *meta_sk); ++int mptcp_getsockopt(struct sock *meta_sk, int level, int optname, ++ char __user *optval, int __user *optlen); +void mptcp_prepare_for_backlog(struct sock *sk, struct sk_buff *skb); +void mptcp_initialize_recv_vars(struct tcp_sock *meta_tp, struct mptcp_cb *mpcb, + __u64 remote_key); @@ -1705,6 +1722,11 @@ index 000000000000..f2efa46027d0 +static inline void mptcp_reinject_data(struct sock *orig_sk, int clone_it) {} +static inline void mptcp_update_sndbuf(const struct tcp_sock *tp) {} +static inline void mptcp_sub_close(struct sock *sk, unsigned long delay) {} ++static inline int mptcp_getsockopt(struct sock *meta_sk, int level, int optname, ++ char __user *optval, int __user *optlen) ++{ ++ return -EOPNOTSUPP; ++} +static inline void mptcp_set_rto(const struct sock *sk) {} +static inline void mptcp_send_fin(const struct sock *meta_sk) {} +static inline void mptcp_parse_options(const uint8_t *ptr, const int opsize, @@ -2664,15 +2686,16 @@ index 60e1241d4b77..ff6185b1d79f 100644 #endif diff --git a/include/uapi/linux/mptcp.h b/include/uapi/linux/mptcp.h new file mode 100644 -index 000000000000..f268e9805fe1 +index 000000000000..e09d83dbdd2e --- /dev/null +++ b/include/uapi/linux/mptcp.h -@@ -0,0 +1,151 @@ +@@ -0,0 +1,213 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* -+ * Netlink API for Multipath TCP ++ * Userspace API for Multipath TCP + * + * Author: Gregory Detal ++ * Christoph Paasch + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License @@ -2683,6 +2706,17 @@ index 000000000000..f268e9805fe1 +#ifndef _LINUX_MPTCP_H +#define _LINUX_MPTCP_H + ++#ifndef __KERNEL__ ++#include /* for sockaddr_in and sockaddr_in6 */ ++#include /* for struct sockaddr */ ++#endif ++ ++#include /* for sockaddr_in */ ++#include /* for sockaddr_in6 */ ++#include /* for sockaddr_storage and sa_family */ ++ ++/** NETLINK API **/ ++ +#define MPTCP_GENL_NAME "mptcp" +#define MPTCP_GENL_EV_GRP_NAME "mptcp_events" +#define MPTCP_GENL_CMD_GRP_NAME "mptcp_commands" @@ -2818,6 +2852,56 @@ index 000000000000..f268e9805fe1 + MPTCPF_EVENT_SUB_PRIORITY = (1 << 8), +}; + ++/** Upstream Linux compatibility **/ ++ ++/* MPTCP socket options */ ++#define MPTCP_INFO_UPSTREAM 1 ++#define MPTCP_TCPINFO 2 ++#define MPTCP_SUBFLOW_ADDRS 3 ++ ++#define MPTCP_INFO_FLAG_FALLBACK _BITUL(0) ++#define MPTCP_INFO_FLAG_REMOTE_KEY_RECEIVED _BITUL(1) ++ ++struct mptcp_info_upstream { ++ __u8 mptcpi_subflows; ++ __u8 mptcpi_add_addr_signal; ++ __u8 mptcpi_add_addr_accepted; ++ __u8 mptcpi_subflows_max; ++ __u8 mptcpi_add_addr_signal_max; ++ __u8 mptcpi_add_addr_accepted_max; ++ __u32 mptcpi_flags; ++ __u32 mptcpi_token; ++ __u64 mptcpi_write_seq; ++ __u64 mptcpi_snd_una; ++ __u64 mptcpi_rcv_nxt; ++ __u8 mptcpi_local_addr_used; ++ __u8 mptcpi_local_addr_max; ++ __u8 mptcpi_csum_enabled; ++}; ++ ++struct mptcp_subflow_data { ++ __u32 size_subflow_data; /* size of this structure in userspace */ ++ __u32 num_subflows; /* must be 0, set by kernel */ ++ __u32 size_kernel; /* must be 0, set by kernel */ ++ __u32 size_user; /* size of one element in data[] */ ++} __attribute__((aligned(8))); ++ ++struct mptcp_subflow_addrs { ++ union { ++ __kernel_sa_family_t sa_family; ++ struct sockaddr sa_local; ++ struct sockaddr_in sin_local; ++ struct sockaddr_in6 sin6_local; ++ struct __kernel_sockaddr_storage ss_local; ++ }; ++ union { ++ struct sockaddr sa_remote; ++ struct sockaddr_in sin_remote; ++ struct sockaddr_in6 sin6_remote; ++ struct __kernel_sockaddr_storage ss_remote; ++ }; ++}; ++ +#endif /* _LINUX_MPTCP_H */ diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h index 81e697978e8b..09ef515261d2 100644 @@ -2933,10 +3017,10 @@ index 449fc0b221f8..08683343642e 100644 obj-$(CONFIG_PACKET) += packet/ obj-$(CONFIG_NET_KEY) += key/ diff --git a/net/core/dev.c b/net/core/dev.c -index a03036456221..aebb337662c3 100644 +index 84bc6d0e8560..4b958f5028f4 100644 --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -7892,7 +7892,7 @@ int __dev_change_flags(struct net_device *dev, unsigned int flags, +@@ -7893,7 +7893,7 @@ int __dev_change_flags(struct net_device *dev, unsigned int flags, dev->flags = (flags & (IFF_DEBUG | IFF_NOTRAILERS | IFF_NOARP | IFF_DYNAMIC | IFF_MULTICAST | IFF_PORTSEL | @@ -3021,7 +3105,7 @@ index 283ddb2dbc7d..8f526a0d1912 100644 + +EXPORT_TRACEPOINT_SYMBOL_GPL(mptcp_retransmit); diff --git a/net/core/sock.c b/net/core/sock.c -index c84f68bff7f5..44675ce7e8de 100644 +index a2b12a5cf42b..222762983441 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -135,6 +135,11 @@ @@ -3519,7 +3603,7 @@ index 3f6c9514c7a9..9dc0cff27ad8 100644 * Normal sockets get it right from inet_csk_route_child_sock() */ diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c -index 0a570d5d0b38..99ca3c55eb19 100644 +index 0a570d5d0b38..521095c03ecf 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -270,6 +270,7 @@ @@ -4280,7 +4364,16 @@ index 0a570d5d0b38..99ca3c55eb19 100644 #ifdef CONFIG_MMU case TCP_ZEROCOPY_RECEIVE: { struct tcp_zerocopy_receive zc; -@@ -3877,7 +4165,9 @@ void tcp_done(struct sock *sk) +@@ -3707,6 +3995,8 @@ int tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, + { + struct inet_connection_sock *icsk = inet_csk(sk); + ++ if (level == SOL_MPTCP) ++ return mptcp_getsockopt(sk, level, optname, optval, optlen); + if (level != SOL_TCP) + return icsk->icsk_af_ops->getsockopt(sk, level, optname, + optval, optlen); +@@ -3877,7 +4167,9 @@ void tcp_done(struct sock *sk) if (sk->sk_state == TCP_SYN_SENT || sk->sk_state == TCP_SYN_RECV) TCP_INC_STATS(sock_net(sk), TCP_MIB_ATTEMPTFAILS); @@ -4290,7 +4383,7 @@ index 0a570d5d0b38..99ca3c55eb19 100644 tcp_clear_xmit_timers(sk); if (req) reqsk_fastopen_remove(sk, req, false); -@@ -3893,6 +4183,8 @@ void tcp_done(struct sock *sk) +@@ -3893,6 +4185,8 @@ void tcp_done(struct sock *sk) int tcp_abort(struct sock *sk, int err) { @@ -4299,7 +4392,7 @@ index 0a570d5d0b38..99ca3c55eb19 100644 if (!sk_fullsock(sk)) { if (sk->sk_state == TCP_NEW_SYN_RECV) { struct request_sock *req = inet_reqsk(sk); -@@ -3906,7 +4198,7 @@ int tcp_abort(struct sock *sk, int err) +@@ -3906,7 +4200,7 @@ int tcp_abort(struct sock *sk, int err) } /* Don't race with userspace socket closes such as tcp_close. */ @@ -4308,7 +4401,7 @@ index 0a570d5d0b38..99ca3c55eb19 100644 if (sk->sk_state == TCP_LISTEN) { tcp_set_state(sk, TCP_CLOSE); -@@ -3915,7 +4207,7 @@ int tcp_abort(struct sock *sk, int err) +@@ -3915,7 +4209,7 @@ int tcp_abort(struct sock *sk, int err) /* Don't race with BH socket closes such as inet_csk_listen_stop. */ local_bh_disable(); @@ -4317,7 +4410,7 @@ index 0a570d5d0b38..99ca3c55eb19 100644 if (!sock_flag(sk, SOCK_DEAD)) { sk->sk_err = err; -@@ -3923,14 +4215,14 @@ int tcp_abort(struct sock *sk, int err) +@@ -3923,14 +4217,14 @@ int tcp_abort(struct sock *sk, int err) smp_wmb(); sk->sk_error_report(sk); if (tcp_need_reset(sk->sk_state)) @@ -4438,7 +4531,7 @@ index 21705b2ddaff..8b439c148e2c 100644 * and queues the child into listener accept queue. */ diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c -index f4e00ff909da..b31087c02c2d 100644 +index 0ebba83dbe22..777c1301e433 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -76,35 +76,15 @@ @@ -4582,7 +4675,7 @@ index f4e00ff909da..b31087c02c2d 100644 /* Normally R but no L won't result in plain S */ if (!dup_sack && (TCP_SKB_CB(skb)->sacked & (TCPCB_LOST|TCPCB_SACKED_RETRANS)) == TCPCB_SACKED_RETRANS) -@@ -2969,7 +2976,7 @@ static bool tcp_ack_update_rtt(struct sock *sk, const int flag, +@@ -2980,7 +2987,7 @@ static bool tcp_ack_update_rtt(struct sock *sk, const int flag, */ tcp_update_rtt_min(sk, ca_rtt_us, flag); tcp_rtt_estimator(sk, seq_rtt_us); @@ -4591,7 +4684,7 @@ index f4e00ff909da..b31087c02c2d 100644 /* RFC6298: only reset backoff on valid RTT measurement. */ inet_csk(sk)->icsk_backoff = 0; -@@ -3037,7 +3044,7 @@ static void tcp_set_xmit_timer(struct sock *sk) +@@ -3048,7 +3055,7 @@ static void tcp_set_xmit_timer(struct sock *sk) } /* If we get here, the whole TSO packet has not been acked. */ @@ -4600,7 +4693,7 @@ index f4e00ff909da..b31087c02c2d 100644 { struct tcp_sock *tp = tcp_sk(sk); u32 packets_acked; -@@ -3057,8 +3064,7 @@ static u32 tcp_tso_acked(struct sock *sk, struct sk_buff *skb) +@@ -3068,8 +3075,7 @@ static u32 tcp_tso_acked(struct sock *sk, struct sk_buff *skb) return packets_acked; } @@ -4610,7 +4703,7 @@ index f4e00ff909da..b31087c02c2d 100644 { const struct skb_shared_info *shinfo; -@@ -3163,6 +3169,8 @@ static int tcp_clean_rtx_queue(struct sock *sk, u32 prior_fack, +@@ -3174,6 +3180,8 @@ static int tcp_clean_rtx_queue(struct sock *sk, u32 prior_fack, */ if (likely(!(scb->tcp_flags & TCPHDR_SYN))) { flag |= FLAG_DATA_ACKED; @@ -4619,7 +4712,7 @@ index f4e00ff909da..b31087c02c2d 100644 } else { flag |= FLAG_SYN_ACKED; tp->retrans_stamp = 0; -@@ -3283,7 +3291,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, u32 prior_fack, +@@ -3294,7 +3302,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, u32 prior_fack, return flag; } @@ -4628,7 +4721,7 @@ index f4e00ff909da..b31087c02c2d 100644 { struct inet_connection_sock *icsk = inet_csk(sk); struct sk_buff *head = tcp_send_head(sk); -@@ -3358,9 +3366,8 @@ static void tcp_cong_control(struct sock *sk, u32 ack, u32 acked_sacked, +@@ -3369,9 +3377,8 @@ static void tcp_cong_control(struct sock *sk, u32 ack, u32 acked_sacked, /* Check that window update is acceptable. * The function assumes that snd_una<=ack<=snd_next. */ @@ -4640,7 +4733,7 @@ index f4e00ff909da..b31087c02c2d 100644 { return after(ack, tp->snd_una) || after(ack_seq, tp->snd_wl1) || -@@ -3599,7 +3606,7 @@ static u32 tcp_newly_delivered(struct sock *sk, u32 prior_delivered, int flag) +@@ -3610,7 +3617,7 @@ static u32 tcp_newly_delivered(struct sock *sk, u32 prior_delivered, int flag) } /* This routine deals with incoming acks, but not outgoing ones. */ @@ -4649,7 +4742,7 @@ index f4e00ff909da..b31087c02c2d 100644 { struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_sock *tp = tcp_sk(sk); -@@ -3722,6 +3729,14 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) +@@ -3733,6 +3740,14 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) tcp_rack_update_reo_wnd(sk, &rs); @@ -4664,7 +4757,7 @@ index f4e00ff909da..b31087c02c2d 100644 if (tp->tlp_high_seq) tcp_process_tlp_ack(sk, ack, flag); -@@ -3866,8 +3881,10 @@ static u16 tcp_parse_mss_option(const struct tcphdr *th, u16 user_mss) +@@ -3877,8 +3892,10 @@ static u16 tcp_parse_mss_option(const struct tcphdr *th, u16 user_mss) */ void tcp_parse_options(const struct net *net, const struct sk_buff *skb, @@ -4677,7 +4770,7 @@ index f4e00ff909da..b31087c02c2d 100644 { const unsigned char *ptr; const struct tcphdr *th = tcp_hdr(skb); -@@ -3953,6 +3970,10 @@ void tcp_parse_options(const struct net *net, +@@ -3964,6 +3981,10 @@ void tcp_parse_options(const struct net *net, */ break; #endif @@ -4688,7 +4781,7 @@ index f4e00ff909da..b31087c02c2d 100644 case TCPOPT_FASTOPEN: tcp_parse_fastopen_option( opsize - TCPOLEN_FASTOPEN_BASE, -@@ -4020,7 +4041,9 @@ static bool tcp_fast_parse_options(const struct net *net, +@@ -4031,7 +4052,9 @@ static bool tcp_fast_parse_options(const struct net *net, return true; } @@ -4699,7 +4792,7 @@ index f4e00ff909da..b31087c02c2d 100644 if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr) tp->rx_opt.rcv_tsecr -= tp->tsoffset; -@@ -4130,7 +4153,7 @@ static inline bool tcp_paws_discard(const struct sock *sk, +@@ -4141,7 +4164,7 @@ static inline bool tcp_paws_discard(const struct sock *sk, static inline bool tcp_sequence(const struct tcp_sock *tp, u32 seq, u32 end_seq) { return !before(end_seq, tp->rcv_wup) && @@ -4708,7 +4801,7 @@ index f4e00ff909da..b31087c02c2d 100644 } /* When we get a reset we do this. */ -@@ -4179,6 +4202,11 @@ void tcp_fin(struct sock *sk) +@@ -4190,6 +4213,11 @@ void tcp_fin(struct sock *sk) { struct tcp_sock *tp = tcp_sk(sk); @@ -4720,7 +4813,7 @@ index f4e00ff909da..b31087c02c2d 100644 inet_csk_schedule_ack(sk); sk->sk_shutdown |= RCV_SHUTDOWN; -@@ -4189,6 +4217,10 @@ void tcp_fin(struct sock *sk) +@@ -4200,6 +4228,10 @@ void tcp_fin(struct sock *sk) case TCP_ESTABLISHED: /* Move to CLOSE_WAIT */ tcp_set_state(sk, TCP_CLOSE_WAIT); @@ -4731,7 +4824,7 @@ index f4e00ff909da..b31087c02c2d 100644 inet_csk_enter_pingpong_mode(sk); break; -@@ -4211,9 +4243,16 @@ void tcp_fin(struct sock *sk) +@@ -4222,9 +4254,16 @@ void tcp_fin(struct sock *sk) tcp_set_state(sk, TCP_CLOSING); break; case TCP_FIN_WAIT2: @@ -4749,7 +4842,7 @@ index f4e00ff909da..b31087c02c2d 100644 break; default: /* Only TCP_LISTEN and TCP_CLOSE are left, in these -@@ -4235,6 +4274,10 @@ void tcp_fin(struct sock *sk) +@@ -4246,6 +4285,10 @@ void tcp_fin(struct sock *sk) if (!sock_flag(sk, SOCK_DEAD)) { sk->sk_state_change(sk); @@ -4760,7 +4853,7 @@ index f4e00ff909da..b31087c02c2d 100644 /* Do not send POLL_HUP for half duplex close. */ if (sk->sk_shutdown == SHUTDOWN_MASK || sk->sk_state == TCP_CLOSE) -@@ -4449,6 +4492,9 @@ static bool tcp_try_coalesce(struct sock *sk, +@@ -4460,6 +4503,9 @@ static bool tcp_try_coalesce(struct sock *sk, *fragstolen = false; @@ -4770,7 +4863,7 @@ index f4e00ff909da..b31087c02c2d 100644 /* Its possible this segment overlaps with prior segment in queue */ if (TCP_SKB_CB(from)->seq != TCP_SKB_CB(to)->end_seq) return false; -@@ -4503,7 +4549,7 @@ static void tcp_drop(struct sock *sk, struct sk_buff *skb) +@@ -4514,7 +4560,7 @@ static void tcp_drop(struct sock *sk, struct sk_buff *skb) /* This one checks to see if we can put data from the * out_of_order queue into the receive_queue. */ @@ -4779,7 +4872,7 @@ index f4e00ff909da..b31087c02c2d 100644 { struct tcp_sock *tp = tcp_sk(sk); __u32 dsack_high = tp->rcv_nxt; -@@ -4526,7 +4572,14 @@ static void tcp_ofo_queue(struct sock *sk) +@@ -4537,7 +4583,14 @@ static void tcp_ofo_queue(struct sock *sk) p = rb_next(p); rb_erase(&skb->rbnode, &tp->out_of_order_queue); @@ -4795,7 +4888,7 @@ index f4e00ff909da..b31087c02c2d 100644 tcp_drop(sk, skb); continue; } -@@ -4556,21 +4609,23 @@ static void tcp_ofo_queue(struct sock *sk) +@@ -4567,21 +4620,23 @@ static void tcp_ofo_queue(struct sock *sk) static int tcp_try_rmem_schedule(struct sock *sk, struct sk_buff *skb, unsigned int size) { @@ -4823,7 +4916,7 @@ index f4e00ff909da..b31087c02c2d 100644 { struct tcp_sock *tp = tcp_sk(sk); struct rb_node **p, *parent; -@@ -4642,7 +4697,8 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) +@@ -4653,7 +4708,8 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) continue; } if (before(seq, TCP_SKB_CB(skb1)->end_seq)) { @@ -4833,7 +4926,7 @@ index f4e00ff909da..b31087c02c2d 100644 /* All the bits are present. Drop. */ NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPOFOMERGE); -@@ -4689,6 +4745,11 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) +@@ -4700,6 +4756,11 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) end_seq); break; } @@ -4845,7 +4938,7 @@ index f4e00ff909da..b31087c02c2d 100644 rb_erase(&skb1->rbnode, &tp->out_of_order_queue); tcp_dsack_extend(sk, TCP_SKB_CB(skb1)->seq, TCP_SKB_CB(skb1)->end_seq); -@@ -4700,7 +4761,7 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) +@@ -4711,7 +4772,7 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) tp->ooo_last_skb = skb; add_sack: @@ -4854,7 +4947,7 @@ index f4e00ff909da..b31087c02c2d 100644 tcp_sack_new_ofo_skb(sk, seq, end_seq); end: if (skb) { -@@ -4714,8 +4775,8 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) +@@ -4725,8 +4786,8 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) } } @@ -4865,7 +4958,7 @@ index f4e00ff909da..b31087c02c2d 100644 { int eaten; struct sk_buff *tail = skb_peek_tail(&sk->sk_receive_queue); -@@ -4790,7 +4851,8 @@ void tcp_data_ready(struct sock *sk) +@@ -4801,7 +4862,8 @@ void tcp_data_ready(struct sock *sk) if (avail < sk->sk_rcvlowat && !tcp_rmem_pressure(sk) && !sock_flag(sk, SOCK_DONE) && @@ -4875,7 +4968,7 @@ index f4e00ff909da..b31087c02c2d 100644 return; sk->sk_data_ready(sk); -@@ -4802,10 +4864,14 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) +@@ -4813,10 +4875,14 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) bool fragstolen; int eaten; @@ -4891,7 +4984,7 @@ index f4e00ff909da..b31087c02c2d 100644 skb_dst_drop(skb); __skb_pull(skb, tcp_hdr(skb)->doff * 4); -@@ -4816,7 +4882,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) +@@ -4827,7 +4893,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) * Out of sequence packets to the out_of_order_queue. */ if (TCP_SKB_CB(skb)->seq == tp->rcv_nxt) { @@ -4900,7 +4993,7 @@ index f4e00ff909da..b31087c02c2d 100644 NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPZEROWINDOWDROP); goto out_of_window; } -@@ -4832,7 +4898,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) +@@ -4843,7 +4909,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) } eaten = tcp_queue_rcv(sk, skb, &fragstolen); @@ -4909,7 +5002,7 @@ index f4e00ff909da..b31087c02c2d 100644 tcp_event_data_recv(sk, skb); if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) tcp_fin(sk); -@@ -4854,7 +4920,11 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) +@@ -4865,7 +4931,11 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) if (eaten > 0) kfree_skb_partial(skb, fragstolen); @@ -4922,7 +5015,7 @@ index f4e00ff909da..b31087c02c2d 100644 tcp_data_ready(sk); return; } -@@ -4874,7 +4944,8 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) +@@ -4885,7 +4955,8 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) } /* Out of window. F.e. zero window probe. */ @@ -4932,7 +5025,7 @@ index f4e00ff909da..b31087c02c2d 100644 goto out_of_window; if (before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) { -@@ -4884,7 +4955,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) +@@ -4895,7 +4966,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) /* If window is closed, drop tail of packet. But after * remembering D-SACK for its head made in previous line. */ @@ -4941,7 +5034,7 @@ index f4e00ff909da..b31087c02c2d 100644 NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPZEROWINDOWDROP); goto out_of_window; } -@@ -5197,7 +5268,7 @@ static int tcp_prune_queue(struct sock *sk) +@@ -5208,7 +5279,7 @@ static int tcp_prune_queue(struct sock *sk) return -1; } @@ -4950,7 +5043,7 @@ index f4e00ff909da..b31087c02c2d 100644 { const struct tcp_sock *tp = tcp_sk(sk); -@@ -5232,7 +5303,7 @@ static void tcp_new_space(struct sock *sk) +@@ -5243,7 +5314,7 @@ static void tcp_new_space(struct sock *sk) { struct tcp_sock *tp = tcp_sk(sk); @@ -4959,7 +5052,7 @@ index f4e00ff909da..b31087c02c2d 100644 tcp_sndbuf_expand(sk); tp->snd_cwnd_stamp = tcp_jiffies32; } -@@ -5256,10 +5327,11 @@ void tcp_check_space(struct sock *sk) +@@ -5267,10 +5338,11 @@ void tcp_check_space(struct sock *sk) sock_reset_flag(sk, SOCK_QUEUE_SHRUNK); /* pairs with tcp_poll() */ smp_mb(); @@ -4974,7 +5067,7 @@ index f4e00ff909da..b31087c02c2d 100644 tcp_chrono_stop(sk, TCP_CHRONO_SNDBUF_LIMITED); } } -@@ -5278,6 +5350,8 @@ static void __tcp_ack_snd_check(struct sock *sk, int ofo_possible) +@@ -5289,6 +5361,8 @@ static void __tcp_ack_snd_check(struct sock *sk, int ofo_possible) { struct tcp_sock *tp = tcp_sk(sk); unsigned long rtt, delay; @@ -4983,7 +5076,7 @@ index f4e00ff909da..b31087c02c2d 100644 /* More than one full frame received... */ if (((tp->rcv_nxt - tp->rcv_wup) > inet_csk(sk)->icsk_ack.rcv_mss && -@@ -5286,8 +5360,8 @@ static void __tcp_ack_snd_check(struct sock *sk, int ofo_possible) +@@ -5297,8 +5371,8 @@ static void __tcp_ack_snd_check(struct sock *sk, int ofo_possible) * If application uses SO_RCVLOWAT, we want send ack now if * we have not received enough bytes to satisfy the condition. */ @@ -4994,7 +5087,7 @@ index f4e00ff909da..b31087c02c2d 100644 /* We ACK each frame or... */ tcp_in_quickack_mode(sk) || /* Protocol state mandates a one-time immediate ACK */ -@@ -5423,6 +5497,10 @@ static void tcp_urg(struct sock *sk, struct sk_buff *skb, const struct tcphdr *t +@@ -5434,6 +5508,10 @@ static void tcp_urg(struct sock *sk, struct sk_buff *skb, const struct tcphdr *t { struct tcp_sock *tp = tcp_sk(sk); @@ -5005,7 +5098,7 @@ index f4e00ff909da..b31087c02c2d 100644 /* Check if we get a new urgent pointer - normally not. */ if (th->urg) tcp_check_urg(sk, th); -@@ -5565,9 +5643,15 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, +@@ -5576,9 +5654,15 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, goto discard; } @@ -5021,7 +5114,7 @@ index f4e00ff909da..b31087c02c2d 100644 tcp_drop(sk, skb); return false; } -@@ -5624,6 +5708,10 @@ void tcp_rcv_established(struct sock *sk, struct sk_buff *skb) +@@ -5635,6 +5719,10 @@ void tcp_rcv_established(struct sock *sk, struct sk_buff *skb) tp->rx_opt.saw_tstamp = 0; @@ -5032,7 +5125,7 @@ index f4e00ff909da..b31087c02c2d 100644 /* pred_flags is 0xS?10 << 16 + snd_wnd * if header_prediction is to be made * 'S' will always be tp->tcp_header_len >> 2 -@@ -5798,7 +5886,7 @@ void tcp_init_transfer(struct sock *sk, int bpf_op) +@@ -5809,7 +5897,7 @@ void tcp_init_transfer(struct sock *sk, int bpf_op) tcp_call_bpf(sk, bpf_op, 0, NULL); tcp_init_congestion_control(sk); @@ -5041,7 +5134,7 @@ index f4e00ff909da..b31087c02c2d 100644 } void tcp_finish_connect(struct sock *sk, struct sk_buff *skb) -@@ -5835,17 +5923,24 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack, +@@ -5846,17 +5934,24 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack, struct tcp_fastopen_cookie *cookie) { struct tcp_sock *tp = tcp_sk(sk); @@ -5068,7 +5161,7 @@ index f4e00ff909da..b31087c02c2d 100644 mss = opt.mss_clamp; } -@@ -5869,7 +5964,11 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack, +@@ -5880,7 +5975,11 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack, tcp_fastopen_cache_set(sk, mss, cookie, syn_drop, try_exp); @@ -5081,7 +5174,7 @@ index f4e00ff909da..b31087c02c2d 100644 skb_rbtree_walk_from(data) { if (__tcp_retransmit_skb(sk, data, 1)) break; -@@ -5924,9 +6023,13 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, +@@ -5935,9 +6034,13 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, struct tcp_sock *tp = tcp_sk(sk); struct tcp_fastopen_cookie foc = { .len = -1 }; int saved_clamp = tp->rx_opt.mss_clamp; @@ -5096,7 +5189,7 @@ index f4e00ff909da..b31087c02c2d 100644 if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr) tp->rx_opt.rcv_tsecr -= tp->tsoffset; -@@ -5987,11 +6090,41 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, +@@ -5998,11 +6101,41 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, tcp_try_undo_spurious_syn(sk); tcp_ack(sk, skb, FLAG_SLOWPATH); @@ -5138,7 +5231,7 @@ index f4e00ff909da..b31087c02c2d 100644 /* RFC1323: The window in SYN & SYN/ACK segments is * never scaled. -@@ -6013,6 +6146,11 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, +@@ -6024,6 +6157,11 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, tp->tcp_header_len = sizeof(struct tcphdr); } @@ -5150,7 +5243,7 @@ index f4e00ff909da..b31087c02c2d 100644 tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); tcp_initialize_rcv_mss(sk); -@@ -6036,9 +6174,12 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, +@@ -6047,9 +6185,12 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, } if (fastopen_fail) return -1; @@ -5165,7 +5258,7 @@ index f4e00ff909da..b31087c02c2d 100644 /* Save one ACK. Data will be ready after * several ticks, if write_pending is set. * -@@ -6077,6 +6218,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, +@@ -6088,6 +6229,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, tcp_paws_reject(&tp->rx_opt, 0)) goto discard_and_undo; @@ -5173,7 +5266,7 @@ index f4e00ff909da..b31087c02c2d 100644 if (th->syn) { /* We see SYN without ACK. It is attempt of * simultaneous connect with crossed SYNs. -@@ -6093,9 +6235,15 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, +@@ -6104,9 +6246,15 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, tp->tcp_header_len = sizeof(struct tcphdr); } @@ -5189,7 +5282,7 @@ index f4e00ff909da..b31087c02c2d 100644 /* RFC1323: The window in SYN & SYN/ACK segments is * never scaled. -@@ -6183,6 +6331,7 @@ static void tcp_rcv_synrecv_state_fastopen(struct sock *sk) +@@ -6194,6 +6342,7 @@ static void tcp_rcv_synrecv_state_fastopen(struct sock *sk) */ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) @@ -5197,7 +5290,7 @@ index f4e00ff909da..b31087c02c2d 100644 { struct tcp_sock *tp = tcp_sk(sk); struct inet_connection_sock *icsk = inet_csk(sk); -@@ -6225,6 +6374,16 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) +@@ -6236,6 +6385,16 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) tp->rx_opt.saw_tstamp = 0; tcp_mstamp_refresh(tp); queued = tcp_rcv_synsent_state_process(sk, skb, th); @@ -5214,7 +5307,7 @@ index f4e00ff909da..b31087c02c2d 100644 if (queued >= 0) return queued; -@@ -6297,6 +6456,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) +@@ -6308,6 +6467,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) if (tp->rx_opt.tstamp_ok) tp->advmss -= TCPOLEN_TSTAMP_ALIGNED; @@ -5223,7 +5316,7 @@ index f4e00ff909da..b31087c02c2d 100644 if (!inet_csk(sk)->icsk_ca_ops->cong_control) tcp_update_pacing_rate(sk); -@@ -6306,9 +6467,34 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) +@@ -6317,9 +6478,34 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) tcp_initialize_rcv_mss(sk); tcp_fast_path_on(tp); @@ -5258,7 +5351,7 @@ index f4e00ff909da..b31087c02c2d 100644 int tmo; if (req) -@@ -6346,7 +6532,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) +@@ -6357,7 +6543,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) tmo = tcp_fin_time(sk); if (tmo > TCP_TIMEWAIT_LEN) { inet_csk_reset_keepalive_timer(sk, tmo - TCP_TIMEWAIT_LEN); @@ -5268,7 +5361,7 @@ index f4e00ff909da..b31087c02c2d 100644 /* Bad case. We could lose such FIN otherwise. * It is not a big problem, but it looks confusing * and not so rare event. We still can lose it now, -@@ -6355,7 +6542,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) +@@ -6366,7 +6553,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) */ inet_csk_reset_keepalive_timer(sk, tmo); } else { @@ -5277,7 +5370,7 @@ index f4e00ff909da..b31087c02c2d 100644 goto discard; } break; -@@ -6363,7 +6550,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) +@@ -6374,7 +6561,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) case TCP_CLOSING: if (tp->snd_una == tp->write_seq) { @@ -5286,7 +5379,7 @@ index f4e00ff909da..b31087c02c2d 100644 goto discard; } break; -@@ -6375,6 +6562,9 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) +@@ -6386,6 +6573,9 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) goto discard; } break; @@ -5296,7 +5389,7 @@ index f4e00ff909da..b31087c02c2d 100644 } /* step 6: check the URG bit */ -@@ -6396,7 +6586,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) +@@ -6407,7 +6597,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) */ if (sk->sk_shutdown & RCV_SHUTDOWN) { if (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq && @@ -5306,7 +5399,7 @@ index f4e00ff909da..b31087c02c2d 100644 NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTONDATA); tcp_reset(sk); return 1; -@@ -6498,6 +6689,8 @@ static void tcp_openreq_init(struct request_sock *req, +@@ -6509,6 +6700,8 @@ static void tcp_openreq_init(struct request_sock *req, ireq->wscale_ok = rx_opt->wscale_ok; ireq->acked = 0; ireq->ecn_ok = 0; @@ -5315,7 +5408,7 @@ index f4e00ff909da..b31087c02c2d 100644 ireq->ir_rmt_port = tcp_hdr(skb)->source; ireq->ir_num = ntohs(tcp_hdr(skb)->dest); ireq->ir_mark = inet_request_mark(sk, skb); -@@ -6628,12 +6821,17 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, +@@ -6639,12 +6832,17 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, /* TW buckets are converted to open requests without * limitations, they conserve resources and peer is * evidently real one. @@ -5334,7 +5427,7 @@ index f4e00ff909da..b31087c02c2d 100644 } if (sk_acceptq_is_full(sk)) { -@@ -6650,8 +6849,8 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, +@@ -6661,8 +6860,8 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, tcp_clear_options(&tmp_opt); tmp_opt.mss_clamp = af_ops->mss_clamp; tmp_opt.user_mss = tp->rx_opt.user_mss; @@ -5345,7 +5438,7 @@ index f4e00ff909da..b31087c02c2d 100644 if (want_cookie && !tmp_opt.saw_tstamp) tcp_clear_options(&tmp_opt); -@@ -6666,7 +6865,8 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, +@@ -6677,7 +6876,8 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, /* Note: tcp_v6_init_req() might override ir_iif for link locals */ inet_rsk(req)->ir_iif = inet_request_bound_dev_if(sk, skb); @@ -5355,7 +5448,7 @@ index f4e00ff909da..b31087c02c2d 100644 if (security_inet_conn_request(sk, skb, req)) goto drop_and_free; -@@ -6704,7 +6904,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, +@@ -6715,7 +6915,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, tcp_ecn_create_request(req, skb, sk, dst); if (want_cookie) { @@ -5364,7 +5457,7 @@ index f4e00ff909da..b31087c02c2d 100644 req->cookie_ts = tmp_opt.tstamp_ok; if (!tmp_opt.tstamp_ok) inet_rsk(req)->ecn_ok = 0; -@@ -6719,17 +6919,31 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, +@@ -6730,17 +6930,31 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, fastopen_sk = tcp_try_fastopen(sk, skb, req, &foc, dst); } if (fastopen_sk) { @@ -9525,10 +9618,10 @@ index 000000000000..9eb7628053f6 +MODULE_VERSION("0.1"); diff --git a/net/mptcp/mptcp_ctrl.c b/net/mptcp/mptcp_ctrl.c new file mode 100644 -index 000000000000..0e8dc7f2aac4 +index 000000000000..ae45253219bd --- /dev/null +++ b/net/mptcp/mptcp_ctrl.c -@@ -0,0 +1,3307 @@ +@@ -0,0 +1,3608 @@ +/* + * MPTCP implementation - MPTCP-control + * @@ -9593,6 +9686,8 @@ index 000000000000..0e8dc7f2aac4 +#include +#include + ++#include ++ +static struct kmem_cache *mptcp_sock_cache __read_mostly; +static struct kmem_cache *mptcp_cb_cache __read_mostly; +static struct kmem_cache *mptcp_tw_cache __read_mostly; @@ -10593,6 +10688,305 @@ index 000000000000..0e8dc7f2aac4 + inet_sk(sub_sk)->recverr = 0; +} + ++static void mptcp_diag_fill_info(struct sock *meta_sk, struct mptcp_info_upstream *info) ++{ ++ struct tcp_sock *meta_tp; ++ struct mptcp_cb *mpcb; ++ u32 flags = 0; ++ ++ memset(info, 0, sizeof(*info)); ++ ++ lock_sock(meta_sk); ++ ++ meta_tp = tcp_sk(meta_sk); ++ mpcb = meta_tp->mpcb; ++ ++ /* If connection fell back to regular TCP we need to set the FALLBACK flag */ ++ if (!mptcp(meta_tp) || meta_tp->request_mptcp == 0) { ++ if (meta_sk->sk_state != TCP_CLOSE) ++ info->mptcpi_flags |= MPTCP_INFO_FLAG_FALLBACK; ++ ++ goto exit; ++ } ++ ++ info->mptcpi_subflows = hweight32(mpcb->path_index_bits); ++ info->mptcpi_add_addr_signal = mpcb->add_addr_signal; ++ info->mptcpi_add_addr_accepted = mpcb->add_addr_accepted; ++ info->mptcpi_subflows_max = sizeof(mpcb->path_index_bits) * 8; ++ /* mptcpi_add_addr_signal_max - addresses endpoint added with the 'signal' flag: ++ * doesn't apply to our model, we don't have ++ * $ ip mptcp endpoints add ADDRESS signal ++ */ ++ info->mptcpi_add_addr_accepted_max = U8_MAX; ++ ++ if (mptcp_in_infinite_mapping_weak(mpcb)) ++ flags |= MPTCP_INFO_FLAG_FALLBACK; ++ if (mpcb->rem_key_set) ++ flags |= MPTCP_INFO_FLAG_REMOTE_KEY_RECEIVED; ++ info->mptcpi_flags = flags; ++ ++ info->mptcpi_token = mpcb->mptcp_loc_token; ++ info->mptcpi_write_seq = meta_tp->write_seq; ++ info->mptcpi_snd_una = meta_tp->snd_una; ++ info->mptcpi_rcv_nxt = meta_tp->rcv_nxt; ++ ++ /* mptcpi_local_addr_used - hard to apply to our model because we can have ++ * multiple subflows on same local addr ++ */ ++ /* mptcpi_local_addr_max - addresses endpoint added with the 'subflow' flag: ++ * doesn't apply to our model, we don't have ++ * $ ip mptcp endpoints add ADDRESS subflow ++ */ ++ info->mptcpi_csum_enabled = mpcb->dss_csum; ++ ++exit: ++ release_sock(meta_sk); ++} ++ ++static int mptcp_getsockopt_info(struct sock *meta_sk, char __user *optval, ++ int __user *optlen) ++{ ++ struct mptcp_info_upstream m_info; ++ int len; ++ ++ if (get_user(len, optlen)) ++ return -EFAULT; ++ ++ len = min_t(unsigned int, len, sizeof(struct mptcp_info_upstream)); ++ ++ mptcp_diag_fill_info(meta_sk, &m_info); ++ ++ if (put_user(len, optlen)) ++ return -EFAULT; ++ ++ if (copy_to_user(optval, &m_info, len)) ++ return -EFAULT; ++ ++ return 0; ++} ++ ++#define MIN_INFO_OPTLEN_SIZE 16 ++ ++static int mptcp_get_subflow_data(struct mptcp_subflow_data *sfd, ++ char __user *optval, int __user *optlen) ++{ ++ int len, copylen; ++ ++ if (get_user(len, optlen)) ++ return -EFAULT; ++ ++ /* if mptcp_subflow_data size is changed, need to adjust ++ * this function to deal with programs using old version. ++ */ ++ BUILD_BUG_ON(sizeof(*sfd) != MIN_INFO_OPTLEN_SIZE); ++ ++ if (len < MIN_INFO_OPTLEN_SIZE) ++ return -EINVAL; ++ ++ memset(sfd, 0, sizeof(*sfd)); ++ ++ copylen = min_t(unsigned int, len, sizeof(*sfd)); ++ if (copy_from_user(sfd, optval, copylen)) ++ return -EFAULT; ++ ++ /* size_subflow_data is u32, but len is signed */ ++ if (sfd->size_subflow_data > INT_MAX || ++ sfd->size_user > INT_MAX) ++ return -EINVAL; ++ ++ if (sfd->size_subflow_data < MIN_INFO_OPTLEN_SIZE || ++ sfd->size_subflow_data > len) ++ return -EINVAL; ++ ++ if (sfd->num_subflows || sfd->size_kernel) ++ return -EINVAL; ++ ++ return len - sfd->size_subflow_data; ++} ++ ++static int mptcp_put_subflow_data(struct mptcp_subflow_data *sfd, ++ char __user *optval, ++ u32 copied, ++ int __user *optlen) ++{ ++ u32 copylen = min_t(u32, sfd->size_subflow_data, sizeof(*sfd)); ++ ++ if (copied) ++ copied += sfd->size_subflow_data; ++ else ++ copied = copylen; ++ ++ if (put_user(copied, optlen)) ++ return -EFAULT; ++ ++ if (copy_to_user(optval, sfd, copylen)) ++ return -EFAULT; ++ ++ return 0; ++} ++ ++static int mptcp_getsockopt_tcpinfo(struct sock *meta_sk, char __user *optval, ++ int __user *optlen) ++{ ++ unsigned int sfcount = 0, copied = 0; ++ struct mptcp_subflow_data sfd; ++ struct mptcp_tcp_sock *mptcp; ++ char __user *infoptr; ++ int len; ++ ++ len = mptcp_get_subflow_data(&sfd, optval, optlen); ++ if (len < 0) ++ return len; ++ ++ sfd.size_kernel = sizeof(struct tcp_info); ++ sfd.size_user = min_t(unsigned int, sfd.size_user, ++ sizeof(struct tcp_info)); ++ ++ infoptr = optval + sfd.size_subflow_data; ++ ++ lock_sock(meta_sk); ++ ++ mptcp_for_each_sub(tcp_sk(meta_sk)->mpcb, mptcp) { ++ struct sock *ssk = mptcp_to_sock(mptcp); ++ ++ ++sfcount; ++ ++ if (len && len >= sfd.size_user) { ++ struct tcp_info info; ++ ++ tcp_get_info(ssk, &info, true); ++ ++ if (copy_to_user(infoptr, &info, sfd.size_user)) { ++ release_sock(meta_sk); ++ return -EFAULT; ++ } ++ ++ infoptr += sfd.size_user; ++ copied += sfd.size_user; ++ len -= sfd.size_user; ++ } ++ } ++ ++ release_sock(meta_sk); ++ ++ sfd.num_subflows = sfcount; ++ ++ if (mptcp_put_subflow_data(&sfd, optval, copied, optlen)) ++ return -EFAULT; ++ ++ return 0; ++} ++ ++static void mptcp_get_sub_addrs(const struct sock *sk, struct mptcp_subflow_addrs *a) ++{ ++ struct inet_sock *inet = inet_sk(sk); ++ ++ memset(a, 0, sizeof(*a)); ++ ++ if (sk->sk_family == AF_INET) { ++ a->sin_local.sin_family = AF_INET; ++ a->sin_local.sin_port = inet->inet_sport; ++ a->sin_local.sin_addr.s_addr = inet->inet_rcv_saddr; ++ ++ if (!a->sin_local.sin_addr.s_addr) ++ a->sin_local.sin_addr.s_addr = inet->inet_saddr; ++ ++ a->sin_remote.sin_family = AF_INET; ++ a->sin_remote.sin_port = inet->inet_dport; ++ a->sin_remote.sin_addr.s_addr = inet->inet_daddr; ++#if IS_ENABLED(CONFIG_IPV6) ++ } else if (sk->sk_family == AF_INET6) { ++ const struct ipv6_pinfo *np = inet6_sk(sk); ++ ++ if (WARN_ON_ONCE(!np)) ++ return; ++ ++ a->sin6_local.sin6_family = AF_INET6; ++ a->sin6_local.sin6_port = inet->inet_sport; ++ ++ if (ipv6_addr_any(&sk->sk_v6_rcv_saddr)) ++ a->sin6_local.sin6_addr = np->saddr; ++ else ++ a->sin6_local.sin6_addr = sk->sk_v6_rcv_saddr; ++ ++ a->sin6_remote.sin6_family = AF_INET6; ++ a->sin6_remote.sin6_port = inet->inet_dport; ++ a->sin6_remote.sin6_addr = sk->sk_v6_daddr; ++#endif ++ } ++} ++ ++static int mptcp_getsockopt_subflow_addrs(struct sock *meta_sk, ++ char __user *optval, ++ int __user *optlen) ++{ ++ unsigned int sfcount = 0, copied = 0; ++ struct mptcp_subflow_data sfd; ++ struct mptcp_tcp_sock *mptcp; ++ char __user *addrptr; ++ int len; ++ ++ len = mptcp_get_subflow_data(&sfd, optval, optlen); ++ if (len < 0) ++ return len; ++ ++ sfd.size_kernel = sizeof(struct mptcp_subflow_addrs); ++ sfd.size_user = min_t(unsigned int, sfd.size_user, ++ sizeof(struct mptcp_subflow_addrs)); ++ ++ addrptr = optval + sfd.size_subflow_data; ++ ++ lock_sock(meta_sk); ++ ++ mptcp_for_each_sub(tcp_sk(meta_sk)->mpcb, mptcp) { ++ struct sock *ssk = mptcp_to_sock(mptcp); ++ ++ ++sfcount; ++ ++ if (len && len >= sfd.size_user) { ++ struct mptcp_subflow_addrs a; ++ ++ mptcp_get_sub_addrs(ssk, &a); ++ ++ if (copy_to_user(addrptr, &a, sfd.size_user)) { ++ release_sock(meta_sk); ++ return -EFAULT; ++ } ++ ++ addrptr += sfd.size_user; ++ copied += sfd.size_user; ++ len -= sfd.size_user; ++ } ++ } ++ ++ release_sock(meta_sk); ++ ++ sfd.num_subflows = sfcount; ++ ++ if (mptcp_put_subflow_data(&sfd, optval, copied, optlen)) ++ return -EFAULT; ++ ++ return 0; ++} ++ ++int mptcp_getsockopt(struct sock *meta_sk, int level, int optname, ++ char __user *optval, int __user *optlen) ++{ ++ if (level != SOL_MPTCP) ++ return -EOPNOTSUPP; ++ ++ switch (optname) { ++ case MPTCP_INFO: ++ return mptcp_getsockopt_info(meta_sk, optval, optlen); ++ case MPTCP_TCPINFO: ++ return mptcp_getsockopt_tcpinfo(meta_sk, optval, optlen); ++ case MPTCP_SUBFLOW_ADDRS: ++ return mptcp_getsockopt_subflow_addrs(meta_sk, optval, optlen); ++ } ++ ++ return -EOPNOTSUPP; ++} ++ +void mptcp_prepare_for_backlog(struct sock *sk, struct sk_buff *skb) +{ + /* In case of success (in mptcp_backlog_rcv) and error (in kfree_skb) of @@ -13039,10 +13433,10 @@ index 000000000000..6b976b2b0c72 +MODULE_VERSION("0.95"); diff --git a/net/mptcp/mptcp_fullmesh.c b/net/mptcp/mptcp_fullmesh.c new file mode 100644 -index 000000000000..65e2cd9bf630 +index 000000000000..ef2c15cbbeaa --- /dev/null +++ b/net/mptcp/mptcp_fullmesh.c -@@ -0,0 +1,1936 @@ +@@ -0,0 +1,1949 @@ +#include +#include + @@ -13236,9 +13630,14 @@ index 000000000000..65e2cd9bf630 + rem4->bitfield = 0; + rem4->retry_bitfield = 0; + rem4->rem4_id = id; -+ mpcb->list_rcvd = 1; + fmp->rem4_bits |= (1 << i); + ++ mpcb->list_rcvd = 1; ++ ++ /* Don't count the address of the initial subflow */ ++ if (id != 0) ++ mpcb->add_addr_accepted++; ++ + return; +} + @@ -13291,9 +13690,14 @@ index 000000000000..65e2cd9bf630 + rem6->bitfield = 0; + rem6->retry_bitfield = 0; + rem6->rem6_id = id; -+ mpcb->list_rcvd = 1; + fmp->rem6_bits |= (1 << i); + ++ mpcb->list_rcvd = 1; ++ ++ /* Don't count the address of the initial subflow */ ++ if (id != 0) ++ mpcb->add_addr_accepted++; ++ + return; +} + @@ -14656,6 +15060,7 @@ index 000000000000..65e2cd9bf630 + if (mpcb->mptcp_ver >= MPTCP_VERSION_1) + *size += MPTCP_SUB_LEN_ADD_ADDR4_ALIGN_VER1; + ++ mpcb->add_addr_signal++; + goto skip_ipv6; + } + @@ -14694,6 +15099,8 @@ index 000000000000..65e2cd9bf630 + *size += MPTCP_SUB_LEN_ADD_ADDR6_ALIGN; + if (mpcb->mptcp_ver >= MPTCP_VERSION_1) + *size += MPTCP_SUB_LEN_ADD_ADDR6_ALIGN_VER1; ++ ++ mpcb->add_addr_signal++; + } + +skip_ipv6: @@ -14981,10 +15388,10 @@ index 000000000000..65e2cd9bf630 +MODULE_VERSION("0.88"); diff --git a/net/mptcp/mptcp_input.c b/net/mptcp/mptcp_input.c new file mode 100644 -index 000000000000..01a81e3f7690 +index 000000000000..41a511b3ef63 --- /dev/null +++ b/net/mptcp/mptcp_input.c -@@ -0,0 +1,2632 @@ +@@ -0,0 +1,2656 @@ +/* + * MPTCP implementation - Sending side + * @@ -15904,20 +16311,44 @@ index 000000000000..01a81e3f7690 + mptcp_skb_trim_head(tmp, sk, tp->mptcp->map_subseq); + } + -+ /* ... or the new skb (tail) has to be split at the end. */ -+ tcp_end_seq = TCP_SKB_CB(skb)->end_seq; -+ if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) -+ tcp_end_seq--; -+ if (after(tcp_end_seq, tp->mptcp->map_subseq + tp->mptcp->map_data_len)) { -+ u32 seq = tp->mptcp->map_subseq + tp->mptcp->map_data_len; -+ MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_DSSSPLITTAIL); -+ if (mptcp_skb_split_tail(skb, sk, seq)) { /* Allocation failed */ -+ /* TODO : maybe handle this here better. -+ * We now just force meta-retransmission. ++ skb_queue_walk_from(&sk->sk_receive_queue, skb) { ++ /* ... or the new skb (tail) has to be split at the end. */ ++ tcp_end_seq = TCP_SKB_CB(skb)->end_seq; ++ if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) ++ tcp_end_seq--; ++ ++ if (tcp_end_seq == tp->mptcp->map_subseq + tp->mptcp->map_data_len) ++ break; ++ ++ if (after(tcp_end_seq, tp->mptcp->map_subseq + tp->mptcp->map_data_len)) { ++ u32 seq = tp->mptcp->map_subseq + tp->mptcp->map_data_len; ++ ++ MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_DSSSPLITTAIL); ++ if (mptcp_skb_split_tail(skb, sk, seq)) { ++ if (net_ratelimit()) ++ pr_err("MPTCP: Could not allocate memory for mptcp_skb_split_tail on seq %u\n", seq); ++ ++ /* allocations are failing - there is not much to do. ++ * Let's try the best and trigger meta-rexmit on the ++ * sender-side by simply dropping all packets up to sk ++ * in the receive-queue. ++ */ ++ ++ skb_queue_walk_safe(&sk->sk_receive_queue, tmp, tmp1) { ++ tp->copied_seq = TCP_SKB_CB(tmp)->end_seq; ++ __skb_unlink(tmp, &sk->sk_receive_queue); ++ __kfree_skb(tmp); ++ ++ if (tmp == skb) ++ break; ++ } ++ } ++ ++ /* We just split an skb in the receive-queue (or removed ++ * a whole bunch of them). ++ * We have to restart as otherwise the list-processing ++ * will fail - thus return -1. + */ -+ tp->copied_seq = TCP_SKB_CB(skb)->end_seq; -+ __skb_unlink(skb, &sk->sk_receive_queue); -+ __kfree_skb(skb); + return -1; + } + } @@ -18726,10 +19157,10 @@ index 000000000000..cf019990447c +MODULE_VERSION("0.88"); diff --git a/net/mptcp/mptcp_netlink.c b/net/mptcp/mptcp_netlink.c new file mode 100644 -index 000000000000..dd696841ea85 +index 000000000000..dd44a87a2971 --- /dev/null +++ b/net/mptcp/mptcp_netlink.c -@@ -0,0 +1,1272 @@ +@@ -0,0 +1,1278 @@ +// SPDX-License-Identifier: GPL-2.0 +/* MPTCP implementation - Netlink Path Manager + * @@ -19147,6 +19578,8 @@ index 000000000000..dd696841ea85 + struct sk_buff *msg; + void *hdr; + ++ mpcb->add_addr_accepted++; ++ + if (!mptcp_nl_must_notify(MPTCPF_EVENT_ANNOUNCED, mpcb->meta_sk)) + return; + @@ -19271,6 +19704,8 @@ index 000000000000..dd696841ea85 + if (skb) + priv->announced4 |= (1 << i); + *size += MPTCP_SUB_LEN_ADD_ADDR4_ALIGN; ++ ++ mpcb->add_addr_signal++; + } + +#if IS_ENABLED(CONFIG_IPV6) @@ -19288,6 +19723,8 @@ index 000000000000..dd696841ea85 + if (skb) + priv->announced6 |= (1 << i); + *size += MPTCP_SUB_LEN_ADD_ADDR6_ALIGN; ++ ++ mpcb->add_addr_signal++; + } +#endif + @@ -24273,7 +24710,7 @@ index 000000000000..6caba957467a +MODULE_DESCRIPTION("MPTCP wVegas"); +MODULE_VERSION("0.1"); diff --git a/net/socket.c b/net/socket.c -index 94358566c9d1..a26eeeda2b4d 100644 +index 02feaf5bd84a..b355036c445b 100644 --- a/net/socket.c +++ b/net/socket.c @@ -91,6 +91,7 @@ From e120659ff7829fc2e0053d12f1628a45b2a352c0 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 14 Oct 2022 18:21:23 +0200 Subject: [PATCH 028/102] Fix bpi-r64 and r7800 compilation --- build.sh | 2 +- config-bpi-r64 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.sh b/build.sh index 03cf5218..cd83c9bb 100755 --- a/build.sh +++ b/build.sh @@ -457,7 +457,7 @@ if [ -f target/linux/bcm27xx/patches-5.15/950-0019-drm-vc4-select-PM.patch ]; th rm -f target/linux/bcm27xx/patches-5.15/950-0019-drm-vc4-select-PM.patch fi if [ -f target/linux/ipq806x/patches-5.4/0063-2-tsens-support-configurable-interrupts.patch ]; then - rm -f target/linux/ipq806x/patches-5.4/0063-2-tsens-support-configurable-interrupts.patch + rm -f target/linux/ipq806x/patches-5.4/0063-* fi #if [ -f target/linux/ipq40xx/patches-5.4/100-GPIO-add-named-gpio-exports.patch ]; then # rm -f target/linux/ipq40xx/patches-5.4/100-GPIO-add-named-gpio-exports.patch diff --git a/config-bpi-r64 b/config-bpi-r64 index 3ab4d1d7..e98a132c 100644 --- a/config-bpi-r64 +++ b/config-bpi-r64 @@ -16,4 +16,4 @@ CONFIG_CRYPTO_GHASH_ARM_CE=y CONFIG_CRYPTO_AES_ARM=y CONFIG_CRYPTO_AES_ARM_CE=y CONFIG_TARGET_ROOTFS_PARTSIZE=900 -CONFIG_TARGET_ROOTFS_INITRAMFS=y +# CONFIG_TARGET_ROOTFS_INITRAMFS is not set From e47b0e22dd5eb4bf5695c32ec8a3fe09161b9b3b Mon Sep 17 00:00:00 2001 From: Anael Orlinski Date: Mon, 17 Oct 2022 19:07:18 +0200 Subject: [PATCH 029/102] Update uboot-rockchip with support for nanopi R4S 1Gb (#2611) --- contributors/anaelorlinski.md | 9 + root/package/boot/uboot-rockchip/Makefile | 7 +- ...01-scripts-remove-dependency-on-swig.patch | 24 + ...-spl-remove-dtoc-of-pdata-generation.patch | 14 +- ...-arm64-rk3399-Add-support-NanoPi-R4s.patch | 290 -------- ...9-split-nanopi-r4s-out-of-evb_rk3399.patch | 637 ++++++++++++++++++ ...9-Add-support-for-multiple-DDR-types.patch | 275 ++++++++ ...anopi4-unify-1GB-4GB-variants-of-R4S.patch | 89 +++ .../of-platdata/nanopi-r2s-rk3328/dt-decl.h | 23 + .../of-platdata/nanopi-r2s-rk3328/dt-plat.c | 48 +- 10 files changed, 1105 insertions(+), 311 deletions(-) create mode 100644 contributors/anaelorlinski.md create mode 100644 root/package/boot/uboot-rockchip/patches/001-scripts-remove-dependency-on-swig.patch delete mode 100644 root/package/boot/uboot-rockchip/patches/102-arm64-rk3399-Add-support-NanoPi-R4s.patch create mode 100644 root/package/boot/uboot-rockchip/patches/202-rockchip-rk3399-split-nanopi-r4s-out-of-evb_rk3399.patch create mode 100644 root/package/boot/uboot-rockchip/patches/203-ram-rk3399-Add-support-for-multiple-DDR-types.patch create mode 100644 root/package/boot/uboot-rockchip/patches/204-board-nanopi4-unify-1GB-4GB-variants-of-R4S.patch create mode 100644 root/package/boot/uboot-rockchip/src/of-platdata/nanopi-r2s-rk3328/dt-decl.h diff --git a/contributors/anaelorlinski.md b/contributors/anaelorlinski.md new file mode 100644 index 00000000..4bc93de0 --- /dev/null +++ b/contributors/anaelorlinski.md @@ -0,0 +1,9 @@ +2022-10-13 + +I hereby agree to the terms of the "OpenMPTCProuter Individual Contributor License Agreement", with MD5 checksum bc827a07eb93611d793ddb7c75083c00. + +I furthermore declare that I am authorized and able to make this agreement and sign this declaration. + +Signed, + +Anael Orlinski https://github.com/anaelorlinski diff --git a/root/package/boot/uboot-rockchip/Makefile b/root/package/boot/uboot-rockchip/Makefile index 75825ce6..17eb2711 100644 --- a/root/package/boot/uboot-rockchip/Makefile +++ b/root/package/boot/uboot-rockchip/Makefile @@ -5,10 +5,10 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk -PKG_VERSION:=2021.04 +PKG_VERSION:=2021.07 PKG_RELEASE:=1 -PKG_HASH:=0d438b1bb5cceb57a18ea2de4a0d51f7be5b05b98717df05938636e0aadfe11a +PKG_HASH:=312b7eeae44581d1362c3a3f02c28d806647756c82ba8c72241c7cdbe68ba77e PKG_MAINTAINER:=Tobias Maedel @@ -52,7 +52,7 @@ define U-Boot/rock-pi-4-rk3399 BUILD_SUBTARGET:=armv8 NAME:=Rock Pi 4 BUILD_DEVICES:= \ - radxa_rock-pi-4 + radxa_rock-pi-4a DEPENDS:=+PACKAGE_u-boot-rock-pi-4-rk3399:arm-trusted-firmware-rockchip PKG_BUILD_DEPENDS:=arm-trusted-firmware-rockchip ATF:=rk3399_bl31.elf @@ -88,6 +88,7 @@ ifneq ($(OF_PLATDATA),) $(CP) $(PKG_BUILD_DIR)/of-platdata/$(OF_PLATDATA)/dt-plat.c $(PKG_BUILD_DIR)/tpl/dts/dt-plat.c $(CP) $(PKG_BUILD_DIR)/of-platdata/$(OF_PLATDATA)/dt-structs-gen.h $(PKG_BUILD_DIR)/include/generated/dt-structs-gen.h + $(CP) $(PKG_BUILD_DIR)/of-platdata/$(OF_PLATDATA)/dt-decl.h $(PKG_BUILD_DIR)/include/generated/dt-decl.h endif $(SED) 's#CONFIG_MKIMAGE_DTC_PATH=.*#CONFIG_MKIMAGE_DTC_PATH="$(PKG_BUILD_DIR)/scripts/dtc/dtc"#g' $(PKG_BUILD_DIR)/.config diff --git a/root/package/boot/uboot-rockchip/patches/001-scripts-remove-dependency-on-swig.patch b/root/package/boot/uboot-rockchip/patches/001-scripts-remove-dependency-on-swig.patch new file mode 100644 index 00000000..05055893 --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/001-scripts-remove-dependency-on-swig.patch @@ -0,0 +1,24 @@ +From b137ca16b54c67d76714ea5a0138741959b0dc29 Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Mon, 13 Jul 2020 23:37:37 +0200 +Subject: [PATCH] scripts: remove dependency on swig + +Don't build the libfdt tool, as it has a dependency on swig (which +OpenWrt does not ship). + +This requires more hacks, as of-platdata generation does not work +without it. + +Signed-off-by: David Bauer +--- + scripts/dtc/Makefile | 2 -- + 1 file changed, 2 deletions(-) + +--- a/scripts/dtc/Makefile ++++ b/scripts/dtc/Makefile +@@ -18,5 +18,3 @@ HOSTCFLAGS_dtc-parser.tab.o := -I$(src) + # dependencies on generated files need to be listed explicitly + $(obj)/dtc-lexer.lex.o: $(obj)/dtc-parser.tab.h + +-# Added for U-Boot +-subdir-$(CONFIG_PYLIBFDT) += pylibfdt diff --git a/root/package/boot/uboot-rockchip/patches/002-spl-remove-dtoc-of-pdata-generation.patch b/root/package/boot/uboot-rockchip/patches/002-spl-remove-dtoc-of-pdata-generation.patch index 61a56c2a..14bcbfb6 100644 --- a/root/package/boot/uboot-rockchip/patches/002-spl-remove-dtoc-of-pdata-generation.patch +++ b/root/package/boot/uboot-rockchip/patches/002-spl-remove-dtoc-of-pdata-generation.patch @@ -17,14 +17,12 @@ Signed-off-by: David Bauer --- a/scripts/Makefile.spl +++ b/scripts/Makefile.spl -@@ -329,10 +329,6 @@ PHONY += dts_dir - dts_dir: - $(shell [ -d $(obj)/dts ] || mkdir -p $(obj)/dts) - --include/generated/dt-structs-gen.h $(u-boot-spl-platdata_c) &: \ -- $(obj)/$(SPL_BIN).dtb dts_dir FORCE +@@ -354,8 +354,6 @@ $(platdata-hdr) $(u-boot-spl-platdata_c) + @# of OF_PLATDATA_INST and this might change between builds. Leaving old + @# ones around is confusing and it is possible that switching the + @# setting again will use the old one instead of regenerating it. +- @rm -f $(u-boot-spl-all-platdata_c) $(u-boot-spl-all-platdata) - $(call if_changed,dtoc) -- + ifdef CONFIG_SAMSUNG ifdef CONFIG_VAR_SIZE_SPL - VAR_SIZE_PARAM = --vs diff --git a/root/package/boot/uboot-rockchip/patches/102-arm64-rk3399-Add-support-NanoPi-R4s.patch b/root/package/boot/uboot-rockchip/patches/102-arm64-rk3399-Add-support-NanoPi-R4s.patch deleted file mode 100644 index f926f52e..00000000 --- a/root/package/boot/uboot-rockchip/patches/102-arm64-rk3399-Add-support-NanoPi-R4s.patch +++ /dev/null @@ -1,290 +0,0 @@ -From b69b9f3f54732c303939eb748aad97cd4cf60168 Mon Sep 17 00:00:00 2001 -From: Xiaobo Tian -Date: Sat, 27 Feb 2021 22:39:11 +0800 -Subject: [PATCH] arm64: rk3399: Add support NanoPi R4s - -NanoPi R4s is SBC base on Rockchip RK3399 hexa-core processor with -dual-Core Cortex-A72 and Mali-T864 GPU with 4GiB(LPDDR4) of RAM, SD card support, -including 2 gigabit ethernet(RTL8211E 1Gbps - RTL8111H 1Gbps) and 2 USB 3.0 port. -port.It also has two GPIO headers which allows further peripherals to be used. - -The devicetree file is taken of the rk3399 nanopi4 Linux kernel [1]. - -[1] https://github.com/torvalds/linux/commit/e7a095908227fb3ccc86d001d9e13c9ae2bef8e6 - -Signed-off-by: xiaobo -Reviewed-by: Kever Yang ---- - arch/arm/dts/Makefile | 1 + - arch/arm/dts/rk3399-nanopi-r4s-u-boot.dtsi | 16 +++ - arch/arm/dts/rk3399-nanopi-r4s.dts | 138 +++++++++++++++++++++ - board/rockchip/evb_rk3399/MAINTAINERS | 6 + - configs/nanopi-r4s-rk3399_defconfig | 62 +++++++++ - 5 files changed, 223 insertions(+) - create mode 100644 arch/arm/dts/rk3399-nanopi-r4s-u-boot.dtsi - create mode 100644 arch/arm/dts/rk3399-nanopi-r4s.dts - create mode 100644 configs/nanopi-r4s-rk3399_defconfig - -diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile -index dd4d4efed31..0a139473811 100644 ---- a/arch/arm/dts/Makefile -+++ b/arch/arm/dts/Makefile -@@ -132,6 +132,7 @@ dtb-$(CONFIG_ROCKCHIP_RK3399) += \ - rk3399-nanopi-m4.dtb \ - rk3399-nanopi-m4-2gb.dtb \ - rk3399-nanopi-neo4.dtb \ -+ rk3399-nanopi-r4s.dtb \ - rk3399-orangepi.dtb \ - rk3399-pinebook-pro.dtb \ - rk3399-puma-haikou.dtb \ -diff --git a/arch/arm/dts/rk3399-nanopi-r4s-u-boot.dtsi b/arch/arm/dts/rk3399-nanopi-r4s-u-boot.dtsi -new file mode 100644 -index 00000000000..cd1642527ba ---- /dev/null -+++ b/arch/arm/dts/rk3399-nanopi-r4s-u-boot.dtsi -@@ -0,0 +1,16 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * RK3399-based FriendlyElec boards device tree source -+ * -+ * Copyright (c) 2016 Fuzhou Rockchip Electronics Co., Ltd -+ * -+ * Copyright (c) 2018 FriendlyElec Computer Tech. Co., Ltd. -+ * (http://www.friendlyarm.com) -+ * -+ * Copyright (c) 2018 Collabora Ltd. -+ * Copyright (c) 2019 Arm Ltd. -+ * Copyright (C) 2020 Xiaobo -+ */ -+ -+#include "rk3399-nanopi4-u-boot.dtsi" -+#include "rk3399-sdram-lpddr4-100.dtsi" -diff --git a/arch/arm/dts/rk3399-nanopi-r4s.dts b/arch/arm/dts/rk3399-nanopi-r4s.dts -new file mode 100644 -index 00000000000..6f2cf17bf1b ---- /dev/null -+++ b/arch/arm/dts/rk3399-nanopi-r4s.dts -@@ -0,0 +1,138 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright (c) 2016 Fuzhou Rockchip Electronics Co., Ltd -+ * -+ * Copyright (c) 2018 FriendlyElec Computer Tech. Co., Ltd. -+ * (http://www.friendlyarm.com) -+ * -+ * Copyright (c) 2018 Collabora Ltd. -+ * Copyright (c) 2019 Arm Ltd. -+ * Copyright (C) 2020 Xiaobo -+ */ -+ -+/dts-v1/; -+#include "rk3399-nanopi4.dtsi" -+ -+/ { -+ model = "FriendlyElec NanoPi R4S"; -+ compatible = "friendlyarm,nanopi-r4s", "rockchip,rk3399"; -+ -+ aliases { -+ ethernet1 = &r8169; -+ }; -+ -+ vdd_5v: vdd-5v { -+ compatible = "regulator-fixed"; -+ regulator-name = "vdd_5v"; -+ regulator-always-on; -+ regulator-boot-on; -+ }; -+ -+ fan: pwm-fan { -+ compatible = "pwm-fan"; -+ cooling-levels = <0 12 18 255>; -+ #cooling-cells = <2>; -+ fan-supply = <&vdd_5v>; -+ pwms = <&pwm1 0 50000 0>; -+ }; -+}; -+ -+&cpu_thermal { -+ trips { -+ cpu_warm: cpu_warm { -+ temperature = <55000>; -+ hysteresis = <2000>; -+ type = "active"; -+ }; -+ -+ cpu_hot: cpu_hot { -+ temperature = <65000>; -+ hysteresis = <2000>; -+ type = "active"; -+ }; -+ }; -+ -+ cooling-maps { -+ map2 { -+ trip = <&cpu_warm>; -+ cooling-device = <&fan THERMAL_NO_LIMIT 1>; -+ }; -+ -+ map3 { -+ trip = <&cpu_hot>; -+ cooling-device = <&fan 2 THERMAL_NO_LIMIT>; -+ }; -+ }; -+}; -+ -+&emmc_phy { -+ status = "disabled"; -+}; -+ -+&fusb0 { -+ status = "disabled"; -+}; -+ -+&leds { -+ lan_led: led-1 { -+ gpios = <&gpio1 RK_PA1 GPIO_ACTIVE_HIGH>; -+ label = "nanopi-r4s:green:lan"; -+ }; -+ -+ wan_led: led-2 { -+ gpios = <&gpio1 RK_PA0 GPIO_ACTIVE_HIGH>; -+ label = "nanopi-r4s:green:wan"; -+ }; -+}; -+ -+&leds_gpio { -+ rockchip,pins = -+ <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>, -+ <1 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>, -+ <1 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>; -+}; -+ -+&pcie0 { -+ max-link-speed = <1>; -+ num-lanes = <1>; -+ vpcie3v3-supply = <&vcc3v3_sys>; -+ -+ pcie@0 { -+ reg = <0x00000000 0 0 0 0>; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ -+ r8169: pcie@0,0 { -+ reg = <0x000000 0 0 0 0>; -+ local-mac-address = [ 00 00 00 00 00 00 ]; -+ }; -+ }; -+}; -+ -+&sdhci { -+ status = "disabled"; -+}; -+ -+&sdio0 { -+ status = "disabled"; -+}; -+ -+&sdmmc { -+ host-index-min = <1>; -+}; -+ -+&u2phy0_host { -+ phy-supply = <&vdd_5v>; -+}; -+ -+&u2phy1_host { -+ status = "disabled"; -+}; -+ -+&usbdrd_dwc3_0 { -+ dr_mode = "host"; -+}; -+ -+&vcc3v3_sys { -+ vin-supply = <&vcc5v0_sys>; -+}; -diff --git a/board/rockchip/evb_rk3399/MAINTAINERS b/board/rockchip/evb_rk3399/MAINTAINERS -index 4c889e06a63..3b9d60eccd4 100644 ---- a/board/rockchip/evb_rk3399/MAINTAINERS -+++ b/board/rockchip/evb_rk3399/MAINTAINERS -@@ -55,6 +55,12 @@ S: Maintained - F: configs/nanopi-neo4-rk3399_defconfig - F: arch/arm/dts/rk3399-nanopi-neo4-u-boot.dtsi - -+NANOPI-R4S -+M: Xiaobo Tian -+S: Maintained -+F: configs/nanopi-r4s-rk3399_defconfig -+F: arch/arm/dts/rk3399-nanopi-r4s-u-boot.dtsi -+ - ORANGEPI-RK3399 - M: Jagan Teki - S: Maintained -diff --git a/configs/nanopi-r4s-rk3399_defconfig b/configs/nanopi-r4s-rk3399_defconfig -new file mode 100644 -index 00000000000..0a3c28b0126 ---- /dev/null -+++ b/configs/nanopi-r4s-rk3399_defconfig -@@ -0,0 +1,62 @@ -+CONFIG_ARM=y -+CONFIG_ARCH_ROCKCHIP=y -+CONFIG_SYS_TEXT_BASE=0x00200000 -+CONFIG_ENV_OFFSET=0x3F8000 -+CONFIG_ROCKCHIP_RK3399=y -+CONFIG_TARGET_EVB_RK3399=y -+CONFIG_NR_DRAM_BANKS=1 -+CONFIG_DEBUG_UART_BASE=0xFF1A0000 -+CONFIG_DEBUG_UART_CLOCK=24000000 -+CONFIG_DEBUG_UART=y -+CONFIG_DEFAULT_FDT_FILE="rockchip/rk3399-nanopi-r4s.dtb" -+CONFIG_DISPLAY_BOARDINFO_LATE=y -+# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set -+CONFIG_SPL_STACK_R=y -+CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x10000 -+CONFIG_TPL=y -+CONFIG_CMD_BOOTZ=y -+CONFIG_CMD_GPT=y -+CONFIG_CMD_MMC=y -+CONFIG_CMD_USB=y -+# CONFIG_CMD_SETEXPR is not set -+CONFIG_CMD_TIME=y -+CONFIG_SPL_OF_CONTROL=y -+CONFIG_DEFAULT_DEVICE_TREE="rk3399-nanopi-r4s" -+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" -+CONFIG_ENV_IS_IN_MMC=y -+CONFIG_SYS_RELOC_GD_ENV_ADDR=y -+CONFIG_ROCKCHIP_GPIO=y -+CONFIG_SYS_I2C_ROCKCHIP=y -+CONFIG_MMC_DW=y -+CONFIG_MMC_DW_ROCKCHIP=y -+CONFIG_MMC_SDHCI=y -+CONFIG_MMC_SDHCI_ROCKCHIP=y -+CONFIG_DM_ETH=y -+CONFIG_ETH_DESIGNWARE=y -+CONFIG_GMAC_ROCKCHIP=y -+CONFIG_PMIC_RK8XX=y -+CONFIG_REGULATOR_PWM=y -+CONFIG_REGULATOR_RK8XX=y -+CONFIG_PWM_ROCKCHIP=y -+CONFIG_RAM_RK3399_LPDDR4=y -+CONFIG_BAUDRATE=1500000 -+CONFIG_DEBUG_UART_SHIFT=2 -+CONFIG_SYSRESET=y -+CONFIG_USB=y -+CONFIG_USB_XHCI_HCD=y -+CONFIG_USB_XHCI_DWC3=y -+CONFIG_USB_EHCI_HCD=y -+CONFIG_USB_EHCI_GENERIC=y -+CONFIG_USB_KEYBOARD=y -+CONFIG_USB_HOST_ETHER=y -+CONFIG_USB_ETHER_ASIX=y -+CONFIG_USB_ETHER_ASIX88179=y -+CONFIG_USB_ETHER_MCS7830=y -+CONFIG_USB_ETHER_RTL8152=y -+CONFIG_USB_ETHER_SMSC95XX=y -+CONFIG_DM_VIDEO=y -+CONFIG_DISPLAY=y -+CONFIG_VIDEO_ROCKCHIP=y -+CONFIG_DISPLAY_ROCKCHIP_HDMI=y -+CONFIG_SPL_TINY_MEMSET=y -+CONFIG_ERRNO_STR=y diff --git a/root/package/boot/uboot-rockchip/patches/202-rockchip-rk3399-split-nanopi-r4s-out-of-evb_rk3399.patch b/root/package/boot/uboot-rockchip/patches/202-rockchip-rk3399-split-nanopi-r4s-out-of-evb_rk3399.patch new file mode 100644 index 00000000..ebdca081 --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/202-rockchip-rk3399-split-nanopi-r4s-out-of-evb_rk3399.patch @@ -0,0 +1,637 @@ +From 244492a7a5451eca042d3ec7ccff8de6e23dd288 Mon Sep 17 00:00:00 2001 +From: hmz007 +Date: Fri, 18 Dec 2020 17:10:35 +0800 +Subject: [PATCH 2/4] rockchip: rk3399: split nanopi-r4s out of evb_rk3399 + +Signed-off-by: hmz007 +--- + arch/arm/mach-rockchip/rk3399/Kconfig | 6 + + board/friendlyarm/nanopi4/Kconfig | 15 +++ + board/friendlyarm/nanopi4/MAINTAINERS | 6 + + board/friendlyarm/nanopi4/Makefile | 8 ++ + board/friendlyarm/nanopi4/README | 122 +++++++++++++++++++ + board/friendlyarm/nanopi4/hwrev.c | 149 ++++++++++++++++++++++++ + board/friendlyarm/nanopi4/hwrev.h | 27 +++++ + board/friendlyarm/nanopi4/nanopi4.c | 148 +++++++++++++++++++++++ + configs/nanopi-r4s-4gb-rk3399_defconfig | 4 +- + configs/nanopi-r4s-rk3399_defconfig | 4 +- + drivers/clk/rockchip/clk_rk3399.c | 2 + + include/configs/nanopi4.h | 24 ++++ + 12 files changed, 511 insertions(+), 4 deletions(-) + create mode 100644 board/friendlyarm/nanopi4/Kconfig + create mode 100644 board/friendlyarm/nanopi4/MAINTAINERS + create mode 100644 board/friendlyarm/nanopi4/Makefile + create mode 100644 board/friendlyarm/nanopi4/README + create mode 100644 board/friendlyarm/nanopi4/hwrev.c + create mode 100644 board/friendlyarm/nanopi4/hwrev.h + create mode 100644 board/friendlyarm/nanopi4/nanopi4.c + create mode 100644 include/configs/nanopi4.h + +diff --git a/arch/arm/mach-rockchip/rk3399/Kconfig b/arch/arm/mach-rockchip/rk3399/Kconfig +index 17628f9171..2a44aae43c 100644 +--- a/arch/arm/mach-rockchip/rk3399/Kconfig ++++ b/arch/arm/mach-rockchip/rk3399/Kconfig +@@ -109,6 +109,11 @@ config TARGET_ROC_PC_RK3399 + * wide voltage input(5V-15V), dual cell battery + * Wifi/BT accessible via expansion board M.2 + ++config TARGET_NANOPI4 ++ bool "FriendlyElec NanoPi 4 Series" ++ help ++ Support for FriendlyElec boards based on RK3399. ++ + endchoice + + config ROCKCHIP_BOOT_MODE_REG +@@ -152,6 +157,7 @@ config SYS_BOOTCOUNT_ADDR + endif # BOOTCOUNT_LIMIT + + source "board/firefly/roc-pc-rk3399/Kconfig" ++source "board/friendlyarm/nanopi4/Kconfig" + source "board/google/gru/Kconfig" + source "board/pine64/pinebook-pro-rk3399/Kconfig" + source "board/pine64/rockpro64_rk3399/Kconfig" +diff --git a/board/friendlyarm/nanopi4/Kconfig b/board/friendlyarm/nanopi4/Kconfig +new file mode 100644 +index 0000000000..f3f9dd7b56 +--- /dev/null ++++ b/board/friendlyarm/nanopi4/Kconfig +@@ -0,0 +1,15 @@ ++if TARGET_NANOPI4 ++ ++config SYS_BOARD ++ default "nanopi4" ++ ++config SYS_VENDOR ++ default "friendlyarm" ++ ++config SYS_CONFIG_NAME ++ default "nanopi4" ++ ++config BOARD_SPECIFIC_OPTIONS ++ def_bool y ++ ++endif +diff --git a/board/friendlyarm/nanopi4/MAINTAINERS b/board/friendlyarm/nanopi4/MAINTAINERS +new file mode 100644 +index 0000000000..b4c35701d6 +--- /dev/null ++++ b/board/friendlyarm/nanopi4/MAINTAINERS +@@ -0,0 +1,6 @@ ++NanoPi 4 Series ++M: ++S: Maintained ++F: board/friendlyarm/nanopi4/ ++F: include/configs/nanopi4.h ++F: configs/nanopi4_defconfig +diff --git a/board/friendlyarm/nanopi4/Makefile b/board/friendlyarm/nanopi4/Makefile +new file mode 100644 +index 0000000000..33a1466567 +--- /dev/null ++++ b/board/friendlyarm/nanopi4/Makefile +@@ -0,0 +1,8 @@ ++# ++# Copyright (C) Guangzhou FriendlyELEC Computer Tech. Co., Ltd. ++# (http://www.friendlyarm.com) ++# ++# SPDX-License-Identifier: GPL-2.0+ ++# ++ ++obj-y += nanopi4.o hwrev.o +diff --git a/board/friendlyarm/nanopi4/README b/board/friendlyarm/nanopi4/README +new file mode 100644 +index 0000000000..c6f58203eb +--- /dev/null ++++ b/board/friendlyarm/nanopi4/README +@@ -0,0 +1,122 @@ ++Introduction ++============ ++ ++RK3399 key features we might use in U-Boot: ++* CPU: ARMv8 64bit Big-Little architecture, ++* Big: dual-core Cortex-A72 ++* Little: quad-core Cortex-A53 ++* IRAM: 200KB ++* DRAM: 4GB-128MB dual-channel ++* eMMC: support eMMC 5.0/5.1, suport HS400, HS200, DDR50 ++* SD/MMC: support SD 3.0, MMC 4.51 ++* USB: USB3.0 type-C port *2 with dwc3 controller ++* USB2.0 EHCI host port *2 ++* Display: RGB/HDMI/DP/MIPI/EDP ++ ++evb key features: ++* regulator: pwm regulator for CPU B/L ++* PMIC: rk808 ++* debug console: UART2 ++ ++In order to support Arm Trust Firmware(ATF), we can use either SPL or ++miniloader from rockchip to do: ++* do DRAM init ++* load and verify ATF image ++* load and verify U-Boot image ++ ++Here is the step-by-step to boot to U-Boot on rk3399. ++ ++Get the Source and prebuild binary ++================================== ++ ++ > mkdir ~/evb_rk3399 ++ > cd ~/evb_rk3399 ++ > git clone https://github.com/ARM-software/arm-trusted-firmware.git ++ > git clone https://github.com/rockchip-linux/rkbin.git ++ > git clone https://github.com/rockchip-linux/rkdeveloptool.git ++ ++ ++Compile ATF ++=========== ++ ++ > cd arm-trusted-firmware ++ > make realclean ++ > make CROSS_COMPILE=aarch64-linux-gnu- PLAT=rk3399 bl31 ++ ++ Get bl31.elf in this step, copy it to U-Boot root dir: ++ > cp build/rk3399/release/bl31/bl31.elf ../u-boot/ ++ ++ Or you can get the bl31.elf directly from Rockchip: ++ > cp rkbin/rk33/rk3399_bl31_v1.00.elf ../u-boot/bl31.elf ++ ++ ++Compile U-Boot ++============== ++ ++ > cd ../u-boot ++ > export CROSS_COMPILE=aarch64-linux-gnu- ++ > make evb-rk3399_defconfig ++ for firefly-rk3399, use below instead: ++ > make firefly-rk3399_defconfig ++ > make ++ > make u-boot.itb ++ ++ Get spl/u-boot-spl.bin and u-boot.itb in this step. ++ ++Compile rkdeveloptool ++===================== ++ ++Get rkdeveloptool installed on your Host in this step. ++ ++Follow instructions in latest README, example: ++ > cd ../rkdeveloptool ++ > autoreconf -i ++ > ./configure ++ > make ++ > sudo make install ++ ++Both origin binaries and Tool are ready now, choose either option 1 or ++option 2 to deploy U-Boot. ++ ++Package the image ++================= ++ ++Package the image for U-Boot SPL(option 1) ++-------------------------------- ++ > cd .. ++ > tools/mkimage -n rk3399 -T rksd -d spl/u-boot-spl.bin idbspl.img ++ ++ Get idbspl.img in this step. ++ ++Package the image for Rockchip miniloader(option 2) ++------------------------------------------ ++ > cd .. ++ > cp arm-trusted-firmware/build/rk3399/release/bl31.elf rkbin/rk33 ++ > ./rkbin/tools/trust_merger rkbin/tools/RK3399TRUST.ini ++ > ./rkbin/tools/loaderimage --pack --uboot u-boot/u-boot-dtb.bin uboot.img ++ ++ Get trust.img and uboot.img in this step. ++ ++Flash the image to eMMC ++======================= ++ ++Flash the image with U-Boot SPL(option 1) ++------------------------------- ++Power on(or reset with RESET KEY) with MASKROM KEY preesed, and then: ++ > rkdeveloptool db rkbin/rk33/rk3399_loader_v1.08.106.bin ++ > rkdeveloptool wl 64 u-boot/idbspl.img ++ > rkdeveloptool wl 0x4000 u-boot/u-boot.itb ++ > rkdeveloptool rd ++ ++Flash the image with Rockchip miniloader(option 2) ++---------------------------------------- ++Power on(or reset with RESET KEY) with MASKROM KEY preesed, and then: ++ > rkdeveloptool db rkbin/rk33/rk3399_loader_v1.08.106.bin ++ > rkdeveloptool ul rkbin/rk33/rk3399_loader_v1.08.106.bin ++ > rkdeveloptool wl 0x4000 u-boot/uboot.img ++ > rkdeveloptool wl 0x6000 u-boot/trust.img ++ > rkdeveloptool rd ++ ++You should be able to get U-Boot log in console/UART2(baurdrate 1500000) ++For more detail, please reference to: ++http://opensource.rock-chips.com/wiki_Boot_option +diff --git a/board/friendlyarm/nanopi4/hwrev.c b/board/friendlyarm/nanopi4/hwrev.c +new file mode 100644 +index 0000000000..9199a927ee +--- /dev/null ++++ b/board/friendlyarm/nanopi4/hwrev.c +@@ -0,0 +1,149 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright (c) 2020 FriendlyElec Computer Tech. Co., Ltd. ++ * (http://www.friendlyarm.com) ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* ++ * ID info: ++ * ID : Volts : ADC value : Bucket ++ * == ===== ========= =========== ++ * 0 : 0.102V: 58 : 0 - 81 ++ * 1 : 0.211V: 120 : 82 - 150 ++ * 2 : 0.319V: 181 : 151 - 211 ++ * 3 : 0.427V: 242 : 212 - 274 ++ * 4 : 0.542V: 307 : 275 - 342 ++ * 5 : 0.666V: 378 : 343 - 411 ++ * 6 : 0.781V: 444 : 412 - 477 ++ * 7 : 0.900V: 511 : 478 - 545 ++ * 8 : 1.023V: 581 : 546 - 613 ++ * 9 : 1.137V: 646 : 614 - 675 ++ * 10 : 1.240V: 704 : 676 - 733 ++ * 11 : 1.343V: 763 : 734 - 795 ++ * 12 : 1.457V: 828 : 796 - 861 ++ * 13 : 1.576V: 895 : 862 - 925 ++ * 14 : 1.684V: 956 : 926 - 989 ++ * 15 : 1.800V: 1023 : 990 - 1023 ++ */ ++static const int id_readings[] = { ++ 81, 150, 211, 274, 342, 411, 477, 545, ++ 613, 675, 733, 795, 861, 925, 989, 1023 ++}; ++ ++static int cached_board_id = -1; ++ ++#define SARADC_BASE 0xFF100000 ++#define SARADC_DATA (SARADC_BASE + 0) ++#define SARADC_CTRL (SARADC_BASE + 8) ++ ++static u32 get_saradc_value(int chn) ++{ ++ int timeout = 0; ++ u32 adc_value = 0; ++ ++ writel(0, SARADC_CTRL); ++ udelay(2); ++ ++ writel(0x28 | chn, SARADC_CTRL); ++ udelay(50); ++ ++ timeout = 0; ++ do { ++ if (readl(SARADC_CTRL) & 0x40) { ++ adc_value = readl(SARADC_DATA) & 0x3FF; ++ goto stop_adc; ++ } ++ ++ udelay(10); ++ } while (timeout++ < 100); ++ ++stop_adc: ++ writel(0, SARADC_CTRL); ++ ++ return adc_value; ++} ++ ++static uint32_t get_adc_index(int chn) ++{ ++ int i; ++ int adc_reading; ++ ++ if (cached_board_id != -1) ++ return cached_board_id; ++ ++ adc_reading = get_saradc_value(chn); ++ for (i = 0; i < ARRAY_SIZE(id_readings); i++) { ++ if (adc_reading <= id_readings[i]) { ++ debug("ADC reading %d, ID %d\n", adc_reading, i); ++ cached_board_id = i; ++ return i; ++ } ++ } ++ ++ /* should die for impossible value */ ++ return 0; ++} ++ ++/* ++ * Board revision list: ++ * 0b00 - NanoPC-T4 ++ * 0b01 - NanoPi M4 ++ * ++ * Extended by ADC_IN4 ++ * Group A: ++ * 0x04 - NanoPi NEO4 ++ * 0x06 - SOC-RK3399 ++ * ++ * Group B: ++ * 0x21 - NanoPi M4 Ver2.0 ++ */ ++static int pcb_rev = -1; ++ ++void bd_hwrev_init(void) ++{ ++#define GPIO4_BASE 0xff790000 ++ struct rockchip_gpio_regs *regs = (void *)GPIO4_BASE; ++ ++#ifdef CONFIG_SPL_BUILD ++ struct udevice *dev; ++ ++ if (uclass_get_device_by_driver(UCLASS_CLK, ++ DM_DRIVER_GET(clk_rk3399), &dev)) ++ return; ++#endif ++ ++ if (pcb_rev >= 0) ++ return; ++ ++ /* D1, D0: input mode */ ++ clrbits_le32(®s->swport_ddr, (0x3 << 24)); ++ pcb_rev = (readl(®s->ext_port) >> 24) & 0x3; ++ ++ if (pcb_rev == 0x3) { ++ /* Revision group A: 0x04 ~ 0x13 */ ++ pcb_rev = 0x4 + get_adc_index(4); ++ ++ } else if (pcb_rev == 0x1) { ++ int idx = get_adc_index(4); ++ ++ /* Revision group B: 0x21 ~ 0x2f */ ++ if (idx > 0) { ++ pcb_rev = 0x20 + idx; ++ } ++ } ++} ++ ++/* To override __weak symbols */ ++u32 get_board_rev(void) ++{ ++ return pcb_rev; ++} ++ +diff --git a/board/friendlyarm/nanopi4/hwrev.h b/board/friendlyarm/nanopi4/hwrev.h +new file mode 100644 +index 0000000000..23b3c7a557 +--- /dev/null ++++ b/board/friendlyarm/nanopi4/hwrev.h +@@ -0,0 +1,27 @@ ++/* ++ * Copyright (C) Guangzhou FriendlyARM Computer Tech. Co., Ltd. ++ * (http://www.friendlyarm.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, you can access it online at ++ * http://www.gnu.org/licenses/gpl-2.0.html. ++ */ ++ ++#ifndef __BD_HW_REV_H__ ++#define __BD_HW_REV_H__ ++ ++extern void bd_hwrev_config_gpio(void); ++extern void bd_hwrev_init(void); ++extern u32 get_board_rev(void); ++ ++#endif /* __BD_HW_REV_H__ */ +diff --git a/board/friendlyarm/nanopi4/nanopi4.c b/board/friendlyarm/nanopi4/nanopi4.c +new file mode 100644 +index 0000000000..a140370ca2 +--- /dev/null ++++ b/board/friendlyarm/nanopi4/nanopi4.c +@@ -0,0 +1,148 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright (c) 2020 FriendlyElec Computer Tech. Co., Ltd. ++ * (http://www.friendlyarm.com) ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_MISC_INIT_R ++static void setup_iodomain(void) ++{ ++ struct rk3399_grf_regs *grf = ++ syscon_get_first_range(ROCKCHIP_SYSCON_GRF); ++ ++ /* BT565 and AUDIO is in 1.8v domain */ ++ rk_setreg(&grf->io_vsel, BIT(0) | BIT(1)); ++} ++ ++static int __maybe_unused mac_read_from_generic_eeprom(u8 *addr) ++{ ++ struct udevice *i2c_dev; ++ int ret; ++ ++ /* Microchip 24AA02xxx EEPROMs with EUI-48 Node Identity */ ++ ret = i2c_get_chip_for_busnum(2, 0x51, 1, &i2c_dev); ++ if (!ret) ++ ret = dm_i2c_read(i2c_dev, 0xfa, addr, 6); ++ ++ return ret; ++} ++ ++static void setup_macaddr(void) ++{ ++#if CONFIG_IS_ENABLED(CMD_NET) ++ int ret; ++ const char *cpuid = env_get("cpuid#"); ++ u8 hash[SHA256_SUM_LEN]; ++ int size = sizeof(hash); ++ u8 mac_addr[6]; ++ int from_eeprom = 0; ++ int lockdown = 0; ++ ++#ifndef CONFIG_ENV_IS_NOWHERE ++ lockdown = env_get_yesno("lockdown") == 1; ++#endif ++ if (lockdown && env_get("ethaddr")) ++ return; ++ ++ ret = mac_read_from_generic_eeprom(mac_addr); ++ if (!ret && is_valid_ethaddr(mac_addr)) { ++ eth_env_set_enetaddr("ethaddr", mac_addr); ++ from_eeprom = 1; ++ } ++ ++ if (!cpuid) { ++ debug("%s: could not retrieve 'cpuid#'\n", __func__); ++ return; ++ } ++ ++ ret = hash_block("sha256", (void *)cpuid, strlen(cpuid), hash, &size); ++ if (ret) { ++ debug("%s: failed to calculate SHA256\n", __func__); ++ return; ++ } ++ ++ /* Copy 6 bytes of the hash to base the MAC address on */ ++ memcpy(mac_addr, hash, 6); ++ ++ /* Make this a valid MAC address and set it */ ++ mac_addr[0] &= 0xfe; /* clear multicast bit */ ++ mac_addr[0] |= 0x02; /* set local assignment bit (IEEE802) */ ++ ++ if (from_eeprom) { ++ eth_env_set_enetaddr("eth1addr", mac_addr); ++ } else { ++ eth_env_set_enetaddr("ethaddr", mac_addr); ++ ++ if (lockdown && env_get("eth1addr")) ++ return; ++ ++ /* Ugly, copy another 4 bytes to generate a similar address */ ++ memcpy(mac_addr + 2, hash + 8, 4); ++ if (!memcmp(hash + 2, hash + 8, 4)) ++ mac_addr[5] ^= 0xff; ++ ++ eth_env_set_enetaddr("eth1addr", mac_addr); ++ } ++#endif ++ ++ return; ++} ++ ++int misc_init_r(void) ++{ ++ const u32 cpuid_offset = 0x7; ++ const u32 cpuid_length = 0x10; ++ u8 cpuid[cpuid_length]; ++ int ret; ++ ++ setup_iodomain(); ++ ++ ret = rockchip_cpuid_from_efuse(cpuid_offset, cpuid_length, cpuid); ++ if (ret) ++ return ret; ++ ++ ret = rockchip_cpuid_set(cpuid, cpuid_length); ++ if (ret) ++ return ret; ++ ++ setup_macaddr(); ++ bd_hwrev_init(); ++ ++ return 0; ++} ++#endif ++ ++#ifdef CONFIG_SERIAL_TAG ++void get_board_serial(struct tag_serialnr *serialnr) ++{ ++ char *serial_string; ++ u64 serial = 0; ++ ++ serial_string = env_get("serial#"); ++ ++ if (serial_string) ++ serial = simple_strtoull(serial_string, NULL, 16); ++ ++ serialnr->high = (u32)(serial >> 32); ++ serialnr->low = (u32)(serial & 0xffffffff); ++} ++#endif +diff --git a/configs/nanopi-r4s-rk3399_defconfig b/configs/nanopi-r4s-rk3399_defconfig +index 034241f209..b67f7c0dc9 100644 +--- a/configs/nanopi-r4s-rk3399_defconfig ++++ b/configs/nanopi-r4s-rk3399_defconfig +@@ -4,13 +4,13 @@ CONFIG_SYS_TEXT_BASE=0x00200000 + CONFIG_NR_DRAM_BANKS=1 + CONFIG_ENV_OFFSET=0x3F8000 +-CONFIG_DEFAULT_DEVICE_TREE="rk3399-nanopi-r4s" + CONFIG_ROCKCHIP_RK3399=y +-CONFIG_TARGET_EVB_RK3399=y ++CONFIG_TARGET_NANOPI4=y + CONFIG_DEBUG_UART_BASE=0xFF1A0000 + CONFIG_DEBUG_UART_CLOCK=24000000 ++CONFIG_DEFAULT_DEVICE_TREE="rk3399-nanopi-r4s" + CONFIG_DEBUG_UART=y + CONFIG_DEFAULT_FDT_FILE="rockchip/rk3399-nanopi-r4s.dtb" +-CONFIG_DISPLAY_BOARDINFO_LATE=y ++CONFIG_MISC_INIT_R=y + # CONFIG_SPL_RAW_IMAGE_SUPPORT is not set + CONFIG_SPL_STACK_R=y + CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x10000 +diff --git a/drivers/clk/rockchip/clk_rk3399.c b/drivers/clk/rockchip/clk_rk3399.c +index 22c373a623..38975c0c65 100644 +--- a/drivers/clk/rockchip/clk_rk3399.c ++++ b/drivers/clk/rockchip/clk_rk3399.c +@@ -1351,6 +1351,8 @@ static void rkclk_init(struct rockchip_cru *cru) + pclk_div << PCLK_PERILP1_DIV_CON_SHIFT | + hclk_div << HCLK_PERILP1_DIV_CON_SHIFT | + HCLK_PERILP1_PLL_SEL_GPLL << HCLK_PERILP1_PLL_SEL_SHIFT); ++ ++ rk3399_saradc_set_clk(cru, 1000000); + } + #endif + +diff --git a/include/configs/nanopi4.h b/include/configs/nanopi4.h +new file mode 100644 +index 0000000000..a86d38976a +--- /dev/null ++++ b/include/configs/nanopi4.h +@@ -0,0 +1,24 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * Copyright (C) Guangzhou FriendlyELEC Computer Tech. Co., Ltd. ++ * (http://www.friendlyarm.com) ++ * ++ * (C) Copyright 2016 Rockchip Electronics Co., Ltd ++ */ ++ ++#ifndef __CONFIG_NANOPI4_H__ ++#define __CONFIG_NANOPI4_H__ ++ ++#define ROCKCHIP_DEVICE_SETTINGS \ ++ "stdin=serial,usbkbd\0" \ ++ "stdout=serial,vidconsole\0" \ ++ "stderr=serial,vidconsole\0" ++ ++#include ++ ++#define SDRAM_BANK_SIZE (2UL << 30) ++ ++#define CONFIG_SERIAL_TAG ++#define CONFIG_REVISION_TAG ++ ++#endif +-- +2.25.1 + diff --git a/root/package/boot/uboot-rockchip/patches/203-ram-rk3399-Add-support-for-multiple-DDR-types.patch b/root/package/boot/uboot-rockchip/patches/203-ram-rk3399-Add-support-for-multiple-DDR-types.patch new file mode 100644 index 00000000..a9795849 --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/203-ram-rk3399-Add-support-for-multiple-DDR-types.patch @@ -0,0 +1,275 @@ +From 1bc90230df5cd55513268f2f7a43abdbad1161b5 Mon Sep 17 00:00:00 2001 +From: hmz007 +Date: Sat, 19 Dec 2020 19:39:14 +0800 +Subject: [PATCH 3/4] ram: rk3399: Add support for multiple DDR types + +Move rockchip,sdram-params to named subnode to include +multiple sdram parameters, and then read the parameters +(by subnode name, first subnode or current node) before +rk3399_dmc_init(). + +Signed-off-by: hmz007 +--- + arch/arm/dts/rk3399-sdram-ddr3-1333.dtsi | 6 ++- + arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi | 5 +- + arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi | 6 ++- + .../arm/dts/rk3399-sdram-lpddr3-2GB-1600.dtsi | 3 ++ + .../arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi | 3 ++ + .../rk3399-sdram-lpddr3-samsung-4GB-1866.dtsi | 3 ++ + arch/arm/dts/rk3399-sdram-lpddr4-100.dtsi | 3 ++ + drivers/ram/rockchip/sdram_rk3399.c | 49 +++++++++++++++---- + 8 files changed, 64 insertions(+), 14 deletions(-) + +diff --git a/arch/arm/dts/rk3399-sdram-ddr3-1333.dtsi b/arch/arm/dts/rk3399-sdram-ddr3-1333.dtsi +index 7fae249536..dad5b7fbd4 100644 +--- a/arch/arm/dts/rk3399-sdram-ddr3-1333.dtsi ++++ b/arch/arm/dts/rk3399-sdram-ddr3-1333.dtsi +@@ -4,7 +4,9 @@ + */ + + &dmc { +- rockchip,sdram-params = < ++ ddr3-1333 { ++ u-boot,dm-pre-reloc; ++ rockchip,sdram-params = < + 0x1 + 0xa + 0x3 +@@ -1536,5 +1538,5 @@ + 0x01010000 + 0x00000000 + >; ++ }; + }; +- +diff --git a/arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi b/arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi +index 23c7c34a9a..238f667a76 100644 +--- a/arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi ++++ b/arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi +@@ -4,7 +4,9 @@ + */ + + &dmc { +- rockchip,sdram-params = < ++ ddr3-1600 { ++ u-boot,dm-pre-reloc; ++ rockchip,sdram-params = < + 0x1 + 0xa + 0x3 +@@ -1536,4 +1538,5 @@ + 0x01010000 + 0x00000000 + >; ++ }; + }; +diff --git a/arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi b/arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi +index ea029ca90a..7f6b95fe42 100644 +--- a/arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi ++++ b/arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi +@@ -4,7 +4,9 @@ + */ + + &dmc { +- rockchip,sdram-params = < ++ ddr3-1866 { ++ u-boot,dm-pre-reloc; ++ rockchip,sdram-params = < + 0x1 + 0xa + 0x3 +@@ -1536,5 +1538,5 @@ + 0x01010000 + 0x00000000 + >; ++ }; + }; +- +diff --git a/arch/arm/dts/rk3399-sdram-lpddr3-2GB-1600.dtsi b/arch/arm/dts/rk3399-sdram-lpddr3-2GB-1600.dtsi +index 7296dbb80e..a83564794e 100644 +--- a/arch/arm/dts/rk3399-sdram-lpddr3-2GB-1600.dtsi ++++ b/arch/arm/dts/rk3399-sdram-lpddr3-2GB-1600.dtsi +@@ -5,6 +5,8 @@ + */ + + &dmc { ++ lpddr3-2GB-1600 { ++ u-boot,dm-pre-reloc; + rockchip,sdram-params = < + 0x1 + 0xa +@@ -1537,4 +1539,5 @@ + 0x01010000 + 0x00000000 + >; ++ }; + }; +diff --git a/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi b/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi +index bf429c21e4..537936c6fb 100644 +--- a/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi ++++ b/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi +@@ -4,6 +4,8 @@ + */ + + &dmc { ++ lpddr3-4GB-1600 { ++ u-boot,dm-pre-reloc; + rockchip,sdram-params = < + 0x2 + 0xa +@@ -1536,4 +1538,5 @@ + 0x01010000 + 0x00000000 + >; ++ }; + }; +diff --git a/arch/arm/dts/rk3399-sdram-lpddr3-samsung-4GB-1866.dtsi b/arch/arm/dts/rk3399-sdram-lpddr3-samsung-4GB-1866.dtsi +index 96f459fd0b..a0acdb5add 100644 +--- a/arch/arm/dts/rk3399-sdram-lpddr3-samsung-4GB-1866.dtsi ++++ b/arch/arm/dts/rk3399-sdram-lpddr3-samsung-4GB-1866.dtsi +@@ -4,6 +4,8 @@ + */ + + &dmc { ++ lpddr3-samsung-4GB-1866 { ++ u-boot,dm-pre-reloc; + rockchip,sdram-params = < + 0x2 + 0xa +@@ -1543,4 +1545,5 @@ + 0x01010000 /* DENALI_PHY_957_DATA */ + 0x00000000 /* DENALI_PHY_958_DATA */ + >; ++ }; + }; +diff --git a/arch/arm/dts/rk3399-sdram-lpddr4-100.dtsi b/arch/arm/dts/rk3399-sdram-lpddr4-100.dtsi +index f0c478d189..21d212236f 100644 +--- a/arch/arm/dts/rk3399-sdram-lpddr4-100.dtsi ++++ b/arch/arm/dts/rk3399-sdram-lpddr4-100.dtsi +@@ -6,6 +6,8 @@ + */ + + &dmc { ++ lpddr4-100 { ++ u-boot,dm-pre-reloc; + rockchip,sdram-params = < + 0x2 + 0xa +@@ -1538,4 +1540,5 @@ + 0x01010000 + 0x00000000 + >; ++ }; + }; +diff --git a/drivers/ram/rockchip/sdram_rk3399.c b/drivers/ram/rockchip/sdram_rk3399.c +index 530c8a2f40..db30105989 100644 +--- a/drivers/ram/rockchip/sdram_rk3399.c ++++ b/drivers/ram/rockchip/sdram_rk3399.c +@@ -1625,7 +1625,6 @@ static void set_ddr_stride(struct rk3399_pmusgrf_regs *pmusgrf, u32 stride) + rk_clrsetreg(&pmusgrf->soc_con4, 0x1f << 10, stride << 10); + } + +-#if !defined(CONFIG_RAM_RK3399_LPDDR4) + static int data_training_first(struct dram_info *dram, u32 channel, u8 rank, + struct rk3399_sdram_params *params) + { +@@ -1715,8 +1714,8 @@ void modify_param(const struct chan_info *chan, + clrsetbits_le32(&denali_pi_params[76], 0x1 << 24, 0x1 << 24); + clrsetbits_le32(&denali_pi_params[77], 0x1, 0x1); + } +-#else + ++#if defined(CONFIG_RAM_RK3399_LPDDR4) + struct rk3399_sdram_params dfs_cfgs_lpddr4[] = { + #include "sdram-rk3399-lpddr4-400.inc" + #include "sdram-rk3399-lpddr4-800.inc" +@@ -3011,20 +3010,40 @@ static int sdram_init(struct dram_info *dram, + return 0; + } + ++__weak const char *rk3399_get_ddrtype(void) ++{ ++ return NULL; ++} ++ + static int rk3399_dmc_of_to_plat(struct udevice *dev) + { + #if !CONFIG_IS_ENABLED(OF_PLATDATA) + struct rockchip_dmc_plat *plat = dev_get_plat(dev); ++ ofnode node = { .np = NULL }; ++ const char *name; + int ret; + +- ret = dev_read_u32_array(dev, "rockchip,sdram-params", +- (u32 *)&plat->sdram_params, +- sizeof(plat->sdram_params) / sizeof(u32)); ++ name = rk3399_get_ddrtype(); ++ if (name) ++ node = dev_read_subnode(dev, name); ++ if (!ofnode_valid(node)) { ++ debug("Failed to read subnode %s\n", name); ++ node = dev_read_first_subnode(dev); ++ } ++ ++ /* fallback to current node */ ++ if (!ofnode_valid(node)) ++ node = dev_ofnode(dev); ++ ++ ret = ofnode_read_u32_array(node, "rockchip,sdram-params", ++ (u32 *)&plat->sdram_params, ++ sizeof(plat->sdram_params) / sizeof(u32)); + if (ret) { + printf("%s: Cannot read rockchip,sdram-params %d\n", + __func__, ret); + return ret; + } ++ + ret = regmap_init_mem(dev_ofnode(dev), &plat->map); + if (ret) + printf("%s: regmap failed %d\n", __func__, ret); +@@ -3051,18 +3070,20 @@ static int conv_of_platdata(struct udevice *dev) + #endif + + static const struct sdram_rk3399_ops rk3399_ops = { +-#if !defined(CONFIG_RAM_RK3399_LPDDR4) + .data_training_first = data_training_first, + .set_rate_index = switch_to_phy_index1, + .modify_param = modify_param, + .get_phy_index_params = get_phy_index_params, +-#else ++}; ++ ++#if defined(CONFIG_RAM_RK3399_LPDDR4) ++static const struct sdram_rk3399_ops lpddr4_ops = { + .data_training_first = lpddr4_mr_detect, + .set_rate_index = lpddr4_set_rate, + .modify_param = lpddr4_modify_param, + .get_phy_index_params = lpddr4_get_phy_index_params, +-#endif + }; ++#endif + + static int rk3399_dmc_init(struct udevice *dev) + { +@@ -3081,7 +3102,17 @@ static int rk3399_dmc_init(struct udevice *dev) + return ret; + #endif + +- priv->ops = &rk3399_ops; ++ if (params->base.dramtype == LPDDR4) { ++#if defined(CONFIG_RAM_RK3399_LPDDR4) ++ priv->ops = &lpddr4_ops; ++#else ++ printf("LPDDR4 support is disable\n"); ++ return -EINVAL; ++#endif ++ } else { ++ priv->ops = &rk3399_ops; ++ } ++ + priv->cic = syscon_get_first_range(ROCKCHIP_SYSCON_CIC); + priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); + priv->pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU); +-- +2.25.1 + diff --git a/root/package/boot/uboot-rockchip/patches/204-board-nanopi4-unify-1GB-4GB-variants-of-R4S.patch b/root/package/boot/uboot-rockchip/patches/204-board-nanopi4-unify-1GB-4GB-variants-of-R4S.patch new file mode 100644 index 00000000..07ce2410 --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/204-board-nanopi4-unify-1GB-4GB-variants-of-R4S.patch @@ -0,0 +1,89 @@ +From 317331b3d7ddcf2a5e7b5a9002ac559627000032 Mon Sep 17 00:00:00 2001 +From: hmz007 +Date: Sat, 19 Dec 2020 20:39:29 +0800 +Subject: [PATCH 4/4] board: nanopi4: unify 1GB/4GB variants of R4S + +Signed-off-by: hmz007 +--- + .../arm/dts/rk3399-nanopi-r4s-4gb-u-boot.dtsi | 8 -- + arch/arm/dts/rk3399-nanopi-r4s-4gb.dts | 114 ------------------ + arch/arm/dts/rk3399-nanopi-r4s-u-boot.dtsi | 2 + + board/friendlyarm/nanopi4/hwrev.c | 36 ++++++ + configs/nanopi-r4s-4gb-rk3399_defconfig | 63 ---------- + configs/nanopi-r4s-rk3399_defconfig | 1 + + 6 files changed, 39 insertions(+), 185 deletions(-) + delete mode 100644 arch/arm/dts/rk3399-nanopi-r4s-4gb-u-boot.dtsi + delete mode 100644 arch/arm/dts/rk3399-nanopi-r4s-4gb.dts + delete mode 100644 configs/nanopi-r4s-4gb-rk3399_defconfig + +diff --git a/arch/arm/dts/rk3399-nanopi-r4s-u-boot.dtsi b/arch/arm/dts/rk3399-nanopi-r4s-u-boot.dtsi +index eb0aca4758..9369a7022a 100644 +--- a/arch/arm/dts/rk3399-nanopi-r4s-u-boot.dtsi ++++ b/arch/arm/dts/rk3399-nanopi-r4s-u-boot.dtsi +@@ -4,4 +4,6 @@ + */ + + #include "rk3399-nanopi4-u-boot.dtsi" + #include "rk3399-sdram-lpddr4-100.dtsi" ++#include "rk3399-sdram-lpddr3-samsung-4GB-1866.dtsi" ++#include "rk3399-sdram-ddr3-1866.dtsi" +diff --git a/board/friendlyarm/nanopi4/hwrev.c b/board/friendlyarm/nanopi4/hwrev.c +index 9199a927ee..812fcef9c7 100644 +--- a/board/friendlyarm/nanopi4/hwrev.c ++++ b/board/friendlyarm/nanopi4/hwrev.c +@@ -101,9 +101,13 @@ static uint32_t get_adc_index(int chn) + * Group A: + * 0x04 - NanoPi NEO4 + * 0x06 - SOC-RK3399 ++ * 0x07 - SOC-RK3399 V2 ++ * 0x09 - NanoPi R4S 1GB ++ * 0x0A - NanoPi R4S 4GB + * + * Group B: + * 0x21 - NanoPi M4 Ver2.0 ++ * 0x22 - NanoPi M4B + */ + static int pcb_rev = -1; + +@@ -141,6 +145,38 @@ void bd_hwrev_init(void) + } + } + ++#ifdef CONFIG_SPL_BUILD ++static struct board_ddrtype { ++ int rev; ++ const char *type; ++} ddrtypes[] = { ++ { 0x00, "lpddr3-samsung-4GB-1866" }, ++ { 0x01, "lpddr3-samsung-4GB-1866" }, ++ { 0x04, "ddr3-1866" }, ++ { 0x06, "ddr3-1866" }, ++ { 0x07, "lpddr4-100" }, ++ { 0x09, "ddr3-1866" }, ++ { 0x0a, "lpddr4-100" }, ++ { 0x21, "lpddr4-100" }, ++ { 0x22, "ddr3-1866" }, ++}; ++ ++const char *rk3399_get_ddrtype(void) { ++ int i; ++ ++ bd_hwrev_init(); ++ printf("Board: rev%02x\n", pcb_rev); ++ ++ for (i = 0; i < ARRAY_SIZE(ddrtypes); i++) { ++ if (ddrtypes[i].rev == pcb_rev) ++ return ddrtypes[i].type; ++ } ++ ++ /* fallback to first subnode (ie, first included dtsi) */ ++ return NULL; ++} ++#endif ++ + /* To override __weak symbols */ + u32 get_board_rev(void) + { +-- +2.25.1 + diff --git a/root/package/boot/uboot-rockchip/src/of-platdata/nanopi-r2s-rk3328/dt-decl.h b/root/package/boot/uboot-rockchip/src/of-platdata/nanopi-r2s-rk3328/dt-decl.h new file mode 100644 index 00000000..0919e4ed --- /dev/null +++ b/root/package/boot/uboot-rockchip/src/of-platdata/nanopi-r2s-rk3328/dt-decl.h @@ -0,0 +1,23 @@ +/* + * DO NOT MODIFY + * + * Declares externs for all device/uclass instances. + * This was generated by dtoc from a .dtb (device tree binary) file. + */ + +#include +#include + +/* driver declarations - these allow DM_DRIVER_GET() to be used */ +extern U_BOOT_DRIVER(rockchip_rk3328_cru); +extern U_BOOT_DRIVER(rockchip_rk3328_dmc); +extern U_BOOT_DRIVER(rockchip_rk3288_dw_mshc); +extern U_BOOT_DRIVER(ns16550_serial); +extern U_BOOT_DRIVER(rockchip_rk3328_grf); + +/* uclass driver declarations - needed for DM_UCLASS_DRIVER_REF() */ +extern UCLASS_DRIVER(clk); +extern UCLASS_DRIVER(mmc); +extern UCLASS_DRIVER(ram); +extern UCLASS_DRIVER(serial); +extern UCLASS_DRIVER(syscon); diff --git a/root/package/boot/uboot-rockchip/src/of-platdata/nanopi-r2s-rk3328/dt-plat.c b/root/package/boot/uboot-rockchip/src/of-platdata/nanopi-r2s-rk3328/dt-plat.c index 1818461e..e5b330c9 100644 --- a/root/package/boot/uboot-rockchip/src/of-platdata/nanopi-r2s-rk3328/dt-plat.c +++ b/root/package/boot/uboot-rockchip/src/of-platdata/nanopi-r2s-rk3328/dt-plat.c @@ -12,19 +12,38 @@ #include #include -/* Node /clock-controller@ff440000 index 0 */ +/* + * driver_info declarations, ordered by 'struct driver_info' linker_list idx: + * + * idx driver_info driver + * --- -------------------- -------------------- + * 0: clock_controller_at_ff440000 rockchip_rk3328_cru + * 1: dmc rockchip_rk3328_dmc + * 2: mmc_at_ff500000 rockchip_rk3288_dw_mshc + * 3: serial_at_ff130000 ns16550_serial + * 4: syscon_at_ff100000 rockchip_rk3328_grf + * --- -------------------- -------------------- + */ + +/* + * Node /clock-controller@ff440000 index 0 + * driver rockchip_rk3328_cru parent None + */ static struct dtd_rockchip_rk3328_cru dtv_clock_controller_at_ff440000 = { .reg = {0xff440000, 0x1000}, .rockchip_grf = 0x3a, }; U_BOOT_DRVINFO(clock_controller_at_ff440000) = { .name = "rockchip_rk3328_cru", - .plat = &dtv_clock_controller_at_ff440000, + .plat = &dtv_clock_controller_at_ff440000, .plat_size = sizeof(dtv_clock_controller_at_ff440000), .parent_idx = -1, }; -/* Node /dmc index 1 */ +/* + * Node /dmc index 1 + * driver rockchip_rk3328_dmc parent None + */ static struct dtd_rockchip_rk3328_dmc dtv_dmc = { .reg = {0xff400000, 0x1000, 0xff780000, 0x3000, 0xff100000, 0x1000, 0xff440000, 0x1000, 0xff720000, 0x1000, 0xff798000, 0x1000}, @@ -56,12 +75,15 @@ static struct dtd_rockchip_rk3328_dmc dtv_dmc = { }; U_BOOT_DRVINFO(dmc) = { .name = "rockchip_rk3328_dmc", - .plat = &dtv_dmc, + .plat = &dtv_dmc, .plat_size = sizeof(dtv_dmc), .parent_idx = -1, }; -/* Node /mmc@ff500000 index 2 */ +/* + * Node /mmc@ff500000 index 2 + * driver rockchip_rk3288_dw_mshc parent None + */ static struct dtd_rockchip_rk3288_dw_mshc dtv_mmc_at_ff500000 = { .bus_width = 0x4, .cap_sd_highspeed = true, @@ -87,12 +109,15 @@ static struct dtd_rockchip_rk3288_dw_mshc dtv_mmc_at_ff500000 = { }; U_BOOT_DRVINFO(mmc_at_ff500000) = { .name = "rockchip_rk3288_dw_mshc", - .plat = &dtv_mmc_at_ff500000, + .plat = &dtv_mmc_at_ff500000, .plat_size = sizeof(dtv_mmc_at_ff500000), .parent_idx = -1, }; -/* Node /serial@ff130000 index 3 */ +/* + * Node /serial@ff130000 index 3 + * driver ns16550_serial parent None + */ static struct dtd_ns16550_serial dtv_serial_at_ff130000 = { .clock_frequency = 0x16e3600, .clocks = { @@ -109,18 +134,21 @@ static struct dtd_ns16550_serial dtv_serial_at_ff130000 = { }; U_BOOT_DRVINFO(serial_at_ff130000) = { .name = "ns16550_serial", - .plat = &dtv_serial_at_ff130000, + .plat = &dtv_serial_at_ff130000, .plat_size = sizeof(dtv_serial_at_ff130000), .parent_idx = -1, }; -/* Node /syscon@ff100000 index 4 */ +/* + * Node /syscon@ff100000 index 4 + * driver rockchip_rk3328_grf parent None + */ static struct dtd_rockchip_rk3328_grf dtv_syscon_at_ff100000 = { .reg = {0xff100000, 0x1000}, }; U_BOOT_DRVINFO(syscon_at_ff100000) = { .name = "rockchip_rk3328_grf", - .plat = &dtv_syscon_at_ff100000, + .plat = &dtv_syscon_at_ff100000, .plat_size = sizeof(dtv_syscon_at_ff100000), .parent_idx = -1, }; From 2f8fb61e10e4865dcc55abc99175ebdef1f1d5f6 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 26 Oct 2022 20:08:30 +0200 Subject: [PATCH 030/102] Add latest patch to MPTCP 5.4 --- .../generic/hack-5.4/690-mptcp_v0.96.patch | 157 ++++++++++++++++++ 1 file changed, 157 insertions(+) diff --git a/root/target/linux/generic/hack-5.4/690-mptcp_v0.96.patch b/root/target/linux/generic/hack-5.4/690-mptcp_v0.96.patch index ec8783d1..537b5e51 100644 --- a/root/target/linux/generic/hack-5.4/690-mptcp_v0.96.patch +++ b/root/target/linux/generic/hack-5.4/690-mptcp_v0.96.patch @@ -24762,3 +24762,160 @@ index cb0631098f91..b9de598828e9 100644 BPF_TCP_MAX_STATES /* Leave at the end! */ }; +diff --git a/net/mptcp/mptcp_output.c b/net/mptcp/mptcp_output.c +index c26e14a702fd..00d2e18aaf96 100644 +--- a/net/mptcp/mptcp_output.c ++++ b/net/mptcp/mptcp_output.c +@@ -1194,7 +1194,9 @@ void mptcp_established_options(struct sock *sk, struct sk_buff *skb, + } + + if (unlikely(mpcb->addr_signal) && mpcb->pm_ops->addr_signal && +- mpcb->mptcp_ver >= MPTCP_VERSION_1 && skb && !mptcp_is_data_seq(skb)) { ++ mpcb->mptcp_ver >= MPTCP_VERSION_1 && ++ skb && !mptcp_is_data_seq(skb) && ++ tp->mptcp->fully_established) { + mpcb->pm_ops->addr_signal(sk, size, opts, skb); + + if (opts->add_addr_v6) +diff --git a/net/mptcp/mptcp_fullmesh.c b/net/mptcp/mptcp_fullmesh.c +index ef2c15cbbeaa..4b97986de824 100644 +--- a/net/mptcp/mptcp_fullmesh.c ++++ b/net/mptcp/mptcp_fullmesh.c +@@ -1603,11 +1603,13 @@ static void full_mesh_addr_signal(struct sock *sk, unsigned *size, + opts->add_addr_v4 = 1; + if (mpcb->mptcp_ver >= MPTCP_VERSION_1) { + u8 mptcp_hash_mac[SHA256_DIGEST_SIZE]; ++ u16 port = 0; + + mptcp_hmac(mpcb->mptcp_ver, (u8 *)&mpcb->mptcp_loc_key, +- (u8 *)&mpcb->mptcp_rem_key, mptcp_hash_mac, 2, ++ (u8 *)&mpcb->mptcp_rem_key, mptcp_hash_mac, 3, + 1, (u8 *)&mptcp_local->locaddr4[ind].loc4_id, +- 4, (u8 *)&opts->add_addr4.addr.s_addr); ++ 4, (u8 *)&opts->add_addr4.addr.s_addr, ++ 2, (u8 *)&port); + opts->add_addr4.trunc_mac = *(u64 *)&mptcp_hash_mac[SHA256_DIGEST_SIZE - sizeof(u64)]; + } + +@@ -1644,11 +1646,13 @@ static void full_mesh_addr_signal(struct sock *sk, unsigned *size, + opts->add_addr_v6 = 1; + if (mpcb->mptcp_ver >= MPTCP_VERSION_1) { + u8 mptcp_hash_mac[SHA256_DIGEST_SIZE]; ++ u16 port = 0; + + mptcp_hmac(mpcb->mptcp_ver, (u8 *)&mpcb->mptcp_loc_key, +- (u8 *)&mpcb->mptcp_rem_key, mptcp_hash_mac, 2, ++ (u8 *)&mpcb->mptcp_rem_key, mptcp_hash_mac, 3, + 1, (u8 *)&mptcp_local->locaddr6[ind].loc6_id, +- 16, (u8 *)&opts->add_addr6.addr.s6_addr); ++ 16, (u8 *)opts->add_addr6.addr.s6_addr, ++ 2, (u8 *)&port); + opts->add_addr6.trunc_mac = *(u64 *)&mptcp_hash_mac[SHA256_DIGEST_SIZE - sizeof(u64)]; + } + +diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c +index d54127de9c3a..0c4db7d5177f 100644 +--- a/net/ipv4/tcp_minisocks.c ++++ b/net/ipv4/tcp_minisocks.c +@@ -847,6 +847,9 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, + return mptcp_check_req_child(sk, child, req, skb, &mopt); + } + ++ /* Fallback to regular TCP */ ++ tcp_sk(child)->mpc = 0; ++ + if (meta_locked) + bh_unlock_sock(sk); + +diff --git a/net/mptcp/mptcp_input.c b/net/mptcp/mptcp_input.c +index 41a511b3ef63..d5c1e8cec703 100644 +--- a/net/mptcp/mptcp_input.c ++++ b/net/mptcp/mptcp_input.c +@@ -1708,7 +1708,7 @@ bool mptcp_handle_ack_in_infinite(struct sock *sk, const struct sk_buff *skb, + * this becomes our data_ack. + */ + if (after(meta_tp->snd_una, tp->mptcp->last_end_data_seq - (tp->snd_nxt - tp->snd_una))) { +- /* Remmeber that meta snd_una is ahead of the game */ ++ /* Remember that meta snd_una is ahead of the game */ + mpcb->infinite_send_una_ahead = 1; + tp->mptcp->rx_opt.data_ack = meta_tp->snd_una; + } else { +diff --git a/net/mptcp/mptcp_ctrl.c b/net/mptcp/mptcp_ctrl.c +index dfeff4e15882..f8b17ac89152 100644 +--- a/net/mptcp/mptcp_ctrl.c ++++ b/net/mptcp/mptcp_ctrl.c +@@ -2533,7 +2533,10 @@ static int __mptcp_check_req_master(struct sock *child, + } + + /* mopt can be NULL when coming from FAST-OPEN */ +- if (mopt && mopt->saw_mpc && mtreq->mptcp_ver == MPTCP_VERSION_1) { ++ if (mopt && mtreq->mptcp_ver == MPTCP_VERSION_1) { ++ if (!mopt->saw_mpc) ++ return 1; ++ + mtreq->mptcp_rem_key = mopt->mptcp_sender_key; + mtreq->rem_key_set = 1; + } +diff --git a/net/mptcp/mptcp_ctrl.c b/net/mptcp/mptcp_ctrl.c +index f8b17ac89152..76eae7ec7d5c 100644 +--- a/net/mptcp/mptcp_ctrl.c ++++ b/net/mptcp/mptcp_ctrl.c +@@ -2528,7 +2528,6 @@ static int __mptcp_check_req_master(struct sock *child, + * must still remove it. + */ + MPTCP_INC_STATS(sock_net(meta_sk), MPTCP_MIB_MPCAPABLEPASSIVEFALLBACK); +- mptcp_reqsk_remove_tk(req); + return 1; + } + +@@ -2565,11 +2564,6 @@ static int __mptcp_check_req_master(struct sock *child, + mpcb->dss_csum = mtreq->dss_csum; + mpcb->server_side = 1; + +- /* Needs to be done here additionally, because when accepting a +- * new connection we pass by __reqsk_free and not reqsk_free. +- */ +- mptcp_reqsk_remove_tk(req); +- + return 0; + } + +diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c +index 1ab36a72d93e..181018192f5d 100644 +--- a/net/ipv4/inet_connection_sock.c ++++ b/net/ipv4/inet_connection_sock.c +@@ -934,13 +934,15 @@ struct sock *inet_csk_reqsk_queue_add(struct sock *sk, + + spin_lock(&queue->rskq_lock); + if (unlikely(sk->sk_state != TCP_LISTEN)) { +- struct tcp_sock *tp = tcp_sk(sk); ++ if (sk->sk_protocol == IPPROTO_TCP) { ++ struct tcp_sock *child_tp = tcp_sk(child); + +- /* in case of mptcp, two locks may been taken, one +- * on the meta, the other on master_sk +- */ +- if (mptcp(tp) && tp->mpcb && tp->mpcb->master_sk) +- bh_unlock_sock(tp->mpcb->master_sk); ++ /* in case of mptcp, two locks may been taken, one ++ * on the meta, the other on master_sk ++ */ ++ if (mptcp(child_tp) && child_tp->mpcb && child_tp->mpcb->master_sk) ++ bh_unlock_sock(child_tp->mpcb->master_sk); ++ } + + inet_child_forget(sk, req, child); + child = NULL; +diff --git a/net/mptcp/mptcp_ctrl.c b/net/mptcp/mptcp_ctrl.c +index 76eae7ec7d5c..8049dea0ded1 100644 +--- a/net/mptcp/mptcp_ctrl.c ++++ b/net/mptcp/mptcp_ctrl.c +@@ -2417,6 +2417,8 @@ void mptcp_disconnect(struct sock *meta_sk) + mptcp_for_each_sub_safe(meta_tp->mpcb, mptcp, tmp) { + struct sock *subsk = mptcp_to_sock(mptcp); + ++ BUG_ON(spin_is_locked(&subsk->sk_lock.slock)); ++ + tcp_sk(subsk)->tcp_disconnect = 1; + + meta_sk->sk_prot->disconnect(subsk, O_NONBLOCK); From 74651444b23bfb98fb2e2f756ab43f7957c52bb8 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Thu, 27 Oct 2022 23:40:42 +0800 Subject: [PATCH 031/102] Update build.sh --- build.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build.sh b/build.sh index 2f3883a4..05db956d 100644 --- a/build.sh +++ b/build.sh @@ -701,6 +701,7 @@ fi scripts/feeds install -a cp .config.keep .config scripts/feeds install kmod-macremapper +chmod -R 777 feeds/openmptcprouter echo "Done" if [ ! -f "../../../$OMR_TARGET_CONFIG" ]; then @@ -711,4 +712,4 @@ fi echo "Building $OMR_DIST for the target $OMR_TARGET with kernel ${OMR_KERNEL}" make defconfig make IGNORE_ERRORS=m "$@" -echo "Done" +echo "Done" \ No newline at end of file From 22a38985a03cd2eb7de676a61abf7b64b68c587c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 3 Nov 2022 12:48:30 +0100 Subject: [PATCH 032/102] Update OpenWRT --- build.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/build.sh b/build.sh index cd83c9bb..3b1c324d 100755 --- a/build.sh +++ b/build.sh @@ -94,13 +94,13 @@ fi if [ "$OMR_OPENWRT" = "default" ]; then if [ "$OMR_KERNEL" = "5.4" ]; then # Use OpenWrt 21.02 for 5.4 kernel - _get_repo "$OMR_TARGET/${OMR_KERNEL}/source" https://github.com/openwrt/openwrt "fc86176363149493810dc0b424583dd120e7f4c7" - _get_repo feeds/${OMR_KERNEL}/packages https://github.com/openwrt/packages "47d63847e1eda46633eb3d369e221e8845a82f7c" - _get_repo feeds/${OMR_KERNEL}/luci https://github.com/openwrt/luci "e01e38cf822b77ee9735da1d519f7eb1c48cce19" + _get_repo "$OMR_TARGET/${OMR_KERNEL}/source" https://github.com/openwrt/openwrt "ab26cddca2e45911a980a60afaee889bd1353a6e" + _get_repo feeds/${OMR_KERNEL}/packages https://github.com/openwrt/packages "6711badf079986f847da07747c95c0a74960b965" + _get_repo feeds/${OMR_KERNEL}/luci https://github.com/openwrt/luci "04257f6704c1b8707ee7a58ca4ec0f18a2133611" else - _get_repo "$OMR_TARGET/${OMR_KERNEL}/source" https://github.com/openwrt/openwrt "2ad949b11dbaa4c634868d55a4452d5a558776bd" - _get_repo feeds/${OMR_KERNEL}/packages https://github.com/openwrt/packages "891b87747a5100d5e8c489cea0882a0a0ce8f127" - _get_repo feeds/${OMR_KERNEL}/luci https://github.com/openwrt/luci "0c5d7dd8d7b04ab6979fb7b6ef953a9a92e37d7a" + _get_repo "$OMR_TARGET/${OMR_KERNEL}/source" https://github.com/openwrt/openwrt "c3322cf04a1b9ee826dcc56944750b6bbcb716ef" + _get_repo feeds/${OMR_KERNEL}/packages https://github.com/openwrt/packages "7960285c3301532e8c464fb06260ce14ae4357a0" + _get_repo feeds/${OMR_KERNEL}/luci https://github.com/openwrt/luci "9ea26a75ed44cde3def5d061a867fa513d365c27" fi elif [ "$OMR_OPENWRT" = "master" ]; then _get_repo "$OMR_TARGET/${OMR_KERNEL}/source" https://github.com/openwrt/openwrt "master" From 5df67914445b181bc9933e2aa39d27b976fe5299 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 9 Nov 2022 20:44:04 +0100 Subject: [PATCH 033/102] Update kernel and fix RUTX for 5.15 kernel --- build.sh | 10 +++- root/include/kernel-version.mk | 3 +- .../hack-5.15/695-Quectel-RM520N.patch | 37 -------------- .../780-usb-net-MeigLink_modem_support.patch | 45 ----------------- root/target/linux/ipq40xx/config-5.15 | 1 + ...7-net-phy-Add-Qualcom-QCA807x-driver.patch | 50 ------------------- ...add-qualcomm-essedma-ethernet-driver.patch | 37 -------------- ...ts-ipq4019-add-ethernet-essedma-node.patch | 3 +- 8 files changed, 14 insertions(+), 172 deletions(-) delete mode 100644 root/target/linux/generic/hack-5.15/695-Quectel-RM520N.patch delete mode 100644 root/target/linux/generic/hack-5.15/780-usb-net-MeigLink_modem_support.patch delete mode 100644 root/target/linux/ipq40xx/patches-5.15/707-net-phy-Add-Qualcom-QCA807x-driver.patch delete mode 100644 root/target/linux/ipq40xx/patches-5.15/710-net-add-qualcomm-essedma-ethernet-driver.patch diff --git a/build.sh b/build.sh index 3b1c324d..cb80f522 100755 --- a/build.sh +++ b/build.sh @@ -522,7 +522,15 @@ fi #if [ -f target/linux/generic/pending-5.15/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch ]; then # rm -f target/linux/generic/pending-5.15/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch #fi - +if [ -f target/linux/bcm27xx/patches-5.15/950-0448-drm-vc4-Fix-definition-of-PAL-M-mode.patch ]; then + rm -f target/linux/bcm27xx/patches-5.15/950-0448-drm-vc4-Fix-definition-of-PAL-M-mode.patch +fi +#if [ -f target/linux/ipq40xx/patches-5.15/707-dt-bindings-net-add-QCA807x-PHY.patch ]; then +# rm -f target/linux/ipq40xx/patches-5.15/707-dt-bindings-net-add-QCA807x-PHY.patch +#fi +#if [ -f target/linux/ipq40xx/patches-5.15/709-arm-dts-ipq4019-QCA807x-properties.patch ]; then +# rm -f target/linux/ipq40xx/patches-5.15/709-arm-dts-ipq4019-QCA807x-properties.patch +#fi if [ "$OMR_KERNEL" = "5.4" ]; then echo "Set to kernel 5.4 for rpi arch" diff --git a/root/include/kernel-version.mk b/root/include/kernel-version.mk index 93320244..d819822b 100644 --- a/root/include/kernel-version.mk +++ b/root/include/kernel-version.mk @@ -7,7 +7,7 @@ ifdef CONFIG_TESTING_KERNEL endif LINUX_VERSION-5.4 = .203 -LINUX_VERSION-5.15 = .63 +LINUX_VERSION-5.15 = .77 LINUX_KERNEL_HASH-5.4.132 = 8466adbfb3579e751ede683496df7bb20f258b5f882250f3dd82be63736d00ef LINUX_KERNEL_HASH-5.4.182 = b2f1201f64f010e9e3c85d6f303a559a7944a80a0244a86b8f5035bd23f1f40d @@ -21,6 +21,7 @@ LINUX_KERNEL_HASH-5.15.29 = 5905e684602c47ae95746d4003cb834335e5451aca4ac7c3013f LINUX_KERNEL_HASH-5.15.36 = 36345db17a937c197c72ca9c7f34c262b3a12f927c237ff7770193014e29c690 LINUX_KERNEL_HASH-5.15.50 = 554d507d37a23810fe8c83912761e4a4f73c40794bc685ff7ca98042fe1bd70f LINUX_KERNEL_HASH-5.15.63 = 6dd3cd1e5a629d0002bc6c6ec7e8ea96710104f38664122dd56c83dfd4eb7341 +LINUX_KERNEL_HASH-5.15.77 = 142f841f33796a84c62fae2f2b96d2120bd8bbf9e0aac4ce157692cdb0afe9f9 remove_uri_prefix=$(subst git://,,$(subst http://,,$(subst https://,,$(1)))) sanitize_uri=$(call qstrip,$(subst @,_,$(subst :,_,$(subst .,_,$(subst -,_,$(subst /,_,$(1))))))) diff --git a/root/target/linux/generic/hack-5.15/695-Quectel-RM520N.patch b/root/target/linux/generic/hack-5.15/695-Quectel-RM520N.patch deleted file mode 100644 index edfb8ee5..00000000 --- a/root/target/linux/generic/hack-5.15/695-Quectel-RM520N.patch +++ /dev/null @@ -1,37 +0,0 @@ -diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c -index a5e8374a8d71..e716395268fe 100644 ---- a/drivers/usb/serial/option.c -+++ b/drivers/usb/serial/option.c -@@ -256,5 +256,7 @@ static void option_instat_callback(struct urb *urb); - #define QUECTEL_PRODUCT_EM12 0x0512 - #define QUECTEL_PRODUCT_RM500Q 0x0800 -+#define QUECTEL_PRODUCT_RM520N 0x0801 -+#define QUECTEL_PRODUCT_RM500U_CN 0x0900 - #define QUECTEL_PRODUCT_EC200S_CN 0x6002 - #define QUECTEL_PRODUCT_EC200T 0x6026 - #define QUECTEL_PRODUCT_RM500K 0x7001 -@@ -1159,6 +1160,11 @@ static const struct usb_device_id option_ids[] = { - { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0, 0) }, - { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0xff, 0x10), - .driver_info = ZLP }, -+ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0xff, 0x30) }, -+ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0, 0x40) }, -+ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0, 0) }, -+ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500U_CN, 0xff, 0, 0), -+ .driver_info = ZLP }, - { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200S_CN, 0xff, 0, 0) }, - { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200T, 0xff, 0, 0) }, - { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500K, 0xff, 0x00, 0x00) }, -diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c -index 709e3c59e340..0cb187def5bc 100644 ---- a/drivers/net/usb/qmi_wwan.c -+++ b/drivers/net/usb/qmi_wwan.c -@@ -1087,6 +1087,8 @@ static const struct usb_device_id products[] = { - {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0512)}, /* Quectel EG12/EM12 */ - {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0620)}, /* Quectel EM160R-GL */ - {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0800)}, /* Quectel RM500Q-GL */ -+ {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0801)}, /* Quectel RM520N */ -+ {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0900)}, /* Quectel RM500U_CN */ - - /* 3. Combined interface devices matching on interface number */ - {QMI_FIXED_INTF(0x0408, 0xea42, 4)}, /* Yota / Megafon M100-1 */ diff --git a/root/target/linux/generic/hack-5.15/780-usb-net-MeigLink_modem_support.patch b/root/target/linux/generic/hack-5.15/780-usb-net-MeigLink_modem_support.patch deleted file mode 100644 index deaa3f26..00000000 --- a/root/target/linux/generic/hack-5.15/780-usb-net-MeigLink_modem_support.patch +++ /dev/null @@ -1,45 +0,0 @@ -From f81700b6bb2eda3756247bce472d8eaf6f466f61 Mon Sep 17 00:00:00 2001 -From: OpenWrt community -Date: Wed, 13 Jul 2022 13:49:26 +0200 -Subject: [PATCH] net/usb/qmi_wwan: add MeigLink modem support - ---- - drivers/net/usb/qmi_wwan.c | 1 + - drivers/usb/serial/option.c | 7 +++++++ - 2 files changed, 8 insertions(+) - ---- a/drivers/net/usb/qmi_wwan.c -+++ b/drivers/net/usb/qmi_wwan.c -@@ -1085,8 +1085,9 @@ static const struct usb_device_id produc - {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0512)}, /* Quectel EG12/EM12 */ - {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0620)}, /* Quectel EM160R-GL */ - {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0800)}, /* Quectel RM500Q-GL */ - {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0801)}, /* Quectel RM520N */ - {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0900)}, /* Quectel RM500U_CN */ -+ {QMI_MATCH_FF_FF_FF(0x05c6, 0xf601)}, /* MeigLink SLM750 */ - - /* 3. Combined interface devices matching on interface number */ - {QMI_FIXED_INTF(0x0408, 0xea42, 4)}, /* Yota / Megafon M100-1 */ ---- a/drivers/usb/serial/option.c -+++ b/drivers/usb/serial/option.c -@@ -243,6 +243,8 @@ static void option_instat_callback(struc - #define UBLOX_PRODUCT_R6XX 0x90fa - /* These Yuga products use Qualcomm's vendor ID */ - #define YUGA_PRODUCT_CLM920_NC5 0x9625 -+/* These MeigLink products use Qualcomm's vendor ID */ -+#define MEIGLINK_PRODUCT_SLM750 0xf601 - - #define QUECTEL_VENDOR_ID 0x2c7c - /* These Quectel products use Quectel's vendor ID */ -@@ -1133,6 +1135,11 @@ static const struct usb_device_id option - { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95, 0xff, 0, 0) }, - { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96), - .driver_info = RSVD(4) }, -+ /* Meiglink products using Qualcomm vendor ID */ -+ // Works OK. In case of some issues check macros that are used by Quectel Products -+ { USB_DEVICE_AND_INTERFACE_INFO(QUALCOMM_VENDOR_ID, MEIGLINK_PRODUCT_SLM750, 0xff, 0xff, 0xff), -+ .driver_info = NUMEP2 }, -+ { USB_DEVICE_AND_INTERFACE_INFO(QUALCOMM_VENDOR_ID, MEIGLINK_PRODUCT_SLM750, 0xff, 0, 0) }, - { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0xff, 0xff), - .driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | NUMEP2 }, - { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0, 0) }, diff --git a/root/target/linux/ipq40xx/config-5.15 b/root/target/linux/ipq40xx/config-5.15 index 7e151805..1a08e66f 100644 --- a/root/target/linux/ipq40xx/config-5.15 +++ b/root/target/linux/ipq40xx/config-5.15 @@ -382,6 +382,7 @@ CONFIG_QCOM_BAM_DMA=y # CONFIG_QCOM_GSBI is not set # CONFIG_QCOM_HFPLL is not set # CONFIG_QCOM_IOMMU is not set +CONFIG_QCOM_IPQ4019_ESS_EDMA=y # CONFIG_QCOM_LLCC is not set # CONFIG_QCOM_OCMEM is not set # CONFIG_QCOM_PDC is not set diff --git a/root/target/linux/ipq40xx/patches-5.15/707-net-phy-Add-Qualcom-QCA807x-driver.patch b/root/target/linux/ipq40xx/patches-5.15/707-net-phy-Add-Qualcom-QCA807x-driver.patch deleted file mode 100644 index ba441022..00000000 --- a/root/target/linux/ipq40xx/patches-5.15/707-net-phy-Add-Qualcom-QCA807x-driver.patch +++ /dev/null @@ -1,50 +0,0 @@ -From f825cdc8bfde7616a14e2163f16303a8973031d2 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Wed, 7 Oct 2020 17:38:48 +0200 -Subject: [PATCH] net: phy: Add Qualcom QCA807x driver - -This adds driver for the Qualcomm QCA8072 and QCA8075 PHY-s. - -They are 2 or 5 port IEEE 802.3 clause 22 compliant 10BASE-Te, 100BASE-TX and 1000BASE-T PHY-s. - -They feature 2 SerDes, one for PSGMII or QSGMII connection with MAC, while second one is SGMII for connection to MAC or fiber. - -Both models have a combo port that supports 1000BASE-X and 100BASE-FX fiber. - -Each PHY inside of QCA807x series has 4 digitally controlled output only pins that natively drive LED-s. -But some vendors used these to driver generic LED-s controlled by userspace, -so lets enable registering each PHY as GPIO controller and add driver for it. - -These are commonly used in Qualcomm IPQ40xx, IPQ60xx and IPQ807x boards. - -Signed-off-by: Robert Marko ---- - drivers/net/phy/Kconfig | 6 ++++++ - drivers/net/phy/Makefile | 1 + - 2 files changed, 7 insertions(+) - ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -320,6 +320,12 @@ config AT803X_PHY - Currently supports the AR8030, AR8031, AR8033, AR8035 and internal - QCA8337(Internal qca8k PHY) model - -+config QCA807X_PHY -+ tristate "Qualcomm QCA807X PHYs" -+ depends on OF_MDIO -+ help -+ Currently supports the QCA8072 and QCA8075 models. -+ - config QSEMI_PHY - tristate "Quality Semiconductor PHYs" - help ---- a/drivers/net/phy/Makefile -+++ b/drivers/net/phy/Makefile -@@ -86,6 +86,7 @@ obj-$(CONFIG_MICROSEMI_PHY) += mscc/ - obj-$(CONFIG_NATIONAL_PHY) += national.o - obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o - obj-$(CONFIG_QSEMI_PHY) += qsemi.o -+obj-$(CONFIG_QCA807X_PHY) += qca807x.o - obj-$(CONFIG_REALTEK_PHY) += realtek.o - obj-$(CONFIG_RENESAS_PHY) += uPD60620.o - obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o diff --git a/root/target/linux/ipq40xx/patches-5.15/710-net-add-qualcomm-essedma-ethernet-driver.patch b/root/target/linux/ipq40xx/patches-5.15/710-net-add-qualcomm-essedma-ethernet-driver.patch deleted file mode 100644 index 793ce721..00000000 --- a/root/target/linux/ipq40xx/patches-5.15/710-net-add-qualcomm-essedma-ethernet-driver.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 12e9319da1adacac92930c899c99f0e1970cac11 Mon Sep 17 00:00:00 2001 -From: Christian Lamparter -Date: Thu, 19 Jan 2017 02:01:31 +0100 -Subject: [PATCH 33/38] NET: add qualcomm essedma ethernet driver - -Signed-off-by: Christian Lamparter ---- - drivers/net/ethernet/qualcomm/Kconfig | 9 +++++++++ - drivers/net/ethernet/qualcomm/Makefile | 1 + - 2 files changed, 10 insertions(+) - ---- a/drivers/net/ethernet/qualcomm/Kconfig -+++ b/drivers/net/ethernet/qualcomm/Kconfig -@@ -62,4 +62,14 @@ config QCOM_EMAC - - source "drivers/net/ethernet/qualcomm/rmnet/Kconfig" - -+config ESSEDMA -+ tristate "Qualcomm Atheros ESS Edma support" -+ depends on OF_MDIO -+ help -+ This driver supports ethernet edma adapter. -+ Say Y to build this driver. -+ -+ To compile this driver as a module, choose M here. The module -+ will be called essedma.ko. -+ - endif # NET_VENDOR_QUALCOMM ---- a/drivers/net/ethernet/qualcomm/Makefile -+++ b/drivers/net/ethernet/qualcomm/Makefile -@@ -10,5 +10,6 @@ obj-$(CONFIG_QCA7000_UART) += qcauart.o - qcauart-objs := qca_uart.o - - obj-y += emac/ -+obj-$(CONFIG_ESSEDMA) += essedma/ - - obj-$(CONFIG_RMNET) += rmnet/ diff --git a/root/target/linux/ipq40xx/patches-5.15/711-dts-ipq4019-add-ethernet-essedma-node.patch b/root/target/linux/ipq40xx/patches-5.15/711-dts-ipq4019-add-ethernet-essedma-node.patch index 3567eb78..706d4ce8 100644 --- a/root/target/linux/ipq40xx/patches-5.15/711-dts-ipq4019-add-ethernet-essedma-node.patch +++ b/root/target/linux/ipq40xx/patches-5.15/711-dts-ipq4019-add-ethernet-essedma-node.patch @@ -16,10 +16,11 @@ Signed-off-by: Christian Lamparter --- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi -@@ -39,6 +39,8 @@ +@@ -39,7 +39,8 @@ spi1 = &blsp1_spi2; i2c0 = &blsp1_i2c3; i2c1 = &blsp1_i2c4; +- ethernet0 = &gmac; + ethernet0 = &gmac0; + ethernet1 = &gmac1; }; From 22b325a07da0dac2dc93f070e00a8495e2494d10 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 10 Nov 2022 08:47:16 +0100 Subject: [PATCH 034/102] Update igc drivers --- .../drivers/net/ethernet/intel/igc/Makefile | 11 + .../drivers/net/ethernet/intel/igc/igc.h | 566 ++ .../drivers/net/ethernet/intel/igc/igc_base.c | 421 ++ .../drivers/net/ethernet/intel/igc/igc_base.h | 90 + .../net/ethernet/intel/igc/igc_defines.h | 533 ++ .../drivers/net/ethernet/intel/igc/igc_diag.c | 186 + .../drivers/net/ethernet/intel/igc/igc_diag.h | 30 + .../drivers/net/ethernet/intel/igc/igc_dump.c | 318 + .../net/ethernet/intel/igc/igc_ethtool.c | 1945 ++++++ .../drivers/net/ethernet/intel/igc/igc_hw.h | 297 + .../drivers/net/ethernet/intel/igc/igc_i225.c | 650 ++ .../drivers/net/ethernet/intel/igc/igc_i225.h | 16 + .../drivers/net/ethernet/intel/igc/igc_mac.c | 881 +++ .../drivers/net/ethernet/intel/igc/igc_mac.h | 39 + .../drivers/net/ethernet/intel/igc/igc_main.c | 5682 +++++++++++++++++ .../drivers/net/ethernet/intel/igc/igc_nvm.c | 215 + .../drivers/net/ethernet/intel/igc/igc_nvm.h | 14 + .../drivers/net/ethernet/intel/igc/igc_phy.c | 787 +++ .../drivers/net/ethernet/intel/igc/igc_phy.h | 21 + .../drivers/net/ethernet/intel/igc/igc_ptp.c | 620 ++ .../drivers/net/ethernet/intel/igc/igc_regs.h | 269 + .../drivers/net/ethernet/intel/igc/igc_tsn.c | 157 + .../drivers/net/ethernet/intel/igc/igc_tsn.h | 9 + 23 files changed, 13757 insertions(+) create mode 100644 root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/Makefile create mode 100644 root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc.h create mode 100644 root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_base.c create mode 100644 root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_base.h create mode 100644 root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_defines.h create mode 100644 root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_diag.c create mode 100644 root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_diag.h create mode 100644 root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_dump.c create mode 100644 root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_ethtool.c create mode 100644 root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_hw.h create mode 100644 root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_i225.c create mode 100644 root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_i225.h create mode 100644 root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_mac.c create mode 100644 root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_mac.h create mode 100644 root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_main.c create mode 100644 root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_nvm.c create mode 100644 root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_nvm.h create mode 100644 root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_phy.c create mode 100644 root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_phy.h create mode 100644 root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_ptp.c create mode 100644 root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_regs.h create mode 100644 root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_tsn.c create mode 100644 root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_tsn.h diff --git a/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/Makefile b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/Makefile new file mode 100644 index 00000000..1c3051db --- /dev/null +++ b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/Makefile @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2018 Intel Corporation + +# +# Intel(R) I225-LM/I225-V 2.5G Ethernet Controller +# + +obj-$(CONFIG_IGC) += igc.o + +igc-objs := igc_main.o igc_mac.o igc_i225.o igc_base.o igc_nvm.o igc_phy.o \ +igc_diag.o igc_ethtool.o igc_ptp.o igc_dump.o igc_tsn.o diff --git a/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc.h b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc.h new file mode 100644 index 00000000..a97bf7a5 --- /dev/null +++ b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc.h @@ -0,0 +1,566 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2018 Intel Corporation */ + +#ifndef _IGC_H_ +#define _IGC_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "igc_hw.h" + +void igc_ethtool_set_ops(struct net_device *); + +/* Transmit and receive queues */ +#define IGC_MAX_RX_QUEUES 4 +#define IGC_MAX_TX_QUEUES 4 + +#define MAX_Q_VECTORS 8 +#define MAX_STD_JUMBO_FRAME_SIZE 9216 + +#define MAX_ETYPE_FILTER 8 +#define IGC_RETA_SIZE 128 + +enum igc_mac_filter_type { + IGC_MAC_FILTER_TYPE_DST = 0, + IGC_MAC_FILTER_TYPE_SRC +}; + +struct igc_tx_queue_stats { + u64 packets; + u64 bytes; + u64 restart_queue; + u64 restart_queue2; +}; + +struct igc_rx_queue_stats { + u64 packets; + u64 bytes; + u64 drops; + u64 csum_err; + u64 alloc_failed; +}; + +struct igc_rx_packet_stats { + u64 ipv4_packets; /* IPv4 headers processed */ + u64 ipv4e_packets; /* IPv4E headers with extensions processed */ + u64 ipv6_packets; /* IPv6 headers processed */ + u64 ipv6e_packets; /* IPv6E headers with extensions processed */ + u64 tcp_packets; /* TCP headers processed */ + u64 udp_packets; /* UDP headers processed */ + u64 sctp_packets; /* SCTP headers processed */ + u64 nfs_packets; /* NFS headers processe */ + u64 other_packets; +}; + +struct igc_ring_container { + struct igc_ring *ring; /* pointer to linked list of rings */ + unsigned int total_bytes; /* total bytes processed this int */ + unsigned int total_packets; /* total packets processed this int */ + u16 work_limit; /* total work allowed per interrupt */ + u8 count; /* total number of rings in vector */ + u8 itr; /* current ITR setting for ring */ +}; + +struct igc_ring { + struct igc_q_vector *q_vector; /* backlink to q_vector */ + struct net_device *netdev; /* back pointer to net_device */ + struct device *dev; /* device for dma mapping */ + union { /* array of buffer info structs */ + struct igc_tx_buffer *tx_buffer_info; + struct igc_rx_buffer *rx_buffer_info; + }; + void *desc; /* descriptor ring memory */ + unsigned long flags; /* ring specific flags */ + void __iomem *tail; /* pointer to ring tail register */ + dma_addr_t dma; /* phys address of the ring */ + unsigned int size; /* length of desc. ring in bytes */ + + u16 count; /* number of desc. in the ring */ + u8 queue_index; /* logical index of the ring*/ + u8 reg_idx; /* physical index of the ring */ + bool launchtime_enable; /* true if LaunchTime is enabled */ + + u32 start_time; + u32 end_time; + + /* everything past this point are written often */ + u16 next_to_clean; + u16 next_to_use; + u16 next_to_alloc; + + union { + /* TX */ + struct { + struct igc_tx_queue_stats tx_stats; + struct u64_stats_sync tx_syncp; + struct u64_stats_sync tx_syncp2; + }; + /* RX */ + struct { + struct igc_rx_queue_stats rx_stats; + struct igc_rx_packet_stats pkt_stats; + struct u64_stats_sync rx_syncp; + struct sk_buff *skb; + }; + }; +} ____cacheline_internodealigned_in_smp; + +/* Board specific private data structure */ +struct igc_adapter { + struct net_device *netdev; + + struct ethtool_eee eee; + u16 eee_advert; + + unsigned long state; + unsigned int flags; + unsigned int num_q_vectors; + + struct msix_entry *msix_entries; + + /* TX */ + u16 tx_work_limit; + u32 tx_timeout_count; + int num_tx_queues; + struct igc_ring *tx_ring[IGC_MAX_TX_QUEUES]; + + /* RX */ + int num_rx_queues; + struct igc_ring *rx_ring[IGC_MAX_RX_QUEUES]; + + struct timer_list watchdog_timer; + struct timer_list dma_err_timer; + struct timer_list phy_info_timer; + + u32 wol; + u32 en_mng_pt; + u16 link_speed; + u16 link_duplex; + + u8 port_num; + + u8 __iomem *io_addr; + /* Interrupt Throttle Rate */ + u32 rx_itr_setting; + u32 tx_itr_setting; + + struct work_struct reset_task; + struct work_struct watchdog_task; + struct work_struct dma_err_task; + bool fc_autoneg; + + u8 tx_timeout_factor; + + int msg_enable; + u32 max_frame_size; + u32 min_frame_size; + + ktime_t base_time; + ktime_t cycle_time; + + /* OS defined structs */ + struct pci_dev *pdev; + /* lock for statistics */ + spinlock_t stats64_lock; + struct rtnl_link_stats64 stats64; + + /* structs defined in igc_hw.h */ + struct igc_hw hw; + struct igc_hw_stats stats; + + struct igc_q_vector *q_vector[MAX_Q_VECTORS]; + u32 eims_enable_mask; + u32 eims_other; + + u16 tx_ring_count; + u16 rx_ring_count; + + u32 tx_hwtstamp_timeouts; + u32 tx_hwtstamp_skipped; + u32 rx_hwtstamp_cleared; + + u32 rss_queues; + u32 rss_indir_tbl_init; + + /* Any access to elements in nfc_rule_list is protected by the + * nfc_rule_lock. + */ + struct mutex nfc_rule_lock; + struct list_head nfc_rule_list; + unsigned int nfc_rule_count; + + u8 rss_indir_tbl[IGC_RETA_SIZE]; + + unsigned long link_check_timeout; + struct igc_info ei; + + u32 test_icr; + + struct ptp_clock *ptp_clock; + struct ptp_clock_info ptp_caps; + struct work_struct ptp_tx_work; + struct sk_buff *ptp_tx_skb; + struct hwtstamp_config tstamp_config; + unsigned long ptp_tx_start; + unsigned int ptp_flags; + /* System time value lock */ + spinlock_t tmreg_lock; + struct cyclecounter cc; + struct timecounter tc; + struct timespec64 prev_ptp_time; /* Pre-reset PTP clock */ + ktime_t ptp_reset_start; /* Reset time in clock mono */ +}; + +void igc_up(struct igc_adapter *adapter); +void igc_down(struct igc_adapter *adapter); +int igc_open(struct net_device *netdev); +int igc_close(struct net_device *netdev); +int igc_setup_tx_resources(struct igc_ring *ring); +int igc_setup_rx_resources(struct igc_ring *ring); +void igc_free_tx_resources(struct igc_ring *ring); +void igc_free_rx_resources(struct igc_ring *ring); +unsigned int igc_get_max_rss_queues(struct igc_adapter *adapter); +void igc_set_flag_queue_pairs(struct igc_adapter *adapter, + const u32 max_rss_queues); +int igc_reinit_queues(struct igc_adapter *adapter); +void igc_write_rss_indir_tbl(struct igc_adapter *adapter); +bool igc_has_link(struct igc_adapter *adapter); +void igc_reset(struct igc_adapter *adapter); +int igc_set_spd_dplx(struct igc_adapter *adapter, u32 spd, u8 dplx); +void igc_update_stats(struct igc_adapter *adapter); + +/* igc_dump declarations */ +void igc_rings_dump(struct igc_adapter *adapter); +void igc_regs_dump(struct igc_adapter *adapter); + +extern char igc_driver_name[]; + +#define IGC_REGS_LEN 740 + +/* flags controlling PTP/1588 function */ +#define IGC_PTP_ENABLED BIT(0) + +/* Flags definitions */ +#define IGC_FLAG_HAS_MSI BIT(0) +#define IGC_FLAG_QUEUE_PAIRS BIT(3) +#define IGC_FLAG_DMAC BIT(4) +#define IGC_FLAG_PTP BIT(8) +#define IGC_FLAG_WOL_SUPPORTED BIT(8) +#define IGC_FLAG_NEED_LINK_UPDATE BIT(9) +#define IGC_FLAG_MEDIA_RESET BIT(10) +#define IGC_FLAG_MAS_ENABLE BIT(12) +#define IGC_FLAG_HAS_MSIX BIT(13) +#define IGC_FLAG_EEE BIT(14) +#define IGC_FLAG_VLAN_PROMISC BIT(15) +#define IGC_FLAG_RX_LEGACY BIT(16) +#define IGC_FLAG_TSN_QBV_ENABLED BIT(17) + +#define IGC_FLAG_RSS_FIELD_IPV4_UDP BIT(6) +#define IGC_FLAG_RSS_FIELD_IPV6_UDP BIT(7) + +#define IGC_MRQC_ENABLE_RSS_MQ 0x00000002 +#define IGC_MRQC_RSS_FIELD_IPV4_UDP 0x00400000 +#define IGC_MRQC_RSS_FIELD_IPV6_UDP 0x00800000 + +/* Interrupt defines */ +#define IGC_START_ITR 648 /* ~6000 ints/sec */ +#define IGC_4K_ITR 980 +#define IGC_20K_ITR 196 +#define IGC_70K_ITR 56 + +#define IGC_DEFAULT_ITR 3 /* dynamic */ +#define IGC_MAX_ITR_USECS 10000 +#define IGC_MIN_ITR_USECS 10 +#define NON_Q_VECTORS 1 +#define MAX_MSIX_ENTRIES 10 + +/* TX/RX descriptor defines */ +#define IGC_DEFAULT_TXD 256 +#define IGC_DEFAULT_TX_WORK 128 +#define IGC_MIN_TXD 80 +#define IGC_MAX_TXD 4096 + +#define IGC_DEFAULT_RXD 256 +#define IGC_MIN_RXD 80 +#define IGC_MAX_RXD 4096 + +/* Supported Rx Buffer Sizes */ +#define IGC_RXBUFFER_256 256 +#define IGC_RXBUFFER_2048 2048 +#define IGC_RXBUFFER_3072 3072 + +#define AUTO_ALL_MODES 0 +#define IGC_RX_HDR_LEN IGC_RXBUFFER_256 + +/* Transmit and receive latency (for PTP timestamps) */ +#define IGC_I225_TX_LATENCY_10 240 +#define IGC_I225_TX_LATENCY_100 58 +#define IGC_I225_TX_LATENCY_1000 80 +#define IGC_I225_TX_LATENCY_2500 1325 +#define IGC_I225_RX_LATENCY_10 6450 +#define IGC_I225_RX_LATENCY_100 185 +#define IGC_I225_RX_LATENCY_1000 300 +#define IGC_I225_RX_LATENCY_2500 1485 + +/* RX and TX descriptor control thresholds. + * PTHRESH - MAC will consider prefetch if it has fewer than this number of + * descriptors available in its onboard memory. + * Setting this to 0 disables RX descriptor prefetch. + * HTHRESH - MAC will only prefetch if there are at least this many descriptors + * available in host memory. + * If PTHRESH is 0, this should also be 0. + * WTHRESH - RX descriptor writeback threshold - MAC will delay writing back + * descriptors until either it has this many to write back, or the + * ITR timer expires. + */ +#define IGC_RX_PTHRESH 8 +#define IGC_RX_HTHRESH 8 +#define IGC_TX_PTHRESH 8 +#define IGC_TX_HTHRESH 1 +#define IGC_RX_WTHRESH 4 +#define IGC_TX_WTHRESH 16 + +#define IGC_RX_DMA_ATTR \ + (DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_WEAK_ORDERING) + +#define IGC_TS_HDR_LEN 16 + +#define IGC_SKB_PAD (NET_SKB_PAD + NET_IP_ALIGN) + +#if (PAGE_SIZE < 8192) +#define IGC_MAX_FRAME_BUILD_SKB \ + (SKB_WITH_OVERHEAD(IGC_RXBUFFER_2048) - IGC_SKB_PAD - IGC_TS_HDR_LEN) +#else +#define IGC_MAX_FRAME_BUILD_SKB (IGC_RXBUFFER_2048 - IGC_TS_HDR_LEN) +#endif + +/* How many Rx Buffers do we bundle into one write to the hardware ? */ +#define IGC_RX_BUFFER_WRITE 16 /* Must be power of 2 */ + +/* VLAN info */ +#define IGC_TX_FLAGS_VLAN_MASK 0xffff0000 + +/* igc_test_staterr - tests bits within Rx descriptor status and error fields */ +static inline __le32 igc_test_staterr(union igc_adv_rx_desc *rx_desc, + const u32 stat_err_bits) +{ + return rx_desc->wb.upper.status_error & cpu_to_le32(stat_err_bits); +} + +enum igc_state_t { + __IGC_TESTING, + __IGC_RESETTING, + __IGC_DOWN, + __IGC_PTP_TX_IN_PROGRESS, +}; + +enum igc_tx_flags { + /* cmd_type flags */ + IGC_TX_FLAGS_VLAN = 0x01, + IGC_TX_FLAGS_TSO = 0x02, + IGC_TX_FLAGS_TSTAMP = 0x04, + + /* olinfo flags */ + IGC_TX_FLAGS_IPV4 = 0x10, + IGC_TX_FLAGS_CSUM = 0x20, +}; + +enum igc_boards { + board_base, +}; + +/* The largest size we can write to the descriptor is 65535. In order to + * maintain a power of two alignment we have to limit ourselves to 32K. + */ +#define IGC_MAX_TXD_PWR 15 +#define IGC_MAX_DATA_PER_TXD BIT(IGC_MAX_TXD_PWR) + +/* Tx Descriptors needed, worst case */ +#define TXD_USE_COUNT(S) DIV_ROUND_UP((S), IGC_MAX_DATA_PER_TXD) +#define DESC_NEEDED (MAX_SKB_FRAGS + 4) + +/* wrapper around a pointer to a socket buffer, + * so a DMA handle can be stored along with the buffer + */ +struct igc_tx_buffer { + union igc_adv_tx_desc *next_to_watch; + unsigned long time_stamp; + struct sk_buff *skb; + unsigned int bytecount; + u16 gso_segs; + __be16 protocol; + + DEFINE_DMA_UNMAP_ADDR(dma); + DEFINE_DMA_UNMAP_LEN(len); + u32 tx_flags; +}; + +struct igc_rx_buffer { + dma_addr_t dma; + struct page *page; +#if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536) + __u32 page_offset; +#else + __u16 page_offset; +#endif + __u16 pagecnt_bias; +}; + +struct igc_q_vector { + struct igc_adapter *adapter; /* backlink */ + void __iomem *itr_register; + u32 eims_value; /* EIMS mask value */ + + u16 itr_val; + u8 set_itr; + + struct igc_ring_container rx, tx; + + struct napi_struct napi; + + struct rcu_head rcu; /* to avoid race with update stats on free */ + char name[IFNAMSIZ + 9]; + struct net_device poll_dev; + + /* for dynamic allocation of rings associated with this q_vector */ + struct igc_ring ring[] ____cacheline_internodealigned_in_smp; +}; + +enum igc_filter_match_flags { + IGC_FILTER_FLAG_ETHER_TYPE = 0x1, + IGC_FILTER_FLAG_VLAN_TCI = 0x2, + IGC_FILTER_FLAG_SRC_MAC_ADDR = 0x4, + IGC_FILTER_FLAG_DST_MAC_ADDR = 0x8, +}; + +struct igc_nfc_filter { + u8 match_flags; + u16 etype; + u16 vlan_tci; + u8 src_addr[ETH_ALEN]; + u8 dst_addr[ETH_ALEN]; +}; + +struct igc_nfc_rule { + struct list_head list; + struct igc_nfc_filter filter; + u32 location; + u16 action; +}; + +/* IGC supports a total of 32 NFC rules: 16 MAC address based,, 8 VLAN priority + * based, and 8 ethertype based. + */ +#define IGC_MAX_RXNFC_RULES 32 + +/* igc_desc_unused - calculate if we have unused descriptors */ +static inline u16 igc_desc_unused(const struct igc_ring *ring) +{ + u16 ntc = ring->next_to_clean; + u16 ntu = ring->next_to_use; + + return ((ntc > ntu) ? 0 : ring->count) + ntc - ntu - 1; +} + +static inline s32 igc_get_phy_info(struct igc_hw *hw) +{ + if (hw->phy.ops.get_phy_info) + return hw->phy.ops.get_phy_info(hw); + + return 0; +} + +static inline s32 igc_reset_phy(struct igc_hw *hw) +{ + if (hw->phy.ops.reset) + return hw->phy.ops.reset(hw); + + return 0; +} + +static inline struct netdev_queue *txring_txq(const struct igc_ring *tx_ring) +{ + return netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index); +} + +enum igc_ring_flags_t { + IGC_RING_FLAG_RX_3K_BUFFER, + IGC_RING_FLAG_RX_BUILD_SKB_ENABLED, + IGC_RING_FLAG_RX_SCTP_CSUM, + IGC_RING_FLAG_RX_LB_VLAN_BSWAP, + IGC_RING_FLAG_TX_CTX_IDX, + IGC_RING_FLAG_TX_DETECT_HANG +}; + +#define ring_uses_large_buffer(ring) \ + test_bit(IGC_RING_FLAG_RX_3K_BUFFER, &(ring)->flags) + +#define ring_uses_build_skb(ring) \ + test_bit(IGC_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags) + +static inline unsigned int igc_rx_bufsz(struct igc_ring *ring) +{ +#if (PAGE_SIZE < 8192) + if (ring_uses_large_buffer(ring)) + return IGC_RXBUFFER_3072; + + if (ring_uses_build_skb(ring)) + return IGC_MAX_FRAME_BUILD_SKB + IGC_TS_HDR_LEN; +#endif + return IGC_RXBUFFER_2048; +} + +static inline unsigned int igc_rx_pg_order(struct igc_ring *ring) +{ +#if (PAGE_SIZE < 8192) + if (ring_uses_large_buffer(ring)) + return 1; +#endif + return 0; +} + +static inline s32 igc_read_phy_reg(struct igc_hw *hw, u32 offset, u16 *data) +{ + if (hw->phy.ops.read_reg) + return hw->phy.ops.read_reg(hw, offset, data); + + return -EOPNOTSUPP; +} + +void igc_reinit_locked(struct igc_adapter *); +struct igc_nfc_rule *igc_get_nfc_rule(struct igc_adapter *adapter, + u32 location); +int igc_add_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule); +void igc_del_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule); + +void igc_ptp_init(struct igc_adapter *adapter); +void igc_ptp_reset(struct igc_adapter *adapter); +void igc_ptp_suspend(struct igc_adapter *adapter); +void igc_ptp_stop(struct igc_adapter *adapter); +void igc_ptp_rx_pktstamp(struct igc_q_vector *q_vector, __le32 *va, + struct sk_buff *skb); +int igc_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr); +int igc_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr); +void igc_ptp_tx_hang(struct igc_adapter *adapter); +void igc_ptp_read(struct igc_adapter *adapter, struct timespec64 *ts); + +#define igc_rx_pg_size(_ring) (PAGE_SIZE << igc_rx_pg_order(_ring)) + +#define IGC_TXD_DCMD (IGC_ADVTXD_DCMD_EOP | IGC_ADVTXD_DCMD_RS) + +#define IGC_RX_DESC(R, i) \ + (&(((union igc_adv_rx_desc *)((R)->desc))[i])) +#define IGC_TX_DESC(R, i) \ + (&(((union igc_adv_tx_desc *)((R)->desc))[i])) +#define IGC_TX_CTXTDESC(R, i) \ + (&(((struct igc_adv_tx_context_desc *)((R)->desc))[i])) + +#endif /* _IGC_H_ */ diff --git a/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_base.c b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_base.c new file mode 100644 index 00000000..f068b66b --- /dev/null +++ b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_base.c @@ -0,0 +1,421 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2018 Intel Corporation */ + +#include + +#include "igc_hw.h" +#include "igc_i225.h" +#include "igc_mac.h" +#include "igc_base.h" +#include "igc.h" + +/** + * igc_reset_hw_base - Reset hardware + * @hw: pointer to the HW structure + * + * This resets the hardware into a known state. This is a + * function pointer entry point called by the api module. + */ +static s32 igc_reset_hw_base(struct igc_hw *hw) +{ + s32 ret_val; + u32 ctrl; + + /* Prevent the PCI-E bus from sticking if there is no TLP connection + * on the last TLP read/write transaction when MAC is reset. + */ + ret_val = igc_disable_pcie_master(hw); + if (ret_val) + hw_dbg("PCI-E Master disable polling has failed\n"); + + hw_dbg("Masking off all interrupts\n"); + wr32(IGC_IMC, 0xffffffff); + + wr32(IGC_RCTL, 0); + wr32(IGC_TCTL, IGC_TCTL_PSP); + wrfl(); + + usleep_range(10000, 20000); + + ctrl = rd32(IGC_CTRL); + + hw_dbg("Issuing a global reset to MAC\n"); + wr32(IGC_CTRL, ctrl | IGC_CTRL_RST); + + ret_val = igc_get_auto_rd_done(hw); + if (ret_val) { + /* When auto config read does not complete, do not + * return with an error. This can happen in situations + * where there is no eeprom and prevents getting link. + */ + hw_dbg("Auto Read Done did not complete\n"); + } + + /* Clear any pending interrupt events. */ + wr32(IGC_IMC, 0xffffffff); + rd32(IGC_ICR); + + return ret_val; +} + +/** + * igc_init_nvm_params_base - Init NVM func ptrs. + * @hw: pointer to the HW structure + */ +static s32 igc_init_nvm_params_base(struct igc_hw *hw) +{ + struct igc_nvm_info *nvm = &hw->nvm; + u32 eecd = rd32(IGC_EECD); + u16 size; + + size = (u16)((eecd & IGC_EECD_SIZE_EX_MASK) >> + IGC_EECD_SIZE_EX_SHIFT); + + /* Added to a constant, "size" becomes the left-shift value + * for setting word_size. + */ + size += NVM_WORD_SIZE_BASE_SHIFT; + + /* Just in case size is out of range, cap it to the largest + * EEPROM size supported + */ + if (size > 15) + size = 15; + + nvm->type = igc_nvm_eeprom_spi; + nvm->word_size = BIT(size); + nvm->opcode_bits = 8; + nvm->delay_usec = 1; + + nvm->page_size = eecd & IGC_EECD_ADDR_BITS ? 32 : 8; + nvm->address_bits = eecd & IGC_EECD_ADDR_BITS ? + 16 : 8; + + if (nvm->word_size == BIT(15)) + nvm->page_size = 128; + + return 0; +} + +/** + * igc_setup_copper_link_base - Configure copper link settings + * @hw: pointer to the HW structure + * + * Configures the link for auto-neg or forced speed and duplex. Then we check + * for link, once link is established calls to configure collision distance + * and flow control are called. + */ +static s32 igc_setup_copper_link_base(struct igc_hw *hw) +{ + s32 ret_val = 0; + u32 ctrl; + + ctrl = rd32(IGC_CTRL); + ctrl |= IGC_CTRL_SLU; + ctrl &= ~(IGC_CTRL_FRCSPD | IGC_CTRL_FRCDPX); + wr32(IGC_CTRL, ctrl); + + ret_val = igc_setup_copper_link(hw); + + return ret_val; +} + +/** + * igc_init_mac_params_base - Init MAC func ptrs. + * @hw: pointer to the HW structure + */ +static s32 igc_init_mac_params_base(struct igc_hw *hw) +{ + struct igc_dev_spec_base *dev_spec = &hw->dev_spec._base; + struct igc_mac_info *mac = &hw->mac; + + /* Set mta register count */ + mac->mta_reg_count = 128; + mac->rar_entry_count = IGC_RAR_ENTRIES; + + /* reset */ + mac->ops.reset_hw = igc_reset_hw_base; + + mac->ops.acquire_swfw_sync = igc_acquire_swfw_sync_i225; + mac->ops.release_swfw_sync = igc_release_swfw_sync_i225; + + /* Allow a single clear of the SW semaphore on I225 */ + if (mac->type == igc_i225) + dev_spec->clear_semaphore_once = true; + + /* physical interface link setup */ + mac->ops.setup_physical_interface = igc_setup_copper_link_base; + + return 0; +} + +/** + * igc_init_phy_params_base - Init PHY func ptrs. + * @hw: pointer to the HW structure + */ +static s32 igc_init_phy_params_base(struct igc_hw *hw) +{ + struct igc_phy_info *phy = &hw->phy; + s32 ret_val = 0; + + phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT_2500; + phy->reset_delay_us = 100; + + /* set lan id */ + hw->bus.func = (rd32(IGC_STATUS) & IGC_STATUS_FUNC_MASK) >> + IGC_STATUS_FUNC_SHIFT; + + /* Make sure the PHY is in a good state. Several people have reported + * firmware leaving the PHY's page select register set to something + * other than the default of zero, which causes the PHY ID read to + * access something other than the intended register. + */ + ret_val = hw->phy.ops.reset(hw); + if (ret_val) { + hw_dbg("Error resetting the PHY\n"); + goto out; + } + + ret_val = igc_get_phy_id(hw); + if (ret_val) + return ret_val; + + igc_check_for_copper_link(hw); + + phy->type = igc_phy_i225; + +out: + return ret_val; +} + +static s32 igc_get_invariants_base(struct igc_hw *hw) +{ + struct igc_mac_info *mac = &hw->mac; + s32 ret_val = 0; + + switch (hw->device_id) { + case IGC_DEV_ID_I225_LM: + case IGC_DEV_ID_I225_V: + case IGC_DEV_ID_I225_I: + case IGC_DEV_ID_I220_V: + case IGC_DEV_ID_I225_K: + case IGC_DEV_ID_I225_K2: + case IGC_DEV_ID_I226_K: + case IGC_DEV_ID_I225_LMVP: + case IGC_DEV_ID_I226_LMVP: + case IGC_DEV_ID_I225_IT: + case IGC_DEV_ID_I226_LM: + case IGC_DEV_ID_I226_V: + case IGC_DEV_ID_I226_IT: + case IGC_DEV_ID_I221_V: + case IGC_DEV_ID_I226_BLANK_NVM: + case IGC_DEV_ID_I225_BLANK_NVM: + mac->type = igc_i225; + break; + default: + return -IGC_ERR_MAC_INIT; + } + + hw->phy.media_type = igc_media_type_copper; + + /* mac initialization and operations */ + ret_val = igc_init_mac_params_base(hw); + if (ret_val) + goto out; + + /* NVM initialization */ + ret_val = igc_init_nvm_params_base(hw); + switch (hw->mac.type) { + case igc_i225: + ret_val = igc_init_nvm_params_i225(hw); + break; + default: + break; + } + + /* setup PHY parameters */ + ret_val = igc_init_phy_params_base(hw); + if (ret_val) + goto out; + +out: + return ret_val; +} + +/** + * igc_acquire_phy_base - Acquire rights to access PHY + * @hw: pointer to the HW structure + * + * Acquire access rights to the correct PHY. This is a + * function pointer entry point called by the api module. + */ +static s32 igc_acquire_phy_base(struct igc_hw *hw) +{ + u16 mask = IGC_SWFW_PHY0_SM; + + return hw->mac.ops.acquire_swfw_sync(hw, mask); +} + +/** + * igc_release_phy_base - Release rights to access PHY + * @hw: pointer to the HW structure + * + * A wrapper to release access rights to the correct PHY. This is a + * function pointer entry point called by the api module. + */ +static void igc_release_phy_base(struct igc_hw *hw) +{ + u16 mask = IGC_SWFW_PHY0_SM; + + hw->mac.ops.release_swfw_sync(hw, mask); +} + +/** + * igc_init_hw_base - Initialize hardware + * @hw: pointer to the HW structure + * + * This inits the hardware readying it for operation. + */ +static s32 igc_init_hw_base(struct igc_hw *hw) +{ + struct igc_mac_info *mac = &hw->mac; + u16 i, rar_count = mac->rar_entry_count; + s32 ret_val = 0; + + /* Setup the receive address */ + igc_init_rx_addrs(hw, rar_count); + + /* Zero out the Multicast HASH table */ + hw_dbg("Zeroing the MTA\n"); + for (i = 0; i < mac->mta_reg_count; i++) + array_wr32(IGC_MTA, i, 0); + + /* Zero out the Unicast HASH table */ + hw_dbg("Zeroing the UTA\n"); + for (i = 0; i < mac->uta_reg_count; i++) + array_wr32(IGC_UTA, i, 0); + + /* Setup link and flow control */ + ret_val = igc_setup_link(hw); + + /* Clear all of the statistics registers (clear on read). It is + * important that we do this after we have tried to establish link + * because the symbol error count will increment wildly if there + * is no link. + */ + igc_clear_hw_cntrs_base(hw); + + return ret_val; +} + +/** + * igc_power_down_phy_copper_base - Remove link during PHY power down + * @hw: pointer to the HW structure + * + * In the case of a PHY power down to save power, or to turn off link during a + * driver unload, or wake on lan is not enabled, remove the link. + */ +void igc_power_down_phy_copper_base(struct igc_hw *hw) +{ + /* If the management interface is not enabled, then power down */ + if (!(igc_enable_mng_pass_thru(hw) || igc_check_reset_block(hw))) + igc_power_down_phy_copper(hw); +} + +/** + * igc_rx_fifo_flush_base - Clean rx fifo after Rx enable + * @hw: pointer to the HW structure + * + * After Rx enable, if manageability is enabled then there is likely some + * bad data at the start of the fifo and possibly in the DMA fifo. This + * function clears the fifos and flushes any packets that came in as rx was + * being enabled. + */ +void igc_rx_fifo_flush_base(struct igc_hw *hw) +{ + u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled; + int i, ms_wait; + + /* disable IPv6 options as per hardware errata */ + rfctl = rd32(IGC_RFCTL); + rfctl |= IGC_RFCTL_IPV6_EX_DIS; + wr32(IGC_RFCTL, rfctl); + + if (!(rd32(IGC_MANC) & IGC_MANC_RCV_TCO_EN)) + return; + + /* Disable all Rx queues */ + for (i = 0; i < 4; i++) { + rxdctl[i] = rd32(IGC_RXDCTL(i)); + wr32(IGC_RXDCTL(i), + rxdctl[i] & ~IGC_RXDCTL_QUEUE_ENABLE); + } + /* Poll all queues to verify they have shut down */ + for (ms_wait = 0; ms_wait < 10; ms_wait++) { + usleep_range(1000, 2000); + rx_enabled = 0; + for (i = 0; i < 4; i++) + rx_enabled |= rd32(IGC_RXDCTL(i)); + if (!(rx_enabled & IGC_RXDCTL_QUEUE_ENABLE)) + break; + } + + if (ms_wait == 10) + hw_dbg("Queue disable timed out after 10ms\n"); + + /* Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all + * incoming packets are rejected. Set enable and wait 2ms so that + * any packet that was coming in as RCTL.EN was set is flushed + */ + wr32(IGC_RFCTL, rfctl & ~IGC_RFCTL_LEF); + + rlpml = rd32(IGC_RLPML); + wr32(IGC_RLPML, 0); + + rctl = rd32(IGC_RCTL); + temp_rctl = rctl & ~(IGC_RCTL_EN | IGC_RCTL_SBP); + temp_rctl |= IGC_RCTL_LPE; + + wr32(IGC_RCTL, temp_rctl); + wr32(IGC_RCTL, temp_rctl | IGC_RCTL_EN); + wrfl(); + usleep_range(2000, 3000); + + /* Enable Rx queues that were previously enabled and restore our + * previous state + */ + for (i = 0; i < 4; i++) + wr32(IGC_RXDCTL(i), rxdctl[i]); + wr32(IGC_RCTL, rctl); + wrfl(); + + wr32(IGC_RLPML, rlpml); + wr32(IGC_RFCTL, rfctl); + + /* Flush receive errors generated by workaround */ + rd32(IGC_ROC); + rd32(IGC_RNBC); + rd32(IGC_MPC); +} + +static struct igc_mac_operations igc_mac_ops_base = { + .init_hw = igc_init_hw_base, + .check_for_link = igc_check_for_copper_link, + .rar_set = igc_rar_set, + .read_mac_addr = igc_read_mac_addr, + .get_speed_and_duplex = igc_get_speed_and_duplex_copper, +}; + +static const struct igc_phy_operations igc_phy_ops_base = { + .acquire = igc_acquire_phy_base, + .release = igc_release_phy_base, + .reset = igc_phy_hw_reset, + .read_reg = igc_read_phy_reg_gpy, + .write_reg = igc_write_phy_reg_gpy, +}; + +const struct igc_info igc_base_info = { + .get_invariants = igc_get_invariants_base, + .mac_ops = &igc_mac_ops_base, + .phy_ops = &igc_phy_ops_base, +}; diff --git a/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_base.h b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_base.h new file mode 100644 index 00000000..ea627ce5 --- /dev/null +++ b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_base.h @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2018 Intel Corporation */ + +#ifndef _IGC_BASE_H_ +#define _IGC_BASE_H_ + +/* forward declaration */ +void igc_rx_fifo_flush_base(struct igc_hw *hw); +void igc_power_down_phy_copper_base(struct igc_hw *hw); + +/* Transmit Descriptor - Advanced */ +union igc_adv_tx_desc { + struct { + __le64 buffer_addr; /* Address of descriptor's data buf */ + __le32 cmd_type_len; + __le32 olinfo_status; + } read; + struct { + __le64 rsvd; /* Reserved */ + __le32 nxtseq_seed; + __le32 status; + } wb; +}; + +/* Context descriptors */ +struct igc_adv_tx_context_desc { + __le32 vlan_macip_lens; + __le32 launch_time; + __le32 type_tucmd_mlhl; + __le32 mss_l4len_idx; +}; + +/* Adv Transmit Descriptor Config Masks */ +#define IGC_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE1588 Timestamp packet */ +#define IGC_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */ +#define IGC_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */ +#define IGC_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */ +#define IGC_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */ +#define IGC_ADVTXD_DCMD_RS 0x08000000 /* Report Status */ +#define IGC_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */ +#define IGC_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */ +#define IGC_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */ +#define IGC_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */ + +#define IGC_RAR_ENTRIES 16 + +/* Receive Descriptor - Advanced */ +union igc_adv_rx_desc { + struct { + __le64 pkt_addr; /* Packet buffer address */ + __le64 hdr_addr; /* Header buffer address */ + } read; + struct { + struct { + union { + __le32 data; + struct { + __le16 pkt_info; /*RSS type, Pkt type*/ + /* Split Header, header buffer len */ + __le16 hdr_info; + } hs_rss; + } lo_dword; + union { + __le32 rss; /* RSS Hash */ + struct { + __le16 ip_id; /* IP id */ + __le16 csum; /* Packet Checksum */ + } csum_ip; + } hi_dword; + } lower; + struct { + __le32 status_error; /* ext status/error */ + __le16 length; /* Packet length */ + __le16 vlan; /* VLAN tag */ + } upper; + } wb; /* writeback */ +}; + +/* Additional Transmit Descriptor Control definitions */ +#define IGC_TXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Tx Queue */ + +/* Additional Receive Descriptor Control definitions */ +#define IGC_RXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Rx Queue */ + +/* SRRCTL bit definitions */ +#define IGC_SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */ +#define IGC_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */ +#define IGC_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000 + +#endif /* _IGC_BASE_H */ diff --git a/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_defines.h b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_defines.h new file mode 100644 index 00000000..12d93d22 --- /dev/null +++ b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_defines.h @@ -0,0 +1,533 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2018 Intel Corporation */ + +#ifndef _IGC_DEFINES_H_ +#define _IGC_DEFINES_H_ + +/* Number of Transmit and Receive Descriptors must be a multiple of 8 */ +#define REQ_TX_DESCRIPTOR_MULTIPLE 8 +#define REQ_RX_DESCRIPTOR_MULTIPLE 8 + +#define IGC_CTRL_EXT_DRV_LOAD 0x10000000 /* Drv loaded bit for FW */ + +/* Definitions for power management and wakeup registers */ +/* Wake Up Control */ +#define IGC_WUC_PME_EN 0x00000002 /* PME Enable */ + +/* Wake Up Filter Control */ +#define IGC_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */ +#define IGC_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */ +#define IGC_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */ +#define IGC_WUFC_MC 0x00000008 /* Directed Multicast Wakeup Enable */ +#define IGC_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */ + +#define IGC_CTRL_ADVD3WUC 0x00100000 /* D3 WUC */ + +/* Wake Up Status */ +#define IGC_WUS_EX 0x00000004 /* Directed Exact */ +#define IGC_WUS_ARPD 0x00000020 /* Directed ARP Request */ +#define IGC_WUS_IPV4 0x00000040 /* Directed IPv4 */ +#define IGC_WUS_IPV6 0x00000080 /* Directed IPv6 */ +#define IGC_WUS_NSD 0x00000400 /* Directed IPv6 Neighbor Solicitation */ + +/* Packet types that are enabled for wake packet delivery */ +#define WAKE_PKT_WUS ( \ + IGC_WUS_EX | \ + IGC_WUS_ARPD | \ + IGC_WUS_IPV4 | \ + IGC_WUS_IPV6 | \ + IGC_WUS_NSD) + +/* Wake Up Packet Length */ +#define IGC_WUPL_MASK 0x00000FFF + +/* Wake Up Packet Memory stores the first 128 bytes of the wake up packet */ +#define IGC_WUPM_BYTES 128 + +/* Loop limit on how long we wait for auto-negotiation to complete */ +#define COPPER_LINK_UP_LIMIT 10 +#define PHY_AUTO_NEG_LIMIT 45 + +/* Number of 100 microseconds we wait for PCI Express master disable */ +#define MASTER_DISABLE_TIMEOUT 800 +/*Blocks new Master requests */ +#define IGC_CTRL_GIO_MASTER_DISABLE 0x00000004 +/* Status of Master requests. */ +#define IGC_STATUS_GIO_MASTER_ENABLE 0x00080000 + +/* Receive Address + * Number of high/low register pairs in the RAR. The RAR (Receive Address + * Registers) holds the directed and multicast addresses that we monitor. + * Technically, we have 16 spots. However, we reserve one of these spots + * (RAR[15]) for our directed address used by controllers with + * manageability enabled, allowing us room for 15 multicast addresses. + */ +#define IGC_RAH_RAH_MASK 0x0000FFFF +#define IGC_RAH_ASEL_MASK 0x00030000 +#define IGC_RAH_ASEL_SRC_ADDR BIT(16) +#define IGC_RAH_QSEL_MASK 0x000C0000 +#define IGC_RAH_QSEL_SHIFT 18 +#define IGC_RAH_QSEL_ENABLE BIT(28) +#define IGC_RAH_AV 0x80000000 /* Receive descriptor valid */ + +#define IGC_RAL_MAC_ADDR_LEN 4 +#define IGC_RAH_MAC_ADDR_LEN 2 + +/* Error Codes */ +#define IGC_SUCCESS 0 +#define IGC_ERR_NVM 1 +#define IGC_ERR_PHY 2 +#define IGC_ERR_CONFIG 3 +#define IGC_ERR_PARAM 4 +#define IGC_ERR_MAC_INIT 5 +#define IGC_ERR_RESET 9 +#define IGC_ERR_MASTER_REQUESTS_PENDING 10 +#define IGC_ERR_BLK_PHY_RESET 12 +#define IGC_ERR_SWFW_SYNC 13 + +/* Device Control */ +#define IGC_CTRL_RST 0x04000000 /* Global reset */ + +#define IGC_CTRL_PHY_RST 0x80000000 /* PHY Reset */ +#define IGC_CTRL_SLU 0x00000040 /* Set link up (Force Link) */ +#define IGC_CTRL_FRCSPD 0x00000800 /* Force Speed */ +#define IGC_CTRL_FRCDPX 0x00001000 /* Force Duplex */ + +#define IGC_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */ +#define IGC_CTRL_TFCE 0x10000000 /* Transmit flow control enable */ + +/* As per the EAS the maximum supported size is 9.5KB (9728 bytes) */ +#define MAX_JUMBO_FRAME_SIZE 0x2600 + +/* PBA constants */ +#define IGC_PBA_34K 0x0022 + +/* SW Semaphore Register */ +#define IGC_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */ +#define IGC_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */ + +/* SWFW_SYNC Definitions */ +#define IGC_SWFW_EEP_SM 0x1 +#define IGC_SWFW_PHY0_SM 0x2 + +/* Autoneg Advertisement Register */ +#define NWAY_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */ +#define NWAY_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */ +#define NWAY_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */ +#define NWAY_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */ +#define NWAY_AR_PAUSE 0x0400 /* Pause operation desired */ +#define NWAY_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */ + +/* Link Partner Ability Register (Base Page) */ +#define NWAY_LPAR_PAUSE 0x0400 /* LP Pause operation desired */ +#define NWAY_LPAR_ASM_DIR 0x0800 /* LP Asymmetric Pause Direction bit */ + +/* 1000BASE-T Control Register */ +#define CR_1000T_ASYM_PAUSE 0x0080 /* Advertise asymmetric pause bit */ +#define CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */ +#define CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */ + +/* 1000BASE-T Status Register */ +#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */ +#define SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */ + +/* PHY GPY 211 registers */ +#define STANDARD_AN_REG_MASK 0x0007 /* MMD */ +#define ANEG_MULTIGBT_AN_CTRL 0x0020 /* MULTI GBT AN Control Register */ +#define MMD_DEVADDR_SHIFT 16 /* Shift MMD to higher bits */ +#define CR_2500T_FD_CAPS 0x0080 /* Advertise 2500T FD capability */ + +/* NVM Control */ +/* Number of milliseconds for NVM auto read done after MAC reset. */ +#define AUTO_READ_DONE_TIMEOUT 10 +#define IGC_EECD_AUTO_RD 0x00000200 /* NVM Auto Read done */ +#define IGC_EECD_REQ 0x00000040 /* NVM Access Request */ +#define IGC_EECD_GNT 0x00000080 /* NVM Access Grant */ +/* NVM Addressing bits based on type 0=small, 1=large */ +#define IGC_EECD_ADDR_BITS 0x00000400 +#define IGC_NVM_GRANT_ATTEMPTS 1000 /* NVM # attempts to gain grant */ +#define IGC_EECD_SIZE_EX_MASK 0x00007800 /* NVM Size */ +#define IGC_EECD_SIZE_EX_SHIFT 11 +#define IGC_EECD_FLUPD_I225 0x00800000 /* Update FLASH */ +#define IGC_EECD_FLUDONE_I225 0x04000000 /* Update FLASH done*/ +#define IGC_EECD_FLASH_DETECTED_I225 0x00080000 /* FLASH detected */ +#define IGC_FLUDONE_ATTEMPTS 20000 +#define IGC_EERD_EEWR_MAX_COUNT 512 /* buffered EEPROM words rw */ + +/* Offset to data in NVM read/write registers */ +#define IGC_NVM_RW_REG_DATA 16 +#define IGC_NVM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */ +#define IGC_NVM_RW_REG_START 1 /* Start operation */ +#define IGC_NVM_RW_ADDR_SHIFT 2 /* Shift to the address bits */ +#define IGC_NVM_POLL_READ 0 /* Flag for polling for read complete */ + +/* NVM Word Offsets */ +#define NVM_CHECKSUM_REG 0x003F + +/* For checksumming, the sum of all words in the NVM should equal 0xBABA. */ +#define NVM_SUM 0xBABA +#define NVM_WORD_SIZE_BASE_SHIFT 6 + +/* Collision related configuration parameters */ +#define IGC_COLLISION_THRESHOLD 15 +#define IGC_CT_SHIFT 4 +#define IGC_COLLISION_DISTANCE 63 +#define IGC_COLD_SHIFT 12 + +/* Device Status */ +#define IGC_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */ +#define IGC_STATUS_LU 0x00000002 /* Link up.0=no,1=link */ +#define IGC_STATUS_FUNC_MASK 0x0000000C /* PCI Function Mask */ +#define IGC_STATUS_FUNC_SHIFT 2 +#define IGC_STATUS_FUNC_1 0x00000004 /* Function 1 */ +#define IGC_STATUS_TXOFF 0x00000010 /* transmission paused */ +#define IGC_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */ +#define IGC_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */ +#define IGC_STATUS_SPEED_2500 0x00400000 /* Speed 2.5Gb/s */ + +#define SPEED_10 10 +#define SPEED_100 100 +#define SPEED_1000 1000 +#define SPEED_2500 2500 +#define HALF_DUPLEX 1 +#define FULL_DUPLEX 2 + +/* 1Gbps and 2.5Gbps half duplex is not supported, nor spec-compliant. */ +#define ADVERTISE_10_HALF 0x0001 +#define ADVERTISE_10_FULL 0x0002 +#define ADVERTISE_100_HALF 0x0004 +#define ADVERTISE_100_FULL 0x0008 +#define ADVERTISE_1000_HALF 0x0010 /* Not used, just FYI */ +#define ADVERTISE_1000_FULL 0x0020 +#define ADVERTISE_2500_HALF 0x0040 /* Not used, just FYI */ +#define ADVERTISE_2500_FULL 0x0080 + +#define IGC_ALL_SPEED_DUPLEX_2500 ( \ + ADVERTISE_10_HALF | ADVERTISE_10_FULL | ADVERTISE_100_HALF | \ + ADVERTISE_100_FULL | ADVERTISE_1000_FULL | ADVERTISE_2500_FULL) + +#define AUTONEG_ADVERTISE_SPEED_DEFAULT_2500 IGC_ALL_SPEED_DUPLEX_2500 + +/* Interrupt Cause Read */ +#define IGC_ICR_TXDW BIT(0) /* Transmit desc written back */ +#define IGC_ICR_TXQE BIT(1) /* Transmit Queue empty */ +#define IGC_ICR_LSC BIT(2) /* Link Status Change */ +#define IGC_ICR_RXSEQ BIT(3) /* Rx sequence error */ +#define IGC_ICR_RXDMT0 BIT(4) /* Rx desc min. threshold (0) */ +#define IGC_ICR_RXO BIT(6) /* Rx overrun */ +#define IGC_ICR_RXT0 BIT(7) /* Rx timer intr (ring 0) */ +#define IGC_ICR_TS BIT(19) /* Time Sync Interrupt */ +#define IGC_ICR_DRSTA BIT(30) /* Device Reset Asserted */ + +/* If this bit asserted, the driver should claim the interrupt */ +#define IGC_ICR_INT_ASSERTED BIT(31) + +#define IGC_ICS_RXT0 IGC_ICR_RXT0 /* Rx timer intr */ + +#define IMS_ENABLE_MASK ( \ + IGC_IMS_RXT0 | \ + IGC_IMS_TXDW | \ + IGC_IMS_RXDMT0 | \ + IGC_IMS_RXSEQ | \ + IGC_IMS_LSC) + +/* Interrupt Mask Set */ +#define IGC_IMS_TXDW IGC_ICR_TXDW /* Tx desc written back */ +#define IGC_IMS_RXSEQ IGC_ICR_RXSEQ /* Rx sequence error */ +#define IGC_IMS_LSC IGC_ICR_LSC /* Link Status Change */ +#define IGC_IMS_DOUTSYNC IGC_ICR_DOUTSYNC /* NIC DMA out of sync */ +#define IGC_IMS_DRSTA IGC_ICR_DRSTA /* Device Reset Asserted */ +#define IGC_IMS_RXT0 IGC_ICR_RXT0 /* Rx timer intr */ +#define IGC_IMS_RXDMT0 IGC_ICR_RXDMT0 /* Rx desc min. threshold */ +#define IGC_IMS_TS IGC_ICR_TS /* Time Sync Interrupt */ + +#define IGC_QVECTOR_MASK 0x7FFC /* Q-vector mask */ +#define IGC_ITR_VAL_MASK 0x04 /* ITR value mask */ + +/* Interrupt Cause Set */ +#define IGC_ICS_LSC IGC_ICR_LSC /* Link Status Change */ +#define IGC_ICS_RXDMT0 IGC_ICR_RXDMT0 /* rx desc min. threshold */ + +#define IGC_ICR_DOUTSYNC 0x10000000 /* NIC DMA out of sync */ +#define IGC_EITR_CNT_IGNR 0x80000000 /* Don't reset counters on write */ +#define IGC_IVAR_VALID 0x80 +#define IGC_GPIE_NSICR 0x00000001 +#define IGC_GPIE_MSIX_MODE 0x00000010 +#define IGC_GPIE_EIAME 0x40000000 +#define IGC_GPIE_PBA 0x80000000 + +/* Receive Descriptor bit definitions */ +#define IGC_RXD_STAT_DD 0x01 /* Descriptor Done */ + +/* Transmit Descriptor bit definitions */ +#define IGC_TXD_DTYP_D 0x00100000 /* Data Descriptor */ +#define IGC_TXD_DTYP_C 0x00000000 /* Context Descriptor */ +#define IGC_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */ +#define IGC_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */ +#define IGC_TXD_CMD_EOP 0x01000000 /* End of Packet */ +#define IGC_TXD_CMD_IC 0x04000000 /* Insert Checksum */ +#define IGC_TXD_CMD_DEXT 0x20000000 /* Desc extension (0 = legacy) */ +#define IGC_TXD_CMD_VLE 0x40000000 /* Add VLAN tag */ +#define IGC_TXD_STAT_DD 0x00000001 /* Descriptor Done */ +#define IGC_TXD_CMD_TCP 0x01000000 /* TCP packet */ +#define IGC_TXD_CMD_IP 0x02000000 /* IP packet */ +#define IGC_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */ +#define IGC_TXD_EXTCMD_TSTAMP 0x00000010 /* IEEE1588 Timestamp packet */ + +/* IPSec Encrypt Enable */ +#define IGC_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */ +#define IGC_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */ + +/* Transmit Control */ +#define IGC_TCTL_EN 0x00000002 /* enable Tx */ +#define IGC_TCTL_PSP 0x00000008 /* pad short packets */ +#define IGC_TCTL_CT 0x00000ff0 /* collision threshold */ +#define IGC_TCTL_COLD 0x003ff000 /* collision distance */ +#define IGC_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */ +#define IGC_TCTL_MULR 0x10000000 /* Multiple request support */ + +/* Flow Control Constants */ +#define FLOW_CONTROL_ADDRESS_LOW 0x00C28001 +#define FLOW_CONTROL_ADDRESS_HIGH 0x00000100 +#define FLOW_CONTROL_TYPE 0x8808 +/* Enable XON frame transmission */ +#define IGC_FCRTL_XONE 0x80000000 + +/* Management Control */ +#define IGC_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */ +#define IGC_MANC_BLK_PHY_RST_ON_IDE 0x00040000 /* Block phy resets */ + +/* Receive Control */ +#define IGC_RCTL_RST 0x00000001 /* Software reset */ +#define IGC_RCTL_EN 0x00000002 /* enable */ +#define IGC_RCTL_SBP 0x00000004 /* store bad packet */ +#define IGC_RCTL_UPE 0x00000008 /* unicast promisc enable */ +#define IGC_RCTL_MPE 0x00000010 /* multicast promisc enable */ +#define IGC_RCTL_LPE 0x00000020 /* long packet enable */ +#define IGC_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */ +#define IGC_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */ + +#define IGC_RCTL_RDMTS_HALF 0x00000000 /* Rx desc min thresh size */ +#define IGC_RCTL_BAM 0x00008000 /* broadcast enable */ + +/* Split Replication Receive Control */ +#define IGC_SRRCTL_TIMESTAMP 0x40000000 +#define IGC_SRRCTL_TIMER1SEL(timer) (((timer) & 0x3) << 14) +#define IGC_SRRCTL_TIMER0SEL(timer) (((timer) & 0x3) << 17) + +/* Receive Descriptor bit definitions */ +#define IGC_RXD_STAT_EOP 0x02 /* End of Packet */ +#define IGC_RXD_STAT_IXSM 0x04 /* Ignore checksum */ +#define IGC_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */ +#define IGC_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */ + +/* Advanced Receive Descriptor bit definitions */ +#define IGC_RXDADV_STAT_TSIP 0x08000 /* timestamp in packet */ + +#define IGC_RXDEXT_STATERR_L4E 0x20000000 +#define IGC_RXDEXT_STATERR_IPE 0x40000000 +#define IGC_RXDEXT_STATERR_RXE 0x80000000 + +#define IGC_MRQC_RSS_FIELD_IPV4_TCP 0x00010000 +#define IGC_MRQC_RSS_FIELD_IPV4 0x00020000 +#define IGC_MRQC_RSS_FIELD_IPV6_TCP_EX 0x00040000 +#define IGC_MRQC_RSS_FIELD_IPV6 0x00100000 +#define IGC_MRQC_RSS_FIELD_IPV6_TCP 0x00200000 + +/* Header split receive */ +#define IGC_RFCTL_IPV6_EX_DIS 0x00010000 +#define IGC_RFCTL_LEF 0x00040000 + +#define IGC_RCTL_SZ_256 0x00030000 /* Rx buffer size 256 */ + +#define IGC_RCTL_MO_SHIFT 12 /* multicast offset shift */ +#define IGC_RCTL_CFIEN 0x00080000 /* canonical form enable */ +#define IGC_RCTL_DPF 0x00400000 /* discard pause frames */ +#define IGC_RCTL_PMCF 0x00800000 /* pass MAC control frames */ +#define IGC_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */ + +#define I225_RXPBSIZE_DEFAULT 0x000000A2 /* RXPBSIZE default */ +#define I225_TXPBSIZE_DEFAULT 0x04000014 /* TXPBSIZE default */ +#define IGC_RXPBS_CFG_TS_EN 0x80000000 /* Timestamp in Rx buffer */ + +#define IGC_TXPBSIZE_TSN 0x04145145 /* 5k bytes buffer for each queue */ + +#define IGC_DTXMXPKTSZ_TSN 0x19 /* 1600 bytes of max TX DMA packet size */ +#define IGC_DTXMXPKTSZ_DEFAULT 0x98 /* 9728-byte Jumbo frames */ + +/* Time Sync Interrupt Causes */ +#define IGC_TSICR_SYS_WRAP BIT(0) /* SYSTIM Wrap around. */ +#define IGC_TSICR_TXTS BIT(1) /* Transmit Timestamp. */ +#define IGC_TSICR_TT0 BIT(3) /* Target Time 0 Trigger. */ +#define IGC_TSICR_TT1 BIT(4) /* Target Time 1 Trigger. */ +#define IGC_TSICR_AUTT0 BIT(5) /* Auxiliary Timestamp 0 Taken. */ +#define IGC_TSICR_AUTT1 BIT(6) /* Auxiliary Timestamp 1 Taken. */ + +#define IGC_TSICR_INTERRUPTS IGC_TSICR_TXTS + +#define IGC_FTQF_VF_BP 0x00008000 +#define IGC_FTQF_1588_TIME_STAMP 0x08000000 +#define IGC_FTQF_MASK 0xF0000000 +#define IGC_FTQF_MASK_PROTO_BP 0x10000000 + +/* Time Sync Receive Control bit definitions */ +#define IGC_TSYNCRXCTL_TYPE_MASK 0x0000000E /* Rx type mask */ +#define IGC_TSYNCRXCTL_TYPE_L2_V2 0x00 +#define IGC_TSYNCRXCTL_TYPE_L4_V1 0x02 +#define IGC_TSYNCRXCTL_TYPE_L2_L4_V2 0x04 +#define IGC_TSYNCRXCTL_TYPE_ALL 0x08 +#define IGC_TSYNCRXCTL_TYPE_EVENT_V2 0x0A +#define IGC_TSYNCRXCTL_ENABLED 0x00000010 /* enable Rx timestamping */ +#define IGC_TSYNCRXCTL_SYSCFI 0x00000020 /* Sys clock frequency */ +#define IGC_TSYNCRXCTL_RXSYNSIG 0x00000400 /* Sample RX tstamp in PHY sop */ + +/* Time Sync Receive Configuration */ +#define IGC_TSYNCRXCFG_PTP_V1_CTRLT_MASK 0x000000FF +#define IGC_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE 0x00 +#define IGC_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE 0x01 + +/* Immediate Interrupt Receive */ +#define IGC_IMIR_CLEAR_MASK 0xF001FFFF /* IMIR Reg Clear Mask */ +#define IGC_IMIR_PORT_BYPASS 0x20000 /* IMIR Port Bypass Bit */ +#define IGC_IMIR_PRIORITY_SHIFT 29 /* IMIR Priority Shift */ +#define IGC_IMIREXT_CLEAR_MASK 0x7FFFF /* IMIREXT Reg Clear Mask */ + +/* Immediate Interrupt Receive Extended */ +#define IGC_IMIREXT_CTRL_BP 0x00080000 /* Bypass check of ctrl bits */ +#define IGC_IMIREXT_SIZE_BP 0x00001000 /* Packet size bypass */ + +/* Time Sync Transmit Control bit definitions */ +#define IGC_TSYNCTXCTL_TXTT_0 0x00000001 /* Tx timestamp reg 0 valid */ +#define IGC_TSYNCTXCTL_ENABLED 0x00000010 /* enable Tx timestamping */ +#define IGC_TSYNCTXCTL_MAX_ALLOWED_DLY_MASK 0x0000F000 /* max delay */ +#define IGC_TSYNCTXCTL_SYNC_COMP_ERR 0x20000000 /* sync err */ +#define IGC_TSYNCTXCTL_SYNC_COMP 0x40000000 /* sync complete */ +#define IGC_TSYNCTXCTL_START_SYNC 0x80000000 /* initiate sync */ +#define IGC_TSYNCTXCTL_TXSYNSIG 0x00000020 /* Sample TX tstamp in PHY sop */ + +/* Transmit Scheduling */ +#define IGC_TQAVCTRL_TRANSMIT_MODE_TSN 0x00000001 +#define IGC_TQAVCTRL_ENHANCED_QAV 0x00000008 + +#define IGC_TXQCTL_QUEUE_MODE_LAUNCHT 0x00000001 +#define IGC_TXQCTL_STRICT_CYCLE 0x00000002 +#define IGC_TXQCTL_STRICT_END 0x00000004 + +/* Receive Checksum Control */ +#define IGC_RXCSUM_CRCOFL 0x00000800 /* CRC32 offload enable */ +#define IGC_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */ + +/* GPY211 - I225 defines */ +#define GPY_MMD_MASK 0xFFFF0000 +#define GPY_MMD_SHIFT 16 +#define GPY_REG_MASK 0x0000FFFF + +#define IGC_MMDAC_FUNC_DATA 0x4000 /* Data, no post increment */ + +/* MAC definitions */ +#define IGC_FACTPS_MNGCG 0x20000000 +#define IGC_FWSM_MODE_MASK 0xE +#define IGC_FWSM_MODE_SHIFT 1 + +/* Management Control */ +#define IGC_MANC_SMBUS_EN 0x00000001 /* SMBus Enabled - RO */ +#define IGC_MANC_ASF_EN 0x00000002 /* ASF Enabled - RO */ + +/* PHY */ +#define PHY_REVISION_MASK 0xFFFFFFF0 +#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ +#define IGC_GEN_POLL_TIMEOUT 1920 + +/* PHY Control Register */ +#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */ +#define MII_CR_POWER_DOWN 0x0800 /* Power down */ +#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */ +#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */ +#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */ +#define MII_CR_SPEED_1000 0x0040 +#define MII_CR_SPEED_100 0x2000 +#define MII_CR_SPEED_10 0x0000 + +/* PHY Status Register */ +#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */ +#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */ +#define IGC_PHY_RST_COMP 0x0100 /* Internal PHY reset completion */ + +/* PHY 1000 MII Register/Bit Definitions */ +/* PHY Registers defined by IEEE */ +#define PHY_CONTROL 0x00 /* Control Register */ +#define PHY_STATUS 0x01 /* Status Register */ +#define PHY_ID1 0x02 /* Phy Id Reg (word 1) */ +#define PHY_ID2 0x03 /* Phy Id Reg (word 2) */ +#define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */ +#define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */ +#define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */ +#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */ + +/* MDI Control */ +#define IGC_MDIC_DATA_MASK 0x0000FFFF +#define IGC_MDIC_REG_MASK 0x001F0000 +#define IGC_MDIC_REG_SHIFT 16 +#define IGC_MDIC_PHY_MASK 0x03E00000 +#define IGC_MDIC_PHY_SHIFT 21 +#define IGC_MDIC_OP_WRITE 0x04000000 +#define IGC_MDIC_OP_READ 0x08000000 +#define IGC_MDIC_READY 0x10000000 +#define IGC_MDIC_INT_EN 0x20000000 +#define IGC_MDIC_ERROR 0x40000000 + +#define IGC_N0_QUEUE -1 + +#define IGC_MAX_MAC_HDR_LEN 127 +#define IGC_MAX_NETWORK_HDR_LEN 511 + +#define IGC_VLANPQF_QSEL(_n, q_idx) ((q_idx) << ((_n) * 4)) +#define IGC_VLANPQF_VALID(_n) (0x1 << (3 + (_n) * 4)) +#define IGC_VLANPQF_QUEUE_MASK 0x03 + +#define IGC_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */ +#define IGC_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type:1=IPv4 */ +#define IGC_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet Type of TCP */ +#define IGC_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 packet TYPE of SCTP */ + +/* Maximum size of the MTA register table in all supported adapters */ +#define MAX_MTA_REG 128 + +/* EEE defines */ +#define IGC_IPCNFG_EEE_2_5G_AN 0x00000010 /* IPCNFG EEE Ena 2.5G AN */ +#define IGC_IPCNFG_EEE_1G_AN 0x00000008 /* IPCNFG EEE Ena 1G AN */ +#define IGC_IPCNFG_EEE_100M_AN 0x00000004 /* IPCNFG EEE Ena 100M AN */ +#define IGC_EEER_EEE_NEG 0x20000000 /* EEE capability nego */ +#define IGC_EEER_TX_LPI_EN 0x00010000 /* EEER Tx LPI Enable */ +#define IGC_EEER_RX_LPI_EN 0x00020000 /* EEER Rx LPI Enable */ +#define IGC_EEER_LPI_FC 0x00040000 /* EEER Ena on Flow Cntrl */ +#define IGC_EEE_SU_LPI_CLK_STP 0x00800000 /* EEE LPI Clock Stop */ + +/* LTR defines */ +#define IGC_LTRC_EEEMS_EN 0x00000020 /* Enable EEE LTR max send */ +#define IGC_RXPBS_SIZE_I225_MASK 0x0000003F /* Rx packet buffer size */ +#define IGC_TW_SYSTEM_1000_MASK 0x000000FF +/* Minimum time for 100BASE-T where no data will be transmit following move out + * of EEE LPI Tx state + */ +#define IGC_TW_SYSTEM_100_MASK 0x0000FF00 +#define IGC_TW_SYSTEM_100_SHIFT 8 +#define IGC_DMACR_DMAC_EN 0x80000000 /* Enable DMA Coalescing */ +#define IGC_DMACR_DMACTHR_MASK 0x00FF0000 +#define IGC_DMACR_DMACTHR_SHIFT 16 +/* Reg val to set scale to 1024 nsec */ +#define IGC_LTRMINV_SCALE_1024 2 +/* Reg val to set scale to 32768 nsec */ +#define IGC_LTRMINV_SCALE_32768 3 +/* Reg val to set scale to 1024 nsec */ +#define IGC_LTRMAXV_SCALE_1024 2 +/* Reg val to set scale to 32768 nsec */ +#define IGC_LTRMAXV_SCALE_32768 3 +#define IGC_LTRMINV_LTRV_MASK 0x000003FF /* LTR minimum value */ +#define IGC_LTRMAXV_LTRV_MASK 0x000003FF /* LTR maximum value */ +#define IGC_LTRMINV_LSNP_REQ 0x00008000 /* LTR Snoop Requirement */ +#define IGC_LTRMINV_SCALE_SHIFT 10 +#define IGC_LTRMAXV_LSNP_REQ 0x00008000 /* LTR Snoop Requirement */ +#define IGC_LTRMAXV_SCALE_SHIFT 10 + +#endif /* _IGC_DEFINES_H_ */ diff --git a/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_diag.c b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_diag.c new file mode 100644 index 00000000..cc621970 --- /dev/null +++ b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_diag.c @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2020 Intel Corporation */ + +#include "igc.h" +#include "igc_diag.h" + +static struct igc_reg_test reg_test[] = { + { IGC_FCAL, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, + { IGC_FCAH, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF }, + { IGC_FCT, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF }, + { IGC_RDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, + { IGC_RDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFF80 }, + { IGC_RDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, + { IGC_RDT(0), 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, + { IGC_FCRTH, 1, PATTERN_TEST, 0x0003FFF0, 0x0003FFF0 }, + { IGC_FCTTV, 1, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, + { IGC_TIPG, 1, PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF }, + { IGC_TDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, + { IGC_TDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFF80 }, + { IGC_TDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, + { IGC_TDT(0), 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, + { IGC_RCTL, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 }, + { IGC_RCTL, 1, SET_READ_TEST, 0x04CFB2FE, 0x003FFFFB }, + { IGC_RCTL, 1, SET_READ_TEST, 0x04CFB2FE, 0xFFFFFFFF }, + { IGC_TCTL, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 }, + { IGC_RA, 16, TABLE64_TEST_LO, + 0xFFFFFFFF, 0xFFFFFFFF }, + { IGC_RA, 16, TABLE64_TEST_HI, + 0x900FFFFF, 0xFFFFFFFF }, + { IGC_MTA, 128, TABLE32_TEST, + 0xFFFFFFFF, 0xFFFFFFFF }, + { 0, 0, 0, 0} +}; + +static bool reg_pattern_test(struct igc_adapter *adapter, u64 *data, int reg, + u32 mask, u32 write) +{ + struct igc_hw *hw = &adapter->hw; + u32 pat, val, before; + static const u32 test_pattern[] = { + 0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF + }; + + for (pat = 0; pat < ARRAY_SIZE(test_pattern); pat++) { + before = rd32(reg); + wr32(reg, test_pattern[pat] & write); + val = rd32(reg); + if (val != (test_pattern[pat] & write & mask)) { + netdev_err(adapter->netdev, + "pattern test reg %04X failed: got 0x%08X expected 0x%08X", + reg, val, test_pattern[pat] & write & mask); + *data = reg; + wr32(reg, before); + return false; + } + wr32(reg, before); + } + return true; +} + +static bool reg_set_and_check(struct igc_adapter *adapter, u64 *data, int reg, + u32 mask, u32 write) +{ + struct igc_hw *hw = &adapter->hw; + u32 val, before; + + before = rd32(reg); + wr32(reg, write & mask); + val = rd32(reg); + if ((write & mask) != (val & mask)) { + netdev_err(adapter->netdev, + "set/check reg %04X test failed: got 0x%08X expected 0x%08X", + reg, (val & mask), (write & mask)); + *data = reg; + wr32(reg, before); + return false; + } + wr32(reg, before); + return true; +} + +bool igc_reg_test(struct igc_adapter *adapter, u64 *data) +{ + struct igc_reg_test *test = reg_test; + struct igc_hw *hw = &adapter->hw; + u32 value, before, after; + u32 i, toggle, b = false; + + /* Because the status register is such a special case, + * we handle it separately from the rest of the register + * tests. Some bits are read-only, some toggle, and some + * are writeable. + */ + toggle = 0x6800D3; + before = rd32(IGC_STATUS); + value = before & toggle; + wr32(IGC_STATUS, toggle); + after = rd32(IGC_STATUS) & toggle; + if (value != after) { + netdev_err(adapter->netdev, + "failed STATUS register test got: 0x%08X expected: 0x%08X", + after, value); + *data = 1; + return false; + } + /* restore previous status */ + wr32(IGC_STATUS, before); + + /* Perform the remainder of the register test, looping through + * the test table until we either fail or reach the null entry. + */ + while (test->reg) { + for (i = 0; i < test->array_len; i++) { + switch (test->test_type) { + case PATTERN_TEST: + b = reg_pattern_test(adapter, data, + test->reg + (i * 0x40), + test->mask, + test->write); + break; + case SET_READ_TEST: + b = reg_set_and_check(adapter, data, + test->reg + (i * 0x40), + test->mask, + test->write); + break; + case TABLE64_TEST_LO: + b = reg_pattern_test(adapter, data, + test->reg + (i * 8), + test->mask, + test->write); + break; + case TABLE64_TEST_HI: + b = reg_pattern_test(adapter, data, + test->reg + 4 + (i * 8), + test->mask, + test->write); + break; + case TABLE32_TEST: + b = reg_pattern_test(adapter, data, + test->reg + (i * 4), + test->mask, + test->write); + break; + } + if (!b) + return false; + } + test++; + } + *data = 0; + return true; +} + +bool igc_eeprom_test(struct igc_adapter *adapter, u64 *data) +{ + struct igc_hw *hw = &adapter->hw; + + *data = 0; + + if (hw->nvm.ops.validate(hw) != IGC_SUCCESS) { + *data = 1; + return false; + } + + return true; +} + +bool igc_link_test(struct igc_adapter *adapter, u64 *data) +{ + bool link_up; + + *data = 0; + + /* add delay to give enough time for autonegotioation to finish */ + if (adapter->hw.mac.autoneg) + ssleep(5); + + link_up = igc_has_link(adapter); + if (!link_up) { + *data = 1; + return false; + } + + return true; +} diff --git a/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_diag.h b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_diag.h new file mode 100644 index 00000000..600658e3 --- /dev/null +++ b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_diag.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2020 Intel Corporation */ + +bool igc_reg_test(struct igc_adapter *adapter, u64 *data); +bool igc_eeprom_test(struct igc_adapter *adapter, u64 *data); +bool igc_link_test(struct igc_adapter *adapter, u64 *data); + +struct igc_reg_test { + u16 reg; + u8 array_len; + u8 test_type; + u32 mask; + u32 write; +}; + +/* In the hardware, registers are laid out either singly, in arrays + * spaced 0x40 bytes apart, or in contiguous tables. We assume + * most tests take place on arrays or single registers (handled + * as a single-element array) and special-case the tables. + * Table tests are always pattern tests. + * + * We also make provision for some required setup steps by specifying + * registers to be written without any read-back testing. + */ + +#define PATTERN_TEST 1 +#define SET_READ_TEST 2 +#define TABLE32_TEST 3 +#define TABLE64_TEST_LO 4 +#define TABLE64_TEST_HI 5 diff --git a/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_dump.c b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_dump.c new file mode 100644 index 00000000..4b9ec7d0 --- /dev/null +++ b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_dump.c @@ -0,0 +1,318 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2018 Intel Corporation */ + +#include "igc.h" + +struct igc_reg_info { + u32 ofs; + char *name; +}; + +static const struct igc_reg_info igc_reg_info_tbl[] = { + /* General Registers */ + {IGC_CTRL, "CTRL"}, + {IGC_STATUS, "STATUS"}, + {IGC_CTRL_EXT, "CTRL_EXT"}, + {IGC_MDIC, "MDIC"}, + + /* Interrupt Registers */ + {IGC_ICR, "ICR"}, + + /* RX Registers */ + {IGC_RCTL, "RCTL"}, + {IGC_RDLEN(0), "RDLEN"}, + {IGC_RDH(0), "RDH"}, + {IGC_RDT(0), "RDT"}, + {IGC_RXDCTL(0), "RXDCTL"}, + {IGC_RDBAL(0), "RDBAL"}, + {IGC_RDBAH(0), "RDBAH"}, + + /* TX Registers */ + {IGC_TCTL, "TCTL"}, + {IGC_TDBAL(0), "TDBAL"}, + {IGC_TDBAH(0), "TDBAH"}, + {IGC_TDLEN(0), "TDLEN"}, + {IGC_TDH(0), "TDH"}, + {IGC_TDT(0), "TDT"}, + {IGC_TXDCTL(0), "TXDCTL"}, + + /* List Terminator */ + {} +}; + +/* igc_regdump - register printout routine */ +static void igc_regdump(struct igc_hw *hw, struct igc_reg_info *reginfo) +{ + struct net_device *dev = igc_get_hw_dev(hw); + int n = 0; + char rname[16]; + u32 regs[8]; + + switch (reginfo->ofs) { + case IGC_RDLEN(0): + for (n = 0; n < 4; n++) + regs[n] = rd32(IGC_RDLEN(n)); + break; + case IGC_RDH(0): + for (n = 0; n < 4; n++) + regs[n] = rd32(IGC_RDH(n)); + break; + case IGC_RDT(0): + for (n = 0; n < 4; n++) + regs[n] = rd32(IGC_RDT(n)); + break; + case IGC_RXDCTL(0): + for (n = 0; n < 4; n++) + regs[n] = rd32(IGC_RXDCTL(n)); + break; + case IGC_RDBAL(0): + for (n = 0; n < 4; n++) + regs[n] = rd32(IGC_RDBAL(n)); + break; + case IGC_RDBAH(0): + for (n = 0; n < 4; n++) + regs[n] = rd32(IGC_RDBAH(n)); + break; + case IGC_TDBAL(0): + for (n = 0; n < 4; n++) + regs[n] = rd32(IGC_RDBAL(n)); + break; + case IGC_TDBAH(0): + for (n = 0; n < 4; n++) + regs[n] = rd32(IGC_TDBAH(n)); + break; + case IGC_TDLEN(0): + for (n = 0; n < 4; n++) + regs[n] = rd32(IGC_TDLEN(n)); + break; + case IGC_TDH(0): + for (n = 0; n < 4; n++) + regs[n] = rd32(IGC_TDH(n)); + break; + case IGC_TDT(0): + for (n = 0; n < 4; n++) + regs[n] = rd32(IGC_TDT(n)); + break; + case IGC_TXDCTL(0): + for (n = 0; n < 4; n++) + regs[n] = rd32(IGC_TXDCTL(n)); + break; + default: + netdev_info(dev, "%-15s %08x\n", reginfo->name, + rd32(reginfo->ofs)); + return; + } + + snprintf(rname, 16, "%s%s", reginfo->name, "[0-3]"); + netdev_info(dev, "%-15s %08x %08x %08x %08x\n", rname, regs[0], regs[1], + regs[2], regs[3]); +} + +/* igc_rings_dump - Tx-rings and Rx-rings */ +void igc_rings_dump(struct igc_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + struct my_u0 { u64 a; u64 b; } *u0; + union igc_adv_tx_desc *tx_desc; + union igc_adv_rx_desc *rx_desc; + struct igc_ring *tx_ring; + struct igc_ring *rx_ring; + u32 staterr; + u16 i, n; + + if (!netif_msg_hw(adapter)) + return; + + netdev_info(netdev, "Device info: state %016lX trans_start %016lX\n", + netdev->state, dev_trans_start(netdev)); + + /* Print TX Ring Summary */ + if (!netif_running(netdev)) + goto exit; + + netdev_info(netdev, "TX Rings Summary\n"); + netdev_info(netdev, "Queue [NTU] [NTC] [bi(ntc)->dma ] leng ntw timestamp\n"); + for (n = 0; n < adapter->num_tx_queues; n++) { + struct igc_tx_buffer *buffer_info; + + tx_ring = adapter->tx_ring[n]; + buffer_info = &tx_ring->tx_buffer_info[tx_ring->next_to_clean]; + + netdev_info(netdev, "%5d %5X %5X %016llX %04X %p %016llX\n", + n, tx_ring->next_to_use, tx_ring->next_to_clean, + (u64)dma_unmap_addr(buffer_info, dma), + dma_unmap_len(buffer_info, len), + buffer_info->next_to_watch, + (u64)buffer_info->time_stamp); + } + + /* Print TX Rings */ + if (!netif_msg_tx_done(adapter)) + goto rx_ring_summary; + + netdev_info(netdev, "TX Rings Dump\n"); + + /* Transmit Descriptor Formats + * + * Advanced Transmit Descriptor + * +--------------------------------------------------------------+ + * 0 | Buffer Address [63:0] | + * +--------------------------------------------------------------+ + * 8 | PAYLEN | PORTS |CC|IDX | STA | DCMD |DTYP|MAC|RSV| DTALEN | + * +--------------------------------------------------------------+ + * 63 46 45 40 39 38 36 35 32 31 24 15 0 + */ + + for (n = 0; n < adapter->num_tx_queues; n++) { + tx_ring = adapter->tx_ring[n]; + netdev_info(netdev, "------------------------------------\n"); + netdev_info(netdev, "TX QUEUE INDEX = %d\n", + tx_ring->queue_index); + netdev_info(netdev, "------------------------------------\n"); + netdev_info(netdev, "T [desc] [address 63:0 ] [PlPOCIStDDM Ln] [bi->dma ] leng ntw timestamp bi->skb\n"); + + for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) { + const char *next_desc; + struct igc_tx_buffer *buffer_info; + + tx_desc = IGC_TX_DESC(tx_ring, i); + buffer_info = &tx_ring->tx_buffer_info[i]; + u0 = (struct my_u0 *)tx_desc; + if (i == tx_ring->next_to_use && + i == tx_ring->next_to_clean) + next_desc = " NTC/U"; + else if (i == tx_ring->next_to_use) + next_desc = " NTU"; + else if (i == tx_ring->next_to_clean) + next_desc = " NTC"; + else + next_desc = ""; + + netdev_info(netdev, "T [0x%03X] %016llX %016llX %016llX %04X %p %016llX %p%s\n", + i, le64_to_cpu(u0->a), + le64_to_cpu(u0->b), + (u64)dma_unmap_addr(buffer_info, dma), + dma_unmap_len(buffer_info, len), + buffer_info->next_to_watch, + (u64)buffer_info->time_stamp, + buffer_info->skb, next_desc); + + if (netif_msg_pktdata(adapter) && buffer_info->skb) + print_hex_dump(KERN_INFO, "", + DUMP_PREFIX_ADDRESS, + 16, 1, buffer_info->skb->data, + dma_unmap_len(buffer_info, len), + true); + } + } + + /* Print RX Rings Summary */ +rx_ring_summary: + netdev_info(netdev, "RX Rings Summary\n"); + netdev_info(netdev, "Queue [NTU] [NTC]\n"); + for (n = 0; n < adapter->num_rx_queues; n++) { + rx_ring = adapter->rx_ring[n]; + netdev_info(netdev, "%5d %5X %5X\n", n, rx_ring->next_to_use, + rx_ring->next_to_clean); + } + + /* Print RX Rings */ + if (!netif_msg_rx_status(adapter)) + goto exit; + + netdev_info(netdev, "RX Rings Dump\n"); + + /* Advanced Receive Descriptor (Read) Format + * 63 1 0 + * +-----------------------------------------------------+ + * 0 | Packet Buffer Address [63:1] |A0/NSE| + * +----------------------------------------------+------+ + * 8 | Header Buffer Address [63:1] | DD | + * +-----------------------------------------------------+ + * + * + * Advanced Receive Descriptor (Write-Back) Format + * + * 63 48 47 32 31 30 21 20 17 16 4 3 0 + * +------------------------------------------------------+ + * 0 | Packet IP |SPH| HDR_LEN | RSV|Packet| RSS | + * | Checksum Ident | | | | Type | Type | + * +------------------------------------------------------+ + * 8 | VLAN Tag | Length | Extended Error | Extended Status | + * +------------------------------------------------------+ + * 63 48 47 32 31 20 19 0 + */ + + for (n = 0; n < adapter->num_rx_queues; n++) { + rx_ring = adapter->rx_ring[n]; + netdev_info(netdev, "------------------------------------\n"); + netdev_info(netdev, "RX QUEUE INDEX = %d\n", + rx_ring->queue_index); + netdev_info(netdev, "------------------------------------\n"); + netdev_info(netdev, "R [desc] [ PktBuf A0] [ HeadBuf DD] [bi->dma ] [bi->skb] <-- Adv Rx Read format\n"); + netdev_info(netdev, "RWB[desc] [PcsmIpSHl PtRs] [vl er S cks ln] ---------------- [bi->skb] <-- Adv Rx Write-Back format\n"); + + for (i = 0; i < rx_ring->count; i++) { + const char *next_desc; + struct igc_rx_buffer *buffer_info; + + buffer_info = &rx_ring->rx_buffer_info[i]; + rx_desc = IGC_RX_DESC(rx_ring, i); + u0 = (struct my_u0 *)rx_desc; + staterr = le32_to_cpu(rx_desc->wb.upper.status_error); + + if (i == rx_ring->next_to_use) + next_desc = " NTU"; + else if (i == rx_ring->next_to_clean) + next_desc = " NTC"; + else + next_desc = ""; + + if (staterr & IGC_RXD_STAT_DD) { + /* Descriptor Done */ + netdev_info(netdev, "%s[0x%03X] %016llX %016llX ---------------- %s\n", + "RWB", i, + le64_to_cpu(u0->a), + le64_to_cpu(u0->b), + next_desc); + } else { + netdev_info(netdev, "%s[0x%03X] %016llX %016llX %016llX %s\n", + "R ", i, + le64_to_cpu(u0->a), + le64_to_cpu(u0->b), + (u64)buffer_info->dma, + next_desc); + + if (netif_msg_pktdata(adapter) && + buffer_info->dma && buffer_info->page) { + print_hex_dump(KERN_INFO, "", + DUMP_PREFIX_ADDRESS, + 16, 1, + page_address + (buffer_info->page) + + buffer_info->page_offset, + igc_rx_bufsz(rx_ring), + true); + } + } + } + } + +exit: + return; +} + +/* igc_regs_dump - registers dump */ +void igc_regs_dump(struct igc_adapter *adapter) +{ + struct igc_hw *hw = &adapter->hw; + struct igc_reg_info *reginfo; + + /* Print Registers */ + netdev_info(adapter->netdev, "Register Dump\n"); + netdev_info(adapter->netdev, "Register Name Value\n"); + for (reginfo = (struct igc_reg_info *)igc_reg_info_tbl; + reginfo->name; reginfo++) { + igc_regdump(hw, reginfo); + } +} diff --git a/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_ethtool.c b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_ethtool.c new file mode 100644 index 00000000..4b260891 --- /dev/null +++ b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_ethtool.c @@ -0,0 +1,1945 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2018 Intel Corporation */ + +/* ethtool support for igc */ +#include +#include +#include + +#include "igc.h" +#include "igc_diag.h" + +/* forward declaration */ +struct igc_stats { + char stat_string[ETH_GSTRING_LEN]; + int sizeof_stat; + int stat_offset; +}; + +#define IGC_STAT(_name, _stat) { \ + .stat_string = _name, \ + .sizeof_stat = sizeof_field(struct igc_adapter, _stat), \ + .stat_offset = offsetof(struct igc_adapter, _stat) \ +} + +static const struct igc_stats igc_gstrings_stats[] = { + IGC_STAT("rx_packets", stats.gprc), + IGC_STAT("tx_packets", stats.gptc), + IGC_STAT("rx_bytes", stats.gorc), + IGC_STAT("tx_bytes", stats.gotc), + IGC_STAT("rx_broadcast", stats.bprc), + IGC_STAT("tx_broadcast", stats.bptc), + IGC_STAT("rx_multicast", stats.mprc), + IGC_STAT("tx_multicast", stats.mptc), + IGC_STAT("multicast", stats.mprc), + IGC_STAT("collisions", stats.colc), + IGC_STAT("rx_crc_errors", stats.crcerrs), + IGC_STAT("rx_no_buffer_count", stats.rnbc), + IGC_STAT("rx_missed_errors", stats.mpc), + IGC_STAT("tx_aborted_errors", stats.ecol), + IGC_STAT("tx_carrier_errors", stats.tncrs), + IGC_STAT("tx_window_errors", stats.latecol), + IGC_STAT("tx_abort_late_coll", stats.latecol), + IGC_STAT("tx_deferred_ok", stats.dc), + IGC_STAT("tx_single_coll_ok", stats.scc), + IGC_STAT("tx_multi_coll_ok", stats.mcc), + IGC_STAT("tx_timeout_count", tx_timeout_count), + IGC_STAT("rx_long_length_errors", stats.roc), + IGC_STAT("rx_short_length_errors", stats.ruc), + IGC_STAT("rx_align_errors", stats.algnerrc), + IGC_STAT("tx_tcp_seg_good", stats.tsctc), + IGC_STAT("tx_tcp_seg_failed", stats.tsctfc), + IGC_STAT("rx_flow_control_xon", stats.xonrxc), + IGC_STAT("rx_flow_control_xoff", stats.xoffrxc), + IGC_STAT("tx_flow_control_xon", stats.xontxc), + IGC_STAT("tx_flow_control_xoff", stats.xofftxc), + IGC_STAT("rx_long_byte_count", stats.gorc), + IGC_STAT("tx_dma_out_of_sync", stats.doosync), + IGC_STAT("tx_smbus", stats.mgptc), + IGC_STAT("rx_smbus", stats.mgprc), + IGC_STAT("dropped_smbus", stats.mgpdc), + IGC_STAT("os2bmc_rx_by_bmc", stats.o2bgptc), + IGC_STAT("os2bmc_tx_by_bmc", stats.b2ospc), + IGC_STAT("os2bmc_tx_by_host", stats.o2bspc), + IGC_STAT("os2bmc_rx_by_host", stats.b2ogprc), + IGC_STAT("tx_hwtstamp_timeouts", tx_hwtstamp_timeouts), + IGC_STAT("tx_hwtstamp_skipped", tx_hwtstamp_skipped), + IGC_STAT("rx_hwtstamp_cleared", rx_hwtstamp_cleared), +}; + +#define IGC_NETDEV_STAT(_net_stat) { \ + .stat_string = __stringify(_net_stat), \ + .sizeof_stat = sizeof_field(struct rtnl_link_stats64, _net_stat), \ + .stat_offset = offsetof(struct rtnl_link_stats64, _net_stat) \ +} + +static const struct igc_stats igc_gstrings_net_stats[] = { + IGC_NETDEV_STAT(rx_errors), + IGC_NETDEV_STAT(tx_errors), + IGC_NETDEV_STAT(tx_dropped), + IGC_NETDEV_STAT(rx_length_errors), + IGC_NETDEV_STAT(rx_over_errors), + IGC_NETDEV_STAT(rx_frame_errors), + IGC_NETDEV_STAT(rx_fifo_errors), + IGC_NETDEV_STAT(tx_fifo_errors), + IGC_NETDEV_STAT(tx_heartbeat_errors) +}; + +enum igc_diagnostics_results { + TEST_REG = 0, + TEST_EEP, + TEST_IRQ, + TEST_LOOP, + TEST_LINK +}; + +static const char igc_gstrings_test[][ETH_GSTRING_LEN] = { + [TEST_REG] = "Register test (offline)", + [TEST_EEP] = "Eeprom test (offline)", + [TEST_IRQ] = "Interrupt test (offline)", + [TEST_LOOP] = "Loopback test (offline)", + [TEST_LINK] = "Link test (on/offline)" +}; + +#define IGC_TEST_LEN (sizeof(igc_gstrings_test) / ETH_GSTRING_LEN) + +#define IGC_GLOBAL_STATS_LEN \ + (sizeof(igc_gstrings_stats) / sizeof(struct igc_stats)) +#define IGC_NETDEV_STATS_LEN \ + (sizeof(igc_gstrings_net_stats) / sizeof(struct igc_stats)) +#define IGC_RX_QUEUE_STATS_LEN \ + (sizeof(struct igc_rx_queue_stats) / sizeof(u64)) +#define IGC_TX_QUEUE_STATS_LEN 3 /* packets, bytes, restart_queue */ +#define IGC_QUEUE_STATS_LEN \ + ((((struct igc_adapter *)netdev_priv(netdev))->num_rx_queues * \ + IGC_RX_QUEUE_STATS_LEN) + \ + (((struct igc_adapter *)netdev_priv(netdev))->num_tx_queues * \ + IGC_TX_QUEUE_STATS_LEN)) +#define IGC_STATS_LEN \ + (IGC_GLOBAL_STATS_LEN + IGC_NETDEV_STATS_LEN + IGC_QUEUE_STATS_LEN) + +static const char igc_priv_flags_strings[][ETH_GSTRING_LEN] = { +#define IGC_PRIV_FLAGS_LEGACY_RX BIT(0) + "legacy-rx", +}; + +#define IGC_PRIV_FLAGS_STR_LEN ARRAY_SIZE(igc_priv_flags_strings) + +static void igc_ethtool_get_drvinfo(struct net_device *netdev, + struct ethtool_drvinfo *drvinfo) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + + strlcpy(drvinfo->driver, igc_driver_name, sizeof(drvinfo->driver)); + + /* add fw_version here */ + strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), + sizeof(drvinfo->bus_info)); + + drvinfo->n_priv_flags = IGC_PRIV_FLAGS_STR_LEN; +} + +static int igc_ethtool_get_regs_len(struct net_device *netdev) +{ + return IGC_REGS_LEN * sizeof(u32); +} + +static void igc_ethtool_get_regs(struct net_device *netdev, + struct ethtool_regs *regs, void *p) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct igc_hw *hw = &adapter->hw; + u32 *regs_buff = p; + u8 i; + + memset(p, 0, IGC_REGS_LEN * sizeof(u32)); + + regs->version = (2u << 24) | (hw->revision_id << 16) | hw->device_id; + + /* General Registers */ + regs_buff[0] = rd32(IGC_CTRL); + regs_buff[1] = rd32(IGC_STATUS); + regs_buff[2] = rd32(IGC_CTRL_EXT); + regs_buff[3] = rd32(IGC_MDIC); + regs_buff[4] = rd32(IGC_CONNSW); + + /* NVM Register */ + regs_buff[5] = rd32(IGC_EECD); + + /* Interrupt */ + /* Reading EICS for EICR because they read the + * same but EICS does not clear on read + */ + regs_buff[6] = rd32(IGC_EICS); + regs_buff[7] = rd32(IGC_EICS); + regs_buff[8] = rd32(IGC_EIMS); + regs_buff[9] = rd32(IGC_EIMC); + regs_buff[10] = rd32(IGC_EIAC); + regs_buff[11] = rd32(IGC_EIAM); + /* Reading ICS for ICR because they read the + * same but ICS does not clear on read + */ + regs_buff[12] = rd32(IGC_ICS); + regs_buff[13] = rd32(IGC_ICS); + regs_buff[14] = rd32(IGC_IMS); + regs_buff[15] = rd32(IGC_IMC); + regs_buff[16] = rd32(IGC_IAC); + regs_buff[17] = rd32(IGC_IAM); + + /* Flow Control */ + regs_buff[18] = rd32(IGC_FCAL); + regs_buff[19] = rd32(IGC_FCAH); + regs_buff[20] = rd32(IGC_FCTTV); + regs_buff[21] = rd32(IGC_FCRTL); + regs_buff[22] = rd32(IGC_FCRTH); + regs_buff[23] = rd32(IGC_FCRTV); + + /* Receive */ + regs_buff[24] = rd32(IGC_RCTL); + regs_buff[25] = rd32(IGC_RXCSUM); + regs_buff[26] = rd32(IGC_RLPML); + regs_buff[27] = rd32(IGC_RFCTL); + + /* Transmit */ + regs_buff[28] = rd32(IGC_TCTL); + regs_buff[29] = rd32(IGC_TIPG); + + /* Wake Up */ + + /* MAC */ + + /* Statistics */ + regs_buff[30] = adapter->stats.crcerrs; + regs_buff[31] = adapter->stats.algnerrc; + regs_buff[32] = adapter->stats.symerrs; + regs_buff[33] = adapter->stats.rxerrc; + regs_buff[34] = adapter->stats.mpc; + regs_buff[35] = adapter->stats.scc; + regs_buff[36] = adapter->stats.ecol; + regs_buff[37] = adapter->stats.mcc; + regs_buff[38] = adapter->stats.latecol; + regs_buff[39] = adapter->stats.colc; + regs_buff[40] = adapter->stats.dc; + regs_buff[41] = adapter->stats.tncrs; + regs_buff[42] = adapter->stats.sec; + regs_buff[43] = adapter->stats.htdpmc; + regs_buff[44] = adapter->stats.rlec; + regs_buff[45] = adapter->stats.xonrxc; + regs_buff[46] = adapter->stats.xontxc; + regs_buff[47] = adapter->stats.xoffrxc; + regs_buff[48] = adapter->stats.xofftxc; + regs_buff[49] = adapter->stats.fcruc; + regs_buff[50] = adapter->stats.prc64; + regs_buff[51] = adapter->stats.prc127; + regs_buff[52] = adapter->stats.prc255; + regs_buff[53] = adapter->stats.prc511; + regs_buff[54] = adapter->stats.prc1023; + regs_buff[55] = adapter->stats.prc1522; + regs_buff[56] = adapter->stats.gprc; + regs_buff[57] = adapter->stats.bprc; + regs_buff[58] = adapter->stats.mprc; + regs_buff[59] = adapter->stats.gptc; + regs_buff[60] = adapter->stats.gorc; + regs_buff[61] = adapter->stats.gotc; + regs_buff[62] = adapter->stats.rnbc; + regs_buff[63] = adapter->stats.ruc; + regs_buff[64] = adapter->stats.rfc; + regs_buff[65] = adapter->stats.roc; + regs_buff[66] = adapter->stats.rjc; + regs_buff[67] = adapter->stats.mgprc; + regs_buff[68] = adapter->stats.mgpdc; + regs_buff[69] = adapter->stats.mgptc; + regs_buff[70] = adapter->stats.tor; + regs_buff[71] = adapter->stats.tot; + regs_buff[72] = adapter->stats.tpr; + regs_buff[73] = adapter->stats.tpt; + regs_buff[74] = adapter->stats.ptc64; + regs_buff[75] = adapter->stats.ptc127; + regs_buff[76] = adapter->stats.ptc255; + regs_buff[77] = adapter->stats.ptc511; + regs_buff[78] = adapter->stats.ptc1023; + regs_buff[79] = adapter->stats.ptc1522; + regs_buff[80] = adapter->stats.mptc; + regs_buff[81] = adapter->stats.bptc; + regs_buff[82] = adapter->stats.tsctc; + regs_buff[83] = adapter->stats.iac; + regs_buff[84] = adapter->stats.rpthc; + regs_buff[85] = adapter->stats.hgptc; + regs_buff[86] = adapter->stats.hgorc; + regs_buff[87] = adapter->stats.hgotc; + regs_buff[88] = adapter->stats.lenerrs; + regs_buff[89] = adapter->stats.scvpc; + regs_buff[90] = adapter->stats.hrmpc; + + for (i = 0; i < 4; i++) + regs_buff[91 + i] = rd32(IGC_SRRCTL(i)); + for (i = 0; i < 4; i++) + regs_buff[95 + i] = rd32(IGC_PSRTYPE(i)); + for (i = 0; i < 4; i++) + regs_buff[99 + i] = rd32(IGC_RDBAL(i)); + for (i = 0; i < 4; i++) + regs_buff[103 + i] = rd32(IGC_RDBAH(i)); + for (i = 0; i < 4; i++) + regs_buff[107 + i] = rd32(IGC_RDLEN(i)); + for (i = 0; i < 4; i++) + regs_buff[111 + i] = rd32(IGC_RDH(i)); + for (i = 0; i < 4; i++) + regs_buff[115 + i] = rd32(IGC_RDT(i)); + for (i = 0; i < 4; i++) + regs_buff[119 + i] = rd32(IGC_RXDCTL(i)); + + for (i = 0; i < 10; i++) + regs_buff[123 + i] = rd32(IGC_EITR(i)); + for (i = 0; i < 16; i++) + regs_buff[139 + i] = rd32(IGC_RAL(i)); + for (i = 0; i < 16; i++) + regs_buff[145 + i] = rd32(IGC_RAH(i)); + + for (i = 0; i < 4; i++) + regs_buff[149 + i] = rd32(IGC_TDBAL(i)); + for (i = 0; i < 4; i++) + regs_buff[152 + i] = rd32(IGC_TDBAH(i)); + for (i = 0; i < 4; i++) + regs_buff[156 + i] = rd32(IGC_TDLEN(i)); + for (i = 0; i < 4; i++) + regs_buff[160 + i] = rd32(IGC_TDH(i)); + for (i = 0; i < 4; i++) + regs_buff[164 + i] = rd32(IGC_TDT(i)); + for (i = 0; i < 4; i++) + regs_buff[168 + i] = rd32(IGC_TXDCTL(i)); + + /* XXX: Due to a bug few lines above, RAL and RAH registers are + * overwritten. To preserve the ABI, we write these registers again in + * regs_buff. + */ + for (i = 0; i < 16; i++) + regs_buff[172 + i] = rd32(IGC_RAL(i)); + for (i = 0; i < 16; i++) + regs_buff[188 + i] = rd32(IGC_RAH(i)); + + regs_buff[204] = rd32(IGC_VLANPQF); + + for (i = 0; i < 8; i++) + regs_buff[205 + i] = rd32(IGC_ETQF(i)); + + regs_buff[213] = adapter->stats.tlpic; + regs_buff[214] = adapter->stats.rlpic; +} + +static void igc_ethtool_get_wol(struct net_device *netdev, + struct ethtool_wolinfo *wol) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + + wol->wolopts = 0; + + if (!(adapter->flags & IGC_FLAG_WOL_SUPPORTED)) + return; + + wol->supported = WAKE_UCAST | WAKE_MCAST | + WAKE_BCAST | WAKE_MAGIC | + WAKE_PHY; + + /* apply any specific unsupported masks here */ + switch (adapter->hw.device_id) { + default: + break; + } + + if (adapter->wol & IGC_WUFC_EX) + wol->wolopts |= WAKE_UCAST; + if (adapter->wol & IGC_WUFC_MC) + wol->wolopts |= WAKE_MCAST; + if (adapter->wol & IGC_WUFC_BC) + wol->wolopts |= WAKE_BCAST; + if (adapter->wol & IGC_WUFC_MAG) + wol->wolopts |= WAKE_MAGIC; + if (adapter->wol & IGC_WUFC_LNKC) + wol->wolopts |= WAKE_PHY; +} + +static int igc_ethtool_set_wol(struct net_device *netdev, + struct ethtool_wolinfo *wol) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + + if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE | WAKE_FILTER)) + return -EOPNOTSUPP; + + if (!(adapter->flags & IGC_FLAG_WOL_SUPPORTED)) + return wol->wolopts ? -EOPNOTSUPP : 0; + + /* these settings will always override what we currently have */ + adapter->wol = 0; + + if (wol->wolopts & WAKE_UCAST) + adapter->wol |= IGC_WUFC_EX; + if (wol->wolopts & WAKE_MCAST) + adapter->wol |= IGC_WUFC_MC; + if (wol->wolopts & WAKE_BCAST) + adapter->wol |= IGC_WUFC_BC; + if (wol->wolopts & WAKE_MAGIC) + adapter->wol |= IGC_WUFC_MAG; + if (wol->wolopts & WAKE_PHY) + adapter->wol |= IGC_WUFC_LNKC; + device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); + + return 0; +} + +static u32 igc_ethtool_get_msglevel(struct net_device *netdev) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + + return adapter->msg_enable; +} + +static void igc_ethtool_set_msglevel(struct net_device *netdev, u32 data) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + + adapter->msg_enable = data; +} + +static int igc_ethtool_nway_reset(struct net_device *netdev) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + + if (netif_running(netdev)) + igc_reinit_locked(adapter); + return 0; +} + +static u32 igc_ethtool_get_link(struct net_device *netdev) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct igc_mac_info *mac = &adapter->hw.mac; + + /* If the link is not reported up to netdev, interrupts are disabled, + * and so the physical link state may have changed since we last + * looked. Set get_link_status to make sure that the true link + * state is interrogated, rather than pulling a cached and possibly + * stale link state from the driver. + */ + if (!netif_carrier_ok(netdev)) + mac->get_link_status = 1; + + return igc_has_link(adapter); +} + +static int igc_ethtool_get_eeprom_len(struct net_device *netdev) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + + return adapter->hw.nvm.word_size * 2; +} + +static int igc_ethtool_get_eeprom(struct net_device *netdev, + struct ethtool_eeprom *eeprom, u8 *bytes) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct igc_hw *hw = &adapter->hw; + int first_word, last_word; + u16 *eeprom_buff; + int ret_val = 0; + u16 i; + + if (eeprom->len == 0) + return -EINVAL; + + eeprom->magic = hw->vendor_id | (hw->device_id << 16); + + first_word = eeprom->offset >> 1; + last_word = (eeprom->offset + eeprom->len - 1) >> 1; + + eeprom_buff = kmalloc_array(last_word - first_word + 1, sizeof(u16), + GFP_KERNEL); + if (!eeprom_buff) + return -ENOMEM; + + if (hw->nvm.type == igc_nvm_eeprom_spi) { + ret_val = hw->nvm.ops.read(hw, first_word, + last_word - first_word + 1, + eeprom_buff); + } else { + for (i = 0; i < last_word - first_word + 1; i++) { + ret_val = hw->nvm.ops.read(hw, first_word + i, 1, + &eeprom_buff[i]); + if (ret_val) + break; + } + } + + /* Device's eeprom is always little-endian, word addressable */ + for (i = 0; i < last_word - first_word + 1; i++) + le16_to_cpus(&eeprom_buff[i]); + + memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1), + eeprom->len); + kfree(eeprom_buff); + + return ret_val; +} + +static int igc_ethtool_set_eeprom(struct net_device *netdev, + struct ethtool_eeprom *eeprom, u8 *bytes) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct igc_hw *hw = &adapter->hw; + int max_len, first_word, last_word, ret_val = 0; + u16 *eeprom_buff; + void *ptr; + u16 i; + + if (eeprom->len == 0) + return -EOPNOTSUPP; + + if (hw->mac.type >= igc_i225 && + !igc_get_flash_presence_i225(hw)) { + return -EOPNOTSUPP; + } + + if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) + return -EFAULT; + + max_len = hw->nvm.word_size * 2; + + first_word = eeprom->offset >> 1; + last_word = (eeprom->offset + eeprom->len - 1) >> 1; + eeprom_buff = kmalloc(max_len, GFP_KERNEL); + if (!eeprom_buff) + return -ENOMEM; + + ptr = (void *)eeprom_buff; + + if (eeprom->offset & 1) { + /* need read/modify/write of first changed EEPROM word + * only the second byte of the word is being modified + */ + ret_val = hw->nvm.ops.read(hw, first_word, 1, + &eeprom_buff[0]); + ptr++; + } + if (((eeprom->offset + eeprom->len) & 1) && ret_val == 0) { + /* need read/modify/write of last changed EEPROM word + * only the first byte of the word is being modified + */ + ret_val = hw->nvm.ops.read(hw, last_word, 1, + &eeprom_buff[last_word - first_word]); + } + + /* Device's eeprom is always little-endian, word addressable */ + for (i = 0; i < last_word - first_word + 1; i++) + le16_to_cpus(&eeprom_buff[i]); + + memcpy(ptr, bytes, eeprom->len); + + for (i = 0; i < last_word - first_word + 1; i++) + eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]); + + ret_val = hw->nvm.ops.write(hw, first_word, + last_word - first_word + 1, eeprom_buff); + + /* Update the checksum if nvm write succeeded */ + if (ret_val == 0) + hw->nvm.ops.update(hw); + + /* check if need: igc_set_fw_version(adapter); */ + kfree(eeprom_buff); + return ret_val; +} + +static void igc_ethtool_get_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + + ring->rx_max_pending = IGC_MAX_RXD; + ring->tx_max_pending = IGC_MAX_TXD; + ring->rx_pending = adapter->rx_ring_count; + ring->tx_pending = adapter->tx_ring_count; +} + +static int igc_ethtool_set_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct igc_ring *temp_ring; + u16 new_rx_count, new_tx_count; + int i, err = 0; + + if (ring->rx_mini_pending || ring->rx_jumbo_pending) + return -EINVAL; + + new_rx_count = min_t(u32, ring->rx_pending, IGC_MAX_RXD); + new_rx_count = max_t(u16, new_rx_count, IGC_MIN_RXD); + new_rx_count = ALIGN(new_rx_count, REQ_RX_DESCRIPTOR_MULTIPLE); + + new_tx_count = min_t(u32, ring->tx_pending, IGC_MAX_TXD); + new_tx_count = max_t(u16, new_tx_count, IGC_MIN_TXD); + new_tx_count = ALIGN(new_tx_count, REQ_TX_DESCRIPTOR_MULTIPLE); + + if (new_tx_count == adapter->tx_ring_count && + new_rx_count == adapter->rx_ring_count) { + /* nothing to do */ + return 0; + } + + while (test_and_set_bit(__IGC_RESETTING, &adapter->state)) + usleep_range(1000, 2000); + + if (!netif_running(adapter->netdev)) { + for (i = 0; i < adapter->num_tx_queues; i++) + adapter->tx_ring[i]->count = new_tx_count; + for (i = 0; i < adapter->num_rx_queues; i++) + adapter->rx_ring[i]->count = new_rx_count; + adapter->tx_ring_count = new_tx_count; + adapter->rx_ring_count = new_rx_count; + goto clear_reset; + } + + if (adapter->num_tx_queues > adapter->num_rx_queues) + temp_ring = vmalloc(array_size(sizeof(struct igc_ring), + adapter->num_tx_queues)); + else + temp_ring = vmalloc(array_size(sizeof(struct igc_ring), + adapter->num_rx_queues)); + + if (!temp_ring) { + err = -ENOMEM; + goto clear_reset; + } + + igc_down(adapter); + + /* We can't just free everything and then setup again, + * because the ISRs in MSI-X mode get passed pointers + * to the Tx and Rx ring structs. + */ + if (new_tx_count != adapter->tx_ring_count) { + for (i = 0; i < adapter->num_tx_queues; i++) { + memcpy(&temp_ring[i], adapter->tx_ring[i], + sizeof(struct igc_ring)); + + temp_ring[i].count = new_tx_count; + err = igc_setup_tx_resources(&temp_ring[i]); + if (err) { + while (i) { + i--; + igc_free_tx_resources(&temp_ring[i]); + } + goto err_setup; + } + } + + for (i = 0; i < adapter->num_tx_queues; i++) { + igc_free_tx_resources(adapter->tx_ring[i]); + + memcpy(adapter->tx_ring[i], &temp_ring[i], + sizeof(struct igc_ring)); + } + + adapter->tx_ring_count = new_tx_count; + } + + if (new_rx_count != adapter->rx_ring_count) { + for (i = 0; i < adapter->num_rx_queues; i++) { + memcpy(&temp_ring[i], adapter->rx_ring[i], + sizeof(struct igc_ring)); + + temp_ring[i].count = new_rx_count; + err = igc_setup_rx_resources(&temp_ring[i]); + if (err) { + while (i) { + i--; + igc_free_rx_resources(&temp_ring[i]); + } + goto err_setup; + } + } + + for (i = 0; i < adapter->num_rx_queues; i++) { + igc_free_rx_resources(adapter->rx_ring[i]); + + memcpy(adapter->rx_ring[i], &temp_ring[i], + sizeof(struct igc_ring)); + } + + adapter->rx_ring_count = new_rx_count; + } +err_setup: + igc_up(adapter); + vfree(temp_ring); +clear_reset: + clear_bit(__IGC_RESETTING, &adapter->state); + return err; +} + +static void igc_ethtool_get_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pause) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct igc_hw *hw = &adapter->hw; + + pause->autoneg = + (adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); + + if (hw->fc.current_mode == igc_fc_rx_pause) { + pause->rx_pause = 1; + } else if (hw->fc.current_mode == igc_fc_tx_pause) { + pause->tx_pause = 1; + } else if (hw->fc.current_mode == igc_fc_full) { + pause->rx_pause = 1; + pause->tx_pause = 1; + } +} + +static int igc_ethtool_set_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pause) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct igc_hw *hw = &adapter->hw; + int retval = 0; + + adapter->fc_autoneg = pause->autoneg; + + while (test_and_set_bit(__IGC_RESETTING, &adapter->state)) + usleep_range(1000, 2000); + + if (adapter->fc_autoneg == AUTONEG_ENABLE) { + hw->fc.requested_mode = igc_fc_default; + if (netif_running(adapter->netdev)) { + igc_down(adapter); + igc_up(adapter); + } else { + igc_reset(adapter); + } + } else { + if (pause->rx_pause && pause->tx_pause) + hw->fc.requested_mode = igc_fc_full; + else if (pause->rx_pause && !pause->tx_pause) + hw->fc.requested_mode = igc_fc_rx_pause; + else if (!pause->rx_pause && pause->tx_pause) + hw->fc.requested_mode = igc_fc_tx_pause; + else if (!pause->rx_pause && !pause->tx_pause) + hw->fc.requested_mode = igc_fc_none; + + hw->fc.current_mode = hw->fc.requested_mode; + + retval = ((hw->phy.media_type == igc_media_type_copper) ? + igc_force_mac_fc(hw) : igc_setup_link(hw)); + } + + clear_bit(__IGC_RESETTING, &adapter->state); + return retval; +} + +static void igc_ethtool_get_strings(struct net_device *netdev, u32 stringset, + u8 *data) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + u8 *p = data; + int i; + + switch (stringset) { + case ETH_SS_TEST: + memcpy(data, *igc_gstrings_test, + IGC_TEST_LEN * ETH_GSTRING_LEN); + break; + case ETH_SS_STATS: + for (i = 0; i < IGC_GLOBAL_STATS_LEN; i++) { + memcpy(p, igc_gstrings_stats[i].stat_string, + ETH_GSTRING_LEN); + p += ETH_GSTRING_LEN; + } + for (i = 0; i < IGC_NETDEV_STATS_LEN; i++) { + memcpy(p, igc_gstrings_net_stats[i].stat_string, + ETH_GSTRING_LEN); + p += ETH_GSTRING_LEN; + } + for (i = 0; i < adapter->num_tx_queues; i++) { + sprintf(p, "tx_queue_%u_packets", i); + p += ETH_GSTRING_LEN; + sprintf(p, "tx_queue_%u_bytes", i); + p += ETH_GSTRING_LEN; + sprintf(p, "tx_queue_%u_restart", i); + p += ETH_GSTRING_LEN; + } + for (i = 0; i < adapter->num_rx_queues; i++) { + sprintf(p, "rx_queue_%u_packets", i); + p += ETH_GSTRING_LEN; + sprintf(p, "rx_queue_%u_bytes", i); + p += ETH_GSTRING_LEN; + sprintf(p, "rx_queue_%u_drops", i); + p += ETH_GSTRING_LEN; + sprintf(p, "rx_queue_%u_csum_err", i); + p += ETH_GSTRING_LEN; + sprintf(p, "rx_queue_%u_alloc_failed", i); + p += ETH_GSTRING_LEN; + } + /* BUG_ON(p - data != IGC_STATS_LEN * ETH_GSTRING_LEN); */ + break; + case ETH_SS_PRIV_FLAGS: + memcpy(data, igc_priv_flags_strings, + IGC_PRIV_FLAGS_STR_LEN * ETH_GSTRING_LEN); + break; + } +} + +static int igc_ethtool_get_sset_count(struct net_device *netdev, int sset) +{ + switch (sset) { + case ETH_SS_STATS: + return IGC_STATS_LEN; + case ETH_SS_TEST: + return IGC_TEST_LEN; + case ETH_SS_PRIV_FLAGS: + return IGC_PRIV_FLAGS_STR_LEN; + default: + return -ENOTSUPP; + } +} + +static void igc_ethtool_get_stats(struct net_device *netdev, + struct ethtool_stats *stats, u64 *data) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct rtnl_link_stats64 *net_stats = &adapter->stats64; + unsigned int start; + struct igc_ring *ring; + int i, j; + char *p; + + spin_lock(&adapter->stats64_lock); + igc_update_stats(adapter); + + for (i = 0; i < IGC_GLOBAL_STATS_LEN; i++) { + p = (char *)adapter + igc_gstrings_stats[i].stat_offset; + data[i] = (igc_gstrings_stats[i].sizeof_stat == + sizeof(u64)) ? *(u64 *)p : *(u32 *)p; + } + for (j = 0; j < IGC_NETDEV_STATS_LEN; j++, i++) { + p = (char *)net_stats + igc_gstrings_net_stats[j].stat_offset; + data[i] = (igc_gstrings_net_stats[j].sizeof_stat == + sizeof(u64)) ? *(u64 *)p : *(u32 *)p; + } + for (j = 0; j < adapter->num_tx_queues; j++) { + u64 restart2; + + ring = adapter->tx_ring[j]; + do { + start = u64_stats_fetch_begin_irq(&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)); + do { + start = u64_stats_fetch_begin_irq(&ring->tx_syncp2); + restart2 = ring->tx_stats.restart_queue2; + } while (u64_stats_fetch_retry_irq(&ring->tx_syncp2, start)); + data[i + 2] += restart2; + + i += IGC_TX_QUEUE_STATS_LEN; + } + for (j = 0; j < adapter->num_rx_queues; j++) { + ring = adapter->rx_ring[j]; + do { + start = u64_stats_fetch_begin_irq(&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)); + i += IGC_RX_QUEUE_STATS_LEN; + } + spin_unlock(&adapter->stats64_lock); +} + +static int igc_ethtool_get_coalesce(struct net_device *netdev, + struct ethtool_coalesce *ec) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + + if (adapter->rx_itr_setting <= 3) + ec->rx_coalesce_usecs = adapter->rx_itr_setting; + else + ec->rx_coalesce_usecs = adapter->rx_itr_setting >> 2; + + if (!(adapter->flags & IGC_FLAG_QUEUE_PAIRS)) { + if (adapter->tx_itr_setting <= 3) + ec->tx_coalesce_usecs = adapter->tx_itr_setting; + else + ec->tx_coalesce_usecs = adapter->tx_itr_setting >> 2; + } + + return 0; +} + +static int igc_ethtool_set_coalesce(struct net_device *netdev, + struct ethtool_coalesce *ec) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + int i; + + if (ec->rx_coalesce_usecs > IGC_MAX_ITR_USECS || + (ec->rx_coalesce_usecs > 3 && + ec->rx_coalesce_usecs < IGC_MIN_ITR_USECS) || + ec->rx_coalesce_usecs == 2) + return -EINVAL; + + if (ec->tx_coalesce_usecs > IGC_MAX_ITR_USECS || + (ec->tx_coalesce_usecs > 3 && + ec->tx_coalesce_usecs < IGC_MIN_ITR_USECS) || + ec->tx_coalesce_usecs == 2) + return -EINVAL; + + if ((adapter->flags & IGC_FLAG_QUEUE_PAIRS) && ec->tx_coalesce_usecs) + return -EINVAL; + + /* If ITR is disabled, disable DMAC */ + if (ec->rx_coalesce_usecs == 0) { + if (adapter->flags & IGC_FLAG_DMAC) + adapter->flags &= ~IGC_FLAG_DMAC; + } + + /* convert to rate of irq's per second */ + if (ec->rx_coalesce_usecs && ec->rx_coalesce_usecs <= 3) + adapter->rx_itr_setting = ec->rx_coalesce_usecs; + else + adapter->rx_itr_setting = ec->rx_coalesce_usecs << 2; + + /* convert to rate of irq's per second */ + if (adapter->flags & IGC_FLAG_QUEUE_PAIRS) + adapter->tx_itr_setting = adapter->rx_itr_setting; + else if (ec->tx_coalesce_usecs && ec->tx_coalesce_usecs <= 3) + adapter->tx_itr_setting = ec->tx_coalesce_usecs; + else + adapter->tx_itr_setting = ec->tx_coalesce_usecs << 2; + + for (i = 0; i < adapter->num_q_vectors; i++) { + struct igc_q_vector *q_vector = adapter->q_vector[i]; + + q_vector->tx.work_limit = adapter->tx_work_limit; + if (q_vector->rx.ring) + q_vector->itr_val = adapter->rx_itr_setting; + else + q_vector->itr_val = adapter->tx_itr_setting; + if (q_vector->itr_val && q_vector->itr_val <= 3) + q_vector->itr_val = IGC_START_ITR; + q_vector->set_itr = 1; + } + + return 0; +} + +#define ETHER_TYPE_FULL_MASK ((__force __be16)~0) +static int igc_ethtool_get_nfc_rule(struct igc_adapter *adapter, + struct ethtool_rxnfc *cmd) +{ + struct ethtool_rx_flow_spec *fsp = &cmd->fs; + struct igc_nfc_rule *rule = NULL; + + cmd->data = IGC_MAX_RXNFC_RULES; + + mutex_lock(&adapter->nfc_rule_lock); + + rule = igc_get_nfc_rule(adapter, fsp->location); + if (!rule) + goto out; + + fsp->flow_type = ETHER_FLOW; + fsp->ring_cookie = rule->action; + + if (rule->filter.match_flags & IGC_FILTER_FLAG_ETHER_TYPE) { + fsp->h_u.ether_spec.h_proto = htons(rule->filter.etype); + fsp->m_u.ether_spec.h_proto = ETHER_TYPE_FULL_MASK; + } + + if (rule->filter.match_flags & IGC_FILTER_FLAG_VLAN_TCI) { + fsp->flow_type |= FLOW_EXT; + fsp->h_ext.vlan_tci = htons(rule->filter.vlan_tci); + fsp->m_ext.vlan_tci = htons(VLAN_PRIO_MASK); + } + + if (rule->filter.match_flags & IGC_FILTER_FLAG_DST_MAC_ADDR) { + ether_addr_copy(fsp->h_u.ether_spec.h_dest, + rule->filter.dst_addr); + eth_broadcast_addr(fsp->m_u.ether_spec.h_dest); + } + + if (rule->filter.match_flags & IGC_FILTER_FLAG_SRC_MAC_ADDR) { + ether_addr_copy(fsp->h_u.ether_spec.h_source, + rule->filter.src_addr); + eth_broadcast_addr(fsp->m_u.ether_spec.h_source); + } + + mutex_unlock(&adapter->nfc_rule_lock); + return 0; + +out: + mutex_unlock(&adapter->nfc_rule_lock); + return -EINVAL; +} + +static int igc_ethtool_get_nfc_rules(struct igc_adapter *adapter, + struct ethtool_rxnfc *cmd, + u32 *rule_locs) +{ + struct igc_nfc_rule *rule; + int cnt = 0; + + cmd->data = IGC_MAX_RXNFC_RULES; + + mutex_lock(&adapter->nfc_rule_lock); + + list_for_each_entry(rule, &adapter->nfc_rule_list, list) { + if (cnt == cmd->rule_cnt) { + mutex_unlock(&adapter->nfc_rule_lock); + return -EMSGSIZE; + } + rule_locs[cnt] = rule->location; + cnt++; + } + + mutex_unlock(&adapter->nfc_rule_lock); + + cmd->rule_cnt = cnt; + + return 0; +} + +static int igc_ethtool_get_rss_hash_opts(struct igc_adapter *adapter, + struct ethtool_rxnfc *cmd) +{ + cmd->data = 0; + + /* Report default options for RSS on igc */ + switch (cmd->flow_type) { + case TCP_V4_FLOW: + cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; + fallthrough; + case UDP_V4_FLOW: + if (adapter->flags & IGC_FLAG_RSS_FIELD_IPV4_UDP) + cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; + fallthrough; + case SCTP_V4_FLOW: + case AH_ESP_V4_FLOW: + case AH_V4_FLOW: + case ESP_V4_FLOW: + case IPV4_FLOW: + cmd->data |= RXH_IP_SRC | RXH_IP_DST; + break; + case TCP_V6_FLOW: + cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; + fallthrough; + case UDP_V6_FLOW: + if (adapter->flags & IGC_FLAG_RSS_FIELD_IPV6_UDP) + cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; + fallthrough; + case SCTP_V6_FLOW: + case AH_ESP_V6_FLOW: + case AH_V6_FLOW: + case ESP_V6_FLOW: + case IPV6_FLOW: + cmd->data |= RXH_IP_SRC | RXH_IP_DST; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int igc_ethtool_get_rxnfc(struct net_device *dev, + struct ethtool_rxnfc *cmd, u32 *rule_locs) +{ + struct igc_adapter *adapter = netdev_priv(dev); + + switch (cmd->cmd) { + case ETHTOOL_GRXRINGS: + cmd->data = adapter->num_rx_queues; + return 0; + case ETHTOOL_GRXCLSRLCNT: + cmd->rule_cnt = adapter->nfc_rule_count; + return 0; + case ETHTOOL_GRXCLSRULE: + return igc_ethtool_get_nfc_rule(adapter, cmd); + case ETHTOOL_GRXCLSRLALL: + return igc_ethtool_get_nfc_rules(adapter, cmd, rule_locs); + case ETHTOOL_GRXFH: + return igc_ethtool_get_rss_hash_opts(adapter, cmd); + default: + return -EOPNOTSUPP; + } +} + +#define UDP_RSS_FLAGS (IGC_FLAG_RSS_FIELD_IPV4_UDP | \ + IGC_FLAG_RSS_FIELD_IPV6_UDP) +static int igc_ethtool_set_rss_hash_opt(struct igc_adapter *adapter, + struct ethtool_rxnfc *nfc) +{ + u32 flags = adapter->flags; + + /* RSS does not support anything other than hashing + * to queues on src and dst IPs and ports + */ + if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST | + RXH_L4_B_0_1 | RXH_L4_B_2_3)) + return -EINVAL; + + switch (nfc->flow_type) { + case TCP_V4_FLOW: + case TCP_V6_FLOW: + if (!(nfc->data & RXH_IP_SRC) || + !(nfc->data & RXH_IP_DST) || + !(nfc->data & RXH_L4_B_0_1) || + !(nfc->data & RXH_L4_B_2_3)) + return -EINVAL; + break; + case UDP_V4_FLOW: + if (!(nfc->data & RXH_IP_SRC) || + !(nfc->data & RXH_IP_DST)) + return -EINVAL; + switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { + case 0: + flags &= ~IGC_FLAG_RSS_FIELD_IPV4_UDP; + break; + case (RXH_L4_B_0_1 | RXH_L4_B_2_3): + flags |= IGC_FLAG_RSS_FIELD_IPV4_UDP; + break; + default: + return -EINVAL; + } + break; + case UDP_V6_FLOW: + if (!(nfc->data & RXH_IP_SRC) || + !(nfc->data & RXH_IP_DST)) + return -EINVAL; + switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { + case 0: + flags &= ~IGC_FLAG_RSS_FIELD_IPV6_UDP; + break; + case (RXH_L4_B_0_1 | RXH_L4_B_2_3): + flags |= IGC_FLAG_RSS_FIELD_IPV6_UDP; + break; + default: + return -EINVAL; + } + break; + case AH_ESP_V4_FLOW: + case AH_V4_FLOW: + case ESP_V4_FLOW: + case SCTP_V4_FLOW: + case AH_ESP_V6_FLOW: + case AH_V6_FLOW: + case ESP_V6_FLOW: + case SCTP_V6_FLOW: + if (!(nfc->data & RXH_IP_SRC) || + !(nfc->data & RXH_IP_DST) || + (nfc->data & RXH_L4_B_0_1) || + (nfc->data & RXH_L4_B_2_3)) + return -EINVAL; + break; + default: + return -EINVAL; + } + + /* if we changed something we need to update flags */ + if (flags != adapter->flags) { + struct igc_hw *hw = &adapter->hw; + u32 mrqc = rd32(IGC_MRQC); + + if ((flags & UDP_RSS_FLAGS) && + !(adapter->flags & UDP_RSS_FLAGS)) + netdev_err(adapter->netdev, + "Enabling UDP RSS: fragmented packets may arrive out of order to the stack above\n"); + + adapter->flags = flags; + + /* Perform hash on these packet types */ + mrqc |= IGC_MRQC_RSS_FIELD_IPV4 | + IGC_MRQC_RSS_FIELD_IPV4_TCP | + IGC_MRQC_RSS_FIELD_IPV6 | + IGC_MRQC_RSS_FIELD_IPV6_TCP; + + mrqc &= ~(IGC_MRQC_RSS_FIELD_IPV4_UDP | + IGC_MRQC_RSS_FIELD_IPV6_UDP); + + if (flags & IGC_FLAG_RSS_FIELD_IPV4_UDP) + mrqc |= IGC_MRQC_RSS_FIELD_IPV4_UDP; + + if (flags & IGC_FLAG_RSS_FIELD_IPV6_UDP) + mrqc |= IGC_MRQC_RSS_FIELD_IPV6_UDP; + + wr32(IGC_MRQC, mrqc); + } + + return 0; +} + +static void igc_ethtool_init_nfc_rule(struct igc_nfc_rule *rule, + const struct ethtool_rx_flow_spec *fsp) +{ + INIT_LIST_HEAD(&rule->list); + + rule->action = fsp->ring_cookie; + rule->location = fsp->location; + + if ((fsp->flow_type & FLOW_EXT) && fsp->m_ext.vlan_tci) { + rule->filter.vlan_tci = ntohs(fsp->h_ext.vlan_tci); + rule->filter.match_flags |= IGC_FILTER_FLAG_VLAN_TCI; + } + + if (fsp->m_u.ether_spec.h_proto == ETHER_TYPE_FULL_MASK) { + rule->filter.etype = ntohs(fsp->h_u.ether_spec.h_proto); + rule->filter.match_flags = IGC_FILTER_FLAG_ETHER_TYPE; + } + + /* Both source and destination address filters only support the full + * mask. + */ + if (is_broadcast_ether_addr(fsp->m_u.ether_spec.h_source)) { + rule->filter.match_flags |= IGC_FILTER_FLAG_SRC_MAC_ADDR; + ether_addr_copy(rule->filter.src_addr, + fsp->h_u.ether_spec.h_source); + } + + if (is_broadcast_ether_addr(fsp->m_u.ether_spec.h_dest)) { + rule->filter.match_flags |= IGC_FILTER_FLAG_DST_MAC_ADDR; + ether_addr_copy(rule->filter.dst_addr, + fsp->h_u.ether_spec.h_dest); + } +} + +/** + * igc_ethtool_check_nfc_rule() - Check if NFC rule is valid + * @adapter: Pointer to adapter + * @rule: Rule under evaluation + * + * The driver doesn't support rules with multiple matches so if more than + * one bit in filter flags is set, @rule is considered invalid. + * + * Also, if there is already another rule with the same filter in a different + * location, @rule is considered invalid. + * + * Context: Expects adapter->nfc_rule_lock to be held by caller. + * + * Return: 0 in case of success, negative errno code otherwise. + */ +static int igc_ethtool_check_nfc_rule(struct igc_adapter *adapter, + struct igc_nfc_rule *rule) +{ + struct net_device *dev = adapter->netdev; + u8 flags = rule->filter.match_flags; + struct igc_nfc_rule *tmp; + + if (!flags) { + netdev_dbg(dev, "Rule with no match\n"); + return -EINVAL; + } + + if (flags & (flags - 1)) { + netdev_dbg(dev, "Rule with multiple matches not supported\n"); + return -EOPNOTSUPP; + } + + list_for_each_entry(tmp, &adapter->nfc_rule_list, list) { + if (!memcmp(&rule->filter, &tmp->filter, + sizeof(rule->filter)) && + tmp->location != rule->location) { + netdev_dbg(dev, "Rule already exists\n"); + return -EEXIST; + } + } + + return 0; +} + +static int igc_ethtool_add_nfc_rule(struct igc_adapter *adapter, + struct ethtool_rxnfc *cmd) +{ + struct net_device *netdev = adapter->netdev; + struct ethtool_rx_flow_spec *fsp = + (struct ethtool_rx_flow_spec *)&cmd->fs; + struct igc_nfc_rule *rule, *old_rule; + int err; + + if (!(netdev->hw_features & NETIF_F_NTUPLE)) { + netdev_dbg(netdev, "N-tuple filters disabled\n"); + return -EOPNOTSUPP; + } + + if ((fsp->flow_type & ~FLOW_EXT) != ETHER_FLOW) { + netdev_dbg(netdev, "Only ethernet flow type is supported\n"); + return -EOPNOTSUPP; + } + + if ((fsp->flow_type & FLOW_EXT) && + fsp->m_ext.vlan_tci != htons(VLAN_PRIO_MASK)) { + netdev_dbg(netdev, "VLAN mask not supported\n"); + return -EOPNOTSUPP; + } + + if (fsp->ring_cookie >= adapter->num_rx_queues) { + netdev_dbg(netdev, "Invalid action\n"); + return -EINVAL; + } + + if (fsp->location >= IGC_MAX_RXNFC_RULES) { + netdev_dbg(netdev, "Invalid location\n"); + return -EINVAL; + } + + rule = kzalloc(sizeof(*rule), GFP_KERNEL); + if (!rule) + return -ENOMEM; + + igc_ethtool_init_nfc_rule(rule, fsp); + + mutex_lock(&adapter->nfc_rule_lock); + + err = igc_ethtool_check_nfc_rule(adapter, rule); + if (err) + goto err; + + old_rule = igc_get_nfc_rule(adapter, fsp->location); + if (old_rule) + igc_del_nfc_rule(adapter, old_rule); + + err = igc_add_nfc_rule(adapter, rule); + if (err) + goto err; + + mutex_unlock(&adapter->nfc_rule_lock); + return 0; + +err: + mutex_unlock(&adapter->nfc_rule_lock); + kfree(rule); + return err; +} + +static int igc_ethtool_del_nfc_rule(struct igc_adapter *adapter, + struct ethtool_rxnfc *cmd) +{ + struct ethtool_rx_flow_spec *fsp = + (struct ethtool_rx_flow_spec *)&cmd->fs; + struct igc_nfc_rule *rule; + + mutex_lock(&adapter->nfc_rule_lock); + + rule = igc_get_nfc_rule(adapter, fsp->location); + if (!rule) { + mutex_unlock(&adapter->nfc_rule_lock); + return -EINVAL; + } + + igc_del_nfc_rule(adapter, rule); + + mutex_unlock(&adapter->nfc_rule_lock); + return 0; +} + +static int igc_ethtool_set_rxnfc(struct net_device *dev, + struct ethtool_rxnfc *cmd) +{ + struct igc_adapter *adapter = netdev_priv(dev); + + switch (cmd->cmd) { + case ETHTOOL_SRXFH: + return igc_ethtool_set_rss_hash_opt(adapter, cmd); + case ETHTOOL_SRXCLSRLINS: + return igc_ethtool_add_nfc_rule(adapter, cmd); + case ETHTOOL_SRXCLSRLDEL: + return igc_ethtool_del_nfc_rule(adapter, cmd); + default: + return -EOPNOTSUPP; + } +} + +void igc_write_rss_indir_tbl(struct igc_adapter *adapter) +{ + struct igc_hw *hw = &adapter->hw; + u32 reg = IGC_RETA(0); + u32 shift = 0; + int i = 0; + + while (i < IGC_RETA_SIZE) { + u32 val = 0; + int j; + + for (j = 3; j >= 0; j--) { + val <<= 8; + val |= adapter->rss_indir_tbl[i + j]; + } + + wr32(reg, val << shift); + reg += 4; + i += 4; + } +} + +static u32 igc_ethtool_get_rxfh_indir_size(struct net_device *netdev) +{ + return IGC_RETA_SIZE; +} + +static int igc_ethtool_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, + u8 *hfunc) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + int i; + + if (hfunc) + *hfunc = ETH_RSS_HASH_TOP; + if (!indir) + return 0; + for (i = 0; i < IGC_RETA_SIZE; i++) + indir[i] = adapter->rss_indir_tbl[i]; + + return 0; +} + +static int igc_ethtool_set_rxfh(struct net_device *netdev, const u32 *indir, + const u8 *key, const u8 hfunc) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + u32 num_queues; + int i; + + /* We do not allow change in unsupported parameters */ + if (key || + (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)) + return -EOPNOTSUPP; + if (!indir) + return 0; + + num_queues = adapter->rss_queues; + + /* Verify user input. */ + for (i = 0; i < IGC_RETA_SIZE; i++) + if (indir[i] >= num_queues) + return -EINVAL; + + for (i = 0; i < IGC_RETA_SIZE; i++) + adapter->rss_indir_tbl[i] = indir[i]; + + igc_write_rss_indir_tbl(adapter); + + return 0; +} + +static void igc_ethtool_get_channels(struct net_device *netdev, + struct ethtool_channels *ch) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + + /* Report maximum channels */ + ch->max_combined = igc_get_max_rss_queues(adapter); + + /* Report info for other vector */ + if (adapter->flags & IGC_FLAG_HAS_MSIX) { + ch->max_other = NON_Q_VECTORS; + ch->other_count = NON_Q_VECTORS; + } + + ch->combined_count = adapter->rss_queues; +} + +static int igc_ethtool_set_channels(struct net_device *netdev, + struct ethtool_channels *ch) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + unsigned int count = ch->combined_count; + unsigned int max_combined = 0; + + /* Verify they are not requesting separate vectors */ + if (!count || ch->rx_count || ch->tx_count) + return -EINVAL; + + /* Verify other_count is valid and has not been changed */ + if (ch->other_count != NON_Q_VECTORS) + return -EINVAL; + + /* Verify the number of channels doesn't exceed hw limits */ + max_combined = igc_get_max_rss_queues(adapter); + if (count > max_combined) + return -EINVAL; + + if (count != adapter->rss_queues) { + adapter->rss_queues = count; + igc_set_flag_queue_pairs(adapter, max_combined); + + /* Hardware has to reinitialize queues and interrupts to + * match the new configuration. + */ + return igc_reinit_queues(adapter); + } + + return 0; +} + +static int igc_ethtool_get_ts_info(struct net_device *dev, + struct ethtool_ts_info *info) +{ + struct igc_adapter *adapter = netdev_priv(dev); + + if (adapter->ptp_clock) + info->phc_index = ptp_clock_index(adapter->ptp_clock); + else + info->phc_index = -1; + + switch (adapter->hw.mac.type) { + case igc_i225: + info->so_timestamping = + SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE | + SOF_TIMESTAMPING_TX_HARDWARE | + SOF_TIMESTAMPING_RX_HARDWARE | + SOF_TIMESTAMPING_RAW_HARDWARE; + + info->tx_types = + BIT(HWTSTAMP_TX_OFF) | + BIT(HWTSTAMP_TX_ON); + + info->rx_filters = BIT(HWTSTAMP_FILTER_NONE); + info->rx_filters |= BIT(HWTSTAMP_FILTER_ALL); + + return 0; + default: + return -EOPNOTSUPP; + } +} + +static u32 igc_ethtool_get_priv_flags(struct net_device *netdev) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + u32 priv_flags = 0; + + if (adapter->flags & IGC_FLAG_RX_LEGACY) + priv_flags |= IGC_PRIV_FLAGS_LEGACY_RX; + + return priv_flags; +} + +static int igc_ethtool_set_priv_flags(struct net_device *netdev, u32 priv_flags) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + unsigned int flags = adapter->flags; + + flags &= ~IGC_FLAG_RX_LEGACY; + if (priv_flags & IGC_PRIV_FLAGS_LEGACY_RX) + flags |= IGC_FLAG_RX_LEGACY; + + if (flags != adapter->flags) { + adapter->flags = flags; + + /* reset interface to repopulate queues */ + if (netif_running(netdev)) + igc_reinit_locked(adapter); + } + + return 0; +} + +static int igc_ethtool_get_eee(struct net_device *netdev, + struct ethtool_eee *edata) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct igc_hw *hw = &adapter->hw; + u32 eeer; + + if (hw->dev_spec._base.eee_enable) + edata->advertised = + mmd_eee_adv_to_ethtool_adv_t(adapter->eee_advert); + + *edata = adapter->eee; + edata->supported = SUPPORTED_Autoneg; + + eeer = rd32(IGC_EEER); + + /* EEE status on negotiated link */ + if (eeer & IGC_EEER_EEE_NEG) + edata->eee_active = true; + + if (eeer & IGC_EEER_TX_LPI_EN) + edata->tx_lpi_enabled = true; + + edata->eee_enabled = hw->dev_spec._base.eee_enable; + + edata->advertised = SUPPORTED_Autoneg; + edata->lp_advertised = SUPPORTED_Autoneg; + + /* Report correct negotiated EEE status for devices that + * wrongly report EEE at half-duplex + */ + if (adapter->link_duplex == HALF_DUPLEX) { + edata->eee_enabled = false; + edata->eee_active = false; + edata->tx_lpi_enabled = false; + edata->advertised &= ~edata->advertised; + } + + return 0; +} + +static int igc_ethtool_set_eee(struct net_device *netdev, + struct ethtool_eee *edata) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct igc_hw *hw = &adapter->hw; + struct ethtool_eee eee_curr; + s32 ret_val; + + memset(&eee_curr, 0, sizeof(struct ethtool_eee)); + + ret_val = igc_ethtool_get_eee(netdev, &eee_curr); + if (ret_val) { + netdev_err(netdev, + "Problem setting EEE advertisement options\n"); + return -EINVAL; + } + + if (eee_curr.eee_enabled) { + if (eee_curr.tx_lpi_enabled != edata->tx_lpi_enabled) { + netdev_err(netdev, + "Setting EEE tx-lpi is not supported\n"); + return -EINVAL; + } + + /* Tx LPI timer is not implemented currently */ + if (edata->tx_lpi_timer) { + netdev_err(netdev, + "Setting EEE Tx LPI timer is not supported\n"); + return -EINVAL; + } + } else if (!edata->eee_enabled) { + netdev_err(netdev, + "Setting EEE options are not supported with EEE disabled\n"); + return -EINVAL; + } + + adapter->eee_advert = ethtool_adv_to_mmd_eee_adv_t(edata->advertised); + if (hw->dev_spec._base.eee_enable != edata->eee_enabled) { + hw->dev_spec._base.eee_enable = edata->eee_enabled; + adapter->flags |= IGC_FLAG_EEE; + + /* reset link */ + if (netif_running(netdev)) + igc_reinit_locked(adapter); + else + igc_reset(adapter); + } + + return 0; +} + +static int igc_ethtool_begin(struct net_device *netdev) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + + pm_runtime_get_sync(&adapter->pdev->dev); + return 0; +} + +static void igc_ethtool_complete(struct net_device *netdev) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + + pm_runtime_put(&adapter->pdev->dev); +} + +static int igc_ethtool_get_link_ksettings(struct net_device *netdev, + struct ethtool_link_ksettings *cmd) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct igc_hw *hw = &adapter->hw; + u32 status; + u32 speed; + + ethtool_link_ksettings_zero_link_mode(cmd, supported); + ethtool_link_ksettings_zero_link_mode(cmd, advertising); + + /* supported link modes */ + ethtool_link_ksettings_add_link_mode(cmd, supported, 10baseT_Half); + ethtool_link_ksettings_add_link_mode(cmd, supported, 10baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, supported, 100baseT_Half); + ethtool_link_ksettings_add_link_mode(cmd, supported, 100baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, supported, 1000baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, supported, 2500baseT_Full); + + /* twisted pair */ + cmd->base.port = PORT_TP; + cmd->base.phy_address = hw->phy.addr; + + /* advertising link modes */ + if (hw->phy.autoneg_advertised & ADVERTISE_10_HALF) + ethtool_link_ksettings_add_link_mode(cmd, advertising, 10baseT_Half); + if (hw->phy.autoneg_advertised & ADVERTISE_10_FULL) + ethtool_link_ksettings_add_link_mode(cmd, advertising, 10baseT_Full); + if (hw->phy.autoneg_advertised & ADVERTISE_100_HALF) + ethtool_link_ksettings_add_link_mode(cmd, advertising, 100baseT_Half); + if (hw->phy.autoneg_advertised & ADVERTISE_100_FULL) + ethtool_link_ksettings_add_link_mode(cmd, advertising, 100baseT_Full); + if (hw->phy.autoneg_advertised & ADVERTISE_1000_FULL) + ethtool_link_ksettings_add_link_mode(cmd, advertising, 1000baseT_Full); + if (hw->phy.autoneg_advertised & ADVERTISE_2500_FULL) + ethtool_link_ksettings_add_link_mode(cmd, advertising, 2500baseT_Full); + + /* set autoneg settings */ + if (hw->mac.autoneg == 1) { + ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + Autoneg); + } + + /* Set pause flow control settings */ + ethtool_link_ksettings_add_link_mode(cmd, supported, Pause); + + switch (hw->fc.requested_mode) { + case igc_fc_full: + ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause); + break; + case igc_fc_rx_pause: + ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + Asym_Pause); + break; + case igc_fc_tx_pause: + ethtool_link_ksettings_add_link_mode(cmd, advertising, + Asym_Pause); + break; + default: + break; + } + + status = pm_runtime_suspended(&adapter->pdev->dev) ? + 0 : rd32(IGC_STATUS); + + if (status & IGC_STATUS_LU) { + if (status & IGC_STATUS_SPEED_1000) { + /* For I225, STATUS will indicate 1G speed in both + * 1 Gbps and 2.5 Gbps link modes. + * An additional bit is used + * to differentiate between 1 Gbps and 2.5 Gbps. + */ + if (hw->mac.type == igc_i225 && + (status & IGC_STATUS_SPEED_2500)) { + speed = SPEED_2500; + } else { + speed = SPEED_1000; + } + } else if (status & IGC_STATUS_SPEED_100) { + speed = SPEED_100; + } else { + speed = SPEED_10; + } + if ((status & IGC_STATUS_FD) || + hw->phy.media_type != igc_media_type_copper) + cmd->base.duplex = DUPLEX_FULL; + else + cmd->base.duplex = DUPLEX_HALF; + } else { + speed = SPEED_UNKNOWN; + cmd->base.duplex = DUPLEX_UNKNOWN; + } + cmd->base.speed = speed; + if (hw->mac.autoneg) + cmd->base.autoneg = AUTONEG_ENABLE; + else + cmd->base.autoneg = AUTONEG_DISABLE; + + /* MDI-X => 2; MDI =>1; Invalid =>0 */ + if (hw->phy.media_type == igc_media_type_copper) + cmd->base.eth_tp_mdix = hw->phy.is_mdix ? ETH_TP_MDI_X : + ETH_TP_MDI; + else + cmd->base.eth_tp_mdix = ETH_TP_MDI_INVALID; + + if (hw->phy.mdix == AUTO_ALL_MODES) + cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO; + else + cmd->base.eth_tp_mdix_ctrl = hw->phy.mdix; + + return 0; +} + +static int +igc_ethtool_set_link_ksettings(struct net_device *netdev, + const struct ethtool_link_ksettings *cmd) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct net_device *dev = adapter->netdev; + struct igc_hw *hw = &adapter->hw; + u32 advertising; + + /* When adapter in resetting mode, autoneg/speed/duplex + * cannot be changed + */ + if (igc_check_reset_block(hw)) { + netdev_err(dev, "Cannot change link characteristics when reset is active\n"); + return -EINVAL; + } + + /* MDI setting is only allowed when autoneg enabled because + * some hardware doesn't allow MDI setting when speed or + * duplex is forced. + */ + if (cmd->base.eth_tp_mdix_ctrl) { + if (cmd->base.eth_tp_mdix_ctrl != ETH_TP_MDI_AUTO && + cmd->base.autoneg != AUTONEG_ENABLE) { + netdev_err(dev, "Forcing MDI/MDI-X state is not supported when link speed and/or duplex are forced\n"); + return -EINVAL; + } + } + + while (test_and_set_bit(__IGC_RESETTING, &adapter->state)) + usleep_range(1000, 2000); + + ethtool_convert_link_mode_to_legacy_u32(&advertising, + cmd->link_modes.advertising); + /* Converting to legacy u32 drops ETHTOOL_LINK_MODE_2500baseT_Full_BIT. + * We have to check this and convert it to ADVERTISE_2500_FULL + * (aka ETHTOOL_LINK_MODE_2500baseX_Full_BIT) explicitly. + */ + if (ethtool_link_ksettings_test_link_mode(cmd, advertising, 2500baseT_Full)) + advertising |= ADVERTISE_2500_FULL; + + if (cmd->base.autoneg == AUTONEG_ENABLE) { + hw->mac.autoneg = 1; + hw->phy.autoneg_advertised = advertising; + if (adapter->fc_autoneg) + hw->fc.requested_mode = igc_fc_default; + } else { + netdev_info(dev, "Force mode currently not supported\n"); + } + + /* MDI-X => 2; MDI => 1; Auto => 3 */ + if (cmd->base.eth_tp_mdix_ctrl) { + /* fix up the value for auto (3 => 0) as zero is mapped + * internally to auto + */ + if (cmd->base.eth_tp_mdix_ctrl == ETH_TP_MDI_AUTO) + hw->phy.mdix = AUTO_ALL_MODES; + else + hw->phy.mdix = cmd->base.eth_tp_mdix_ctrl; + } + + /* reset the link */ + if (netif_running(adapter->netdev)) { + igc_down(adapter); + igc_up(adapter); + } else { + igc_reset(adapter); + } + + clear_bit(__IGC_RESETTING, &adapter->state); + + return 0; +} + +static void igc_ethtool_diag_test(struct net_device *netdev, + struct ethtool_test *eth_test, u64 *data) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + bool if_running = netif_running(netdev); + + if (eth_test->flags == ETH_TEST_FL_OFFLINE) { + netdev_info(adapter->netdev, "Offline testing starting"); + set_bit(__IGC_TESTING, &adapter->state); + + /* Link test performed before hardware reset so autoneg doesn't + * interfere with test result + */ + if (!igc_link_test(adapter, &data[TEST_LINK])) + eth_test->flags |= ETH_TEST_FL_FAILED; + + if (if_running) + igc_close(netdev); + else + igc_reset(adapter); + + netdev_info(adapter->netdev, "Register testing starting"); + if (!igc_reg_test(adapter, &data[TEST_REG])) + eth_test->flags |= ETH_TEST_FL_FAILED; + + igc_reset(adapter); + + netdev_info(adapter->netdev, "EEPROM testing starting"); + if (!igc_eeprom_test(adapter, &data[TEST_EEP])) + eth_test->flags |= ETH_TEST_FL_FAILED; + + igc_reset(adapter); + + /* loopback and interrupt tests + * will be implemented in the future + */ + data[TEST_LOOP] = 0; + data[TEST_IRQ] = 0; + + clear_bit(__IGC_TESTING, &adapter->state); + if (if_running) + igc_open(netdev); + } else { + netdev_info(adapter->netdev, "Online testing starting"); + + /* register, eeprom, intr and loopback tests not run online */ + data[TEST_REG] = 0; + data[TEST_EEP] = 0; + data[TEST_IRQ] = 0; + data[TEST_LOOP] = 0; + + if (!igc_link_test(adapter, &data[TEST_LINK])) + eth_test->flags |= ETH_TEST_FL_FAILED; + } + + msleep_interruptible(4 * 1000); +} + +static const struct ethtool_ops igc_ethtool_ops = { + .get_drvinfo = igc_ethtool_get_drvinfo, + .get_regs_len = igc_ethtool_get_regs_len, + .get_regs = igc_ethtool_get_regs, + .get_wol = igc_ethtool_get_wol, + .set_wol = igc_ethtool_set_wol, + .get_msglevel = igc_ethtool_get_msglevel, + .set_msglevel = igc_ethtool_set_msglevel, + .nway_reset = igc_ethtool_nway_reset, + .get_link = igc_ethtool_get_link, + .get_eeprom_len = igc_ethtool_get_eeprom_len, + .get_eeprom = igc_ethtool_get_eeprom, + .set_eeprom = igc_ethtool_set_eeprom, + .get_ringparam = igc_ethtool_get_ringparam, + .set_ringparam = igc_ethtool_set_ringparam, + .get_pauseparam = igc_ethtool_get_pauseparam, + .set_pauseparam = igc_ethtool_set_pauseparam, + .get_strings = igc_ethtool_get_strings, + .get_sset_count = igc_ethtool_get_sset_count, + .get_ethtool_stats = igc_ethtool_get_stats, + .get_coalesce = igc_ethtool_get_coalesce, + .set_coalesce = igc_ethtool_set_coalesce, + .get_rxnfc = igc_ethtool_get_rxnfc, + .set_rxnfc = igc_ethtool_set_rxnfc, + .get_rxfh_indir_size = igc_ethtool_get_rxfh_indir_size, + .get_rxfh = igc_ethtool_get_rxfh, + .set_rxfh = igc_ethtool_set_rxfh, + .get_ts_info = igc_ethtool_get_ts_info, + .get_channels = igc_ethtool_get_channels, + .set_channels = igc_ethtool_set_channels, + .get_priv_flags = igc_ethtool_get_priv_flags, + .set_priv_flags = igc_ethtool_set_priv_flags, + .get_eee = igc_ethtool_get_eee, + .set_eee = igc_ethtool_set_eee, + .begin = igc_ethtool_begin, + .complete = igc_ethtool_complete, + .get_link_ksettings = igc_ethtool_get_link_ksettings, + .set_link_ksettings = igc_ethtool_set_link_ksettings, + .self_test = igc_ethtool_diag_test, +}; + +void igc_ethtool_set_ops(struct net_device *netdev) +{ + netdev->ethtool_ops = &igc_ethtool_ops; +} diff --git a/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_hw.h b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_hw.h new file mode 100644 index 00000000..a45b41cc --- /dev/null +++ b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_hw.h @@ -0,0 +1,297 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2018 Intel Corporation */ + +#ifndef _IGC_HW_H_ +#define _IGC_HW_H_ + +#include +#include +#include + +#include "igc_regs.h" +#include "igc_defines.h" +#include "igc_mac.h" +#include "igc_phy.h" +#include "igc_nvm.h" +#include "igc_i225.h" +#include "igc_base.h" + +#define IGC_DEV_ID_I225_LM 0x15F2 +#define IGC_DEV_ID_I225_V 0x15F3 +#define IGC_DEV_ID_I225_I 0x15F8 +#define IGC_DEV_ID_I220_V 0x15F7 +#define IGC_DEV_ID_I225_K 0x3100 +#define IGC_DEV_ID_I225_K2 0x3101 +#define IGC_DEV_ID_I226_K 0x3102 +#define IGC_DEV_ID_I225_LMVP 0x5502 +#define IGC_DEV_ID_I226_LMVP 0x5503 +#define IGC_DEV_ID_I225_IT 0x0D9F +#define IGC_DEV_ID_I226_LM 0x125B +#define IGC_DEV_ID_I226_V 0x125C +#define IGC_DEV_ID_I226_IT 0x125D +#define IGC_DEV_ID_I221_V 0x125E +#define IGC_DEV_ID_I226_BLANK_NVM 0x125F +#define IGC_DEV_ID_I225_BLANK_NVM 0x15FD + +/* Function pointers for the MAC. */ +struct igc_mac_operations { + s32 (*check_for_link)(struct igc_hw *hw); + s32 (*reset_hw)(struct igc_hw *hw); + s32 (*init_hw)(struct igc_hw *hw); + s32 (*setup_physical_interface)(struct igc_hw *hw); + void (*rar_set)(struct igc_hw *hw, u8 *address, u32 index); + s32 (*read_mac_addr)(struct igc_hw *hw); + s32 (*get_speed_and_duplex)(struct igc_hw *hw, u16 *speed, + u16 *duplex); + s32 (*acquire_swfw_sync)(struct igc_hw *hw, u16 mask); + void (*release_swfw_sync)(struct igc_hw *hw, u16 mask); +}; + +enum igc_mac_type { + igc_undefined = 0, + igc_i225, + igc_num_macs /* List is 1-based, so subtract 1 for true count. */ +}; + +enum igc_phy_type { + igc_phy_unknown = 0, + igc_phy_i225, +}; + +enum igc_media_type { + igc_media_type_unknown = 0, + igc_media_type_copper = 1, + igc_num_media_types +}; + +enum igc_nvm_type { + igc_nvm_unknown = 0, + igc_nvm_eeprom_spi, +}; + +struct igc_info { + s32 (*get_invariants)(struct igc_hw *hw); + struct igc_mac_operations *mac_ops; + const struct igc_phy_operations *phy_ops; + struct igc_nvm_operations *nvm_ops; +}; + +extern const struct igc_info igc_base_info; + +struct igc_mac_info { + struct igc_mac_operations ops; + + u8 addr[ETH_ALEN]; + u8 perm_addr[ETH_ALEN]; + + enum igc_mac_type type; + + u32 mc_filter_type; + + u16 mta_reg_count; + u16 uta_reg_count; + + u32 mta_shadow[MAX_MTA_REG]; + u16 rar_entry_count; + + u8 forced_speed_duplex; + + bool asf_firmware_present; + bool arc_subsystem_valid; + + bool autoneg; + bool autoneg_failed; + bool get_link_status; +}; + +struct igc_nvm_operations { + s32 (*acquire)(struct igc_hw *hw); + s32 (*read)(struct igc_hw *hw, u16 offset, u16 i, u16 *data); + void (*release)(struct igc_hw *hw); + s32 (*write)(struct igc_hw *hw, u16 offset, u16 i, u16 *data); + s32 (*update)(struct igc_hw *hw); + s32 (*validate)(struct igc_hw *hw); + s32 (*valid_led_default)(struct igc_hw *hw, u16 *data); +}; + +struct igc_phy_operations { + s32 (*acquire)(struct igc_hw *hw); + s32 (*check_reset_block)(struct igc_hw *hw); + s32 (*force_speed_duplex)(struct igc_hw *hw); + s32 (*get_phy_info)(struct igc_hw *hw); + s32 (*read_reg)(struct igc_hw *hw, u32 address, u16 *data); + void (*release)(struct igc_hw *hw); + s32 (*reset)(struct igc_hw *hw); + s32 (*write_reg)(struct igc_hw *hw, u32 address, u16 data); +}; + +struct igc_nvm_info { + struct igc_nvm_operations ops; + enum igc_nvm_type type; + + u16 word_size; + u16 delay_usec; + u16 address_bits; + u16 opcode_bits; + u16 page_size; +}; + +struct igc_phy_info { + struct igc_phy_operations ops; + + enum igc_phy_type type; + + u32 addr; + u32 id; + u32 reset_delay_us; /* in usec */ + u32 revision; + + enum igc_media_type media_type; + + u16 autoneg_advertised; + u16 autoneg_mask; + + u8 mdix; + + bool is_mdix; + bool speed_downgraded; + bool autoneg_wait_to_complete; +}; + +struct igc_bus_info { + u16 func; + u16 pci_cmd_word; +}; + +enum igc_fc_mode { + igc_fc_none = 0, + igc_fc_rx_pause, + igc_fc_tx_pause, + igc_fc_full, + igc_fc_default = 0xFF +}; + +struct igc_fc_info { + u32 high_water; /* Flow control high-water mark */ + u32 low_water; /* Flow control low-water mark */ + u16 pause_time; /* Flow control pause timer */ + bool send_xon; /* Flow control send XON */ + bool strict_ieee; /* Strict IEEE mode */ + enum igc_fc_mode current_mode; /* Type of flow control */ + enum igc_fc_mode requested_mode; +}; + +struct igc_dev_spec_base { + bool clear_semaphore_once; + bool eee_enable; +}; + +struct igc_hw { + void *back; + + u8 __iomem *hw_addr; + unsigned long io_base; + + struct igc_mac_info mac; + struct igc_fc_info fc; + struct igc_nvm_info nvm; + struct igc_phy_info phy; + + struct igc_bus_info bus; + + union { + struct igc_dev_spec_base _base; + } dev_spec; + + u16 device_id; + u16 subsystem_vendor_id; + u16 subsystem_device_id; + u16 vendor_id; + + u8 revision_id; +}; + +/* Statistics counters collected by the MAC */ +struct igc_hw_stats { + u64 crcerrs; + u64 algnerrc; + u64 symerrs; + u64 rxerrc; + u64 mpc; + u64 scc; + u64 ecol; + u64 mcc; + u64 latecol; + u64 colc; + u64 dc; + u64 tncrs; + u64 sec; + u64 cexterr; + u64 rlec; + u64 xonrxc; + u64 xontxc; + u64 xoffrxc; + u64 xofftxc; + u64 fcruc; + u64 prc64; + u64 prc127; + u64 prc255; + u64 prc511; + u64 prc1023; + u64 prc1522; + u64 tlpic; + u64 rlpic; + u64 gprc; + u64 bprc; + u64 mprc; + u64 gptc; + u64 gorc; + u64 gotc; + u64 rnbc; + u64 ruc; + u64 rfc; + u64 roc; + u64 rjc; + u64 mgprc; + u64 mgpdc; + u64 mgptc; + u64 tor; + u64 tot; + u64 tpr; + u64 tpt; + u64 ptc64; + u64 ptc127; + u64 ptc255; + u64 ptc511; + u64 ptc1023; + u64 ptc1522; + u64 mptc; + u64 bptc; + u64 tsctc; + u64 tsctfc; + u64 iac; + u64 htdpmc; + u64 rpthc; + u64 hgptc; + u64 hgorc; + u64 hgotc; + u64 lenerrs; + u64 scvpc; + u64 hrmpc; + u64 doosync; + u64 o2bgptc; + u64 o2bspc; + u64 b2ospc; + u64 b2ogprc; +}; + +struct net_device *igc_get_hw_dev(struct igc_hw *hw); +#define hw_dbg(format, arg...) \ + netdev_dbg(igc_get_hw_dev(hw), format, ##arg) + +s32 igc_read_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value); +s32 igc_write_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value); +void igc_read_pci_cfg(struct igc_hw *hw, u32 reg, u16 *value); +void igc_write_pci_cfg(struct igc_hw *hw, u32 reg, u16 *value); + +#endif /* _IGC_HW_H_ */ diff --git a/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_i225.c b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_i225.c new file mode 100644 index 00000000..85031c53 --- /dev/null +++ b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_i225.c @@ -0,0 +1,650 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2018 Intel Corporation */ + +#include + +#include "igc_hw.h" + +/** + * igc_get_hw_semaphore_i225 - Acquire hardware semaphore + * @hw: pointer to the HW structure + * + * Acquire the necessary semaphores for exclusive access to the EEPROM. + * Set the EEPROM access request bit and wait for EEPROM access grant bit. + * Return successful if access grant bit set, else clear the request for + * EEPROM access and return -IGC_ERR_NVM (-1). + */ +static s32 igc_acquire_nvm_i225(struct igc_hw *hw) +{ + return igc_acquire_swfw_sync_i225(hw, IGC_SWFW_EEP_SM); +} + +/** + * igc_release_nvm_i225 - Release exclusive access to EEPROM + * @hw: pointer to the HW structure + * + * Stop any current commands to the EEPROM and clear the EEPROM request bit, + * then release the semaphores acquired. + */ +static void igc_release_nvm_i225(struct igc_hw *hw) +{ + igc_release_swfw_sync_i225(hw, IGC_SWFW_EEP_SM); +} + +/** + * igc_get_hw_semaphore_i225 - Acquire hardware semaphore + * @hw: pointer to the HW structure + * + * Acquire the HW semaphore to access the PHY or NVM + */ +static s32 igc_get_hw_semaphore_i225(struct igc_hw *hw) +{ + s32 timeout = hw->nvm.word_size + 1; + s32 i = 0; + u32 swsm; + + /* Get the SW semaphore */ + while (i < timeout) { + swsm = rd32(IGC_SWSM); + if (!(swsm & IGC_SWSM_SMBI)) + break; + + usleep_range(500, 600); + i++; + } + + if (i == timeout) { + /* In rare circumstances, the SW semaphore may already be held + * unintentionally. Clear the semaphore once before giving up. + */ + if (hw->dev_spec._base.clear_semaphore_once) { + hw->dev_spec._base.clear_semaphore_once = false; + igc_put_hw_semaphore(hw); + for (i = 0; i < timeout; i++) { + swsm = rd32(IGC_SWSM); + if (!(swsm & IGC_SWSM_SMBI)) + break; + + usleep_range(500, 600); + } + } + + /* If we do not have the semaphore here, we have to give up. */ + if (i == timeout) { + hw_dbg("Driver can't access device - SMBI bit is set.\n"); + return -IGC_ERR_NVM; + } + } + + /* Get the FW semaphore. */ + for (i = 0; i < timeout; i++) { + swsm = rd32(IGC_SWSM); + wr32(IGC_SWSM, swsm | IGC_SWSM_SWESMBI); + + /* Semaphore acquired if bit latched */ + if (rd32(IGC_SWSM) & IGC_SWSM_SWESMBI) + break; + + usleep_range(500, 600); + } + + if (i == timeout) { + /* Release semaphores */ + igc_put_hw_semaphore(hw); + hw_dbg("Driver can't access the NVM\n"); + return -IGC_ERR_NVM; + } + + return 0; +} + +/** + * igc_acquire_swfw_sync_i225 - Acquire SW/FW semaphore + * @hw: pointer to the HW structure + * @mask: specifies which semaphore to acquire + * + * Acquire the SW/FW semaphore to access the PHY or NVM. The mask + * will also specify which port we're acquiring the lock for. + */ +s32 igc_acquire_swfw_sync_i225(struct igc_hw *hw, u16 mask) +{ + s32 i = 0, timeout = 200; + u32 fwmask = mask << 16; + u32 swmask = mask; + s32 ret_val = 0; + u32 swfw_sync; + + while (i < timeout) { + if (igc_get_hw_semaphore_i225(hw)) { + ret_val = -IGC_ERR_SWFW_SYNC; + goto out; + } + + swfw_sync = rd32(IGC_SW_FW_SYNC); + if (!(swfw_sync & (fwmask | swmask))) + break; + + /* Firmware currently using resource (fwmask) */ + igc_put_hw_semaphore(hw); + mdelay(5); + i++; + } + + if (i == timeout) { + hw_dbg("Driver can't access resource, SW_FW_SYNC timeout.\n"); + ret_val = -IGC_ERR_SWFW_SYNC; + goto out; + } + + swfw_sync |= swmask; + wr32(IGC_SW_FW_SYNC, swfw_sync); + + igc_put_hw_semaphore(hw); +out: + return ret_val; +} + +/** + * igc_release_swfw_sync_i225 - Release SW/FW semaphore + * @hw: pointer to the HW structure + * @mask: specifies which semaphore to acquire + * + * Release the SW/FW semaphore used to access the PHY or NVM. The mask + * will also specify which port we're releasing the lock for. + */ +void igc_release_swfw_sync_i225(struct igc_hw *hw, u16 mask) +{ + u32 swfw_sync; + + /* Releasing the resource requires first getting the HW semaphore. + * If we fail to get the semaphore, there is nothing we can do, + * except log an error and quit. We are not allowed to hang here + * indefinitely, as it may cause denial of service or system crash. + */ + if (igc_get_hw_semaphore_i225(hw)) { + hw_dbg("Failed to release SW_FW_SYNC.\n"); + return; + } + + swfw_sync = rd32(IGC_SW_FW_SYNC); + swfw_sync &= ~mask; + wr32(IGC_SW_FW_SYNC, swfw_sync); + + igc_put_hw_semaphore(hw); +} + +/** + * igc_read_nvm_srrd_i225 - Reads Shadow Ram using EERD register + * @hw: pointer to the HW structure + * @offset: offset of word in the Shadow Ram to read + * @words: number of words to read + * @data: word read from the Shadow Ram + * + * Reads a 16 bit word from the Shadow Ram using the EERD register. + * Uses necessary synchronization semaphores. + */ +static s32 igc_read_nvm_srrd_i225(struct igc_hw *hw, u16 offset, u16 words, + u16 *data) +{ + s32 status = 0; + u16 i, count; + + /* We cannot hold synchronization semaphores for too long, + * because of forceful takeover procedure. However it is more efficient + * to read in bursts than synchronizing access for each word. + */ + for (i = 0; i < words; i += IGC_EERD_EEWR_MAX_COUNT) { + count = (words - i) / IGC_EERD_EEWR_MAX_COUNT > 0 ? + IGC_EERD_EEWR_MAX_COUNT : (words - i); + + status = hw->nvm.ops.acquire(hw); + if (status) + break; + + status = igc_read_nvm_eerd(hw, offset, count, data + i); + hw->nvm.ops.release(hw); + if (status) + break; + } + + return status; +} + +/** + * igc_write_nvm_srwr - Write to Shadow Ram using EEWR + * @hw: pointer to the HW structure + * @offset: offset within the Shadow Ram to be written to + * @words: number of words to write + * @data: 16 bit word(s) to be written to the Shadow Ram + * + * Writes data to Shadow Ram at offset using EEWR register. + * + * If igc_update_nvm_checksum is not called after this function , the + * Shadow Ram will most likely contain an invalid checksum. + */ +static s32 igc_write_nvm_srwr(struct igc_hw *hw, u16 offset, u16 words, + u16 *data) +{ + struct igc_nvm_info *nvm = &hw->nvm; + s32 ret_val = -IGC_ERR_NVM; + u32 attempts = 100000; + u32 i, k, eewr = 0; + + /* A check for invalid values: offset too large, too many words, + * too many words for the offset, and not enough words. + */ + if (offset >= nvm->word_size || (words > (nvm->word_size - offset)) || + words == 0) { + hw_dbg("nvm parameter(s) out of bounds\n"); + goto out; + } + + for (i = 0; i < words; i++) { + eewr = ((offset + i) << IGC_NVM_RW_ADDR_SHIFT) | + (data[i] << IGC_NVM_RW_REG_DATA) | + IGC_NVM_RW_REG_START; + + wr32(IGC_SRWR, eewr); + + for (k = 0; k < attempts; k++) { + if (IGC_NVM_RW_REG_DONE & + rd32(IGC_SRWR)) { + ret_val = 0; + break; + } + udelay(5); + } + + if (ret_val) { + hw_dbg("Shadow RAM write EEWR timed out\n"); + break; + } + } + +out: + return ret_val; +} + +/** + * igc_write_nvm_srwr_i225 - Write to Shadow RAM using EEWR + * @hw: pointer to the HW structure + * @offset: offset within the Shadow RAM to be written to + * @words: number of words to write + * @data: 16 bit word(s) to be written to the Shadow RAM + * + * Writes data to Shadow RAM at offset using EEWR register. + * + * If igc_update_nvm_checksum is not called after this function , the + * data will not be committed to FLASH and also Shadow RAM will most likely + * contain an invalid checksum. + * + * If error code is returned, data and Shadow RAM may be inconsistent - buffer + * partially written. + */ +static s32 igc_write_nvm_srwr_i225(struct igc_hw *hw, u16 offset, u16 words, + u16 *data) +{ + s32 status = 0; + u16 i, count; + + /* We cannot hold synchronization semaphores for too long, + * because of forceful takeover procedure. However it is more efficient + * to write in bursts than synchronizing access for each word. + */ + for (i = 0; i < words; i += IGC_EERD_EEWR_MAX_COUNT) { + count = (words - i) / IGC_EERD_EEWR_MAX_COUNT > 0 ? + IGC_EERD_EEWR_MAX_COUNT : (words - i); + + status = hw->nvm.ops.acquire(hw); + if (status) + break; + + status = igc_write_nvm_srwr(hw, offset, count, data + i); + hw->nvm.ops.release(hw); + if (status) + break; + } + + return status; +} + +/** + * igc_validate_nvm_checksum_i225 - Validate EEPROM checksum + * @hw: pointer to the HW structure + * + * Calculates the EEPROM checksum by reading/adding each word of the EEPROM + * and then verifies that the sum of the EEPROM is equal to 0xBABA. + */ +static s32 igc_validate_nvm_checksum_i225(struct igc_hw *hw) +{ + s32 (*read_op_ptr)(struct igc_hw *hw, u16 offset, u16 count, + u16 *data); + s32 status = 0; + + status = hw->nvm.ops.acquire(hw); + if (status) + goto out; + + /* Replace the read function with semaphore grabbing with + * the one that skips this for a while. + * We have semaphore taken already here. + */ + read_op_ptr = hw->nvm.ops.read; + hw->nvm.ops.read = igc_read_nvm_eerd; + + status = igc_validate_nvm_checksum(hw); + + /* Revert original read operation. */ + hw->nvm.ops.read = read_op_ptr; + + hw->nvm.ops.release(hw); + +out: + return status; +} + +/** + * igc_pool_flash_update_done_i225 - Pool FLUDONE status + * @hw: pointer to the HW structure + */ +static s32 igc_pool_flash_update_done_i225(struct igc_hw *hw) +{ + s32 ret_val = -IGC_ERR_NVM; + u32 i, reg; + + for (i = 0; i < IGC_FLUDONE_ATTEMPTS; i++) { + reg = rd32(IGC_EECD); + if (reg & IGC_EECD_FLUDONE_I225) { + ret_val = 0; + break; + } + udelay(5); + } + + return ret_val; +} + +/** + * igc_update_flash_i225 - Commit EEPROM to the flash + * @hw: pointer to the HW structure + */ +static s32 igc_update_flash_i225(struct igc_hw *hw) +{ + s32 ret_val = 0; + u32 flup; + + ret_val = igc_pool_flash_update_done_i225(hw); + if (ret_val == -IGC_ERR_NVM) { + hw_dbg("Flash update time out\n"); + goto out; + } + + flup = rd32(IGC_EECD) | IGC_EECD_FLUPD_I225; + wr32(IGC_EECD, flup); + + ret_val = igc_pool_flash_update_done_i225(hw); + if (ret_val) + hw_dbg("Flash update time out\n"); + else + hw_dbg("Flash update complete\n"); + +out: + return ret_val; +} + +/** + * igc_update_nvm_checksum_i225 - Update EEPROM checksum + * @hw: pointer to the HW structure + * + * Updates the EEPROM checksum by reading/adding each word of the EEPROM + * up to the checksum. Then calculates the EEPROM checksum and writes the + * value to the EEPROM. Next commit EEPROM data onto the Flash. + */ +static s32 igc_update_nvm_checksum_i225(struct igc_hw *hw) +{ + u16 checksum = 0; + s32 ret_val = 0; + u16 i, nvm_data; + + /* Read the first word from the EEPROM. If this times out or fails, do + * not continue or we could be in for a very long wait while every + * EEPROM read fails + */ + ret_val = igc_read_nvm_eerd(hw, 0, 1, &nvm_data); + if (ret_val) { + hw_dbg("EEPROM read failed\n"); + goto out; + } + + ret_val = hw->nvm.ops.acquire(hw); + if (ret_val) + goto out; + + /* Do not use hw->nvm.ops.write, hw->nvm.ops.read + * because we do not want to take the synchronization + * semaphores twice here. + */ + + for (i = 0; i < NVM_CHECKSUM_REG; i++) { + ret_val = igc_read_nvm_eerd(hw, i, 1, &nvm_data); + if (ret_val) { + hw->nvm.ops.release(hw); + hw_dbg("NVM Read Error while updating checksum.\n"); + goto out; + } + checksum += nvm_data; + } + checksum = (u16)NVM_SUM - checksum; + ret_val = igc_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1, + &checksum); + if (ret_val) { + hw->nvm.ops.release(hw); + hw_dbg("NVM Write Error while updating checksum.\n"); + goto out; + } + + hw->nvm.ops.release(hw); + + ret_val = igc_update_flash_i225(hw); + +out: + return ret_val; +} + +/** + * igc_get_flash_presence_i225 - Check if flash device is detected + * @hw: pointer to the HW structure + */ +bool igc_get_flash_presence_i225(struct igc_hw *hw) +{ + bool ret_val = false; + u32 eec = 0; + + eec = rd32(IGC_EECD); + if (eec & IGC_EECD_FLASH_DETECTED_I225) + ret_val = true; + + return ret_val; +} + +/** + * igc_init_nvm_params_i225 - Init NVM func ptrs. + * @hw: pointer to the HW structure + */ +s32 igc_init_nvm_params_i225(struct igc_hw *hw) +{ + struct igc_nvm_info *nvm = &hw->nvm; + + nvm->ops.acquire = igc_acquire_nvm_i225; + nvm->ops.release = igc_release_nvm_i225; + + /* NVM Function Pointers */ + if (igc_get_flash_presence_i225(hw)) { + nvm->ops.read = igc_read_nvm_srrd_i225; + nvm->ops.write = igc_write_nvm_srwr_i225; + nvm->ops.validate = igc_validate_nvm_checksum_i225; + nvm->ops.update = igc_update_nvm_checksum_i225; + } else { + nvm->ops.read = igc_read_nvm_eerd; + nvm->ops.write = NULL; + nvm->ops.validate = NULL; + nvm->ops.update = NULL; + } + return 0; +} + +/** + * igc_set_eee_i225 - Enable/disable EEE support + * @hw: pointer to the HW structure + * @adv2p5G: boolean flag enabling 2.5G EEE advertisement + * @adv1G: boolean flag enabling 1G EEE advertisement + * @adv100M: boolean flag enabling 100M EEE advertisement + * + * Enable/disable EEE based on setting in dev_spec structure. + **/ +s32 igc_set_eee_i225(struct igc_hw *hw, bool adv2p5G, bool adv1G, + bool adv100M) +{ + u32 ipcnfg, eeer; + + ipcnfg = rd32(IGC_IPCNFG); + eeer = rd32(IGC_EEER); + + /* enable or disable per user setting */ + if (hw->dev_spec._base.eee_enable) { + u32 eee_su = rd32(IGC_EEE_SU); + + if (adv100M) + ipcnfg |= IGC_IPCNFG_EEE_100M_AN; + else + ipcnfg &= ~IGC_IPCNFG_EEE_100M_AN; + + if (adv1G) + ipcnfg |= IGC_IPCNFG_EEE_1G_AN; + else + ipcnfg &= ~IGC_IPCNFG_EEE_1G_AN; + + if (adv2p5G) + ipcnfg |= IGC_IPCNFG_EEE_2_5G_AN; + else + ipcnfg &= ~IGC_IPCNFG_EEE_2_5G_AN; + + eeer |= (IGC_EEER_TX_LPI_EN | IGC_EEER_RX_LPI_EN | + IGC_EEER_LPI_FC); + + /* This bit should not be set in normal operation. */ + if (eee_su & IGC_EEE_SU_LPI_CLK_STP) + hw_dbg("LPI Clock Stop Bit should not be set!\n"); + } else { + ipcnfg &= ~(IGC_IPCNFG_EEE_2_5G_AN | IGC_IPCNFG_EEE_1G_AN | + IGC_IPCNFG_EEE_100M_AN); + eeer &= ~(IGC_EEER_TX_LPI_EN | IGC_EEER_RX_LPI_EN | + IGC_EEER_LPI_FC); + } + wr32(IGC_IPCNFG, ipcnfg); + wr32(IGC_EEER, eeer); + rd32(IGC_IPCNFG); + rd32(IGC_EEER); + + return IGC_SUCCESS; +} + +/* igc_set_ltr_i225 - Set Latency Tolerance Reporting thresholds + * @hw: pointer to the HW structure + * @link: bool indicating link status + * + * Set the LTR thresholds based on the link speed (Mbps), EEE, and DMAC + * settings, otherwise specify that there is no LTR requirement. + */ +s32 igc_set_ltr_i225(struct igc_hw *hw, bool link) +{ + u32 tw_system, ltrc, ltrv, ltr_min, ltr_max, scale_min, scale_max; + u16 speed, duplex; + s32 size; + + /* If we do not have link, LTR thresholds are zero. */ + if (link) { + hw->mac.ops.get_speed_and_duplex(hw, &speed, &duplex); + + /* Check if using copper interface with EEE enabled or if the + * link speed is 10 Mbps. + */ + if (hw->dev_spec._base.eee_enable && + speed != SPEED_10) { + /* EEE enabled, so send LTRMAX threshold. */ + ltrc = rd32(IGC_LTRC) | + IGC_LTRC_EEEMS_EN; + wr32(IGC_LTRC, ltrc); + + /* Calculate tw_system (nsec). */ + if (speed == SPEED_100) { + tw_system = ((rd32(IGC_EEE_SU) & + IGC_TW_SYSTEM_100_MASK) >> + IGC_TW_SYSTEM_100_SHIFT) * 500; + } else { + tw_system = (rd32(IGC_EEE_SU) & + IGC_TW_SYSTEM_1000_MASK) * 500; + } + } else { + tw_system = 0; + } + + /* Get the Rx packet buffer size. */ + size = rd32(IGC_RXPBS) & + IGC_RXPBS_SIZE_I225_MASK; + + /* Calculations vary based on DMAC settings. */ + if (rd32(IGC_DMACR) & IGC_DMACR_DMAC_EN) { + size -= (rd32(IGC_DMACR) & + IGC_DMACR_DMACTHR_MASK) >> + IGC_DMACR_DMACTHR_SHIFT; + /* Convert size to bits. */ + size *= 1024 * 8; + } else { + /* Convert size to bytes, subtract the MTU, and then + * convert the size to bits. + */ + size *= 1024; + size *= 8; + } + + if (size < 0) { + hw_dbg("Invalid effective Rx buffer size %d\n", + size); + return -IGC_ERR_CONFIG; + } + + /* Calculate the thresholds. Since speed is in Mbps, simplify + * the calculation by multiplying size/speed by 1000 for result + * to be in nsec before dividing by the scale in nsec. Set the + * scale such that the LTR threshold fits in the register. + */ + ltr_min = (1000 * size) / speed; + ltr_max = ltr_min + tw_system; + scale_min = (ltr_min / 1024) < 1024 ? IGC_LTRMINV_SCALE_1024 : + IGC_LTRMINV_SCALE_32768; + scale_max = (ltr_max / 1024) < 1024 ? IGC_LTRMAXV_SCALE_1024 : + IGC_LTRMAXV_SCALE_32768; + ltr_min /= scale_min == IGC_LTRMINV_SCALE_1024 ? 1024 : 32768; + ltr_min -= 1; + ltr_max /= scale_max == IGC_LTRMAXV_SCALE_1024 ? 1024 : 32768; + ltr_max -= 1; + + /* Only write the LTR thresholds if they differ from before. */ + ltrv = rd32(IGC_LTRMINV); + if (ltr_min != (ltrv & IGC_LTRMINV_LTRV_MASK)) { + ltrv = IGC_LTRMINV_LSNP_REQ | ltr_min | + (scale_min << IGC_LTRMINV_SCALE_SHIFT); + wr32(IGC_LTRMINV, ltrv); + } + + ltrv = rd32(IGC_LTRMAXV); + if (ltr_max != (ltrv & IGC_LTRMAXV_LTRV_MASK)) { + ltrv = IGC_LTRMAXV_LSNP_REQ | ltr_max | + (scale_max << IGC_LTRMAXV_SCALE_SHIFT); + wr32(IGC_LTRMAXV, ltrv); + } + } + + return IGC_SUCCESS; +} diff --git a/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_i225.h b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_i225.h new file mode 100644 index 00000000..dae47e4f --- /dev/null +++ b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_i225.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2018 Intel Corporation */ + +#ifndef _IGC_I225_H_ +#define _IGC_I225_H_ + +s32 igc_acquire_swfw_sync_i225(struct igc_hw *hw, u16 mask); +void igc_release_swfw_sync_i225(struct igc_hw *hw, u16 mask); + +s32 igc_init_nvm_params_i225(struct igc_hw *hw); +bool igc_get_flash_presence_i225(struct igc_hw *hw); +s32 igc_set_eee_i225(struct igc_hw *hw, bool adv2p5G, bool adv1G, + bool adv100M); +s32 igc_set_ltr_i225(struct igc_hw *hw, bool link); + +#endif diff --git a/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_mac.c b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_mac.c new file mode 100644 index 00000000..67b8ffd2 --- /dev/null +++ b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_mac.c @@ -0,0 +1,881 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2018 Intel Corporation */ + +#include +#include + +#include "igc_mac.h" +#include "igc_hw.h" + +/** + * igc_disable_pcie_master - Disables PCI-express master access + * @hw: pointer to the HW structure + * + * Returns 0 (0) if successful, else returns -10 + * (-IGC_ERR_MASTER_REQUESTS_PENDING) if master disable bit has not caused + * the master requests to be disabled. + * + * Disables PCI-Express master access and verifies there are no pending + * requests. + */ +s32 igc_disable_pcie_master(struct igc_hw *hw) +{ + s32 timeout = MASTER_DISABLE_TIMEOUT; + s32 ret_val = 0; + u32 ctrl; + + ctrl = rd32(IGC_CTRL); + ctrl |= IGC_CTRL_GIO_MASTER_DISABLE; + wr32(IGC_CTRL, ctrl); + + while (timeout) { + if (!(rd32(IGC_STATUS) & + IGC_STATUS_GIO_MASTER_ENABLE)) + break; + usleep_range(2000, 3000); + timeout--; + } + + if (!timeout) { + hw_dbg("Master requests are pending.\n"); + ret_val = -IGC_ERR_MASTER_REQUESTS_PENDING; + goto out; + } + +out: + return ret_val; +} + +/** + * igc_init_rx_addrs - Initialize receive addresses + * @hw: pointer to the HW structure + * @rar_count: receive address registers + * + * Setup the receive address registers by setting the base receive address + * register to the devices MAC address and clearing all the other receive + * address registers to 0. + */ +void igc_init_rx_addrs(struct igc_hw *hw, u16 rar_count) +{ + u8 mac_addr[ETH_ALEN] = {0}; + u32 i; + + /* Setup the receive address */ + hw_dbg("Programming MAC Address into RAR[0]\n"); + + hw->mac.ops.rar_set(hw, hw->mac.addr, 0); + + /* Zero out the other (rar_entry_count - 1) receive addresses */ + hw_dbg("Clearing RAR[1-%u]\n", rar_count - 1); + for (i = 1; i < rar_count; i++) + hw->mac.ops.rar_set(hw, mac_addr, i); +} + +/** + * igc_set_fc_watermarks - Set flow control high/low watermarks + * @hw: pointer to the HW structure + * + * Sets the flow control high/low threshold (watermark) registers. If + * flow control XON frame transmission is enabled, then set XON frame + * transmission as well. + */ +static s32 igc_set_fc_watermarks(struct igc_hw *hw) +{ + u32 fcrtl = 0, fcrth = 0; + + /* Set the flow control receive threshold registers. Normally, + * these registers will be set to a default threshold that may be + * adjusted later by the driver's runtime code. However, if the + * ability to transmit pause frames is not enabled, then these + * registers will be set to 0. + */ + if (hw->fc.current_mode & igc_fc_tx_pause) { + /* We need to set up the Receive Threshold high and low water + * marks as well as (optionally) enabling the transmission of + * XON frames. + */ + fcrtl = hw->fc.low_water; + if (hw->fc.send_xon) + fcrtl |= IGC_FCRTL_XONE; + + fcrth = hw->fc.high_water; + } + wr32(IGC_FCRTL, fcrtl); + wr32(IGC_FCRTH, fcrth); + + return 0; +} + +/** + * igc_setup_link - Setup flow control and link settings + * @hw: pointer to the HW structure + * + * Determines which flow control settings to use, then configures flow + * control. Calls the appropriate media-specific link configuration + * function. Assuming the adapter has a valid link partner, a valid link + * should be established. Assumes the hardware has previously been reset + * and the transmitter and receiver are not enabled. + */ +s32 igc_setup_link(struct igc_hw *hw) +{ + s32 ret_val = 0; + + /* In the case of the phy reset being blocked, we already have a link. + * We do not need to set it up again. + */ + if (igc_check_reset_block(hw)) + goto out; + + /* If requested flow control is set to default, set flow control + * to the both 'rx' and 'tx' pause frames. + */ + if (hw->fc.requested_mode == igc_fc_default) + hw->fc.requested_mode = igc_fc_full; + + /* We want to save off the original Flow Control configuration just + * in case we get disconnected and then reconnected into a different + * hub or switch with different Flow Control capabilities. + */ + hw->fc.current_mode = hw->fc.requested_mode; + + hw_dbg("After fix-ups FlowControl is now = %x\n", hw->fc.current_mode); + + /* Call the necessary media_type subroutine to configure the link. */ + ret_val = hw->mac.ops.setup_physical_interface(hw); + if (ret_val) + goto out; + + /* Initialize the flow control address, type, and PAUSE timer + * registers to their default values. This is done even if flow + * control is disabled, because it does not hurt anything to + * initialize these registers. + */ + hw_dbg("Initializing the Flow Control address, type and timer regs\n"); + wr32(IGC_FCT, FLOW_CONTROL_TYPE); + wr32(IGC_FCAH, FLOW_CONTROL_ADDRESS_HIGH); + wr32(IGC_FCAL, FLOW_CONTROL_ADDRESS_LOW); + + wr32(IGC_FCTTV, hw->fc.pause_time); + + ret_val = igc_set_fc_watermarks(hw); + +out: + return ret_val; +} + +/** + * igc_force_mac_fc - Force the MAC's flow control settings + * @hw: pointer to the HW structure + * + * Force the MAC's flow control settings. Sets the TFCE and RFCE bits in the + * device control register to reflect the adapter settings. TFCE and RFCE + * need to be explicitly set by software when a copper PHY is used because + * autonegotiation is managed by the PHY rather than the MAC. Software must + * also configure these bits when link is forced on a fiber connection. + */ +s32 igc_force_mac_fc(struct igc_hw *hw) +{ + s32 ret_val = 0; + u32 ctrl; + + ctrl = rd32(IGC_CTRL); + + /* Because we didn't get link via the internal auto-negotiation + * mechanism (we either forced link or we got link via PHY + * auto-neg), we have to manually enable/disable transmit an + * receive flow control. + * + * The "Case" statement below enables/disable flow control + * according to the "hw->fc.current_mode" parameter. + * + * The possible values of the "fc" parameter are: + * 0: Flow control is completely disabled + * 1: Rx flow control is enabled (we can receive pause + * frames but not send pause frames). + * 2: Tx flow control is enabled (we can send pause frames + * frames but we do not receive pause frames). + * 3: Both Rx and TX flow control (symmetric) is enabled. + * other: No other values should be possible at this point. + */ + hw_dbg("hw->fc.current_mode = %u\n", hw->fc.current_mode); + + switch (hw->fc.current_mode) { + case igc_fc_none: + ctrl &= (~(IGC_CTRL_TFCE | IGC_CTRL_RFCE)); + break; + case igc_fc_rx_pause: + ctrl &= (~IGC_CTRL_TFCE); + ctrl |= IGC_CTRL_RFCE; + break; + case igc_fc_tx_pause: + ctrl &= (~IGC_CTRL_RFCE); + ctrl |= IGC_CTRL_TFCE; + break; + case igc_fc_full: + ctrl |= (IGC_CTRL_TFCE | IGC_CTRL_RFCE); + break; + default: + hw_dbg("Flow control param set incorrectly\n"); + ret_val = -IGC_ERR_CONFIG; + goto out; + } + + wr32(IGC_CTRL, ctrl); + +out: + return ret_val; +} + +/** + * igc_clear_hw_cntrs_base - Clear base hardware counters + * @hw: pointer to the HW structure + * + * Clears the base hardware counters by reading the counter registers. + */ +void igc_clear_hw_cntrs_base(struct igc_hw *hw) +{ + rd32(IGC_CRCERRS); + rd32(IGC_MPC); + rd32(IGC_SCC); + rd32(IGC_ECOL); + rd32(IGC_MCC); + rd32(IGC_LATECOL); + rd32(IGC_COLC); + rd32(IGC_RERC); + rd32(IGC_DC); + rd32(IGC_RLEC); + rd32(IGC_XONRXC); + rd32(IGC_XONTXC); + rd32(IGC_XOFFRXC); + rd32(IGC_XOFFTXC); + rd32(IGC_FCRUC); + rd32(IGC_GPRC); + rd32(IGC_BPRC); + rd32(IGC_MPRC); + rd32(IGC_GPTC); + rd32(IGC_GORCL); + rd32(IGC_GORCH); + rd32(IGC_GOTCL); + rd32(IGC_GOTCH); + rd32(IGC_RNBC); + rd32(IGC_RUC); + rd32(IGC_RFC); + rd32(IGC_ROC); + rd32(IGC_RJC); + rd32(IGC_TORL); + rd32(IGC_TORH); + rd32(IGC_TOTL); + rd32(IGC_TOTH); + rd32(IGC_TPR); + rd32(IGC_TPT); + rd32(IGC_MPTC); + rd32(IGC_BPTC); + + rd32(IGC_PRC64); + rd32(IGC_PRC127); + rd32(IGC_PRC255); + rd32(IGC_PRC511); + rd32(IGC_PRC1023); + rd32(IGC_PRC1522); + rd32(IGC_PTC64); + rd32(IGC_PTC127); + rd32(IGC_PTC255); + rd32(IGC_PTC511); + rd32(IGC_PTC1023); + rd32(IGC_PTC1522); + + rd32(IGC_ALGNERRC); + rd32(IGC_RXERRC); + rd32(IGC_TNCRS); + rd32(IGC_HTDPMC); + rd32(IGC_TSCTC); + + rd32(IGC_MGTPRC); + rd32(IGC_MGTPDC); + rd32(IGC_MGTPTC); + + rd32(IGC_IAC); + + rd32(IGC_RPTHC); + rd32(IGC_TLPIC); + rd32(IGC_RLPIC); + rd32(IGC_HGPTC); + rd32(IGC_RXDMTC); + rd32(IGC_HGORCL); + rd32(IGC_HGORCH); + rd32(IGC_HGOTCL); + rd32(IGC_HGOTCH); + rd32(IGC_LENERRS); +} + +/** + * igc_rar_set - Set receive address register + * @hw: pointer to the HW structure + * @addr: pointer to the receive address + * @index: receive address array register + * + * Sets the receive address array register at index to the address passed + * in by addr. + */ +void igc_rar_set(struct igc_hw *hw, u8 *addr, u32 index) +{ + u32 rar_low, rar_high; + + /* HW expects these in little endian so we reverse the byte order + * from network order (big endian) to little endian + */ + rar_low = ((u32)addr[0] | + ((u32)addr[1] << 8) | + ((u32)addr[2] << 16) | ((u32)addr[3] << 24)); + + rar_high = ((u32)addr[4] | ((u32)addr[5] << 8)); + + /* If MAC address zero, no need to set the AV bit */ + if (rar_low || rar_high) + rar_high |= IGC_RAH_AV; + + /* Some bridges will combine consecutive 32-bit writes into + * a single burst write, which will malfunction on some parts. + * The flushes avoid this. + */ + wr32(IGC_RAL(index), rar_low); + wrfl(); + wr32(IGC_RAH(index), rar_high); + wrfl(); +} + +/** + * igc_check_for_copper_link - Check for link (Copper) + * @hw: pointer to the HW structure + * + * Checks to see of the link status of the hardware has changed. If a + * change in link status has been detected, then we read the PHY registers + * to get the current speed/duplex if link exists. + */ +s32 igc_check_for_copper_link(struct igc_hw *hw) +{ + struct igc_mac_info *mac = &hw->mac; + bool link = false; + s32 ret_val; + + /* We only want to go out to the PHY registers to see if Auto-Neg + * has completed and/or if our link status has changed. The + * get_link_status flag is set upon receiving a Link Status + * Change or Rx Sequence Error interrupt. + */ + if (!mac->get_link_status) { + ret_val = 0; + goto out; + } + + /* First we want to see if the MII Status Register reports + * link. If so, then we want to get the current speed/duplex + * of the PHY. + */ + ret_val = igc_phy_has_link(hw, 1, 0, &link); + if (ret_val) + goto out; + + if (!link) + goto out; /* No link detected */ + + mac->get_link_status = false; + + /* Check if there was DownShift, must be checked + * immediately after link-up + */ + igc_check_downshift(hw); + + /* If we are forcing speed/duplex, then we simply return since + * we have already determined whether we have link or not. + */ + if (!mac->autoneg) { + ret_val = -IGC_ERR_CONFIG; + goto out; + } + + /* Auto-Neg is enabled. Auto Speed Detection takes care + * of MAC speed/duplex configuration. So we only need to + * configure Collision Distance in the MAC. + */ + igc_config_collision_dist(hw); + + /* Configure Flow Control now that Auto-Neg has completed. + * First, we need to restore the desired flow control + * settings because we may have had to re-autoneg with a + * different link partner. + */ + ret_val = igc_config_fc_after_link_up(hw); + if (ret_val) + hw_dbg("Error configuring flow control\n"); + +out: + /* Now that we are aware of our link settings, we can set the LTR + * thresholds. + */ + ret_val = igc_set_ltr_i225(hw, link); + + return ret_val; +} + +/** + * igc_config_collision_dist - Configure collision distance + * @hw: pointer to the HW structure + * + * Configures the collision distance to the default value and is used + * during link setup. Currently no func pointer exists and all + * implementations are handled in the generic version of this function. + */ +void igc_config_collision_dist(struct igc_hw *hw) +{ + u32 tctl; + + tctl = rd32(IGC_TCTL); + + tctl &= ~IGC_TCTL_COLD; + tctl |= IGC_COLLISION_DISTANCE << IGC_COLD_SHIFT; + + wr32(IGC_TCTL, tctl); + wrfl(); +} + +/** + * igc_config_fc_after_link_up - Configures flow control after link + * @hw: pointer to the HW structure + * + * Checks the status of auto-negotiation after link up to ensure that the + * speed and duplex were not forced. If the link needed to be forced, then + * flow control needs to be forced also. If auto-negotiation is enabled + * and did not fail, then we configure flow control based on our link + * partner. + */ +s32 igc_config_fc_after_link_up(struct igc_hw *hw) +{ + u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg; + struct igc_mac_info *mac = &hw->mac; + u16 speed, duplex; + s32 ret_val = 0; + + /* Check for the case where we have fiber media and auto-neg failed + * so we had to force link. In this case, we need to force the + * configuration of the MAC to match the "fc" parameter. + */ + if (mac->autoneg_failed) + ret_val = igc_force_mac_fc(hw); + + if (ret_val) { + hw_dbg("Error forcing flow control settings\n"); + goto out; + } + + /* Check for the case where we have copper media and auto-neg is + * enabled. In this case, we need to check and see if Auto-Neg + * has completed, and if so, how the PHY and link partner has + * flow control configured. + */ + if (mac->autoneg) { + /* Read the MII Status Register and check to see if AutoNeg + * has completed. We read this twice because this reg has + * some "sticky" (latched) bits. + */ + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, + &mii_status_reg); + if (ret_val) + goto out; + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, + &mii_status_reg); + if (ret_val) + goto out; + + if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) { + hw_dbg("Copper PHY and Auto Neg has not completed.\n"); + goto out; + } + + /* The AutoNeg process has completed, so we now need to + * read both the Auto Negotiation Advertisement + * Register (Address 4) and the Auto_Negotiation Base + * Page Ability Register (Address 5) to determine how + * flow control was negotiated. + */ + ret_val = hw->phy.ops.read_reg(hw, PHY_AUTONEG_ADV, + &mii_nway_adv_reg); + if (ret_val) + goto out; + ret_val = hw->phy.ops.read_reg(hw, PHY_LP_ABILITY, + &mii_nway_lp_ability_reg); + if (ret_val) + goto out; + /* Two bits in the Auto Negotiation Advertisement Register + * (Address 4) and two bits in the Auto Negotiation Base + * Page Ability Register (Address 5) determine flow control + * for both the PHY and the link partner. The following + * table, taken out of the IEEE 802.3ab/D6.0 dated March 25, + * 1999, describes these PAUSE resolution bits and how flow + * control is determined based upon these settings. + * NOTE: DC = Don't Care + * + * LOCAL DEVICE | LINK PARTNER + * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution + *-------|---------|-------|---------|-------------------- + * 0 | 0 | DC | DC | igc_fc_none + * 0 | 1 | 0 | DC | igc_fc_none + * 0 | 1 | 1 | 0 | igc_fc_none + * 0 | 1 | 1 | 1 | igc_fc_tx_pause + * 1 | 0 | 0 | DC | igc_fc_none + * 1 | DC | 1 | DC | igc_fc_full + * 1 | 1 | 0 | 0 | igc_fc_none + * 1 | 1 | 0 | 1 | igc_fc_rx_pause + * + * Are both PAUSE bits set to 1? If so, this implies + * Symmetric Flow Control is enabled at both ends. The + * ASM_DIR bits are irrelevant per the spec. + * + * For Symmetric Flow Control: + * + * LOCAL DEVICE | LINK PARTNER + * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result + *-------|---------|-------|---------|-------------------- + * 1 | DC | 1 | DC | IGC_fc_full + * + */ + if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && + (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) { + /* Now we need to check if the user selected RX ONLY + * of pause frames. In this case, we had to advertise + * FULL flow control because we could not advertise RX + * ONLY. Hence, we must now check to see if we need to + * turn OFF the TRANSMISSION of PAUSE frames. + */ + if (hw->fc.requested_mode == igc_fc_full) { + hw->fc.current_mode = igc_fc_full; + hw_dbg("Flow Control = FULL.\n"); + } else { + hw->fc.current_mode = igc_fc_rx_pause; + hw_dbg("Flow Control = RX PAUSE frames only.\n"); + } + } + + /* For receiving PAUSE frames ONLY. + * + * LOCAL DEVICE | LINK PARTNER + * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result + *-------|---------|-------|---------|-------------------- + * 0 | 1 | 1 | 1 | igc_fc_tx_pause + */ + else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) && + (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && + (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && + (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { + hw->fc.current_mode = igc_fc_tx_pause; + hw_dbg("Flow Control = TX PAUSE frames only.\n"); + } + /* For transmitting PAUSE frames ONLY. + * + * LOCAL DEVICE | LINK PARTNER + * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result + *-------|---------|-------|---------|-------------------- + * 1 | 1 | 0 | 1 | igc_fc_rx_pause + */ + else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && + (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && + !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && + (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { + hw->fc.current_mode = igc_fc_rx_pause; + hw_dbg("Flow Control = RX PAUSE frames only.\n"); + } + /* Per the IEEE spec, at this point flow control should be + * disabled. However, we want to consider that we could + * be connected to a legacy switch that doesn't advertise + * desired flow control, but can be forced on the link + * partner. So if we advertised no flow control, that is + * what we will resolve to. If we advertised some kind of + * receive capability (Rx Pause Only or Full Flow Control) + * and the link partner advertised none, we will configure + * ourselves to enable Rx Flow Control only. We can do + * this safely for two reasons: If the link partner really + * didn't want flow control enabled, and we enable Rx, no + * harm done since we won't be receiving any PAUSE frames + * anyway. If the intent on the link partner was to have + * flow control enabled, then by us enabling RX only, we + * can at least receive pause frames and process them. + * This is a good idea because in most cases, since we are + * predominantly a server NIC, more times than not we will + * be asked to delay transmission of packets than asking + * our link partner to pause transmission of frames. + */ + else if ((hw->fc.requested_mode == igc_fc_none) || + (hw->fc.requested_mode == igc_fc_tx_pause) || + (hw->fc.strict_ieee)) { + hw->fc.current_mode = igc_fc_none; + hw_dbg("Flow Control = NONE.\n"); + } else { + hw->fc.current_mode = igc_fc_rx_pause; + hw_dbg("Flow Control = RX PAUSE frames only.\n"); + } + + /* Now we need to do one last check... If we auto- + * negotiated to HALF DUPLEX, flow control should not be + * enabled per IEEE 802.3 spec. + */ + ret_val = hw->mac.ops.get_speed_and_duplex(hw, &speed, &duplex); + if (ret_val) { + hw_dbg("Error getting link speed and duplex\n"); + goto out; + } + + if (duplex == HALF_DUPLEX) + hw->fc.current_mode = igc_fc_none; + + /* Now we call a subroutine to actually force the MAC + * controller to use the correct flow control settings. + */ + ret_val = igc_force_mac_fc(hw); + if (ret_val) { + hw_dbg("Error forcing flow control settings\n"); + goto out; + } + } + +out: + return ret_val; +} + +/** + * igc_get_auto_rd_done - Check for auto read completion + * @hw: pointer to the HW structure + * + * Check EEPROM for Auto Read done bit. + */ +s32 igc_get_auto_rd_done(struct igc_hw *hw) +{ + s32 ret_val = 0; + s32 i = 0; + + while (i < AUTO_READ_DONE_TIMEOUT) { + if (rd32(IGC_EECD) & IGC_EECD_AUTO_RD) + break; + usleep_range(1000, 2000); + i++; + } + + if (i == AUTO_READ_DONE_TIMEOUT) { + hw_dbg("Auto read by HW from NVM has not completed.\n"); + ret_val = -IGC_ERR_RESET; + goto out; + } + +out: + return ret_val; +} + +/** + * igc_get_speed_and_duplex_copper - Retrieve current speed/duplex + * @hw: pointer to the HW structure + * @speed: stores the current speed + * @duplex: stores the current duplex + * + * Read the status register for the current speed/duplex and store the current + * speed and duplex for copper connections. + */ +s32 igc_get_speed_and_duplex_copper(struct igc_hw *hw, u16 *speed, + u16 *duplex) +{ + u32 status; + + status = rd32(IGC_STATUS); + if (status & IGC_STATUS_SPEED_1000) { + /* For I225, STATUS will indicate 1G speed in both 1 Gbps + * and 2.5 Gbps link modes. An additional bit is used + * to differentiate between 1 Gbps and 2.5 Gbps. + */ + if (hw->mac.type == igc_i225 && + (status & IGC_STATUS_SPEED_2500)) { + *speed = SPEED_2500; + hw_dbg("2500 Mbs, "); + } else { + *speed = SPEED_1000; + hw_dbg("1000 Mbs, "); + } + } else if (status & IGC_STATUS_SPEED_100) { + *speed = SPEED_100; + hw_dbg("100 Mbs, "); + } else { + *speed = SPEED_10; + hw_dbg("10 Mbs, "); + } + + if (status & IGC_STATUS_FD) { + *duplex = FULL_DUPLEX; + hw_dbg("Full Duplex\n"); + } else { + *duplex = HALF_DUPLEX; + hw_dbg("Half Duplex\n"); + } + + return 0; +} + +/** + * igc_put_hw_semaphore - Release hardware semaphore + * @hw: pointer to the HW structure + * + * Release hardware semaphore used to access the PHY or NVM + */ +void igc_put_hw_semaphore(struct igc_hw *hw) +{ + u32 swsm; + + swsm = rd32(IGC_SWSM); + + swsm &= ~(IGC_SWSM_SMBI | IGC_SWSM_SWESMBI); + + wr32(IGC_SWSM, swsm); +} + +/** + * igc_enable_mng_pass_thru - Enable processing of ARP's + * @hw: pointer to the HW structure + * + * Verifies the hardware needs to leave interface enabled so that frames can + * be directed to and from the management interface. + */ +bool igc_enable_mng_pass_thru(struct igc_hw *hw) +{ + bool ret_val = false; + u32 fwsm, factps; + u32 manc; + + if (!hw->mac.asf_firmware_present) + goto out; + + manc = rd32(IGC_MANC); + + if (!(manc & IGC_MANC_RCV_TCO_EN)) + goto out; + + if (hw->mac.arc_subsystem_valid) { + fwsm = rd32(IGC_FWSM); + factps = rd32(IGC_FACTPS); + + if (!(factps & IGC_FACTPS_MNGCG) && + ((fwsm & IGC_FWSM_MODE_MASK) == + (igc_mng_mode_pt << IGC_FWSM_MODE_SHIFT))) { + ret_val = true; + goto out; + } + } else { + if ((manc & IGC_MANC_SMBUS_EN) && + !(manc & IGC_MANC_ASF_EN)) { + ret_val = true; + goto out; + } + } + +out: + return ret_val; +} + +/** + * igc_hash_mc_addr - Generate a multicast hash value + * @hw: pointer to the HW structure + * @mc_addr: pointer to a multicast address + * + * Generates a multicast address hash value which is used to determine + * the multicast filter table array address and new table value. See + * igc_mta_set() + **/ +static u32 igc_hash_mc_addr(struct igc_hw *hw, u8 *mc_addr) +{ + u32 hash_value, hash_mask; + u8 bit_shift = 0; + + /* Register count multiplied by bits per register */ + hash_mask = (hw->mac.mta_reg_count * 32) - 1; + + /* For a mc_filter_type of 0, bit_shift is the number of left-shifts + * where 0xFF would still fall within the hash mask. + */ + while (hash_mask >> bit_shift != 0xFF) + bit_shift++; + + /* The portion of the address that is used for the hash table + * is determined by the mc_filter_type setting. + * The algorithm is such that there is a total of 8 bits of shifting. + * The bit_shift for a mc_filter_type of 0 represents the number of + * left-shifts where the MSB of mc_addr[5] would still fall within + * the hash_mask. Case 0 does this exactly. Since there are a total + * of 8 bits of shifting, then mc_addr[4] will shift right the + * remaining number of bits. Thus 8 - bit_shift. The rest of the + * cases are a variation of this algorithm...essentially raising the + * number of bits to shift mc_addr[5] left, while still keeping the + * 8-bit shifting total. + * + * For example, given the following Destination MAC Address and an + * MTA register count of 128 (thus a 4096-bit vector and 0xFFF mask), + * we can see that the bit_shift for case 0 is 4. These are the hash + * values resulting from each mc_filter_type... + * [0] [1] [2] [3] [4] [5] + * 01 AA 00 12 34 56 + * LSB MSB + * + * case 0: hash_value = ((0x34 >> 4) | (0x56 << 4)) & 0xFFF = 0x563 + * case 1: hash_value = ((0x34 >> 3) | (0x56 << 5)) & 0xFFF = 0xAC6 + * case 2: hash_value = ((0x34 >> 2) | (0x56 << 6)) & 0xFFF = 0x163 + * case 3: hash_value = ((0x34 >> 0) | (0x56 << 8)) & 0xFFF = 0x634 + */ + switch (hw->mac.mc_filter_type) { + default: + case 0: + break; + case 1: + bit_shift += 1; + break; + case 2: + bit_shift += 2; + break; + case 3: + bit_shift += 4; + break; + } + + hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) | + (((u16)mc_addr[5]) << bit_shift))); + + return hash_value; +} + +/** + * igc_update_mc_addr_list - Update Multicast addresses + * @hw: pointer to the HW structure + * @mc_addr_list: array of multicast addresses to program + * @mc_addr_count: number of multicast addresses to program + * + * Updates entire Multicast Table Array. + * The caller must have a packed mc_addr_list of multicast addresses. + **/ +void igc_update_mc_addr_list(struct igc_hw *hw, + u8 *mc_addr_list, u32 mc_addr_count) +{ + u32 hash_value, hash_bit, hash_reg; + int i; + + /* clear mta_shadow */ + memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow)); + + /* update mta_shadow from mc_addr_list */ + for (i = 0; (u32)i < mc_addr_count; i++) { + hash_value = igc_hash_mc_addr(hw, mc_addr_list); + + hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1); + hash_bit = hash_value & 0x1F; + + hw->mac.mta_shadow[hash_reg] |= BIT(hash_bit); + mc_addr_list += ETH_ALEN; + } + + /* replace the entire MTA table */ + for (i = hw->mac.mta_reg_count - 1; i >= 0; i--) + array_wr32(IGC_MTA, i, hw->mac.mta_shadow[i]); + wrfl(); +} diff --git a/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_mac.h b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_mac.h new file mode 100644 index 00000000..b5963f86 --- /dev/null +++ b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_mac.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2018 Intel Corporation */ + +#ifndef _IGC_MAC_H_ +#define _IGC_MAC_H_ + +#include "igc_hw.h" +#include "igc_phy.h" +#include "igc_defines.h" + +/* forward declaration */ +s32 igc_disable_pcie_master(struct igc_hw *hw); +s32 igc_check_for_copper_link(struct igc_hw *hw); +s32 igc_config_fc_after_link_up(struct igc_hw *hw); +s32 igc_force_mac_fc(struct igc_hw *hw); +void igc_init_rx_addrs(struct igc_hw *hw, u16 rar_count); +s32 igc_setup_link(struct igc_hw *hw); +void igc_clear_hw_cntrs_base(struct igc_hw *hw); +s32 igc_get_auto_rd_done(struct igc_hw *hw); +void igc_put_hw_semaphore(struct igc_hw *hw); +void igc_rar_set(struct igc_hw *hw, u8 *addr, u32 index); +void igc_config_collision_dist(struct igc_hw *hw); + +s32 igc_get_speed_and_duplex_copper(struct igc_hw *hw, u16 *speed, + u16 *duplex); + +bool igc_enable_mng_pass_thru(struct igc_hw *hw); +void igc_update_mc_addr_list(struct igc_hw *hw, + u8 *mc_addr_list, u32 mc_addr_count); + +enum igc_mng_mode { + igc_mng_mode_none = 0, + igc_mng_mode_asf, + igc_mng_mode_pt, + igc_mng_mode_ipmi, + igc_mng_mode_host_if_only +}; + +#endif diff --git a/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_main.c b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_main.c new file mode 100644 index 00000000..f23bcefa --- /dev/null +++ b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_main.c @@ -0,0 +1,5682 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2018 Intel Corporation */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "igc.h" +#include "igc_hw.h" +#include "igc_tsn.h" + +#define DRV_SUMMARY "Intel(R) 2.5G Ethernet Linux Driver" + +#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK) + +static int debug = -1; + +MODULE_AUTHOR("Intel Corporation, "); +MODULE_DESCRIPTION(DRV_SUMMARY); +MODULE_LICENSE("GPL v2"); +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); + +char igc_driver_name[] = "igc"; +static const char igc_driver_string[] = DRV_SUMMARY; +static const char igc_copyright[] = + "Copyright(c) 2018 Intel Corporation."; + +static const struct igc_info *igc_info_tbl[] = { + [board_base] = &igc_base_info, +}; + +static const struct pci_device_id igc_pci_tbl[] = { + { PCI_VDEVICE(INTEL, IGC_DEV_ID_I225_LM), board_base }, + { PCI_VDEVICE(INTEL, IGC_DEV_ID_I225_V), board_base }, + { PCI_VDEVICE(INTEL, IGC_DEV_ID_I225_I), board_base }, + { PCI_VDEVICE(INTEL, IGC_DEV_ID_I220_V), board_base }, + { PCI_VDEVICE(INTEL, IGC_DEV_ID_I225_K), board_base }, + { PCI_VDEVICE(INTEL, IGC_DEV_ID_I225_K2), board_base }, + { PCI_VDEVICE(INTEL, IGC_DEV_ID_I226_K), board_base }, + { PCI_VDEVICE(INTEL, IGC_DEV_ID_I225_LMVP), board_base }, + { PCI_VDEVICE(INTEL, IGC_DEV_ID_I226_LMVP), board_base }, + { PCI_VDEVICE(INTEL, IGC_DEV_ID_I225_IT), board_base }, + { PCI_VDEVICE(INTEL, IGC_DEV_ID_I226_LM), board_base }, + { PCI_VDEVICE(INTEL, IGC_DEV_ID_I226_V), board_base }, + { PCI_VDEVICE(INTEL, IGC_DEV_ID_I226_IT), board_base }, + { PCI_VDEVICE(INTEL, IGC_DEV_ID_I221_V), board_base }, + { PCI_VDEVICE(INTEL, IGC_DEV_ID_I226_BLANK_NVM), board_base }, + { PCI_VDEVICE(INTEL, IGC_DEV_ID_I225_BLANK_NVM), board_base }, + /* required last entry */ + {0, } +}; + +MODULE_DEVICE_TABLE(pci, igc_pci_tbl); + +enum latency_range { + lowest_latency = 0, + low_latency = 1, + bulk_latency = 2, + latency_invalid = 255 +}; + +void igc_reset(struct igc_adapter *adapter) +{ + struct net_device *dev = adapter->netdev; + struct igc_hw *hw = &adapter->hw; + struct igc_fc_info *fc = &hw->fc; + u32 pba, hwm; + + /* Repartition PBA for greater than 9k MTU if required */ + pba = IGC_PBA_34K; + + /* flow control settings + * The high water mark must be low enough to fit one full frame + * after transmitting the pause frame. As such we must have enough + * space to allow for us to complete our current transmit and then + * receive the frame that is in progress from the link partner. + * Set it to: + * - the full Rx FIFO size minus one full Tx plus one full Rx frame + */ + hwm = (pba << 10) - (adapter->max_frame_size + MAX_JUMBO_FRAME_SIZE); + + fc->high_water = hwm & 0xFFFFFFF0; /* 16-byte granularity */ + fc->low_water = fc->high_water - 16; + fc->pause_time = 0xFFFF; + fc->send_xon = 1; + fc->current_mode = fc->requested_mode; + + hw->mac.ops.reset_hw(hw); + + if (hw->mac.ops.init_hw(hw)) + netdev_err(dev, "Error on hardware initialization\n"); + + /* Re-establish EEE setting */ + igc_set_eee_i225(hw, true, true, true); + + if (!netif_running(adapter->netdev)) + igc_power_down_phy_copper_base(&adapter->hw); + + /* Re-enable PTP, where applicable. */ + igc_ptp_reset(adapter); + + /* Re-enable TSN offloading, where applicable. */ + igc_tsn_offload_apply(adapter); + + igc_get_phy_info(hw); +} + +/** + * igc_power_up_link - Power up the phy link + * @adapter: address of board private structure + */ +static void igc_power_up_link(struct igc_adapter *adapter) +{ + igc_reset_phy(&adapter->hw); + + igc_power_up_phy_copper(&adapter->hw); + + igc_setup_link(&adapter->hw); +} + +/** + * igc_release_hw_control - release control of the h/w to f/w + * @adapter: address of board private structure + * + * igc_release_hw_control resets CTRL_EXT:DRV_LOAD bit. + * For ASF and Pass Through versions of f/w this means that the + * driver is no longer loaded. + */ +static void igc_release_hw_control(struct igc_adapter *adapter) +{ + struct igc_hw *hw = &adapter->hw; + u32 ctrl_ext; + + if (!pci_device_is_present(adapter->pdev)) + return; + + /* Let firmware take over control of h/w */ + ctrl_ext = rd32(IGC_CTRL_EXT); + wr32(IGC_CTRL_EXT, + ctrl_ext & ~IGC_CTRL_EXT_DRV_LOAD); +} + +/** + * igc_get_hw_control - get control of the h/w from f/w + * @adapter: address of board private structure + * + * igc_get_hw_control sets CTRL_EXT:DRV_LOAD bit. + * For ASF and Pass Through versions of f/w this means that + * the driver is loaded. + */ +static void igc_get_hw_control(struct igc_adapter *adapter) +{ + struct igc_hw *hw = &adapter->hw; + u32 ctrl_ext; + + /* Let firmware know the driver has taken over */ + ctrl_ext = rd32(IGC_CTRL_EXT); + wr32(IGC_CTRL_EXT, + ctrl_ext | IGC_CTRL_EXT_DRV_LOAD); +} + +/** + * igc_clean_tx_ring - Free Tx Buffers + * @tx_ring: ring to be cleaned + */ +static void igc_clean_tx_ring(struct igc_ring *tx_ring) +{ + u16 i = tx_ring->next_to_clean; + struct igc_tx_buffer *tx_buffer = &tx_ring->tx_buffer_info[i]; + + while (i != tx_ring->next_to_use) { + union igc_adv_tx_desc *eop_desc, *tx_desc; + + /* Free all the Tx ring sk_buffs */ + dev_kfree_skb_any(tx_buffer->skb); + + /* unmap skb header data */ + dma_unmap_single(tx_ring->dev, + dma_unmap_addr(tx_buffer, dma), + dma_unmap_len(tx_buffer, len), + DMA_TO_DEVICE); + + /* check for eop_desc to determine the end of the packet */ + eop_desc = tx_buffer->next_to_watch; + tx_desc = IGC_TX_DESC(tx_ring, i); + + /* unmap remaining buffers */ + while (tx_desc != eop_desc) { + tx_buffer++; + tx_desc++; + i++; + if (unlikely(i == tx_ring->count)) { + i = 0; + tx_buffer = tx_ring->tx_buffer_info; + tx_desc = IGC_TX_DESC(tx_ring, 0); + } + + /* unmap any remaining paged data */ + if (dma_unmap_len(tx_buffer, len)) + dma_unmap_page(tx_ring->dev, + dma_unmap_addr(tx_buffer, dma), + dma_unmap_len(tx_buffer, len), + DMA_TO_DEVICE); + } + + tx_buffer->next_to_watch = NULL; + + /* move us one more past the eop_desc for start of next pkt */ + tx_buffer++; + i++; + if (unlikely(i == tx_ring->count)) { + i = 0; + tx_buffer = tx_ring->tx_buffer_info; + } + } + + /* reset BQL for queue */ + netdev_tx_reset_queue(txring_txq(tx_ring)); + + /* reset next_to_use and next_to_clean */ + tx_ring->next_to_use = 0; + tx_ring->next_to_clean = 0; +} + +/** + * igc_free_tx_resources - Free Tx Resources per Queue + * @tx_ring: Tx descriptor ring for a specific queue + * + * Free all transmit software resources + */ +void igc_free_tx_resources(struct igc_ring *tx_ring) +{ + igc_clean_tx_ring(tx_ring); + + vfree(tx_ring->tx_buffer_info); + tx_ring->tx_buffer_info = NULL; + + /* if not set, then don't free */ + if (!tx_ring->desc) + return; + + dma_free_coherent(tx_ring->dev, tx_ring->size, + tx_ring->desc, tx_ring->dma); + + tx_ring->desc = NULL; +} + +/** + * igc_free_all_tx_resources - Free Tx Resources for All Queues + * @adapter: board private structure + * + * Free all transmit software resources + */ +static void igc_free_all_tx_resources(struct igc_adapter *adapter) +{ + int i; + + for (i = 0; i < adapter->num_tx_queues; i++) + igc_free_tx_resources(adapter->tx_ring[i]); +} + +/** + * igc_clean_all_tx_rings - Free Tx Buffers for all queues + * @adapter: board private structure + */ +static void igc_clean_all_tx_rings(struct igc_adapter *adapter) +{ + int i; + + for (i = 0; i < adapter->num_tx_queues; i++) + if (adapter->tx_ring[i]) + igc_clean_tx_ring(adapter->tx_ring[i]); +} + +/** + * igc_setup_tx_resources - allocate Tx resources (Descriptors) + * @tx_ring: tx descriptor ring (for a specific queue) to setup + * + * Return 0 on success, negative on failure + */ +int igc_setup_tx_resources(struct igc_ring *tx_ring) +{ + struct net_device *ndev = tx_ring->netdev; + struct device *dev = tx_ring->dev; + int size = 0; + + size = sizeof(struct igc_tx_buffer) * tx_ring->count; + tx_ring->tx_buffer_info = vzalloc(size); + if (!tx_ring->tx_buffer_info) + goto err; + + /* round up to nearest 4K */ + tx_ring->size = tx_ring->count * sizeof(union igc_adv_tx_desc); + tx_ring->size = ALIGN(tx_ring->size, 4096); + + tx_ring->desc = dma_alloc_coherent(dev, tx_ring->size, + &tx_ring->dma, GFP_KERNEL); + + if (!tx_ring->desc) + goto err; + + tx_ring->next_to_use = 0; + tx_ring->next_to_clean = 0; + + return 0; + +err: + vfree(tx_ring->tx_buffer_info); + netdev_err(ndev, "Unable to allocate memory for Tx descriptor ring\n"); + return -ENOMEM; +} + +/** + * igc_setup_all_tx_resources - wrapper to allocate Tx resources for all queues + * @adapter: board private structure + * + * Return 0 on success, negative on failure + */ +static int igc_setup_all_tx_resources(struct igc_adapter *adapter) +{ + struct net_device *dev = adapter->netdev; + int i, err = 0; + + for (i = 0; i < adapter->num_tx_queues; i++) { + err = igc_setup_tx_resources(adapter->tx_ring[i]); + if (err) { + netdev_err(dev, "Error on Tx queue %u setup\n", i); + for (i--; i >= 0; i--) + igc_free_tx_resources(adapter->tx_ring[i]); + break; + } + } + + return err; +} + +/** + * igc_clean_rx_ring - Free Rx Buffers per Queue + * @rx_ring: ring to free buffers from + */ +static void igc_clean_rx_ring(struct igc_ring *rx_ring) +{ + u16 i = rx_ring->next_to_clean; + + dev_kfree_skb(rx_ring->skb); + rx_ring->skb = NULL; + + /* Free all the Rx ring sk_buffs */ + while (i != rx_ring->next_to_alloc) { + struct igc_rx_buffer *buffer_info = &rx_ring->rx_buffer_info[i]; + + /* Invalidate cache lines that may have been written to by + * device so that we avoid corrupting memory. + */ + dma_sync_single_range_for_cpu(rx_ring->dev, + buffer_info->dma, + buffer_info->page_offset, + igc_rx_bufsz(rx_ring), + DMA_FROM_DEVICE); + + /* free resources associated with mapping */ + dma_unmap_page_attrs(rx_ring->dev, + buffer_info->dma, + igc_rx_pg_size(rx_ring), + DMA_FROM_DEVICE, + IGC_RX_DMA_ATTR); + __page_frag_cache_drain(buffer_info->page, + buffer_info->pagecnt_bias); + + i++; + if (i == rx_ring->count) + i = 0; + } + + rx_ring->next_to_alloc = 0; + rx_ring->next_to_clean = 0; + rx_ring->next_to_use = 0; +} + +/** + * igc_clean_all_rx_rings - Free Rx Buffers for all queues + * @adapter: board private structure + */ +static void igc_clean_all_rx_rings(struct igc_adapter *adapter) +{ + int i; + + for (i = 0; i < adapter->num_rx_queues; i++) + if (adapter->rx_ring[i]) + igc_clean_rx_ring(adapter->rx_ring[i]); +} + +/** + * igc_free_rx_resources - Free Rx Resources + * @rx_ring: ring to clean the resources from + * + * Free all receive software resources + */ +void igc_free_rx_resources(struct igc_ring *rx_ring) +{ + igc_clean_rx_ring(rx_ring); + + vfree(rx_ring->rx_buffer_info); + rx_ring->rx_buffer_info = NULL; + + /* if not set, then don't free */ + if (!rx_ring->desc) + return; + + dma_free_coherent(rx_ring->dev, rx_ring->size, + rx_ring->desc, rx_ring->dma); + + rx_ring->desc = NULL; +} + +/** + * igc_free_all_rx_resources - Free Rx Resources for All Queues + * @adapter: board private structure + * + * Free all receive software resources + */ +static void igc_free_all_rx_resources(struct igc_adapter *adapter) +{ + int i; + + for (i = 0; i < adapter->num_rx_queues; i++) + igc_free_rx_resources(adapter->rx_ring[i]); +} + +/** + * igc_setup_rx_resources - allocate Rx resources (Descriptors) + * @rx_ring: rx descriptor ring (for a specific queue) to setup + * + * Returns 0 on success, negative on failure + */ +int igc_setup_rx_resources(struct igc_ring *rx_ring) +{ + struct net_device *ndev = rx_ring->netdev; + struct device *dev = rx_ring->dev; + int size, desc_len; + + size = sizeof(struct igc_rx_buffer) * rx_ring->count; + rx_ring->rx_buffer_info = vzalloc(size); + if (!rx_ring->rx_buffer_info) + goto err; + + desc_len = sizeof(union igc_adv_rx_desc); + + /* Round up to nearest 4K */ + rx_ring->size = rx_ring->count * desc_len; + rx_ring->size = ALIGN(rx_ring->size, 4096); + + rx_ring->desc = dma_alloc_coherent(dev, rx_ring->size, + &rx_ring->dma, GFP_KERNEL); + + if (!rx_ring->desc) + goto err; + + rx_ring->next_to_alloc = 0; + rx_ring->next_to_clean = 0; + rx_ring->next_to_use = 0; + + return 0; + +err: + vfree(rx_ring->rx_buffer_info); + rx_ring->rx_buffer_info = NULL; + netdev_err(ndev, "Unable to allocate memory for Rx descriptor ring\n"); + return -ENOMEM; +} + +/** + * igc_setup_all_rx_resources - wrapper to allocate Rx resources + * (Descriptors) for all queues + * @adapter: board private structure + * + * Return 0 on success, negative on failure + */ +static int igc_setup_all_rx_resources(struct igc_adapter *adapter) +{ + struct net_device *dev = adapter->netdev; + int i, err = 0; + + for (i = 0; i < adapter->num_rx_queues; i++) { + err = igc_setup_rx_resources(adapter->rx_ring[i]); + if (err) { + netdev_err(dev, "Error on Rx queue %u setup\n", i); + for (i--; i >= 0; i--) + igc_free_rx_resources(adapter->rx_ring[i]); + break; + } + } + + return err; +} + +/** + * igc_configure_rx_ring - Configure a receive ring after Reset + * @adapter: board private structure + * @ring: receive ring to be configured + * + * Configure the Rx unit of the MAC after a reset. + */ +static void igc_configure_rx_ring(struct igc_adapter *adapter, + struct igc_ring *ring) +{ + struct igc_hw *hw = &adapter->hw; + union igc_adv_rx_desc *rx_desc; + int reg_idx = ring->reg_idx; + u32 srrctl = 0, rxdctl = 0; + u64 rdba = ring->dma; + + /* disable the queue */ + wr32(IGC_RXDCTL(reg_idx), 0); + + /* Set DMA base address registers */ + wr32(IGC_RDBAL(reg_idx), + rdba & 0x00000000ffffffffULL); + wr32(IGC_RDBAH(reg_idx), rdba >> 32); + wr32(IGC_RDLEN(reg_idx), + ring->count * sizeof(union igc_adv_rx_desc)); + + /* initialize head and tail */ + ring->tail = adapter->io_addr + IGC_RDT(reg_idx); + wr32(IGC_RDH(reg_idx), 0); + writel(0, ring->tail); + + /* reset next-to- use/clean to place SW in sync with hardware */ + ring->next_to_clean = 0; + ring->next_to_use = 0; + + /* set descriptor configuration */ + srrctl = IGC_RX_HDR_LEN << IGC_SRRCTL_BSIZEHDRSIZE_SHIFT; + if (ring_uses_large_buffer(ring)) + srrctl |= IGC_RXBUFFER_3072 >> IGC_SRRCTL_BSIZEPKT_SHIFT; + else + srrctl |= IGC_RXBUFFER_2048 >> IGC_SRRCTL_BSIZEPKT_SHIFT; + srrctl |= IGC_SRRCTL_DESCTYPE_ADV_ONEBUF; + + wr32(IGC_SRRCTL(reg_idx), srrctl); + + rxdctl |= IGC_RX_PTHRESH; + rxdctl |= IGC_RX_HTHRESH << 8; + rxdctl |= IGC_RX_WTHRESH << 16; + + /* initialize rx_buffer_info */ + memset(ring->rx_buffer_info, 0, + sizeof(struct igc_rx_buffer) * ring->count); + + /* initialize Rx descriptor 0 */ + rx_desc = IGC_RX_DESC(ring, 0); + rx_desc->wb.upper.length = 0; + + /* enable receive descriptor fetching */ + rxdctl |= IGC_RXDCTL_QUEUE_ENABLE; + + wr32(IGC_RXDCTL(reg_idx), rxdctl); +} + +/** + * igc_configure_rx - Configure receive Unit after Reset + * @adapter: board private structure + * + * Configure the Rx unit of the MAC after a reset. + */ +static void igc_configure_rx(struct igc_adapter *adapter) +{ + int i; + + /* Setup the HW Rx Head and Tail Descriptor Pointers and + * the Base and Length of the Rx Descriptor Ring + */ + for (i = 0; i < adapter->num_rx_queues; i++) + igc_configure_rx_ring(adapter, adapter->rx_ring[i]); +} + +/** + * igc_configure_tx_ring - Configure transmit ring after Reset + * @adapter: board private structure + * @ring: tx ring to configure + * + * Configure a transmit ring after a reset. + */ +static void igc_configure_tx_ring(struct igc_adapter *adapter, + struct igc_ring *ring) +{ + struct igc_hw *hw = &adapter->hw; + int reg_idx = ring->reg_idx; + u64 tdba = ring->dma; + u32 txdctl = 0; + + /* disable the queue */ + wr32(IGC_TXDCTL(reg_idx), 0); + wrfl(); + mdelay(10); + + wr32(IGC_TDLEN(reg_idx), + ring->count * sizeof(union igc_adv_tx_desc)); + wr32(IGC_TDBAL(reg_idx), + tdba & 0x00000000ffffffffULL); + wr32(IGC_TDBAH(reg_idx), tdba >> 32); + + ring->tail = adapter->io_addr + IGC_TDT(reg_idx); + wr32(IGC_TDH(reg_idx), 0); + writel(0, ring->tail); + + txdctl |= IGC_TX_PTHRESH; + txdctl |= IGC_TX_HTHRESH << 8; + txdctl |= IGC_TX_WTHRESH << 16; + + txdctl |= IGC_TXDCTL_QUEUE_ENABLE; + wr32(IGC_TXDCTL(reg_idx), txdctl); +} + +/** + * igc_configure_tx - Configure transmit Unit after Reset + * @adapter: board private structure + * + * Configure the Tx unit of the MAC after a reset. + */ +static void igc_configure_tx(struct igc_adapter *adapter) +{ + int i; + + for (i = 0; i < adapter->num_tx_queues; i++) + igc_configure_tx_ring(adapter, adapter->tx_ring[i]); +} + +/** + * igc_setup_mrqc - configure the multiple receive queue control registers + * @adapter: Board private structure + */ +static void igc_setup_mrqc(struct igc_adapter *adapter) +{ + struct igc_hw *hw = &adapter->hw; + u32 j, num_rx_queues; + u32 mrqc, rxcsum; + u32 rss_key[10]; + + netdev_rss_key_fill(rss_key, sizeof(rss_key)); + for (j = 0; j < 10; j++) + wr32(IGC_RSSRK(j), rss_key[j]); + + num_rx_queues = adapter->rss_queues; + + if (adapter->rss_indir_tbl_init != num_rx_queues) { + for (j = 0; j < IGC_RETA_SIZE; j++) + adapter->rss_indir_tbl[j] = + (j * num_rx_queues) / IGC_RETA_SIZE; + adapter->rss_indir_tbl_init = num_rx_queues; + } + igc_write_rss_indir_tbl(adapter); + + /* Disable raw packet checksumming so that RSS hash is placed in + * descriptor on writeback. No need to enable TCP/UDP/IP checksum + * offloads as they are enabled by default + */ + rxcsum = rd32(IGC_RXCSUM); + rxcsum |= IGC_RXCSUM_PCSD; + + /* Enable Receive Checksum Offload for SCTP */ + rxcsum |= IGC_RXCSUM_CRCOFL; + + /* Don't need to set TUOFL or IPOFL, they default to 1 */ + wr32(IGC_RXCSUM, rxcsum); + + /* Generate RSS hash based on packet types, TCP/UDP + * port numbers and/or IPv4/v6 src and dst addresses + */ + mrqc = IGC_MRQC_RSS_FIELD_IPV4 | + IGC_MRQC_RSS_FIELD_IPV4_TCP | + IGC_MRQC_RSS_FIELD_IPV6 | + IGC_MRQC_RSS_FIELD_IPV6_TCP | + IGC_MRQC_RSS_FIELD_IPV6_TCP_EX; + + if (adapter->flags & IGC_FLAG_RSS_FIELD_IPV4_UDP) + mrqc |= IGC_MRQC_RSS_FIELD_IPV4_UDP; + if (adapter->flags & IGC_FLAG_RSS_FIELD_IPV6_UDP) + mrqc |= IGC_MRQC_RSS_FIELD_IPV6_UDP; + + mrqc |= IGC_MRQC_ENABLE_RSS_MQ; + + wr32(IGC_MRQC, mrqc); +} + +/** + * igc_setup_rctl - configure the receive control registers + * @adapter: Board private structure + */ +static void igc_setup_rctl(struct igc_adapter *adapter) +{ + struct igc_hw *hw = &adapter->hw; + u32 rctl; + + rctl = rd32(IGC_RCTL); + + rctl &= ~(3 << IGC_RCTL_MO_SHIFT); + rctl &= ~(IGC_RCTL_LBM_TCVR | IGC_RCTL_LBM_MAC); + + rctl |= IGC_RCTL_EN | IGC_RCTL_BAM | IGC_RCTL_RDMTS_HALF | + (hw->mac.mc_filter_type << IGC_RCTL_MO_SHIFT); + + /* enable stripping of CRC. Newer features require + * that the HW strips the CRC. + */ + rctl |= IGC_RCTL_SECRC; + + /* disable store bad packets and clear size bits. */ + rctl &= ~(IGC_RCTL_SBP | IGC_RCTL_SZ_256); + + /* enable LPE to allow for reception of jumbo frames */ + rctl |= IGC_RCTL_LPE; + + /* disable queue 0 to prevent tail write w/o re-config */ + wr32(IGC_RXDCTL(0), 0); + + /* This is useful for sniffing bad packets. */ + if (adapter->netdev->features & NETIF_F_RXALL) { + /* UPE and MPE will be handled by normal PROMISC logic + * in set_rx_mode + */ + rctl |= (IGC_RCTL_SBP | /* Receive bad packets */ + IGC_RCTL_BAM | /* RX All Bcast Pkts */ + IGC_RCTL_PMCF); /* RX All MAC Ctrl Pkts */ + + rctl &= ~(IGC_RCTL_DPF | /* Allow filtered pause */ + IGC_RCTL_CFIEN); /* Disable VLAN CFIEN Filter */ + } + + wr32(IGC_RCTL, rctl); +} + +/** + * igc_setup_tctl - configure the transmit control registers + * @adapter: Board private structure + */ +static void igc_setup_tctl(struct igc_adapter *adapter) +{ + struct igc_hw *hw = &adapter->hw; + u32 tctl; + + /* disable queue 0 which icould be enabled by default */ + wr32(IGC_TXDCTL(0), 0); + + /* Program the Transmit Control Register */ + tctl = rd32(IGC_TCTL); + tctl &= ~IGC_TCTL_CT; + tctl |= IGC_TCTL_PSP | IGC_TCTL_RTLC | + (IGC_COLLISION_THRESHOLD << IGC_CT_SHIFT); + + /* Enable transmits */ + tctl |= IGC_TCTL_EN; + + wr32(IGC_TCTL, tctl); +} + +/** + * igc_set_mac_filter_hw() - Set MAC address filter in hardware + * @adapter: Pointer to adapter where the filter should be set + * @index: Filter index + * @type: MAC address filter type (source or destination) + * @addr: MAC address + * @queue: If non-negative, queue assignment feature is enabled and frames + * matching the filter are enqueued onto 'queue'. Otherwise, queue + * assignment is disabled. + */ +static void igc_set_mac_filter_hw(struct igc_adapter *adapter, int index, + enum igc_mac_filter_type type, + const u8 *addr, int queue) +{ + struct net_device *dev = adapter->netdev; + struct igc_hw *hw = &adapter->hw; + u32 ral, rah; + + if (WARN_ON(index >= hw->mac.rar_entry_count)) + return; + + ral = le32_to_cpup((__le32 *)(addr)); + rah = le16_to_cpup((__le16 *)(addr + 4)); + + if (type == IGC_MAC_FILTER_TYPE_SRC) { + rah &= ~IGC_RAH_ASEL_MASK; + rah |= IGC_RAH_ASEL_SRC_ADDR; + } + + if (queue >= 0) { + rah &= ~IGC_RAH_QSEL_MASK; + rah |= (queue << IGC_RAH_QSEL_SHIFT); + rah |= IGC_RAH_QSEL_ENABLE; + } + + rah |= IGC_RAH_AV; + + wr32(IGC_RAL(index), ral); + wr32(IGC_RAH(index), rah); + + netdev_dbg(dev, "MAC address filter set in HW: index %d", index); +} + +/** + * igc_clear_mac_filter_hw() - Clear MAC address filter in hardware + * @adapter: Pointer to adapter where the filter should be cleared + * @index: Filter index + */ +static void igc_clear_mac_filter_hw(struct igc_adapter *adapter, int index) +{ + struct net_device *dev = adapter->netdev; + struct igc_hw *hw = &adapter->hw; + + if (WARN_ON(index >= hw->mac.rar_entry_count)) + return; + + wr32(IGC_RAL(index), 0); + wr32(IGC_RAH(index), 0); + + netdev_dbg(dev, "MAC address filter cleared in HW: index %d", index); +} + +/* Set default MAC address for the PF in the first RAR entry */ +static void igc_set_default_mac_filter(struct igc_adapter *adapter) +{ + struct net_device *dev = adapter->netdev; + u8 *addr = adapter->hw.mac.addr; + + netdev_dbg(dev, "Set default MAC address filter: address %pM", addr); + + igc_set_mac_filter_hw(adapter, 0, IGC_MAC_FILTER_TYPE_DST, addr, -1); +} + +/** + * igc_set_mac - Change the Ethernet Address of the NIC + * @netdev: network interface device structure + * @p: pointer to an address structure + * + * Returns 0 on success, negative on failure + */ +static int igc_set_mac(struct net_device *netdev, void *p) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct igc_hw *hw = &adapter->hw; + struct sockaddr *addr = p; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len); + + /* set the correct pool for the new PF MAC address in entry 0 */ + igc_set_default_mac_filter(adapter); + + return 0; +} + +/** + * igc_write_mc_addr_list - write multicast addresses to MTA + * @netdev: network interface device structure + * + * Writes multicast address list to the MTA hash table. + * Returns: -ENOMEM on failure + * 0 on no addresses written + * X on writing X addresses to MTA + **/ +static int igc_write_mc_addr_list(struct net_device *netdev) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct igc_hw *hw = &adapter->hw; + struct netdev_hw_addr *ha; + u8 *mta_list; + int i; + + if (netdev_mc_empty(netdev)) { + /* nothing to program, so clear mc list */ + igc_update_mc_addr_list(hw, NULL, 0); + return 0; + } + + mta_list = kcalloc(netdev_mc_count(netdev), 6, GFP_ATOMIC); + if (!mta_list) + return -ENOMEM; + + /* The shared function expects a packed array of only addresses. */ + i = 0; + netdev_for_each_mc_addr(ha, netdev) + memcpy(mta_list + (i++ * ETH_ALEN), ha->addr, ETH_ALEN); + + igc_update_mc_addr_list(hw, mta_list, i); + kfree(mta_list); + + return netdev_mc_count(netdev); +} + +static __le32 igc_tx_launchtime(struct igc_adapter *adapter, ktime_t txtime) +{ + ktime_t cycle_time = adapter->cycle_time; + ktime_t base_time = adapter->base_time; + u32 launchtime; + + /* FIXME: when using ETF together with taprio, we may have a + * case where 'delta' is larger than the cycle_time, this may + * cause problems if we don't read the current value of + * IGC_BASET, as the value writen into the launchtime + * descriptor field may be misinterpreted. + */ + div_s64_rem(ktime_sub_ns(txtime, base_time), cycle_time, &launchtime); + + return cpu_to_le32(launchtime); +} + +static void igc_tx_ctxtdesc(struct igc_ring *tx_ring, + struct igc_tx_buffer *first, + u32 vlan_macip_lens, u32 type_tucmd, + u32 mss_l4len_idx) +{ + struct igc_adv_tx_context_desc *context_desc; + u16 i = tx_ring->next_to_use; + + context_desc = IGC_TX_CTXTDESC(tx_ring, i); + + i++; + tx_ring->next_to_use = (i < tx_ring->count) ? i : 0; + + /* set bits to identify this as an advanced context descriptor */ + type_tucmd |= IGC_TXD_CMD_DEXT | IGC_ADVTXD_DTYP_CTXT; + + /* For i225, context index must be unique per ring. */ + if (test_bit(IGC_RING_FLAG_TX_CTX_IDX, &tx_ring->flags)) + mss_l4len_idx |= tx_ring->reg_idx << 4; + + context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens); + context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd); + context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx); + + /* We assume there is always a valid Tx time available. Invalid times + * should have been handled by the upper layers. + */ + if (tx_ring->launchtime_enable) { + struct igc_adapter *adapter = netdev_priv(tx_ring->netdev); + ktime_t txtime = first->skb->tstamp; + + first->skb->tstamp = ktime_set(0, 0); + context_desc->launch_time = igc_tx_launchtime(adapter, + txtime); + } else { + context_desc->launch_time = 0; + } +} + +static inline bool igc_ipv6_csum_is_sctp(struct sk_buff *skb) +{ + unsigned int offset = 0; + + ipv6_find_hdr(skb, &offset, IPPROTO_SCTP, NULL, NULL); + + return offset == skb_checksum_start_offset(skb); +} + +static void igc_tx_csum(struct igc_ring *tx_ring, struct igc_tx_buffer *first) +{ + struct sk_buff *skb = first->skb; + u32 vlan_macip_lens = 0; + u32 type_tucmd = 0; + + if (skb->ip_summed != CHECKSUM_PARTIAL) { +csum_failed: + if (!(first->tx_flags & IGC_TX_FLAGS_VLAN) && + !tx_ring->launchtime_enable) + return; + goto no_csum; + } + + switch (skb->csum_offset) { + case offsetof(struct tcphdr, check): + type_tucmd = IGC_ADVTXD_TUCMD_L4T_TCP; + fallthrough; + case offsetof(struct udphdr, check): + break; + case offsetof(struct sctphdr, checksum): + /* validate that this is actually an SCTP request */ + if ((first->protocol == htons(ETH_P_IP) && + (ip_hdr(skb)->protocol == IPPROTO_SCTP)) || + (first->protocol == htons(ETH_P_IPV6) && + igc_ipv6_csum_is_sctp(skb))) { + type_tucmd = IGC_ADVTXD_TUCMD_L4T_SCTP; + break; + } + fallthrough; + default: + skb_checksum_help(skb); + goto csum_failed; + } + + /* update TX checksum flag */ + first->tx_flags |= IGC_TX_FLAGS_CSUM; + vlan_macip_lens = skb_checksum_start_offset(skb) - + skb_network_offset(skb); +no_csum: + vlan_macip_lens |= skb_network_offset(skb) << IGC_ADVTXD_MACLEN_SHIFT; + vlan_macip_lens |= first->tx_flags & IGC_TX_FLAGS_VLAN_MASK; + + igc_tx_ctxtdesc(tx_ring, first, vlan_macip_lens, type_tucmd, 0); +} + +static int __igc_maybe_stop_tx(struct igc_ring *tx_ring, const u16 size) +{ + struct net_device *netdev = tx_ring->netdev; + + netif_stop_subqueue(netdev, tx_ring->queue_index); + + /* memory barriier comment */ + smp_mb(); + + /* We need to check again in a case another CPU has just + * made room available. + */ + if (igc_desc_unused(tx_ring) < size) + return -EBUSY; + + /* A reprieve! */ + netif_wake_subqueue(netdev, tx_ring->queue_index); + + u64_stats_update_begin(&tx_ring->tx_syncp2); + tx_ring->tx_stats.restart_queue2++; + u64_stats_update_end(&tx_ring->tx_syncp2); + + return 0; +} + +static inline int igc_maybe_stop_tx(struct igc_ring *tx_ring, const u16 size) +{ + if (igc_desc_unused(tx_ring) >= size) + return 0; + return __igc_maybe_stop_tx(tx_ring, size); +} + +#define IGC_SET_FLAG(_input, _flag, _result) \ + (((_flag) <= (_result)) ? \ + ((u32)((_input) & (_flag)) * ((_result) / (_flag))) : \ + ((u32)((_input) & (_flag)) / ((_flag) / (_result)))) + +static u32 igc_tx_cmd_type(struct sk_buff *skb, u32 tx_flags) +{ + /* set type for advanced descriptor with frame checksum insertion */ + u32 cmd_type = IGC_ADVTXD_DTYP_DATA | + IGC_ADVTXD_DCMD_DEXT | + IGC_ADVTXD_DCMD_IFCS; + + /* set segmentation bits for TSO */ + cmd_type |= IGC_SET_FLAG(tx_flags, IGC_TX_FLAGS_TSO, + (IGC_ADVTXD_DCMD_TSE)); + + /* set timestamp bit if present */ + cmd_type |= IGC_SET_FLAG(tx_flags, IGC_TX_FLAGS_TSTAMP, + (IGC_ADVTXD_MAC_TSTAMP)); + + return cmd_type; +} + +static void igc_tx_olinfo_status(struct igc_ring *tx_ring, + union igc_adv_tx_desc *tx_desc, + u32 tx_flags, unsigned int paylen) +{ + u32 olinfo_status = paylen << IGC_ADVTXD_PAYLEN_SHIFT; + + /* insert L4 checksum */ + olinfo_status |= (tx_flags & IGC_TX_FLAGS_CSUM) * + ((IGC_TXD_POPTS_TXSM << 8) / + IGC_TX_FLAGS_CSUM); + + /* insert IPv4 checksum */ + olinfo_status |= (tx_flags & IGC_TX_FLAGS_IPV4) * + (((IGC_TXD_POPTS_IXSM << 8)) / + IGC_TX_FLAGS_IPV4); + + tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status); +} + +static int igc_tx_map(struct igc_ring *tx_ring, + struct igc_tx_buffer *first, + const u8 hdr_len) +{ + struct sk_buff *skb = first->skb; + struct igc_tx_buffer *tx_buffer; + union igc_adv_tx_desc *tx_desc; + u32 tx_flags = first->tx_flags; + skb_frag_t *frag; + u16 i = tx_ring->next_to_use; + unsigned int data_len, size; + dma_addr_t dma; + u32 cmd_type = igc_tx_cmd_type(skb, tx_flags); + + tx_desc = IGC_TX_DESC(tx_ring, i); + + igc_tx_olinfo_status(tx_ring, tx_desc, tx_flags, skb->len - hdr_len); + + size = skb_headlen(skb); + data_len = skb->data_len; + + dma = dma_map_single(tx_ring->dev, skb->data, size, DMA_TO_DEVICE); + + tx_buffer = first; + + for (frag = &skb_shinfo(skb)->frags[0];; frag++) { + if (dma_mapping_error(tx_ring->dev, dma)) + goto dma_error; + + /* record length, and DMA address */ + dma_unmap_len_set(tx_buffer, len, size); + dma_unmap_addr_set(tx_buffer, dma, dma); + + tx_desc->read.buffer_addr = cpu_to_le64(dma); + + while (unlikely(size > IGC_MAX_DATA_PER_TXD)) { + tx_desc->read.cmd_type_len = + cpu_to_le32(cmd_type ^ IGC_MAX_DATA_PER_TXD); + + i++; + tx_desc++; + if (i == tx_ring->count) { + tx_desc = IGC_TX_DESC(tx_ring, 0); + i = 0; + } + tx_desc->read.olinfo_status = 0; + + dma += IGC_MAX_DATA_PER_TXD; + size -= IGC_MAX_DATA_PER_TXD; + + tx_desc->read.buffer_addr = cpu_to_le64(dma); + } + + if (likely(!data_len)) + break; + + tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type ^ size); + + i++; + tx_desc++; + if (i == tx_ring->count) { + tx_desc = IGC_TX_DESC(tx_ring, 0); + i = 0; + } + tx_desc->read.olinfo_status = 0; + + size = skb_frag_size(frag); + data_len -= size; + + dma = skb_frag_dma_map(tx_ring->dev, frag, 0, + size, DMA_TO_DEVICE); + + tx_buffer = &tx_ring->tx_buffer_info[i]; + } + + /* write last descriptor with RS and EOP bits */ + cmd_type |= size | IGC_TXD_DCMD; + tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type); + + netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount); + + /* set the timestamp */ + first->time_stamp = jiffies; + + skb_tx_timestamp(skb); + + /* Force memory writes to complete before letting h/w know there + * are new descriptors to fetch. (Only applicable for weak-ordered + * memory model archs, such as IA-64). + * + * We also need this memory barrier to make certain all of the + * status bits have been updated before next_to_watch is written. + */ + wmb(); + + /* set next_to_watch value indicating a packet is present */ + first->next_to_watch = tx_desc; + + i++; + if (i == tx_ring->count) + i = 0; + + tx_ring->next_to_use = i; + + /* Make sure there is space in the ring for the next send. */ + igc_maybe_stop_tx(tx_ring, DESC_NEEDED); + + if (netif_xmit_stopped(txring_txq(tx_ring)) || !netdev_xmit_more()) { + writel(i, tx_ring->tail); + } + + return 0; +dma_error: + netdev_err(tx_ring->netdev, "TX DMA map failed\n"); + tx_buffer = &tx_ring->tx_buffer_info[i]; + + /* clear dma mappings for failed tx_buffer_info map */ + while (tx_buffer != first) { + if (dma_unmap_len(tx_buffer, len)) + dma_unmap_page(tx_ring->dev, + dma_unmap_addr(tx_buffer, dma), + dma_unmap_len(tx_buffer, len), + DMA_TO_DEVICE); + dma_unmap_len_set(tx_buffer, len, 0); + + if (i-- == 0) + i += tx_ring->count; + tx_buffer = &tx_ring->tx_buffer_info[i]; + } + + if (dma_unmap_len(tx_buffer, len)) + dma_unmap_single(tx_ring->dev, + dma_unmap_addr(tx_buffer, dma), + dma_unmap_len(tx_buffer, len), + DMA_TO_DEVICE); + dma_unmap_len_set(tx_buffer, len, 0); + + dev_kfree_skb_any(tx_buffer->skb); + tx_buffer->skb = NULL; + + tx_ring->next_to_use = i; + + return -1; +} + +static int igc_tso(struct igc_ring *tx_ring, + struct igc_tx_buffer *first, + u8 *hdr_len) +{ + u32 vlan_macip_lens, type_tucmd, mss_l4len_idx; + struct sk_buff *skb = first->skb; + union { + struct iphdr *v4; + struct ipv6hdr *v6; + unsigned char *hdr; + } ip; + union { + struct tcphdr *tcp; + struct udphdr *udp; + unsigned char *hdr; + } l4; + u32 paylen, l4_offset; + int err; + + if (skb->ip_summed != CHECKSUM_PARTIAL) + return 0; + + if (!skb_is_gso(skb)) + return 0; + + err = skb_cow_head(skb, 0); + if (err < 0) + return err; + + ip.hdr = skb_network_header(skb); + l4.hdr = skb_checksum_start(skb); + + /* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */ + type_tucmd = IGC_ADVTXD_TUCMD_L4T_TCP; + + /* initialize outer IP header fields */ + if (ip.v4->version == 4) { + unsigned char *csum_start = skb_checksum_start(skb); + unsigned char *trans_start = ip.hdr + (ip.v4->ihl * 4); + + /* IP header will have to cancel out any data that + * is not a part of the outer IP header + */ + ip.v4->check = csum_fold(csum_partial(trans_start, + csum_start - trans_start, + 0)); + type_tucmd |= IGC_ADVTXD_TUCMD_IPV4; + + ip.v4->tot_len = 0; + first->tx_flags |= IGC_TX_FLAGS_TSO | + IGC_TX_FLAGS_CSUM | + IGC_TX_FLAGS_IPV4; + } else { + ip.v6->payload_len = 0; + first->tx_flags |= IGC_TX_FLAGS_TSO | + IGC_TX_FLAGS_CSUM; + } + + /* determine offset of inner transport header */ + l4_offset = l4.hdr - skb->data; + + /* remove payload length from inner checksum */ + paylen = skb->len - l4_offset; + if (type_tucmd & IGC_ADVTXD_TUCMD_L4T_TCP) { + /* compute length of segmentation header */ + *hdr_len = (l4.tcp->doff * 4) + l4_offset; + csum_replace_by_diff(&l4.tcp->check, + (__force __wsum)htonl(paylen)); + } else { + /* compute length of segmentation header */ + *hdr_len = sizeof(*l4.udp) + l4_offset; + csum_replace_by_diff(&l4.udp->check, + (__force __wsum)htonl(paylen)); + } + + /* update gso size and bytecount with header size */ + first->gso_segs = skb_shinfo(skb)->gso_segs; + first->bytecount += (first->gso_segs - 1) * *hdr_len; + + /* MSS L4LEN IDX */ + mss_l4len_idx = (*hdr_len - l4_offset) << IGC_ADVTXD_L4LEN_SHIFT; + mss_l4len_idx |= skb_shinfo(skb)->gso_size << IGC_ADVTXD_MSS_SHIFT; + + /* VLAN MACLEN IPLEN */ + vlan_macip_lens = l4.hdr - ip.hdr; + vlan_macip_lens |= (ip.hdr - skb->data) << IGC_ADVTXD_MACLEN_SHIFT; + vlan_macip_lens |= first->tx_flags & IGC_TX_FLAGS_VLAN_MASK; + + igc_tx_ctxtdesc(tx_ring, first, vlan_macip_lens, + type_tucmd, mss_l4len_idx); + + return 1; +} + +static netdev_tx_t igc_xmit_frame_ring(struct sk_buff *skb, + struct igc_ring *tx_ring) +{ + u16 count = TXD_USE_COUNT(skb_headlen(skb)); + __be16 protocol = vlan_get_protocol(skb); + struct igc_tx_buffer *first; + u32 tx_flags = 0; + unsigned short f; + u8 hdr_len = 0; + int tso = 0; + + /* need: 1 descriptor per page * PAGE_SIZE/IGC_MAX_DATA_PER_TXD, + * + 1 desc for skb_headlen/IGC_MAX_DATA_PER_TXD, + * + 2 desc gap to keep tail from touching head, + * + 1 desc for context descriptor, + * otherwise try next time + */ + for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) + count += TXD_USE_COUNT(skb_frag_size( + &skb_shinfo(skb)->frags[f])); + + if (igc_maybe_stop_tx(tx_ring, count + 3)) { + /* this is a hard error */ + return NETDEV_TX_BUSY; + } + + /* record the location of the first descriptor for this packet */ + first = &tx_ring->tx_buffer_info[tx_ring->next_to_use]; + first->skb = skb; + first->bytecount = skb->len; + first->gso_segs = 1; + + if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { + struct igc_adapter *adapter = netdev_priv(tx_ring->netdev); + + /* FIXME: add support for retrieving timestamps from + * the other timer registers before skipping the + * timestamping request. + */ + if (adapter->tstamp_config.tx_type == HWTSTAMP_TX_ON && + !test_and_set_bit_lock(__IGC_PTP_TX_IN_PROGRESS, + &adapter->state)) { + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; + tx_flags |= IGC_TX_FLAGS_TSTAMP; + + adapter->ptp_tx_skb = skb_get(skb); + adapter->ptp_tx_start = jiffies; + } else { + adapter->tx_hwtstamp_skipped++; + } + } + + /* record initial flags and protocol */ + first->tx_flags = tx_flags; + first->protocol = protocol; + + tso = igc_tso(tx_ring, first, &hdr_len); + if (tso < 0) + goto out_drop; + else if (!tso) + igc_tx_csum(tx_ring, first); + + igc_tx_map(tx_ring, first, hdr_len); + + return NETDEV_TX_OK; + +out_drop: + dev_kfree_skb_any(first->skb); + first->skb = NULL; + + return NETDEV_TX_OK; +} + +static inline struct igc_ring *igc_tx_queue_mapping(struct igc_adapter *adapter, + struct sk_buff *skb) +{ + unsigned int r_idx = skb->queue_mapping; + + if (r_idx >= adapter->num_tx_queues) + r_idx = r_idx % adapter->num_tx_queues; + + return adapter->tx_ring[r_idx]; +} + +static netdev_tx_t igc_xmit_frame(struct sk_buff *skb, + struct net_device *netdev) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + + /* The minimum packet size with TCTL.PSP set is 17 so pad the skb + * in order to meet this minimum size requirement. + */ + if (skb->len < 17) { + if (skb_padto(skb, 17)) + return NETDEV_TX_OK; + skb->len = 17; + } + + return igc_xmit_frame_ring(skb, igc_tx_queue_mapping(adapter, skb)); +} + +static void igc_rx_checksum(struct igc_ring *ring, + union igc_adv_rx_desc *rx_desc, + struct sk_buff *skb) +{ + skb_checksum_none_assert(skb); + + /* Ignore Checksum bit is set */ + if (igc_test_staterr(rx_desc, IGC_RXD_STAT_IXSM)) + return; + + /* Rx checksum disabled via ethtool */ + if (!(ring->netdev->features & NETIF_F_RXCSUM)) + return; + + /* TCP/UDP checksum error bit is set */ + if (igc_test_staterr(rx_desc, + IGC_RXDEXT_STATERR_L4E | + IGC_RXDEXT_STATERR_IPE)) { + /* work around errata with sctp packets where the TCPE aka + * L4E bit is set incorrectly on 64 byte (60 byte w/o crc) + * packets (aka let the stack check the crc32c) + */ + if (!(skb->len == 60 && + test_bit(IGC_RING_FLAG_RX_SCTP_CSUM, &ring->flags))) { + u64_stats_update_begin(&ring->rx_syncp); + ring->rx_stats.csum_err++; + u64_stats_update_end(&ring->rx_syncp); + } + /* let the stack verify checksum errors */ + return; + } + /* It must be a TCP or UDP packet with a valid checksum */ + if (igc_test_staterr(rx_desc, IGC_RXD_STAT_TCPCS | + IGC_RXD_STAT_UDPCS)) + skb->ip_summed = CHECKSUM_UNNECESSARY; + + netdev_dbg(ring->netdev, "cksum success: bits %08X\n", + le32_to_cpu(rx_desc->wb.upper.status_error)); +} + +static inline void igc_rx_hash(struct igc_ring *ring, + union igc_adv_rx_desc *rx_desc, + struct sk_buff *skb) +{ + if (ring->netdev->features & NETIF_F_RXHASH) + skb_set_hash(skb, + le32_to_cpu(rx_desc->wb.lower.hi_dword.rss), + PKT_HASH_TYPE_L3); +} + +/** + * igc_process_skb_fields - Populate skb header fields from Rx descriptor + * @rx_ring: rx descriptor ring packet is being transacted on + * @rx_desc: pointer to the EOP Rx descriptor + * @skb: pointer to current skb being populated + * + * This function checks the ring, descriptor, and packet information in order + * to populate the hash, checksum, VLAN, protocol, and other fields within the + * skb. + */ +static void igc_process_skb_fields(struct igc_ring *rx_ring, + union igc_adv_rx_desc *rx_desc, + struct sk_buff *skb) +{ + igc_rx_hash(rx_ring, rx_desc, skb); + + igc_rx_checksum(rx_ring, rx_desc, skb); + + skb_record_rx_queue(skb, rx_ring->queue_index); + + skb->protocol = eth_type_trans(skb, rx_ring->netdev); +} + +static struct igc_rx_buffer *igc_get_rx_buffer(struct igc_ring *rx_ring, + const unsigned int size) +{ + struct igc_rx_buffer *rx_buffer; + + rx_buffer = &rx_ring->rx_buffer_info[rx_ring->next_to_clean]; + prefetchw(rx_buffer->page); + + /* we are reusing so sync this buffer for CPU use */ + dma_sync_single_range_for_cpu(rx_ring->dev, + rx_buffer->dma, + rx_buffer->page_offset, + size, + DMA_FROM_DEVICE); + + rx_buffer->pagecnt_bias--; + + return rx_buffer; +} + +/** + * igc_add_rx_frag - Add contents of Rx buffer to sk_buff + * @rx_ring: rx descriptor ring to transact packets on + * @rx_buffer: buffer containing page to add + * @skb: sk_buff to place the data into + * @size: size of buffer to be added + * + * This function will add the data contained in rx_buffer->page to the skb. + */ +static void igc_add_rx_frag(struct igc_ring *rx_ring, + struct igc_rx_buffer *rx_buffer, + struct sk_buff *skb, + unsigned int size) +{ +#if (PAGE_SIZE < 8192) + unsigned int truesize = igc_rx_pg_size(rx_ring) / 2; + + skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, rx_buffer->page, + rx_buffer->page_offset, size, truesize); + rx_buffer->page_offset ^= truesize; +#else + unsigned int truesize = ring_uses_build_skb(rx_ring) ? + SKB_DATA_ALIGN(IGC_SKB_PAD + size) : + SKB_DATA_ALIGN(size); + skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, rx_buffer->page, + rx_buffer->page_offset, size, truesize); + rx_buffer->page_offset += truesize; +#endif +} + +static struct sk_buff *igc_build_skb(struct igc_ring *rx_ring, + struct igc_rx_buffer *rx_buffer, + union igc_adv_rx_desc *rx_desc, + unsigned int size) +{ + void *va = page_address(rx_buffer->page) + rx_buffer->page_offset; +#if (PAGE_SIZE < 8192) + unsigned int truesize = igc_rx_pg_size(rx_ring) / 2; +#else + unsigned int truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) + + SKB_DATA_ALIGN(IGC_SKB_PAD + size); +#endif + struct sk_buff *skb; + + /* prefetch first cache line of first page */ + prefetch(va); +#if L1_CACHE_BYTES < 128 + prefetch(va + L1_CACHE_BYTES); +#endif + + /* build an skb around the page buffer */ + skb = build_skb(va - IGC_SKB_PAD, truesize); + if (unlikely(!skb)) + return NULL; + + /* update pointers within the skb to store the data */ + skb_reserve(skb, IGC_SKB_PAD); + __skb_put(skb, size); + + /* update buffer offset */ +#if (PAGE_SIZE < 8192) + rx_buffer->page_offset ^= truesize; +#else + rx_buffer->page_offset += truesize; +#endif + + return skb; +} + +static struct sk_buff *igc_construct_skb(struct igc_ring *rx_ring, + struct igc_rx_buffer *rx_buffer, + union igc_adv_rx_desc *rx_desc, + unsigned int size) +{ + void *va = page_address(rx_buffer->page) + rx_buffer->page_offset; +#if (PAGE_SIZE < 8192) + unsigned int truesize = igc_rx_pg_size(rx_ring) / 2; +#else + unsigned int truesize = SKB_DATA_ALIGN(size); +#endif + unsigned int headlen; + struct sk_buff *skb; + + /* prefetch first cache line of first page */ + prefetch(va); +#if L1_CACHE_BYTES < 128 + prefetch(va + L1_CACHE_BYTES); +#endif + + /* allocate a skb to store the frags */ + skb = napi_alloc_skb(&rx_ring->q_vector->napi, IGC_RX_HDR_LEN); + if (unlikely(!skb)) + return NULL; + + if (unlikely(igc_test_staterr(rx_desc, IGC_RXDADV_STAT_TSIP))) { + igc_ptp_rx_pktstamp(rx_ring->q_vector, va, skb); + va += IGC_TS_HDR_LEN; + size -= IGC_TS_HDR_LEN; + } + + /* Determine available headroom for copy */ + headlen = size; + if (headlen > IGC_RX_HDR_LEN) + headlen = eth_get_headlen(skb->dev, va, IGC_RX_HDR_LEN); + + /* align pull length to size of long to optimize memcpy performance */ + memcpy(__skb_put(skb, headlen), va, ALIGN(headlen, sizeof(long))); + + /* update all of the pointers */ + size -= headlen; + if (size) { + skb_add_rx_frag(skb, 0, rx_buffer->page, + (va + headlen) - page_address(rx_buffer->page), + size, truesize); +#if (PAGE_SIZE < 8192) + rx_buffer->page_offset ^= truesize; +#else + rx_buffer->page_offset += truesize; +#endif + } else { + rx_buffer->pagecnt_bias++; + } + + return skb; +} + +/** + * igc_reuse_rx_page - page flip buffer and store it back on the ring + * @rx_ring: rx descriptor ring to store buffers on + * @old_buff: donor buffer to have page reused + * + * Synchronizes page for reuse by the adapter + */ +static void igc_reuse_rx_page(struct igc_ring *rx_ring, + struct igc_rx_buffer *old_buff) +{ + u16 nta = rx_ring->next_to_alloc; + struct igc_rx_buffer *new_buff; + + new_buff = &rx_ring->rx_buffer_info[nta]; + + /* update, and store next to alloc */ + nta++; + rx_ring->next_to_alloc = (nta < rx_ring->count) ? nta : 0; + + /* Transfer page from old buffer to new buffer. + * Move each member individually to avoid possible store + * forwarding stalls. + */ + new_buff->dma = old_buff->dma; + new_buff->page = old_buff->page; + new_buff->page_offset = old_buff->page_offset; + new_buff->pagecnt_bias = old_buff->pagecnt_bias; +} + +static inline bool igc_page_is_reserved(struct page *page) +{ + return (page_to_nid(page) != numa_mem_id()) || page_is_pfmemalloc(page); +} + +static bool igc_can_reuse_rx_page(struct igc_rx_buffer *rx_buffer) +{ + unsigned int pagecnt_bias = rx_buffer->pagecnt_bias; + struct page *page = rx_buffer->page; + + /* avoid re-using remote pages */ + if (unlikely(igc_page_is_reserved(page))) + return false; + +#if (PAGE_SIZE < 8192) + /* if we are only owner of page we can reuse it */ + if (unlikely((page_ref_count(page) - pagecnt_bias) > 1)) + return false; +#else +#define IGC_LAST_OFFSET \ + (SKB_WITH_OVERHEAD(PAGE_SIZE) - IGC_RXBUFFER_2048) + + if (rx_buffer->page_offset > IGC_LAST_OFFSET) + return false; +#endif + + /* If we have drained the page fragment pool we need to update + * the pagecnt_bias and page count so that we fully restock the + * number of references the driver holds. + */ + if (unlikely(!pagecnt_bias)) { + page_ref_add(page, USHRT_MAX); + rx_buffer->pagecnt_bias = USHRT_MAX; + } + + return true; +} + +/** + * igc_is_non_eop - process handling of non-EOP buffers + * @rx_ring: Rx ring being processed + * @rx_desc: Rx descriptor for current buffer + * + * This function updates next to clean. If the buffer is an EOP buffer + * this function exits returning false, otherwise it will place the + * sk_buff in the next buffer to be chained and return true indicating + * that this is in fact a non-EOP buffer. + */ +static bool igc_is_non_eop(struct igc_ring *rx_ring, + union igc_adv_rx_desc *rx_desc) +{ + u32 ntc = rx_ring->next_to_clean + 1; + + /* fetch, update, and store next to clean */ + ntc = (ntc < rx_ring->count) ? ntc : 0; + rx_ring->next_to_clean = ntc; + + prefetch(IGC_RX_DESC(rx_ring, ntc)); + + if (likely(igc_test_staterr(rx_desc, IGC_RXD_STAT_EOP))) + return false; + + return true; +} + +/** + * igc_cleanup_headers - Correct corrupted or empty headers + * @rx_ring: rx descriptor ring packet is being transacted on + * @rx_desc: pointer to the EOP Rx descriptor + * @skb: pointer to current skb being fixed + * + * Address the case where we are pulling data in on pages only + * and as such no data is present in the skb header. + * + * In addition if skb is not at least 60 bytes we need to pad it so that + * it is large enough to qualify as a valid Ethernet frame. + * + * Returns true if an error was encountered and skb was freed. + */ +static bool igc_cleanup_headers(struct igc_ring *rx_ring, + union igc_adv_rx_desc *rx_desc, + struct sk_buff *skb) +{ + if (unlikely(igc_test_staterr(rx_desc, IGC_RXDEXT_STATERR_RXE))) { + struct net_device *netdev = rx_ring->netdev; + + if (!(netdev->features & NETIF_F_RXALL)) { + dev_kfree_skb_any(skb); + return true; + } + } + + /* if eth_skb_pad returns an error the skb was freed */ + if (eth_skb_pad(skb)) + return true; + + return false; +} + +static void igc_put_rx_buffer(struct igc_ring *rx_ring, + struct igc_rx_buffer *rx_buffer) +{ + if (igc_can_reuse_rx_page(rx_buffer)) { + /* hand second half of page back to the ring */ + igc_reuse_rx_page(rx_ring, rx_buffer); + } else { + /* We are not reusing the buffer so unmap it and free + * any references we are holding to it + */ + dma_unmap_page_attrs(rx_ring->dev, rx_buffer->dma, + igc_rx_pg_size(rx_ring), DMA_FROM_DEVICE, + IGC_RX_DMA_ATTR); + __page_frag_cache_drain(rx_buffer->page, + rx_buffer->pagecnt_bias); + } + + /* clear contents of rx_buffer */ + rx_buffer->page = NULL; +} + +static inline unsigned int igc_rx_offset(struct igc_ring *rx_ring) +{ + return ring_uses_build_skb(rx_ring) ? IGC_SKB_PAD : 0; +} + +static bool igc_alloc_mapped_page(struct igc_ring *rx_ring, + struct igc_rx_buffer *bi) +{ + struct page *page = bi->page; + dma_addr_t dma; + + /* since we are recycling buffers we should seldom need to alloc */ + if (likely(page)) + return true; + + /* alloc new page for storage */ + page = dev_alloc_pages(igc_rx_pg_order(rx_ring)); + if (unlikely(!page)) { + rx_ring->rx_stats.alloc_failed++; + return false; + } + + /* map page for use */ + dma = dma_map_page_attrs(rx_ring->dev, page, 0, + igc_rx_pg_size(rx_ring), + DMA_FROM_DEVICE, + IGC_RX_DMA_ATTR); + + /* if mapping failed free memory back to system since + * there isn't much point in holding memory we can't use + */ + if (dma_mapping_error(rx_ring->dev, dma)) { + __free_page(page); + + rx_ring->rx_stats.alloc_failed++; + return false; + } + + bi->dma = dma; + bi->page = page; + bi->page_offset = igc_rx_offset(rx_ring); + bi->pagecnt_bias = 1; + + return true; +} + +/** + * igc_alloc_rx_buffers - Replace used receive buffers; packet split + * @rx_ring: rx descriptor ring + * @cleaned_count: number of buffers to clean + */ +static void igc_alloc_rx_buffers(struct igc_ring *rx_ring, u16 cleaned_count) +{ + union igc_adv_rx_desc *rx_desc; + u16 i = rx_ring->next_to_use; + struct igc_rx_buffer *bi; + u16 bufsz; + + /* nothing to do */ + if (!cleaned_count) + return; + + rx_desc = IGC_RX_DESC(rx_ring, i); + bi = &rx_ring->rx_buffer_info[i]; + i -= rx_ring->count; + + bufsz = igc_rx_bufsz(rx_ring); + + do { + if (!igc_alloc_mapped_page(rx_ring, bi)) + break; + + /* sync the buffer for use by the device */ + dma_sync_single_range_for_device(rx_ring->dev, bi->dma, + bi->page_offset, bufsz, + DMA_FROM_DEVICE); + + /* Refresh the desc even if buffer_addrs didn't change + * because each write-back erases this info. + */ + rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset); + + rx_desc++; + bi++; + i++; + if (unlikely(!i)) { + rx_desc = IGC_RX_DESC(rx_ring, 0); + bi = rx_ring->rx_buffer_info; + i -= rx_ring->count; + } + + /* clear the length for the next_to_use descriptor */ + rx_desc->wb.upper.length = 0; + + cleaned_count--; + } while (cleaned_count); + + i += rx_ring->count; + + if (rx_ring->next_to_use != i) { + /* record the next descriptor to use */ + rx_ring->next_to_use = i; + + /* update next to alloc since we have filled the ring */ + rx_ring->next_to_alloc = i; + + /* Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, + * such as IA-64). + */ + wmb(); + writel(i, rx_ring->tail); + } +} + +static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget) +{ + unsigned int total_bytes = 0, total_packets = 0; + struct igc_ring *rx_ring = q_vector->rx.ring; + struct sk_buff *skb = rx_ring->skb; + u16 cleaned_count = igc_desc_unused(rx_ring); + + while (likely(total_packets < budget)) { + union igc_adv_rx_desc *rx_desc; + struct igc_rx_buffer *rx_buffer; + unsigned int size; + + /* return some buffers to hardware, one at a time is too slow */ + if (cleaned_count >= IGC_RX_BUFFER_WRITE) { + igc_alloc_rx_buffers(rx_ring, cleaned_count); + cleaned_count = 0; + } + + rx_desc = IGC_RX_DESC(rx_ring, rx_ring->next_to_clean); + size = le16_to_cpu(rx_desc->wb.upper.length); + if (!size) + break; + + /* This memory barrier is needed to keep us from reading + * any other fields out of the rx_desc until we know the + * descriptor has been written back + */ + dma_rmb(); + + rx_buffer = igc_get_rx_buffer(rx_ring, size); + + /* retrieve a buffer from the ring */ + if (skb) + igc_add_rx_frag(rx_ring, rx_buffer, skb, size); + else if (ring_uses_build_skb(rx_ring)) + skb = igc_build_skb(rx_ring, rx_buffer, rx_desc, size); + else + skb = igc_construct_skb(rx_ring, rx_buffer, + rx_desc, size); + + /* exit if we failed to retrieve a buffer */ + if (!skb) { + rx_ring->rx_stats.alloc_failed++; + rx_buffer->pagecnt_bias++; + break; + } + + igc_put_rx_buffer(rx_ring, rx_buffer); + cleaned_count++; + + /* fetch next buffer in frame if non-eop */ + if (igc_is_non_eop(rx_ring, rx_desc)) + continue; + + /* verify the packet layout is correct */ + if (igc_cleanup_headers(rx_ring, rx_desc, skb)) { + skb = NULL; + continue; + } + + /* probably a little skewed due to removing CRC */ + total_bytes += skb->len; + + /* populate checksum, VLAN, and protocol */ + igc_process_skb_fields(rx_ring, rx_desc, skb); + + napi_gro_receive(&q_vector->napi, skb); + + /* reset skb pointer */ + skb = NULL; + + /* update budget accounting */ + total_packets++; + } + + /* place incomplete frames back on ring for completion */ + rx_ring->skb = skb; + + u64_stats_update_begin(&rx_ring->rx_syncp); + rx_ring->rx_stats.packets += total_packets; + rx_ring->rx_stats.bytes += total_bytes; + u64_stats_update_end(&rx_ring->rx_syncp); + q_vector->rx.total_packets += total_packets; + q_vector->rx.total_bytes += total_bytes; + + if (cleaned_count) + igc_alloc_rx_buffers(rx_ring, cleaned_count); + + return total_packets; +} + +/** + * igc_clean_tx_irq - Reclaim resources after transmit completes + * @q_vector: pointer to q_vector containing needed info + * @napi_budget: Used to determine if we are in netpoll + * + * returns true if ring is completely cleaned + */ +static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget) +{ + struct igc_adapter *adapter = q_vector->adapter; + unsigned int total_bytes = 0, total_packets = 0; + unsigned int budget = q_vector->tx.work_limit; + struct igc_ring *tx_ring = q_vector->tx.ring; + unsigned int i = tx_ring->next_to_clean; + struct igc_tx_buffer *tx_buffer; + union igc_adv_tx_desc *tx_desc; + + if (test_bit(__IGC_DOWN, &adapter->state)) + return true; + + tx_buffer = &tx_ring->tx_buffer_info[i]; + tx_desc = IGC_TX_DESC(tx_ring, i); + i -= tx_ring->count; + + do { + union igc_adv_tx_desc *eop_desc = tx_buffer->next_to_watch; + + /* if next_to_watch is not set then there is no work pending */ + if (!eop_desc) + break; + + /* prevent any other reads prior to eop_desc */ + smp_rmb(); + + /* if DD is not set pending work has not been completed */ + if (!(eop_desc->wb.status & cpu_to_le32(IGC_TXD_STAT_DD))) + break; + + /* clear next_to_watch to prevent false hangs */ + tx_buffer->next_to_watch = NULL; + + /* update the statistics for this packet */ + total_bytes += tx_buffer->bytecount; + total_packets += tx_buffer->gso_segs; + + /* free the skb */ + napi_consume_skb(tx_buffer->skb, napi_budget); + + /* unmap skb header data */ + dma_unmap_single(tx_ring->dev, + dma_unmap_addr(tx_buffer, dma), + dma_unmap_len(tx_buffer, len), + DMA_TO_DEVICE); + + /* clear tx_buffer data */ + dma_unmap_len_set(tx_buffer, len, 0); + + /* clear last DMA location and unmap remaining buffers */ + while (tx_desc != eop_desc) { + tx_buffer++; + tx_desc++; + i++; + if (unlikely(!i)) { + i -= tx_ring->count; + tx_buffer = tx_ring->tx_buffer_info; + tx_desc = IGC_TX_DESC(tx_ring, 0); + } + + /* unmap any remaining paged data */ + if (dma_unmap_len(tx_buffer, len)) { + dma_unmap_page(tx_ring->dev, + dma_unmap_addr(tx_buffer, dma), + dma_unmap_len(tx_buffer, len), + DMA_TO_DEVICE); + dma_unmap_len_set(tx_buffer, len, 0); + } + } + + /* move us one more past the eop_desc for start of next pkt */ + tx_buffer++; + tx_desc++; + i++; + if (unlikely(!i)) { + i -= tx_ring->count; + tx_buffer = tx_ring->tx_buffer_info; + tx_desc = IGC_TX_DESC(tx_ring, 0); + } + + /* issue prefetch for next Tx descriptor */ + prefetch(tx_desc); + + /* update budget accounting */ + budget--; + } while (likely(budget)); + + netdev_tx_completed_queue(txring_txq(tx_ring), + total_packets, total_bytes); + + i += tx_ring->count; + tx_ring->next_to_clean = i; + u64_stats_update_begin(&tx_ring->tx_syncp); + tx_ring->tx_stats.bytes += total_bytes; + tx_ring->tx_stats.packets += total_packets; + u64_stats_update_end(&tx_ring->tx_syncp); + q_vector->tx.total_bytes += total_bytes; + q_vector->tx.total_packets += total_packets; + + if (test_bit(IGC_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags)) { + struct igc_hw *hw = &adapter->hw; + + /* Detect a transmit hang in hardware, this serializes the + * check with the clearing of time_stamp and movement of i + */ + clear_bit(IGC_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags); + if (tx_buffer->next_to_watch && + time_after(jiffies, tx_buffer->time_stamp + + (adapter->tx_timeout_factor * HZ)) && + !(rd32(IGC_STATUS) & IGC_STATUS_TXOFF)) { + /* detected Tx unit hang */ + netdev_err(tx_ring->netdev, + "Detected Tx Unit Hang\n" + " Tx Queue <%d>\n" + " TDH <%x>\n" + " TDT <%x>\n" + " next_to_use <%x>\n" + " next_to_clean <%x>\n" + "buffer_info[next_to_clean]\n" + " time_stamp <%lx>\n" + " next_to_watch <%p>\n" + " jiffies <%lx>\n" + " desc.status <%x>\n", + tx_ring->queue_index, + rd32(IGC_TDH(tx_ring->reg_idx)), + readl(tx_ring->tail), + tx_ring->next_to_use, + tx_ring->next_to_clean, + tx_buffer->time_stamp, + tx_buffer->next_to_watch, + jiffies, + tx_buffer->next_to_watch->wb.status); + netif_stop_subqueue(tx_ring->netdev, + tx_ring->queue_index); + + /* we are about to reset, no point in enabling stuff */ + return true; + } + } + +#define TX_WAKE_THRESHOLD (DESC_NEEDED * 2) + if (unlikely(total_packets && + netif_carrier_ok(tx_ring->netdev) && + igc_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD)) { + /* Make sure that anybody stopping the queue after this + * sees the new next_to_clean. + */ + smp_mb(); + if (__netif_subqueue_stopped(tx_ring->netdev, + tx_ring->queue_index) && + !(test_bit(__IGC_DOWN, &adapter->state))) { + netif_wake_subqueue(tx_ring->netdev, + tx_ring->queue_index); + + u64_stats_update_begin(&tx_ring->tx_syncp); + tx_ring->tx_stats.restart_queue++; + u64_stats_update_end(&tx_ring->tx_syncp); + } + } + + return !!budget; +} + +static int igc_find_mac_filter(struct igc_adapter *adapter, + enum igc_mac_filter_type type, const u8 *addr) +{ + struct igc_hw *hw = &adapter->hw; + int max_entries = hw->mac.rar_entry_count; + u32 ral, rah; + int i; + + for (i = 0; i < max_entries; i++) { + ral = rd32(IGC_RAL(i)); + rah = rd32(IGC_RAH(i)); + + if (!(rah & IGC_RAH_AV)) + continue; + if (!!(rah & IGC_RAH_ASEL_SRC_ADDR) != type) + continue; + if ((rah & IGC_RAH_RAH_MASK) != + le16_to_cpup((__le16 *)(addr + 4))) + continue; + if (ral != le32_to_cpup((__le32 *)(addr))) + continue; + + return i; + } + + return -1; +} + +static int igc_get_avail_mac_filter_slot(struct igc_adapter *adapter) +{ + struct igc_hw *hw = &adapter->hw; + int max_entries = hw->mac.rar_entry_count; + u32 rah; + int i; + + for (i = 0; i < max_entries; i++) { + rah = rd32(IGC_RAH(i)); + + if (!(rah & IGC_RAH_AV)) + return i; + } + + return -1; +} + +/** + * igc_add_mac_filter() - Add MAC address filter + * @adapter: Pointer to adapter where the filter should be added + * @type: MAC address filter type (source or destination) + * @addr: MAC address + * @queue: If non-negative, queue assignment feature is enabled and frames + * matching the filter are enqueued onto 'queue'. Otherwise, queue + * assignment is disabled. + * + * Return: 0 in case of success, negative errno code otherwise. + */ +static int igc_add_mac_filter(struct igc_adapter *adapter, + enum igc_mac_filter_type type, const u8 *addr, + int queue) +{ + struct net_device *dev = adapter->netdev; + int index; + + index = igc_find_mac_filter(adapter, type, addr); + if (index >= 0) + goto update_filter; + + index = igc_get_avail_mac_filter_slot(adapter); + if (index < 0) + return -ENOSPC; + + netdev_dbg(dev, "Add MAC address filter: index %d type %s address %pM queue %d\n", + index, type == IGC_MAC_FILTER_TYPE_DST ? "dst" : "src", + addr, queue); + +update_filter: + igc_set_mac_filter_hw(adapter, index, type, addr, queue); + return 0; +} + +/** + * igc_del_mac_filter() - Delete MAC address filter + * @adapter: Pointer to adapter where the filter should be deleted from + * @type: MAC address filter type (source or destination) + * @addr: MAC address + */ +static void igc_del_mac_filter(struct igc_adapter *adapter, + enum igc_mac_filter_type type, const u8 *addr) +{ + struct net_device *dev = adapter->netdev; + int index; + + index = igc_find_mac_filter(adapter, type, addr); + if (index < 0) + return; + + if (index == 0) { + /* If this is the default filter, we don't actually delete it. + * We just reset to its default value i.e. disable queue + * assignment. + */ + netdev_dbg(dev, "Disable default MAC filter queue assignment"); + + igc_set_mac_filter_hw(adapter, 0, type, addr, -1); + } else { + netdev_dbg(dev, "Delete MAC address filter: index %d type %s address %pM\n", + index, + type == IGC_MAC_FILTER_TYPE_DST ? "dst" : "src", + addr); + + igc_clear_mac_filter_hw(adapter, index); + } +} + +/** + * igc_add_vlan_prio_filter() - Add VLAN priority filter + * @adapter: Pointer to adapter where the filter should be added + * @prio: VLAN priority value + * @queue: Queue number which matching frames are assigned to + * + * Return: 0 in case of success, negative errno code otherwise. + */ +static int igc_add_vlan_prio_filter(struct igc_adapter *adapter, int prio, + int queue) +{ + struct net_device *dev = adapter->netdev; + struct igc_hw *hw = &adapter->hw; + u32 vlanpqf; + + vlanpqf = rd32(IGC_VLANPQF); + + if (vlanpqf & IGC_VLANPQF_VALID(prio)) { + netdev_dbg(dev, "VLAN priority filter already in use\n"); + return -EEXIST; + } + + vlanpqf |= IGC_VLANPQF_QSEL(prio, queue); + vlanpqf |= IGC_VLANPQF_VALID(prio); + + wr32(IGC_VLANPQF, vlanpqf); + + netdev_dbg(dev, "Add VLAN priority filter: prio %d queue %d\n", + prio, queue); + return 0; +} + +/** + * igc_del_vlan_prio_filter() - Delete VLAN priority filter + * @adapter: Pointer to adapter where the filter should be deleted from + * @prio: VLAN priority value + */ +static void igc_del_vlan_prio_filter(struct igc_adapter *adapter, int prio) +{ + struct igc_hw *hw = &adapter->hw; + u32 vlanpqf; + + vlanpqf = rd32(IGC_VLANPQF); + + vlanpqf &= ~IGC_VLANPQF_VALID(prio); + vlanpqf &= ~IGC_VLANPQF_QSEL(prio, IGC_VLANPQF_QUEUE_MASK); + + wr32(IGC_VLANPQF, vlanpqf); + + netdev_dbg(adapter->netdev, "Delete VLAN priority filter: prio %d\n", + prio); +} + +static int igc_get_avail_etype_filter_slot(struct igc_adapter *adapter) +{ + struct igc_hw *hw = &adapter->hw; + int i; + + for (i = 0; i < MAX_ETYPE_FILTER; i++) { + u32 etqf = rd32(IGC_ETQF(i)); + + if (!(etqf & IGC_ETQF_FILTER_ENABLE)) + return i; + } + + return -1; +} + +/** + * igc_add_etype_filter() - Add ethertype filter + * @adapter: Pointer to adapter where the filter should be added + * @etype: Ethertype value + * @queue: If non-negative, queue assignment feature is enabled and frames + * matching the filter are enqueued onto 'queue'. Otherwise, queue + * assignment is disabled. + * + * Return: 0 in case of success, negative errno code otherwise. + */ +static int igc_add_etype_filter(struct igc_adapter *adapter, u16 etype, + int queue) +{ + struct igc_hw *hw = &adapter->hw; + int index; + u32 etqf; + + index = igc_get_avail_etype_filter_slot(adapter); + if (index < 0) + return -ENOSPC; + + etqf = rd32(IGC_ETQF(index)); + + etqf &= ~IGC_ETQF_ETYPE_MASK; + etqf |= etype; + + if (queue >= 0) { + etqf &= ~IGC_ETQF_QUEUE_MASK; + etqf |= (queue << IGC_ETQF_QUEUE_SHIFT); + etqf |= IGC_ETQF_QUEUE_ENABLE; + } + + etqf |= IGC_ETQF_FILTER_ENABLE; + + wr32(IGC_ETQF(index), etqf); + + netdev_dbg(adapter->netdev, "Add ethertype filter: etype %04x queue %d\n", + etype, queue); + return 0; +} + +static int igc_find_etype_filter(struct igc_adapter *adapter, u16 etype) +{ + struct igc_hw *hw = &adapter->hw; + int i; + + for (i = 0; i < MAX_ETYPE_FILTER; i++) { + u32 etqf = rd32(IGC_ETQF(i)); + + if ((etqf & IGC_ETQF_ETYPE_MASK) == etype) + return i; + } + + return -1; +} + +/** + * igc_del_etype_filter() - Delete ethertype filter + * @adapter: Pointer to adapter where the filter should be deleted from + * @etype: Ethertype value + */ +static void igc_del_etype_filter(struct igc_adapter *adapter, u16 etype) +{ + struct igc_hw *hw = &adapter->hw; + int index; + + index = igc_find_etype_filter(adapter, etype); + if (index < 0) + return; + + wr32(IGC_ETQF(index), 0); + + netdev_dbg(adapter->netdev, "Delete ethertype filter: etype %04x\n", + etype); +} + +static int igc_enable_nfc_rule(struct igc_adapter *adapter, + const struct igc_nfc_rule *rule) +{ + int err; + + if (rule->filter.match_flags & IGC_FILTER_FLAG_ETHER_TYPE) { + err = igc_add_etype_filter(adapter, rule->filter.etype, + rule->action); + if (err) + return err; + } + + if (rule->filter.match_flags & IGC_FILTER_FLAG_SRC_MAC_ADDR) { + err = igc_add_mac_filter(adapter, IGC_MAC_FILTER_TYPE_SRC, + rule->filter.src_addr, rule->action); + if (err) + return err; + } + + if (rule->filter.match_flags & IGC_FILTER_FLAG_DST_MAC_ADDR) { + err = igc_add_mac_filter(adapter, IGC_MAC_FILTER_TYPE_DST, + rule->filter.dst_addr, rule->action); + if (err) + return err; + } + + if (rule->filter.match_flags & IGC_FILTER_FLAG_VLAN_TCI) { + int prio = (rule->filter.vlan_tci & VLAN_PRIO_MASK) >> + VLAN_PRIO_SHIFT; + + err = igc_add_vlan_prio_filter(adapter, prio, rule->action); + if (err) + return err; + } + + return 0; +} + +static void igc_disable_nfc_rule(struct igc_adapter *adapter, + const struct igc_nfc_rule *rule) +{ + if (rule->filter.match_flags & IGC_FILTER_FLAG_ETHER_TYPE) + igc_del_etype_filter(adapter, rule->filter.etype); + + if (rule->filter.match_flags & IGC_FILTER_FLAG_VLAN_TCI) { + int prio = (rule->filter.vlan_tci & VLAN_PRIO_MASK) >> + VLAN_PRIO_SHIFT; + + igc_del_vlan_prio_filter(adapter, prio); + } + + if (rule->filter.match_flags & IGC_FILTER_FLAG_SRC_MAC_ADDR) + igc_del_mac_filter(adapter, IGC_MAC_FILTER_TYPE_SRC, + rule->filter.src_addr); + + if (rule->filter.match_flags & IGC_FILTER_FLAG_DST_MAC_ADDR) + igc_del_mac_filter(adapter, IGC_MAC_FILTER_TYPE_DST, + rule->filter.dst_addr); +} + +/** + * igc_get_nfc_rule() - Get NFC rule + * @adapter: Pointer to adapter + * @location: Rule location + * + * Context: Expects adapter->nfc_rule_lock to be held by caller. + * + * Return: Pointer to NFC rule at @location. If not found, NULL. + */ +struct igc_nfc_rule *igc_get_nfc_rule(struct igc_adapter *adapter, + u32 location) +{ + struct igc_nfc_rule *rule; + + list_for_each_entry(rule, &adapter->nfc_rule_list, list) { + if (rule->location == location) + return rule; + if (rule->location > location) + break; + } + + return NULL; +} + +/** + * igc_del_nfc_rule() - Delete NFC rule + * @adapter: Pointer to adapter + * @rule: Pointer to rule to be deleted + * + * Disable NFC rule in hardware and delete it from adapter. + * + * Context: Expects adapter->nfc_rule_lock to be held by caller. + */ +void igc_del_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule) +{ + igc_disable_nfc_rule(adapter, rule); + + list_del(&rule->list); + adapter->nfc_rule_count--; + + kfree(rule); +} + +static void igc_flush_nfc_rules(struct igc_adapter *adapter) +{ + struct igc_nfc_rule *rule, *tmp; + + mutex_lock(&adapter->nfc_rule_lock); + + list_for_each_entry_safe(rule, tmp, &adapter->nfc_rule_list, list) + igc_del_nfc_rule(adapter, rule); + + mutex_unlock(&adapter->nfc_rule_lock); +} + +/** + * igc_add_nfc_rule() - Add NFC rule + * @adapter: Pointer to adapter + * @rule: Pointer to rule to be added + * + * Enable NFC rule in hardware and add it to adapter. + * + * Context: Expects adapter->nfc_rule_lock to be held by caller. + * + * Return: 0 on success, negative errno on failure. + */ +int igc_add_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule) +{ + struct igc_nfc_rule *pred, *cur; + int err; + + err = igc_enable_nfc_rule(adapter, rule); + if (err) + return err; + + pred = NULL; + list_for_each_entry(cur, &adapter->nfc_rule_list, list) { + if (cur->location >= rule->location) + break; + pred = cur; + } + + list_add(&rule->list, pred ? &pred->list : &adapter->nfc_rule_list); + adapter->nfc_rule_count++; + return 0; +} + +static void igc_restore_nfc_rules(struct igc_adapter *adapter) +{ + struct igc_nfc_rule *rule; + + mutex_lock(&adapter->nfc_rule_lock); + + list_for_each_entry_reverse(rule, &adapter->nfc_rule_list, list) + igc_enable_nfc_rule(adapter, rule); + + mutex_unlock(&adapter->nfc_rule_lock); +} + +static int igc_uc_sync(struct net_device *netdev, const unsigned char *addr) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + + return igc_add_mac_filter(adapter, IGC_MAC_FILTER_TYPE_DST, addr, -1); +} + +static int igc_uc_unsync(struct net_device *netdev, const unsigned char *addr) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + + igc_del_mac_filter(adapter, IGC_MAC_FILTER_TYPE_DST, addr); + return 0; +} + +/** + * igc_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set + * @netdev: network interface device structure + * + * The set_rx_mode entry point is called whenever the unicast or multicast + * address lists or the network interface flags are updated. This routine is + * responsible for configuring the hardware for proper unicast, multicast, + * promiscuous mode, and all-multi behavior. + */ +static void igc_set_rx_mode(struct net_device *netdev) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct igc_hw *hw = &adapter->hw; + u32 rctl = 0, rlpml = MAX_JUMBO_FRAME_SIZE; + int count; + + /* Check for Promiscuous and All Multicast modes */ + if (netdev->flags & IFF_PROMISC) { + rctl |= IGC_RCTL_UPE | IGC_RCTL_MPE; + } else { + if (netdev->flags & IFF_ALLMULTI) { + rctl |= IGC_RCTL_MPE; + } else { + /* Write addresses to the MTA, if the attempt fails + * then we should just turn on promiscuous mode so + * that we can at least receive multicast traffic + */ + count = igc_write_mc_addr_list(netdev); + if (count < 0) + rctl |= IGC_RCTL_MPE; + } + } + + /* Write addresses to available RAR registers, if there is not + * sufficient space to store all the addresses then enable + * unicast promiscuous mode + */ + if (__dev_uc_sync(netdev, igc_uc_sync, igc_uc_unsync)) + rctl |= IGC_RCTL_UPE; + + /* update state of unicast and multicast */ + rctl |= rd32(IGC_RCTL) & ~(IGC_RCTL_UPE | IGC_RCTL_MPE); + wr32(IGC_RCTL, rctl); + +#if (PAGE_SIZE < 8192) + if (adapter->max_frame_size <= IGC_MAX_FRAME_BUILD_SKB) + rlpml = IGC_MAX_FRAME_BUILD_SKB; +#endif + wr32(IGC_RLPML, rlpml); +} + +/** + * igc_configure - configure the hardware for RX and TX + * @adapter: private board structure + */ +static void igc_configure(struct igc_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + int i = 0; + + igc_get_hw_control(adapter); + igc_set_rx_mode(netdev); + + igc_setup_tctl(adapter); + igc_setup_mrqc(adapter); + igc_setup_rctl(adapter); + + igc_set_default_mac_filter(adapter); + igc_restore_nfc_rules(adapter); + + igc_configure_tx(adapter); + igc_configure_rx(adapter); + + igc_rx_fifo_flush_base(&adapter->hw); + + /* call igc_desc_unused which always leaves + * at least 1 descriptor unused to make sure + * next_to_use != next_to_clean + */ + for (i = 0; i < adapter->num_rx_queues; i++) { + struct igc_ring *ring = adapter->rx_ring[i]; + + igc_alloc_rx_buffers(ring, igc_desc_unused(ring)); + } +} + +/** + * igc_write_ivar - configure ivar for given MSI-X vector + * @hw: pointer to the HW structure + * @msix_vector: vector number we are allocating to a given ring + * @index: row index of IVAR register to write within IVAR table + * @offset: column offset of in IVAR, should be multiple of 8 + * + * The IVAR table consists of 2 columns, + * each containing an cause allocation for an Rx and Tx ring, and a + * variable number of rows depending on the number of queues supported. + */ +static void igc_write_ivar(struct igc_hw *hw, int msix_vector, + int index, int offset) +{ + u32 ivar = array_rd32(IGC_IVAR0, index); + + /* clear any bits that are currently set */ + ivar &= ~((u32)0xFF << offset); + + /* write vector and valid bit */ + ivar |= (msix_vector | IGC_IVAR_VALID) << offset; + + array_wr32(IGC_IVAR0, index, ivar); +} + +static void igc_assign_vector(struct igc_q_vector *q_vector, int msix_vector) +{ + struct igc_adapter *adapter = q_vector->adapter; + struct igc_hw *hw = &adapter->hw; + int rx_queue = IGC_N0_QUEUE; + int tx_queue = IGC_N0_QUEUE; + + if (q_vector->rx.ring) + rx_queue = q_vector->rx.ring->reg_idx; + if (q_vector->tx.ring) + tx_queue = q_vector->tx.ring->reg_idx; + + switch (hw->mac.type) { + case igc_i225: + if (rx_queue > IGC_N0_QUEUE) + igc_write_ivar(hw, msix_vector, + rx_queue >> 1, + (rx_queue & 0x1) << 4); + if (tx_queue > IGC_N0_QUEUE) + igc_write_ivar(hw, msix_vector, + tx_queue >> 1, + ((tx_queue & 0x1) << 4) + 8); + q_vector->eims_value = BIT(msix_vector); + break; + default: + WARN_ONCE(hw->mac.type != igc_i225, "Wrong MAC type\n"); + break; + } + + /* add q_vector eims value to global eims_enable_mask */ + adapter->eims_enable_mask |= q_vector->eims_value; + + /* configure q_vector to set itr on first interrupt */ + q_vector->set_itr = 1; +} + +/** + * igc_configure_msix - Configure MSI-X hardware + * @adapter: Pointer to adapter structure + * + * igc_configure_msix sets up the hardware to properly + * generate MSI-X interrupts. + */ +static void igc_configure_msix(struct igc_adapter *adapter) +{ + struct igc_hw *hw = &adapter->hw; + int i, vector = 0; + u32 tmp; + + adapter->eims_enable_mask = 0; + + /* set vector for other causes, i.e. link changes */ + switch (hw->mac.type) { + case igc_i225: + /* Turn on MSI-X capability first, or our settings + * won't stick. And it will take days to debug. + */ + wr32(IGC_GPIE, IGC_GPIE_MSIX_MODE | + IGC_GPIE_PBA | IGC_GPIE_EIAME | + IGC_GPIE_NSICR); + + /* enable msix_other interrupt */ + adapter->eims_other = BIT(vector); + tmp = (vector++ | IGC_IVAR_VALID) << 8; + + wr32(IGC_IVAR_MISC, tmp); + break; + default: + /* do nothing, since nothing else supports MSI-X */ + break; + } /* switch (hw->mac.type) */ + + adapter->eims_enable_mask |= adapter->eims_other; + + for (i = 0; i < adapter->num_q_vectors; i++) + igc_assign_vector(adapter->q_vector[i], vector++); + + wrfl(); +} + +/** + * igc_irq_enable - Enable default interrupt generation settings + * @adapter: board private structure + */ +static void igc_irq_enable(struct igc_adapter *adapter) +{ + struct igc_hw *hw = &adapter->hw; + + if (adapter->msix_entries) { + u32 ims = IGC_IMS_LSC | IGC_IMS_DOUTSYNC | IGC_IMS_DRSTA; + u32 regval = rd32(IGC_EIAC); + + wr32(IGC_EIAC, regval | adapter->eims_enable_mask); + regval = rd32(IGC_EIAM); + wr32(IGC_EIAM, regval | adapter->eims_enable_mask); + wr32(IGC_EIMS, adapter->eims_enable_mask); + wr32(IGC_IMS, ims); + } else { + wr32(IGC_IMS, IMS_ENABLE_MASK | IGC_IMS_DRSTA); + wr32(IGC_IAM, IMS_ENABLE_MASK | IGC_IMS_DRSTA); + } +} + +/** + * igc_irq_disable - Mask off interrupt generation on the NIC + * @adapter: board private structure + */ +static void igc_irq_disable(struct igc_adapter *adapter) +{ + struct igc_hw *hw = &adapter->hw; + + if (adapter->msix_entries) { + u32 regval = rd32(IGC_EIAM); + + wr32(IGC_EIAM, regval & ~adapter->eims_enable_mask); + wr32(IGC_EIMC, adapter->eims_enable_mask); + regval = rd32(IGC_EIAC); + wr32(IGC_EIAC, regval & ~adapter->eims_enable_mask); + } + + wr32(IGC_IAM, 0); + wr32(IGC_IMC, ~0); + wrfl(); + + if (adapter->msix_entries) { + int vector = 0, i; + + synchronize_irq(adapter->msix_entries[vector++].vector); + + for (i = 0; i < adapter->num_q_vectors; i++) + synchronize_irq(adapter->msix_entries[vector++].vector); + } else { + synchronize_irq(adapter->pdev->irq); + } +} + +void igc_set_flag_queue_pairs(struct igc_adapter *adapter, + const u32 max_rss_queues) +{ + /* Determine if we need to pair queues. */ + /* If rss_queues > half of max_rss_queues, pair the queues in + * order to conserve interrupts due to limited supply. + */ + if (adapter->rss_queues > (max_rss_queues / 2)) + adapter->flags |= IGC_FLAG_QUEUE_PAIRS; + else + adapter->flags &= ~IGC_FLAG_QUEUE_PAIRS; +} + +unsigned int igc_get_max_rss_queues(struct igc_adapter *adapter) +{ + return IGC_MAX_RX_QUEUES; +} + +static void igc_init_queue_configuration(struct igc_adapter *adapter) +{ + u32 max_rss_queues; + + max_rss_queues = igc_get_max_rss_queues(adapter); + adapter->rss_queues = min_t(u32, max_rss_queues, num_online_cpus()); + + igc_set_flag_queue_pairs(adapter, max_rss_queues); +} + +/** + * igc_reset_q_vector - Reset config for interrupt vector + * @adapter: board private structure to initialize + * @v_idx: Index of vector to be reset + * + * If NAPI is enabled it will delete any references to the + * NAPI struct. This is preparation for igc_free_q_vector. + */ +static void igc_reset_q_vector(struct igc_adapter *adapter, int v_idx) +{ + struct igc_q_vector *q_vector = adapter->q_vector[v_idx]; + + /* if we're coming from igc_set_interrupt_capability, the vectors are + * not yet allocated + */ + if (!q_vector) + return; + + if (q_vector->tx.ring) + adapter->tx_ring[q_vector->tx.ring->queue_index] = NULL; + + if (q_vector->rx.ring) + adapter->rx_ring[q_vector->rx.ring->queue_index] = NULL; + + netif_napi_del(&q_vector->napi); +} + +/** + * igc_free_q_vector - Free memory allocated for specific interrupt vector + * @adapter: board private structure to initialize + * @v_idx: Index of vector to be freed + * + * This function frees the memory allocated to the q_vector. + */ +static void igc_free_q_vector(struct igc_adapter *adapter, int v_idx) +{ + struct igc_q_vector *q_vector = adapter->q_vector[v_idx]; + + adapter->q_vector[v_idx] = NULL; + + /* igc_get_stats64() might access the rings on this vector, + * we must wait a grace period before freeing it. + */ + if (q_vector) + kfree_rcu(q_vector, rcu); +} + +/** + * igc_free_q_vectors - Free memory allocated for interrupt vectors + * @adapter: board private structure to initialize + * + * This function frees the memory allocated to the q_vectors. In addition if + * NAPI is enabled it will delete any references to the NAPI struct prior + * to freeing the q_vector. + */ +static void igc_free_q_vectors(struct igc_adapter *adapter) +{ + int v_idx = adapter->num_q_vectors; + + adapter->num_tx_queues = 0; + adapter->num_rx_queues = 0; + adapter->num_q_vectors = 0; + + while (v_idx--) { + igc_reset_q_vector(adapter, v_idx); + igc_free_q_vector(adapter, v_idx); + } +} + +/** + * igc_update_itr - update the dynamic ITR value based on statistics + * @q_vector: pointer to q_vector + * @ring_container: ring info to update the itr for + * + * Stores a new ITR value based on packets and byte + * counts during the last interrupt. The advantage of per interrupt + * computation is faster updates and more accurate ITR for the current + * traffic pattern. Constants in this function were computed + * based on theoretical maximum wire speed and thresholds were set based + * on testing data as well as attempting to minimize response time + * while increasing bulk throughput. + * NOTE: These calculations are only valid when operating in a single- + * queue environment. + */ +static void igc_update_itr(struct igc_q_vector *q_vector, + struct igc_ring_container *ring_container) +{ + unsigned int packets = ring_container->total_packets; + unsigned int bytes = ring_container->total_bytes; + u8 itrval = ring_container->itr; + + /* no packets, exit with status unchanged */ + if (packets == 0) + return; + + switch (itrval) { + case lowest_latency: + /* handle TSO and jumbo frames */ + if (bytes / packets > 8000) + itrval = bulk_latency; + else if ((packets < 5) && (bytes > 512)) + itrval = low_latency; + break; + case low_latency: /* 50 usec aka 20000 ints/s */ + if (bytes > 10000) { + /* this if handles the TSO accounting */ + if (bytes / packets > 8000) + itrval = bulk_latency; + else if ((packets < 10) || ((bytes / packets) > 1200)) + itrval = bulk_latency; + else if ((packets > 35)) + itrval = lowest_latency; + } else if (bytes / packets > 2000) { + itrval = bulk_latency; + } else if (packets <= 2 && bytes < 512) { + itrval = lowest_latency; + } + break; + case bulk_latency: /* 250 usec aka 4000 ints/s */ + if (bytes > 25000) { + if (packets > 35) + itrval = low_latency; + } else if (bytes < 1500) { + itrval = low_latency; + } + break; + } + + /* clear work counters since we have the values we need */ + ring_container->total_bytes = 0; + ring_container->total_packets = 0; + + /* write updated itr to ring container */ + ring_container->itr = itrval; +} + +static void igc_set_itr(struct igc_q_vector *q_vector) +{ + struct igc_adapter *adapter = q_vector->adapter; + u32 new_itr = q_vector->itr_val; + u8 current_itr = 0; + + /* for non-gigabit speeds, just fix the interrupt rate at 4000 */ + switch (adapter->link_speed) { + case SPEED_10: + case SPEED_100: + current_itr = 0; + new_itr = IGC_4K_ITR; + goto set_itr_now; + default: + break; + } + + igc_update_itr(q_vector, &q_vector->tx); + igc_update_itr(q_vector, &q_vector->rx); + + current_itr = max(q_vector->rx.itr, q_vector->tx.itr); + + /* conservative mode (itr 3) eliminates the lowest_latency setting */ + if (current_itr == lowest_latency && + ((q_vector->rx.ring && adapter->rx_itr_setting == 3) || + (!q_vector->rx.ring && adapter->tx_itr_setting == 3))) + current_itr = low_latency; + + switch (current_itr) { + /* counts and packets in update_itr are dependent on these numbers */ + case lowest_latency: + new_itr = IGC_70K_ITR; /* 70,000 ints/sec */ + break; + case low_latency: + new_itr = IGC_20K_ITR; /* 20,000 ints/sec */ + break; + case bulk_latency: + new_itr = IGC_4K_ITR; /* 4,000 ints/sec */ + break; + default: + break; + } + +set_itr_now: + if (new_itr != q_vector->itr_val) { + /* this attempts to bias the interrupt rate towards Bulk + * by adding intermediate steps when interrupt rate is + * increasing + */ + new_itr = new_itr > q_vector->itr_val ? + max((new_itr * q_vector->itr_val) / + (new_itr + (q_vector->itr_val >> 2)), + new_itr) : new_itr; + /* Don't write the value here; it resets the adapter's + * internal timer, and causes us to delay far longer than + * we should between interrupts. Instead, we write the ITR + * value at the beginning of the next interrupt so the timing + * ends up being correct. + */ + q_vector->itr_val = new_itr; + q_vector->set_itr = 1; + } +} + +static void igc_reset_interrupt_capability(struct igc_adapter *adapter) +{ + int v_idx = adapter->num_q_vectors; + + if (adapter->msix_entries) { + pci_disable_msix(adapter->pdev); + kfree(adapter->msix_entries); + adapter->msix_entries = NULL; + } else if (adapter->flags & IGC_FLAG_HAS_MSI) { + pci_disable_msi(adapter->pdev); + } + + while (v_idx--) + igc_reset_q_vector(adapter, v_idx); +} + +/** + * igc_set_interrupt_capability - set MSI or MSI-X if supported + * @adapter: Pointer to adapter structure + * @msix: boolean value for MSI-X capability + * + * Attempt to configure interrupts using the best available + * capabilities of the hardware and kernel. + */ +static void igc_set_interrupt_capability(struct igc_adapter *adapter, + bool msix) +{ + int numvecs, i; + int err; + + if (!msix) + goto msi_only; + adapter->flags |= IGC_FLAG_HAS_MSIX; + + /* Number of supported queues. */ + adapter->num_rx_queues = adapter->rss_queues; + + adapter->num_tx_queues = adapter->rss_queues; + + /* start with one vector for every Rx queue */ + numvecs = adapter->num_rx_queues; + + /* if Tx handler is separate add 1 for every Tx queue */ + if (!(adapter->flags & IGC_FLAG_QUEUE_PAIRS)) + numvecs += adapter->num_tx_queues; + + /* store the number of vectors reserved for queues */ + adapter->num_q_vectors = numvecs; + + /* add 1 vector for link status interrupts */ + numvecs++; + + adapter->msix_entries = kcalloc(numvecs, sizeof(struct msix_entry), + GFP_KERNEL); + + if (!adapter->msix_entries) + return; + + /* populate entry values */ + for (i = 0; i < numvecs; i++) + adapter->msix_entries[i].entry = i; + + err = pci_enable_msix_range(adapter->pdev, + adapter->msix_entries, + numvecs, + numvecs); + if (err > 0) + return; + + kfree(adapter->msix_entries); + adapter->msix_entries = NULL; + + igc_reset_interrupt_capability(adapter); + +msi_only: + adapter->flags &= ~IGC_FLAG_HAS_MSIX; + + adapter->rss_queues = 1; + adapter->flags |= IGC_FLAG_QUEUE_PAIRS; + adapter->num_rx_queues = 1; + adapter->num_tx_queues = 1; + adapter->num_q_vectors = 1; + if (!pci_enable_msi(adapter->pdev)) + adapter->flags |= IGC_FLAG_HAS_MSI; +} + +/** + * igc_update_ring_itr - update the dynamic ITR value based on packet size + * @q_vector: pointer to q_vector + * + * Stores a new ITR value based on strictly on packet size. This + * algorithm is less sophisticated than that used in igc_update_itr, + * due to the difficulty of synchronizing statistics across multiple + * receive rings. The divisors and thresholds used by this function + * were determined based on theoretical maximum wire speed and testing + * data, in order to minimize response time while increasing bulk + * throughput. + * NOTE: This function is called only when operating in a multiqueue + * receive environment. + */ +static void igc_update_ring_itr(struct igc_q_vector *q_vector) +{ + struct igc_adapter *adapter = q_vector->adapter; + int new_val = q_vector->itr_val; + int avg_wire_size = 0; + unsigned int packets; + + /* For non-gigabit speeds, just fix the interrupt rate at 4000 + * ints/sec - ITR timer value of 120 ticks. + */ + switch (adapter->link_speed) { + case SPEED_10: + case SPEED_100: + new_val = IGC_4K_ITR; + goto set_itr_val; + default: + break; + } + + packets = q_vector->rx.total_packets; + if (packets) + avg_wire_size = q_vector->rx.total_bytes / packets; + + packets = q_vector->tx.total_packets; + if (packets) + avg_wire_size = max_t(u32, avg_wire_size, + q_vector->tx.total_bytes / packets); + + /* if avg_wire_size isn't set no work was done */ + if (!avg_wire_size) + goto clear_counts; + + /* Add 24 bytes to size to account for CRC, preamble, and gap */ + avg_wire_size += 24; + + /* Don't starve jumbo frames */ + avg_wire_size = min(avg_wire_size, 3000); + + /* Give a little boost to mid-size frames */ + if (avg_wire_size > 300 && avg_wire_size < 1200) + new_val = avg_wire_size / 3; + else + new_val = avg_wire_size / 2; + + /* conservative mode (itr 3) eliminates the lowest_latency setting */ + if (new_val < IGC_20K_ITR && + ((q_vector->rx.ring && adapter->rx_itr_setting == 3) || + (!q_vector->rx.ring && adapter->tx_itr_setting == 3))) + new_val = IGC_20K_ITR; + +set_itr_val: + if (new_val != q_vector->itr_val) { + q_vector->itr_val = new_val; + q_vector->set_itr = 1; + } +clear_counts: + q_vector->rx.total_bytes = 0; + q_vector->rx.total_packets = 0; + q_vector->tx.total_bytes = 0; + q_vector->tx.total_packets = 0; +} + +static void igc_ring_irq_enable(struct igc_q_vector *q_vector) +{ + struct igc_adapter *adapter = q_vector->adapter; + struct igc_hw *hw = &adapter->hw; + + if ((q_vector->rx.ring && (adapter->rx_itr_setting & 3)) || + (!q_vector->rx.ring && (adapter->tx_itr_setting & 3))) { + if (adapter->num_q_vectors == 1) + igc_set_itr(q_vector); + else + igc_update_ring_itr(q_vector); + } + + if (!test_bit(__IGC_DOWN, &adapter->state)) { + if (adapter->msix_entries) + wr32(IGC_EIMS, q_vector->eims_value); + else + igc_irq_enable(adapter); + } +} + +static void igc_add_ring(struct igc_ring *ring, + struct igc_ring_container *head) +{ + head->ring = ring; + head->count++; +} + +/** + * igc_cache_ring_register - Descriptor ring to register mapping + * @adapter: board private structure to initialize + * + * Once we know the feature-set enabled for the device, we'll cache + * the register offset the descriptor ring is assigned to. + */ +static void igc_cache_ring_register(struct igc_adapter *adapter) +{ + int i = 0, j = 0; + + switch (adapter->hw.mac.type) { + case igc_i225: + default: + for (; i < adapter->num_rx_queues; i++) + adapter->rx_ring[i]->reg_idx = i; + for (; j < adapter->num_tx_queues; j++) + adapter->tx_ring[j]->reg_idx = j; + break; + } +} + +/** + * igc_poll - NAPI Rx polling callback + * @napi: napi polling structure + * @budget: count of how many packets we should handle + */ +static int igc_poll(struct napi_struct *napi, int budget) +{ + struct igc_q_vector *q_vector = container_of(napi, + struct igc_q_vector, + napi); + bool clean_complete = true; + int work_done = 0; + + if (q_vector->tx.ring) + clean_complete = igc_clean_tx_irq(q_vector, budget); + + if (q_vector->rx.ring) { + int cleaned = igc_clean_rx_irq(q_vector, budget); + + work_done += cleaned; + if (cleaned >= budget) + clean_complete = false; + } + + /* If all work not completed, return budget and keep polling */ + if (!clean_complete) + return budget; + + /* Exit the polling mode, but don't re-enable interrupts if stack might + * poll us due to busy-polling + */ + if (likely(napi_complete_done(napi, work_done))) + igc_ring_irq_enable(q_vector); + + return min(work_done, budget - 1); +} + +/** + * igc_alloc_q_vector - Allocate memory for a single interrupt vector + * @adapter: board private structure to initialize + * @v_count: q_vectors allocated on adapter, used for ring interleaving + * @v_idx: index of vector in adapter struct + * @txr_count: total number of Tx rings to allocate + * @txr_idx: index of first Tx ring to allocate + * @rxr_count: total number of Rx rings to allocate + * @rxr_idx: index of first Rx ring to allocate + * + * We allocate one q_vector. If allocation fails we return -ENOMEM. + */ +static int igc_alloc_q_vector(struct igc_adapter *adapter, + unsigned int v_count, unsigned int v_idx, + unsigned int txr_count, unsigned int txr_idx, + unsigned int rxr_count, unsigned int rxr_idx) +{ + struct igc_q_vector *q_vector; + struct igc_ring *ring; + int ring_count; + + /* igc only supports 1 Tx and/or 1 Rx queue per vector */ + if (txr_count > 1 || rxr_count > 1) + return -ENOMEM; + + ring_count = txr_count + rxr_count; + + /* allocate q_vector and rings */ + q_vector = adapter->q_vector[v_idx]; + if (!q_vector) + q_vector = kzalloc(struct_size(q_vector, ring, ring_count), + GFP_KERNEL); + else + memset(q_vector, 0, struct_size(q_vector, ring, ring_count)); + if (!q_vector) + return -ENOMEM; + + /* initialize NAPI */ + netif_napi_add(adapter->netdev, &q_vector->napi, + igc_poll, 64); + + /* tie q_vector and adapter together */ + adapter->q_vector[v_idx] = q_vector; + q_vector->adapter = adapter; + + /* initialize work limits */ + q_vector->tx.work_limit = adapter->tx_work_limit; + + /* initialize ITR configuration */ + q_vector->itr_register = adapter->io_addr + IGC_EITR(0); + q_vector->itr_val = IGC_START_ITR; + + /* initialize pointer to rings */ + ring = q_vector->ring; + + /* initialize ITR */ + if (rxr_count) { + /* rx or rx/tx vector */ + if (!adapter->rx_itr_setting || adapter->rx_itr_setting > 3) + q_vector->itr_val = adapter->rx_itr_setting; + } else { + /* tx only vector */ + if (!adapter->tx_itr_setting || adapter->tx_itr_setting > 3) + q_vector->itr_val = adapter->tx_itr_setting; + } + + if (txr_count) { + /* assign generic ring traits */ + ring->dev = &adapter->pdev->dev; + ring->netdev = adapter->netdev; + + /* configure backlink on ring */ + ring->q_vector = q_vector; + + /* update q_vector Tx values */ + igc_add_ring(ring, &q_vector->tx); + + /* apply Tx specific ring traits */ + ring->count = adapter->tx_ring_count; + ring->queue_index = txr_idx; + + /* assign ring to adapter */ + adapter->tx_ring[txr_idx] = ring; + + /* push pointer to next ring */ + ring++; + } + + if (rxr_count) { + /* assign generic ring traits */ + ring->dev = &adapter->pdev->dev; + ring->netdev = adapter->netdev; + + /* configure backlink on ring */ + ring->q_vector = q_vector; + + /* update q_vector Rx values */ + igc_add_ring(ring, &q_vector->rx); + + /* apply Rx specific ring traits */ + ring->count = adapter->rx_ring_count; + ring->queue_index = rxr_idx; + + /* assign ring to adapter */ + adapter->rx_ring[rxr_idx] = ring; + } + + return 0; +} + +/** + * igc_alloc_q_vectors - Allocate memory for interrupt vectors + * @adapter: board private structure to initialize + * + * We allocate one q_vector per queue interrupt. If allocation fails we + * return -ENOMEM. + */ +static int igc_alloc_q_vectors(struct igc_adapter *adapter) +{ + int rxr_remaining = adapter->num_rx_queues; + int txr_remaining = adapter->num_tx_queues; + int rxr_idx = 0, txr_idx = 0, v_idx = 0; + int q_vectors = adapter->num_q_vectors; + int err; + + if (q_vectors >= (rxr_remaining + txr_remaining)) { + for (; rxr_remaining; v_idx++) { + err = igc_alloc_q_vector(adapter, q_vectors, v_idx, + 0, 0, 1, rxr_idx); + + if (err) + goto err_out; + + /* update counts and index */ + rxr_remaining--; + rxr_idx++; + } + } + + for (; v_idx < q_vectors; v_idx++) { + int rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors - v_idx); + int tqpv = DIV_ROUND_UP(txr_remaining, q_vectors - v_idx); + + err = igc_alloc_q_vector(adapter, q_vectors, v_idx, + tqpv, txr_idx, rqpv, rxr_idx); + + if (err) + goto err_out; + + /* update counts and index */ + rxr_remaining -= rqpv; + txr_remaining -= tqpv; + rxr_idx++; + txr_idx++; + } + + return 0; + +err_out: + adapter->num_tx_queues = 0; + adapter->num_rx_queues = 0; + adapter->num_q_vectors = 0; + + while (v_idx--) + igc_free_q_vector(adapter, v_idx); + + return -ENOMEM; +} + +/** + * igc_init_interrupt_scheme - initialize interrupts, allocate queues/vectors + * @adapter: Pointer to adapter structure + * @msix: boolean for MSI-X capability + * + * This function initializes the interrupts and allocates all of the queues. + */ +static int igc_init_interrupt_scheme(struct igc_adapter *adapter, bool msix) +{ + struct net_device *dev = adapter->netdev; + int err = 0; + + igc_set_interrupt_capability(adapter, msix); + + err = igc_alloc_q_vectors(adapter); + if (err) { + netdev_err(dev, "Unable to allocate memory for vectors\n"); + goto err_alloc_q_vectors; + } + + igc_cache_ring_register(adapter); + + return 0; + +err_alloc_q_vectors: + igc_reset_interrupt_capability(adapter); + return err; +} + +/** + * igc_sw_init - Initialize general software structures (struct igc_adapter) + * @adapter: board private structure to initialize + * + * igc_sw_init initializes the Adapter private data structure. + * Fields are initialized based on PCI device information and + * OS network device settings (MTU size). + */ +static int igc_sw_init(struct igc_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; + struct igc_hw *hw = &adapter->hw; + + pci_read_config_word(pdev, PCI_COMMAND, &hw->bus.pci_cmd_word); + + /* set default ring sizes */ + adapter->tx_ring_count = IGC_DEFAULT_TXD; + adapter->rx_ring_count = IGC_DEFAULT_RXD; + + /* set default ITR values */ + adapter->rx_itr_setting = IGC_DEFAULT_ITR; + adapter->tx_itr_setting = IGC_DEFAULT_ITR; + + /* set default work limits */ + adapter->tx_work_limit = IGC_DEFAULT_TX_WORK; + + /* adjust max frame to be at least the size of a standard frame */ + adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN + + VLAN_HLEN; + adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN; + + mutex_init(&adapter->nfc_rule_lock); + INIT_LIST_HEAD(&adapter->nfc_rule_list); + adapter->nfc_rule_count = 0; + + spin_lock_init(&adapter->stats64_lock); + /* Assume MSI-X interrupts, will be checked during IRQ allocation */ + adapter->flags |= IGC_FLAG_HAS_MSIX; + + igc_init_queue_configuration(adapter); + + /* This call may decrease the number of queues */ + if (igc_init_interrupt_scheme(adapter, true)) { + netdev_err(netdev, "Unable to allocate memory for queues\n"); + return -ENOMEM; + } + + /* Explicitly disable IRQ since the NIC can be in any state. */ + igc_irq_disable(adapter); + + set_bit(__IGC_DOWN, &adapter->state); + + return 0; +} + +/** + * igc_up - Open the interface and prepare it to handle traffic + * @adapter: board private structure + */ +void igc_up(struct igc_adapter *adapter) +{ + struct igc_hw *hw = &adapter->hw; + int i = 0; + + /* hardware has been reset, we need to reload some things */ + igc_configure(adapter); + + clear_bit(__IGC_DOWN, &adapter->state); + + for (i = 0; i < adapter->num_q_vectors; i++) + napi_enable(&adapter->q_vector[i]->napi); + + if (adapter->msix_entries) + igc_configure_msix(adapter); + else + igc_assign_vector(adapter->q_vector[0], 0); + + /* Clear any pending interrupts. */ + rd32(IGC_ICR); + igc_irq_enable(adapter); + + netif_tx_start_all_queues(adapter->netdev); + + /* start the watchdog. */ + hw->mac.get_link_status = 1; + schedule_work(&adapter->watchdog_task); +} + +/** + * igc_update_stats - Update the board statistics counters + * @adapter: board private structure + */ +void igc_update_stats(struct igc_adapter *adapter) +{ + struct rtnl_link_stats64 *net_stats = &adapter->stats64; + struct pci_dev *pdev = adapter->pdev; + struct igc_hw *hw = &adapter->hw; + u64 _bytes, _packets; + u64 bytes, packets; + unsigned int start; + u32 mpc; + int i; + + /* Prevent stats update while adapter is being reset, or if the pci + * connection is down. + */ + if (adapter->link_speed == 0) + return; + if (pci_channel_offline(pdev)) + return; + + packets = 0; + bytes = 0; + + rcu_read_lock(); + for (i = 0; i < adapter->num_rx_queues; i++) { + struct igc_ring *ring = adapter->rx_ring[i]; + u32 rqdpc = rd32(IGC_RQDPC(i)); + + if (hw->mac.type >= igc_i225) + wr32(IGC_RQDPC(i), 0); + + if (rqdpc) { + ring->rx_stats.drops += rqdpc; + net_stats->rx_fifo_errors += rqdpc; + } + + do { + start = u64_stats_fetch_begin_irq(&ring->rx_syncp); + _bytes = ring->rx_stats.bytes; + _packets = ring->rx_stats.packets; + } while (u64_stats_fetch_retry_irq(&ring->rx_syncp, start)); + bytes += _bytes; + packets += _packets; + } + + net_stats->rx_bytes = bytes; + net_stats->rx_packets = packets; + + packets = 0; + bytes = 0; + for (i = 0; i < adapter->num_tx_queues; i++) { + struct igc_ring *ring = adapter->tx_ring[i]; + + do { + start = u64_stats_fetch_begin_irq(&ring->tx_syncp); + _bytes = ring->tx_stats.bytes; + _packets = ring->tx_stats.packets; + } while (u64_stats_fetch_retry_irq(&ring->tx_syncp, start)); + bytes += _bytes; + packets += _packets; + } + net_stats->tx_bytes = bytes; + net_stats->tx_packets = packets; + rcu_read_unlock(); + + /* read stats registers */ + adapter->stats.crcerrs += rd32(IGC_CRCERRS); + adapter->stats.gprc += rd32(IGC_GPRC); + adapter->stats.gorc += rd32(IGC_GORCL); + rd32(IGC_GORCH); /* clear GORCL */ + adapter->stats.bprc += rd32(IGC_BPRC); + adapter->stats.mprc += rd32(IGC_MPRC); + adapter->stats.roc += rd32(IGC_ROC); + + adapter->stats.prc64 += rd32(IGC_PRC64); + adapter->stats.prc127 += rd32(IGC_PRC127); + adapter->stats.prc255 += rd32(IGC_PRC255); + adapter->stats.prc511 += rd32(IGC_PRC511); + adapter->stats.prc1023 += rd32(IGC_PRC1023); + adapter->stats.prc1522 += rd32(IGC_PRC1522); + adapter->stats.tlpic += rd32(IGC_TLPIC); + adapter->stats.rlpic += rd32(IGC_RLPIC); + + mpc = rd32(IGC_MPC); + adapter->stats.mpc += mpc; + net_stats->rx_fifo_errors += mpc; + adapter->stats.scc += rd32(IGC_SCC); + adapter->stats.ecol += rd32(IGC_ECOL); + adapter->stats.mcc += rd32(IGC_MCC); + adapter->stats.latecol += rd32(IGC_LATECOL); + adapter->stats.dc += rd32(IGC_DC); + adapter->stats.rlec += rd32(IGC_RLEC); + adapter->stats.xonrxc += rd32(IGC_XONRXC); + adapter->stats.xontxc += rd32(IGC_XONTXC); + adapter->stats.xoffrxc += rd32(IGC_XOFFRXC); + adapter->stats.xofftxc += rd32(IGC_XOFFTXC); + adapter->stats.fcruc += rd32(IGC_FCRUC); + adapter->stats.gptc += rd32(IGC_GPTC); + adapter->stats.gotc += rd32(IGC_GOTCL); + rd32(IGC_GOTCH); /* clear GOTCL */ + adapter->stats.rnbc += rd32(IGC_RNBC); + adapter->stats.ruc += rd32(IGC_RUC); + adapter->stats.rfc += rd32(IGC_RFC); + adapter->stats.rjc += rd32(IGC_RJC); + adapter->stats.tor += rd32(IGC_TORH); + adapter->stats.tot += rd32(IGC_TOTH); + adapter->stats.tpr += rd32(IGC_TPR); + + adapter->stats.ptc64 += rd32(IGC_PTC64); + adapter->stats.ptc127 += rd32(IGC_PTC127); + adapter->stats.ptc255 += rd32(IGC_PTC255); + adapter->stats.ptc511 += rd32(IGC_PTC511); + adapter->stats.ptc1023 += rd32(IGC_PTC1023); + adapter->stats.ptc1522 += rd32(IGC_PTC1522); + + adapter->stats.mptc += rd32(IGC_MPTC); + adapter->stats.bptc += rd32(IGC_BPTC); + + adapter->stats.tpt += rd32(IGC_TPT); + adapter->stats.colc += rd32(IGC_COLC); + adapter->stats.colc += rd32(IGC_RERC); + + adapter->stats.algnerrc += rd32(IGC_ALGNERRC); + + adapter->stats.tsctc += rd32(IGC_TSCTC); + + adapter->stats.iac += rd32(IGC_IAC); + + /* Fill out the OS statistics structure */ + net_stats->multicast = adapter->stats.mprc; + net_stats->collisions = adapter->stats.colc; + + /* Rx Errors */ + + /* RLEC on some newer hardware can be incorrect so build + * our own version based on RUC and ROC + */ + net_stats->rx_errors = adapter->stats.rxerrc + + adapter->stats.crcerrs + adapter->stats.algnerrc + + adapter->stats.ruc + adapter->stats.roc + + adapter->stats.cexterr; + net_stats->rx_length_errors = adapter->stats.ruc + + adapter->stats.roc; + net_stats->rx_crc_errors = adapter->stats.crcerrs; + net_stats->rx_frame_errors = adapter->stats.algnerrc; + net_stats->rx_missed_errors = adapter->stats.mpc; + + /* Tx Errors */ + net_stats->tx_errors = adapter->stats.ecol + + adapter->stats.latecol; + net_stats->tx_aborted_errors = adapter->stats.ecol; + net_stats->tx_window_errors = adapter->stats.latecol; + net_stats->tx_carrier_errors = adapter->stats.tncrs; + + /* Tx Dropped needs to be maintained elsewhere */ + + /* Management Stats */ + adapter->stats.mgptc += rd32(IGC_MGTPTC); + adapter->stats.mgprc += rd32(IGC_MGTPRC); + adapter->stats.mgpdc += rd32(IGC_MGTPDC); +} + +/** + * igc_down - Close the interface + * @adapter: board private structure + */ +void igc_down(struct igc_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + struct igc_hw *hw = &adapter->hw; + u32 tctl, rctl; + int i = 0; + + set_bit(__IGC_DOWN, &adapter->state); + + igc_ptp_suspend(adapter); + + if (pci_device_is_present(adapter->pdev)) { + /* disable receives in the hardware */ + rctl = rd32(IGC_RCTL); + wr32(IGC_RCTL, rctl & ~IGC_RCTL_EN); + /* flush and sleep below */ + } + /* set trans_start so we don't get spurious watchdogs during reset */ + netif_trans_update(netdev); + + netif_carrier_off(netdev); + netif_tx_stop_all_queues(netdev); + + if (pci_device_is_present(adapter->pdev)) { + /* disable transmits in the hardware */ + tctl = rd32(IGC_TCTL); + tctl &= ~IGC_TCTL_EN; + wr32(IGC_TCTL, tctl); + /* flush both disables and wait for them to finish */ + wrfl(); + usleep_range(10000, 20000); + + igc_irq_disable(adapter); + } + + adapter->flags &= ~IGC_FLAG_NEED_LINK_UPDATE; + + for (i = 0; i < adapter->num_q_vectors; i++) { + if (adapter->q_vector[i]) { + napi_synchronize(&adapter->q_vector[i]->napi); + napi_disable(&adapter->q_vector[i]->napi); + } + } + + del_timer_sync(&adapter->watchdog_timer); + del_timer_sync(&adapter->phy_info_timer); + + /* record the stats before reset*/ + spin_lock(&adapter->stats64_lock); + igc_update_stats(adapter); + spin_unlock(&adapter->stats64_lock); + + adapter->link_speed = 0; + adapter->link_duplex = 0; + + if (!pci_channel_offline(adapter->pdev)) + igc_reset(adapter); + + /* clear VLAN promisc flag so VFTA will be updated if necessary */ + adapter->flags &= ~IGC_FLAG_VLAN_PROMISC; + + igc_clean_all_tx_rings(adapter); + igc_clean_all_rx_rings(adapter); +} + +void igc_reinit_locked(struct igc_adapter *adapter) +{ + while (test_and_set_bit(__IGC_RESETTING, &adapter->state)) + usleep_range(1000, 2000); + igc_down(adapter); + igc_up(adapter); + clear_bit(__IGC_RESETTING, &adapter->state); +} + +static void igc_reset_task(struct work_struct *work) +{ + struct igc_adapter *adapter; + + adapter = container_of(work, struct igc_adapter, reset_task); + + rtnl_lock(); + /* If we're already down or resetting, just bail */ + if (test_bit(__IGC_DOWN, &adapter->state) || + test_bit(__IGC_RESETTING, &adapter->state)) { + rtnl_unlock(); + return; + } + + igc_rings_dump(adapter); + igc_regs_dump(adapter); + netdev_err(adapter->netdev, "Reset adapter\n"); + igc_reinit_locked(adapter); + rtnl_unlock(); +} + +/** + * igc_change_mtu - Change the Maximum Transfer Unit + * @netdev: network interface device structure + * @new_mtu: new value for maximum frame size + * + * Returns 0 on success, negative on failure + */ +static int igc_change_mtu(struct net_device *netdev, int new_mtu) +{ + int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; + struct igc_adapter *adapter = netdev_priv(netdev); + + /* adjust max frame to be at least the size of a standard frame */ + if (max_frame < (ETH_FRAME_LEN + ETH_FCS_LEN)) + max_frame = ETH_FRAME_LEN + ETH_FCS_LEN; + + while (test_and_set_bit(__IGC_RESETTING, &adapter->state)) + usleep_range(1000, 2000); + + /* igc_down has a dependency on max_frame_size */ + adapter->max_frame_size = max_frame; + + if (netif_running(netdev)) + igc_down(adapter); + + netdev_dbg(netdev, "changing MTU from %d to %d\n", netdev->mtu, new_mtu); + netdev->mtu = new_mtu; + + if (netif_running(netdev)) + igc_up(adapter); + else + igc_reset(adapter); + + clear_bit(__IGC_RESETTING, &adapter->state); + + return 0; +} + +/** + * igc_get_stats64 - Get System Network Statistics + * @netdev: network interface device structure + * @stats: rtnl_link_stats64 pointer + * + * Returns the address of the device statistics structure. + * The statistics are updated here and also from the timer callback. + */ +static void igc_get_stats64(struct net_device *netdev, + struct rtnl_link_stats64 *stats) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + + spin_lock(&adapter->stats64_lock); + if (!test_bit(__IGC_RESETTING, &adapter->state)) + igc_update_stats(adapter); + memcpy(stats, &adapter->stats64, sizeof(*stats)); + spin_unlock(&adapter->stats64_lock); +} + +static netdev_features_t igc_fix_features(struct net_device *netdev, + netdev_features_t features) +{ + /* Since there is no support for separate Rx/Tx vlan accel + * enable/disable make sure Tx flag is always in same state as Rx. + */ + if (features & NETIF_F_HW_VLAN_CTAG_RX) + features |= NETIF_F_HW_VLAN_CTAG_TX; + else + features &= ~NETIF_F_HW_VLAN_CTAG_TX; + + return features; +} + +static int igc_set_features(struct net_device *netdev, + netdev_features_t features) +{ + netdev_features_t changed = netdev->features ^ features; + struct igc_adapter *adapter = netdev_priv(netdev); + + /* Add VLAN support */ + if (!(changed & (NETIF_F_RXALL | NETIF_F_NTUPLE))) + return 0; + + if (!(features & NETIF_F_NTUPLE)) + igc_flush_nfc_rules(adapter); + + netdev->features = features; + + if (netif_running(netdev)) + igc_reinit_locked(adapter); + else + igc_reset(adapter); + + return 1; +} + +static netdev_features_t +igc_features_check(struct sk_buff *skb, struct net_device *dev, + netdev_features_t features) +{ + unsigned int network_hdr_len, mac_hdr_len; + + /* Make certain the headers can be described by a context descriptor */ + mac_hdr_len = skb_network_header(skb) - skb->data; + if (unlikely(mac_hdr_len > IGC_MAX_MAC_HDR_LEN)) + return features & ~(NETIF_F_HW_CSUM | + NETIF_F_SCTP_CRC | + NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_TSO | + NETIF_F_TSO6); + + network_hdr_len = skb_checksum_start(skb) - skb_network_header(skb); + if (unlikely(network_hdr_len > IGC_MAX_NETWORK_HDR_LEN)) + return features & ~(NETIF_F_HW_CSUM | + NETIF_F_SCTP_CRC | + NETIF_F_TSO | + NETIF_F_TSO6); + + /* We can only support IPv4 TSO in tunnels if we can mangle the + * inner IP ID field, so strip TSO if MANGLEID is not supported. + */ + if (skb->encapsulation && !(features & NETIF_F_TSO_MANGLEID)) + features &= ~NETIF_F_TSO; + + return features; +} + +static void igc_tsync_interrupt(struct igc_adapter *adapter) +{ + struct igc_hw *hw = &adapter->hw; + u32 tsicr = rd32(IGC_TSICR); + u32 ack = 0; + + if (tsicr & IGC_TSICR_TXTS) { + /* retrieve hardware timestamp */ + schedule_work(&adapter->ptp_tx_work); + ack |= IGC_TSICR_TXTS; + } + + /* acknowledge the interrupts */ + wr32(IGC_TSICR, ack); +} + +/** + * igc_msix_other - msix other interrupt handler + * @irq: interrupt number + * @data: pointer to a q_vector + */ +static irqreturn_t igc_msix_other(int irq, void *data) +{ + struct igc_adapter *adapter = data; + struct igc_hw *hw = &adapter->hw; + u32 icr = rd32(IGC_ICR); + + /* reading ICR causes bit 31 of EICR to be cleared */ + if (icr & IGC_ICR_DRSTA) + schedule_work(&adapter->reset_task); + + if (icr & IGC_ICR_DOUTSYNC) { + /* HW is reporting DMA is out of sync */ + adapter->stats.doosync++; + } + + if (icr & IGC_ICR_LSC) { + hw->mac.get_link_status = 1; + /* guard against interrupt when we're going down */ + if (!test_bit(__IGC_DOWN, &adapter->state)) + mod_timer(&adapter->watchdog_timer, jiffies + 1); + } + + if (icr & IGC_ICR_TS) + igc_tsync_interrupt(adapter); + + wr32(IGC_EIMS, adapter->eims_other); + + return IRQ_HANDLED; +} + +static void igc_write_itr(struct igc_q_vector *q_vector) +{ + u32 itr_val = q_vector->itr_val & IGC_QVECTOR_MASK; + + if (!q_vector->set_itr) + return; + + if (!itr_val) + itr_val = IGC_ITR_VAL_MASK; + + itr_val |= IGC_EITR_CNT_IGNR; + + writel(itr_val, q_vector->itr_register); + q_vector->set_itr = 0; +} + +static irqreturn_t igc_msix_ring(int irq, void *data) +{ + struct igc_q_vector *q_vector = data; + + /* Write the ITR value calculated from the previous interrupt. */ + igc_write_itr(q_vector); + + napi_schedule(&q_vector->napi); + + return IRQ_HANDLED; +} + +/** + * igc_request_msix - Initialize MSI-X interrupts + * @adapter: Pointer to adapter structure + * + * igc_request_msix allocates MSI-X vectors and requests interrupts from the + * kernel. + */ +static int igc_request_msix(struct igc_adapter *adapter) +{ + unsigned int num_q_vectors = adapter->num_q_vectors; + int i = 0, err = 0, vector = 0, free_vector = 0; + struct net_device *netdev = adapter->netdev; + + err = request_irq(adapter->msix_entries[vector].vector, + &igc_msix_other, 0, netdev->name, adapter); + if (err) + goto err_out; + + if (num_q_vectors > MAX_Q_VECTORS) { + num_q_vectors = MAX_Q_VECTORS; + dev_warn(&adapter->pdev->dev, + "The number of queue vectors (%d) is higher than max allowed (%d)\n", + adapter->num_q_vectors, MAX_Q_VECTORS); + } + for (i = 0; i < num_q_vectors; i++) { + struct igc_q_vector *q_vector = adapter->q_vector[i]; + + vector++; + + q_vector->itr_register = adapter->io_addr + IGC_EITR(vector); + + if (q_vector->rx.ring && q_vector->tx.ring) + sprintf(q_vector->name, "%s-TxRx-%u", netdev->name, + q_vector->rx.ring->queue_index); + else if (q_vector->tx.ring) + sprintf(q_vector->name, "%s-tx-%u", netdev->name, + q_vector->tx.ring->queue_index); + else if (q_vector->rx.ring) + sprintf(q_vector->name, "%s-rx-%u", netdev->name, + q_vector->rx.ring->queue_index); + else + sprintf(q_vector->name, "%s-unused", netdev->name); + + err = request_irq(adapter->msix_entries[vector].vector, + igc_msix_ring, 0, q_vector->name, + q_vector); + if (err) + goto err_free; + } + + igc_configure_msix(adapter); + return 0; + +err_free: + /* free already assigned IRQs */ + free_irq(adapter->msix_entries[free_vector++].vector, adapter); + + vector--; + for (i = 0; i < vector; i++) { + free_irq(adapter->msix_entries[free_vector++].vector, + adapter->q_vector[i]); + } +err_out: + return err; +} + +/** + * igc_clear_interrupt_scheme - reset the device to a state of no interrupts + * @adapter: Pointer to adapter structure + * + * This function resets the device so that it has 0 rx queues, tx queues, and + * MSI-X interrupts allocated. + */ +static void igc_clear_interrupt_scheme(struct igc_adapter *adapter) +{ + igc_free_q_vectors(adapter); + igc_reset_interrupt_capability(adapter); +} + +/* Need to wait a few seconds after link up to get diagnostic information from + * the phy + */ +static void igc_update_phy_info(struct timer_list *t) +{ + struct igc_adapter *adapter = from_timer(adapter, t, phy_info_timer); + + igc_get_phy_info(&adapter->hw); +} + +/** + * igc_has_link - check shared code for link and determine up/down + * @adapter: pointer to driver private info + */ +bool igc_has_link(struct igc_adapter *adapter) +{ + struct igc_hw *hw = &adapter->hw; + bool link_active = false; + + /* get_link_status is set on LSC (link status) interrupt or + * rx sequence error interrupt. get_link_status will stay + * false until the igc_check_for_link establishes link + * for copper adapters ONLY + */ + if (!hw->mac.get_link_status) + return true; + hw->mac.ops.check_for_link(hw); + link_active = !hw->mac.get_link_status; + + if (hw->mac.type == igc_i225) { + if (!netif_carrier_ok(adapter->netdev)) { + adapter->flags &= ~IGC_FLAG_NEED_LINK_UPDATE; + } else if (!(adapter->flags & IGC_FLAG_NEED_LINK_UPDATE)) { + adapter->flags |= IGC_FLAG_NEED_LINK_UPDATE; + adapter->link_check_timeout = jiffies; + } + } + + return link_active; +} + +/** + * igc_watchdog - Timer Call-back + * @t: timer for the watchdog + */ +static void igc_watchdog(struct timer_list *t) +{ + struct igc_adapter *adapter = from_timer(adapter, t, watchdog_timer); + /* Do the rest outside of interrupt context */ + schedule_work(&adapter->watchdog_task); +} + +static void igc_watchdog_task(struct work_struct *work) +{ + struct igc_adapter *adapter = container_of(work, + struct igc_adapter, + watchdog_task); + struct net_device *netdev = adapter->netdev; + struct igc_hw *hw = &adapter->hw; + struct igc_phy_info *phy = &hw->phy; + u16 phy_data, retry_count = 20; + u32 link; + int i; + + link = igc_has_link(adapter); + + if (adapter->flags & IGC_FLAG_NEED_LINK_UPDATE) { + if (time_after(jiffies, (adapter->link_check_timeout + HZ))) + adapter->flags &= ~IGC_FLAG_NEED_LINK_UPDATE; + else + link = false; + } + + if (link) { + /* Cancel scheduled suspend requests. */ + pm_runtime_resume(netdev->dev.parent); + + if (!netif_carrier_ok(netdev)) { + u32 ctrl; + + hw->mac.ops.get_speed_and_duplex(hw, + &adapter->link_speed, + &adapter->link_duplex); + + ctrl = rd32(IGC_CTRL); + /* Link status message must follow this format */ + netdev_info(netdev, + "NIC Link is Up %d Mbps %s Duplex, Flow Control: %s\n", + adapter->link_speed, + adapter->link_duplex == FULL_DUPLEX ? + "Full" : "Half", + (ctrl & IGC_CTRL_TFCE) && + (ctrl & IGC_CTRL_RFCE) ? "RX/TX" : + (ctrl & IGC_CTRL_RFCE) ? "RX" : + (ctrl & IGC_CTRL_TFCE) ? "TX" : "None"); + + /* disable EEE if enabled */ + if ((adapter->flags & IGC_FLAG_EEE) && + adapter->link_duplex == HALF_DUPLEX) { + netdev_info(netdev, + "EEE Disabled: unsupported at half duplex. Re-enable using ethtool when at full duplex\n"); + adapter->hw.dev_spec._base.eee_enable = false; + adapter->flags &= ~IGC_FLAG_EEE; + } + + /* check if SmartSpeed worked */ + igc_check_downshift(hw); + if (phy->speed_downgraded) + netdev_warn(netdev, "Link Speed was downgraded by SmartSpeed\n"); + + /* adjust timeout factor according to speed/duplex */ + adapter->tx_timeout_factor = 1; + switch (adapter->link_speed) { + case SPEED_10: + adapter->tx_timeout_factor = 14; + break; + case SPEED_100: + case SPEED_1000: + case SPEED_2500: + adapter->tx_timeout_factor = 7; + break; + } + + if (adapter->link_speed != SPEED_1000) + goto no_wait; + + /* wait for Remote receiver status OK */ +retry_read_status: + if (!igc_read_phy_reg(hw, PHY_1000T_STATUS, + &phy_data)) { + if (!(phy_data & SR_1000T_REMOTE_RX_STATUS) && + retry_count) { + msleep(100); + retry_count--; + goto retry_read_status; + } else if (!retry_count) { + netdev_err(netdev, "exceed max 2 second\n"); + } + } else { + netdev_err(netdev, "read 1000Base-T Status Reg\n"); + } +no_wait: + netif_carrier_on(netdev); + + /* link state has changed, schedule phy info update */ + if (!test_bit(__IGC_DOWN, &adapter->state)) + mod_timer(&adapter->phy_info_timer, + round_jiffies(jiffies + 2 * HZ)); + } + } else { + if (netif_carrier_ok(netdev)) { + adapter->link_speed = 0; + adapter->link_duplex = 0; + + /* Links status message must follow this format */ + netdev_info(netdev, "NIC Link is Down\n"); + netif_carrier_off(netdev); + + /* link state has changed, schedule phy info update */ + if (!test_bit(__IGC_DOWN, &adapter->state)) + mod_timer(&adapter->phy_info_timer, + round_jiffies(jiffies + 2 * HZ)); + + /* link is down, time to check for alternate media */ + if (adapter->flags & IGC_FLAG_MAS_ENABLE) { + if (adapter->flags & IGC_FLAG_MEDIA_RESET) { + schedule_work(&adapter->reset_task); + /* return immediately */ + return; + } + } + pm_schedule_suspend(netdev->dev.parent, + MSEC_PER_SEC * 5); + + /* also check for alternate media here */ + } else if (!netif_carrier_ok(netdev) && + (adapter->flags & IGC_FLAG_MAS_ENABLE)) { + if (adapter->flags & IGC_FLAG_MEDIA_RESET) { + schedule_work(&adapter->reset_task); + /* return immediately */ + return; + } + } + } + + spin_lock(&adapter->stats64_lock); + igc_update_stats(adapter); + spin_unlock(&adapter->stats64_lock); + + for (i = 0; i < adapter->num_tx_queues; i++) { + struct igc_ring *tx_ring = adapter->tx_ring[i]; + + if (!netif_carrier_ok(netdev)) { + /* We've lost link, so the controller stops DMA, + * but we've got queued Tx work that's never going + * to get done, so reset controller to flush Tx. + * (Do the reset outside of interrupt context). + */ + if (igc_desc_unused(tx_ring) + 1 < tx_ring->count) { + adapter->tx_timeout_count++; + schedule_work(&adapter->reset_task); + /* return immediately since reset is imminent */ + return; + } + } + + /* Force detection of hung controller every watchdog period */ + set_bit(IGC_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags); + } + + /* Cause software interrupt to ensure Rx ring is cleaned */ + if (adapter->flags & IGC_FLAG_HAS_MSIX) { + u32 eics = 0; + + for (i = 0; i < adapter->num_q_vectors; i++) + eics |= adapter->q_vector[i]->eims_value; + wr32(IGC_EICS, eics); + } else { + wr32(IGC_ICS, IGC_ICS_RXDMT0); + } + + igc_ptp_tx_hang(adapter); + + /* Reset the timer */ + if (!test_bit(__IGC_DOWN, &adapter->state)) { + if (adapter->flags & IGC_FLAG_NEED_LINK_UPDATE) + mod_timer(&adapter->watchdog_timer, + round_jiffies(jiffies + HZ)); + else + mod_timer(&adapter->watchdog_timer, + round_jiffies(jiffies + 2 * HZ)); + } +} + +/** + * igc_intr_msi - Interrupt Handler + * @irq: interrupt number + * @data: pointer to a network interface device structure + */ +static irqreturn_t igc_intr_msi(int irq, void *data) +{ + struct igc_adapter *adapter = data; + struct igc_q_vector *q_vector = adapter->q_vector[0]; + struct igc_hw *hw = &adapter->hw; + /* read ICR disables interrupts using IAM */ + u32 icr = rd32(IGC_ICR); + + igc_write_itr(q_vector); + + if (icr & IGC_ICR_DRSTA) + schedule_work(&adapter->reset_task); + + if (icr & IGC_ICR_DOUTSYNC) { + /* HW is reporting DMA is out of sync */ + adapter->stats.doosync++; + } + + if (icr & (IGC_ICR_RXSEQ | IGC_ICR_LSC)) { + hw->mac.get_link_status = 1; + if (!test_bit(__IGC_DOWN, &adapter->state)) + mod_timer(&adapter->watchdog_timer, jiffies + 1); + } + + if (icr & IGC_ICR_TS) + igc_tsync_interrupt(adapter); + + napi_schedule(&q_vector->napi); + + return IRQ_HANDLED; +} + +/** + * igc_intr - Legacy Interrupt Handler + * @irq: interrupt number + * @data: pointer to a network interface device structure + */ +static irqreturn_t igc_intr(int irq, void *data) +{ + struct igc_adapter *adapter = data; + struct igc_q_vector *q_vector = adapter->q_vector[0]; + struct igc_hw *hw = &adapter->hw; + /* Interrupt Auto-Mask...upon reading ICR, interrupts are masked. No + * need for the IMC write + */ + u32 icr = rd32(IGC_ICR); + + /* IMS will not auto-mask if INT_ASSERTED is not set, and if it is + * not set, then the adapter didn't send an interrupt + */ + if (!(icr & IGC_ICR_INT_ASSERTED)) + return IRQ_NONE; + + igc_write_itr(q_vector); + + if (icr & IGC_ICR_DRSTA) + schedule_work(&adapter->reset_task); + + if (icr & IGC_ICR_DOUTSYNC) { + /* HW is reporting DMA is out of sync */ + adapter->stats.doosync++; + } + + if (icr & (IGC_ICR_RXSEQ | IGC_ICR_LSC)) { + hw->mac.get_link_status = 1; + /* guard against interrupt when we're going down */ + if (!test_bit(__IGC_DOWN, &adapter->state)) + mod_timer(&adapter->watchdog_timer, jiffies + 1); + } + + if (icr & IGC_ICR_TS) + igc_tsync_interrupt(adapter); + + napi_schedule(&q_vector->napi); + + return IRQ_HANDLED; +} + +static void igc_free_irq(struct igc_adapter *adapter) +{ + if (adapter->msix_entries) { + int vector = 0, i; + + free_irq(adapter->msix_entries[vector++].vector, adapter); + + for (i = 0; i < adapter->num_q_vectors; i++) + free_irq(adapter->msix_entries[vector++].vector, + adapter->q_vector[i]); + } else { + free_irq(adapter->pdev->irq, adapter); + } +} + +/** + * igc_request_irq - initialize interrupts + * @adapter: Pointer to adapter structure + * + * Attempts to configure interrupts using the best available + * capabilities of the hardware and kernel. + */ +static int igc_request_irq(struct igc_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; + int err = 0; + + if (adapter->flags & IGC_FLAG_HAS_MSIX) { + err = igc_request_msix(adapter); + if (!err) + goto request_done; + /* fall back to MSI */ + igc_free_all_tx_resources(adapter); + igc_free_all_rx_resources(adapter); + + igc_clear_interrupt_scheme(adapter); + err = igc_init_interrupt_scheme(adapter, false); + if (err) + goto request_done; + igc_setup_all_tx_resources(adapter); + igc_setup_all_rx_resources(adapter); + igc_configure(adapter); + } + + igc_assign_vector(adapter->q_vector[0], 0); + + if (adapter->flags & IGC_FLAG_HAS_MSI) { + err = request_irq(pdev->irq, &igc_intr_msi, 0, + netdev->name, adapter); + if (!err) + goto request_done; + + /* fall back to legacy interrupts */ + igc_reset_interrupt_capability(adapter); + adapter->flags &= ~IGC_FLAG_HAS_MSI; + } + + err = request_irq(pdev->irq, &igc_intr, IRQF_SHARED, + netdev->name, adapter); + + if (err) + netdev_err(netdev, "Error %d getting interrupt\n", err); + +request_done: + return err; +} + +/** + * __igc_open - Called when a network interface is made active + * @netdev: network interface device structure + * @resuming: boolean indicating if the device is resuming + * + * Returns 0 on success, negative value on failure + * + * The open entry point is called when a network interface is made + * active by the system (IFF_UP). At this point all resources needed + * for transmit and receive operations are allocated, the interrupt + * handler is registered with the OS, the watchdog timer is started, + * and the stack is notified that the interface is ready. + */ +static int __igc_open(struct net_device *netdev, bool resuming) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct pci_dev *pdev = adapter->pdev; + struct igc_hw *hw = &adapter->hw; + int err = 0; + int i = 0; + + /* disallow open during test */ + + if (test_bit(__IGC_TESTING, &adapter->state)) { + WARN_ON(resuming); + return -EBUSY; + } + + if (!resuming) + pm_runtime_get_sync(&pdev->dev); + + netif_carrier_off(netdev); + + /* allocate transmit descriptors */ + err = igc_setup_all_tx_resources(adapter); + if (err) + goto err_setup_tx; + + /* allocate receive descriptors */ + err = igc_setup_all_rx_resources(adapter); + if (err) + goto err_setup_rx; + + igc_power_up_link(adapter); + + igc_configure(adapter); + + err = igc_request_irq(adapter); + if (err) + goto err_req_irq; + + /* Notify the stack of the actual queue counts. */ + err = netif_set_real_num_tx_queues(netdev, adapter->num_tx_queues); + if (err) + goto err_set_queues; + + err = netif_set_real_num_rx_queues(netdev, adapter->num_rx_queues); + if (err) + goto err_set_queues; + + clear_bit(__IGC_DOWN, &adapter->state); + + for (i = 0; i < adapter->num_q_vectors; i++) + napi_enable(&adapter->q_vector[i]->napi); + + /* Clear any pending interrupts. */ + rd32(IGC_ICR); + igc_irq_enable(adapter); + + if (!resuming) + pm_runtime_put(&pdev->dev); + + netif_tx_start_all_queues(netdev); + + /* start the watchdog. */ + hw->mac.get_link_status = 1; + schedule_work(&adapter->watchdog_task); + + return IGC_SUCCESS; + +err_set_queues: + igc_free_irq(adapter); +err_req_irq: + igc_release_hw_control(adapter); + igc_power_down_phy_copper_base(&adapter->hw); + igc_free_all_rx_resources(adapter); +err_setup_rx: + igc_free_all_tx_resources(adapter); +err_setup_tx: + igc_reset(adapter); + if (!resuming) + pm_runtime_put(&pdev->dev); + + return err; +} + +int igc_open(struct net_device *netdev) +{ + return __igc_open(netdev, false); +} + +/** + * __igc_close - Disables a network interface + * @netdev: network interface device structure + * @suspending: boolean indicating the device is suspending + * + * Returns 0, this is not allowed to fail + * + * The close entry point is called when an interface is de-activated + * by the OS. The hardware is still under the driver's control, but + * needs to be disabled. A global MAC reset is issued to stop the + * hardware, and all transmit and receive resources are freed. + */ +static int __igc_close(struct net_device *netdev, bool suspending) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct pci_dev *pdev = adapter->pdev; + + WARN_ON(test_bit(__IGC_RESETTING, &adapter->state)); + + if (!suspending) + pm_runtime_get_sync(&pdev->dev); + + igc_down(adapter); + + igc_release_hw_control(adapter); + + igc_free_irq(adapter); + + igc_free_all_tx_resources(adapter); + igc_free_all_rx_resources(adapter); + + if (!suspending) + pm_runtime_put_sync(&pdev->dev); + + return 0; +} + +int igc_close(struct net_device *netdev) +{ + if (netif_device_present(netdev) || netdev->dismantle) + return __igc_close(netdev, false); + return 0; +} + +/** + * igc_ioctl - Access the hwtstamp interface + * @netdev: network interface device structure + * @ifr: interface request data + * @cmd: ioctl command + **/ +static int igc_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) +{ + switch (cmd) { + case SIOCGHWTSTAMP: + return igc_ptp_get_ts_config(netdev, ifr); + case SIOCSHWTSTAMP: + return igc_ptp_set_ts_config(netdev, ifr); + default: + return -EOPNOTSUPP; + } +} + +static int igc_save_launchtime_params(struct igc_adapter *adapter, int queue, + bool enable) +{ + struct igc_ring *ring; + int i; + + if (queue < 0 || queue >= adapter->num_tx_queues) + return -EINVAL; + + ring = adapter->tx_ring[queue]; + ring->launchtime_enable = enable; + + if (adapter->base_time) + return 0; + + adapter->cycle_time = NSEC_PER_SEC; + + for (i = 0; i < adapter->num_tx_queues; i++) { + ring = adapter->tx_ring[i]; + ring->start_time = 0; + ring->end_time = NSEC_PER_SEC; + } + + return 0; +} + +static bool is_base_time_past(ktime_t base_time, const struct timespec64 *now) +{ + struct timespec64 b; + + b = ktime_to_timespec64(base_time); + + return timespec64_compare(now, &b) > 0; +} + +static bool validate_schedule(struct igc_adapter *adapter, + const struct tc_taprio_qopt_offload *qopt) +{ + int queue_uses[IGC_MAX_TX_QUEUES] = { }; + struct timespec64 now; + size_t n; + + if (qopt->cycle_time_extension) + return false; + + igc_ptp_read(adapter, &now); + + /* If we program the controller's BASET registers with a time + * in the future, it will hold all the packets until that + * time, causing a lot of TX Hangs, so to avoid that, we + * reject schedules that would start in the future. + */ + if (!is_base_time_past(qopt->base_time, &now)) + return false; + + for (n = 0; n < qopt->num_entries; n++) { + const struct tc_taprio_sched_entry *e; + int i; + + e = &qopt->entries[n]; + + /* i225 only supports "global" frame preemption + * settings. + */ + if (e->command != TC_TAPRIO_CMD_SET_GATES) + return false; + + for (i = 0; i < adapter->num_tx_queues; i++) { + if (e->gate_mask & BIT(i)) + queue_uses[i]++; + + if (queue_uses[i] > 1) + return false; + } + } + + return true; +} + +static int igc_tsn_enable_launchtime(struct igc_adapter *adapter, + struct tc_etf_qopt_offload *qopt) +{ + struct igc_hw *hw = &adapter->hw; + int err; + + if (hw->mac.type != igc_i225) + return -EOPNOTSUPP; + + err = igc_save_launchtime_params(adapter, qopt->queue, qopt->enable); + if (err) + return err; + + return igc_tsn_offload_apply(adapter); +} + +static int igc_save_qbv_schedule(struct igc_adapter *adapter, + struct tc_taprio_qopt_offload *qopt) +{ + u32 start_time = 0, end_time = 0; + size_t n; + + if (!qopt->enable) { + adapter->base_time = 0; + return 0; + } + + if (adapter->base_time) + return -EALREADY; + + if (!validate_schedule(adapter, qopt)) + return -EINVAL; + + adapter->cycle_time = qopt->cycle_time; + adapter->base_time = qopt->base_time; + + /* FIXME: be a little smarter about cases when the gate for a + * queue stays open for more than one entry. + */ + for (n = 0; n < qopt->num_entries; n++) { + struct tc_taprio_sched_entry *e = &qopt->entries[n]; + int i; + + end_time += e->interval; + + for (i = 0; i < adapter->num_tx_queues; i++) { + struct igc_ring *ring = adapter->tx_ring[i]; + + if (!(e->gate_mask & BIT(i))) + continue; + + ring->start_time = start_time; + ring->end_time = end_time; + } + + start_time += e->interval; + } + + return 0; +} + +static int igc_tsn_enable_qbv_scheduling(struct igc_adapter *adapter, + struct tc_taprio_qopt_offload *qopt) +{ + struct igc_hw *hw = &adapter->hw; + int err; + + if (hw->mac.type != igc_i225) + return -EOPNOTSUPP; + + err = igc_save_qbv_schedule(adapter, qopt); + if (err) + return err; + + return igc_tsn_offload_apply(adapter); +} + +static int igc_setup_tc(struct net_device *dev, enum tc_setup_type type, + void *type_data) +{ + struct igc_adapter *adapter = netdev_priv(dev); + + switch (type) { + case TC_SETUP_QDISC_TAPRIO: + return igc_tsn_enable_qbv_scheduling(adapter, type_data); + + case TC_SETUP_QDISC_ETF: + return igc_tsn_enable_launchtime(adapter, type_data); + + default: + return -EOPNOTSUPP; + } +} + +static const struct net_device_ops igc_netdev_ops = { + .ndo_open = igc_open, + .ndo_stop = igc_close, + .ndo_start_xmit = igc_xmit_frame, + .ndo_set_rx_mode = igc_set_rx_mode, + .ndo_set_mac_address = igc_set_mac, + .ndo_change_mtu = igc_change_mtu, + .ndo_get_stats64 = igc_get_stats64, + .ndo_fix_features = igc_fix_features, + .ndo_set_features = igc_set_features, + .ndo_features_check = igc_features_check, + .ndo_do_ioctl = igc_ioctl, + .ndo_setup_tc = igc_setup_tc, +}; + +/* PCIe configuration access */ +void igc_read_pci_cfg(struct igc_hw *hw, u32 reg, u16 *value) +{ + struct igc_adapter *adapter = hw->back; + + pci_read_config_word(adapter->pdev, reg, value); +} + +void igc_write_pci_cfg(struct igc_hw *hw, u32 reg, u16 *value) +{ + struct igc_adapter *adapter = hw->back; + + pci_write_config_word(adapter->pdev, reg, *value); +} + +s32 igc_read_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value) +{ + struct igc_adapter *adapter = hw->back; + + if (!pci_is_pcie(adapter->pdev)) + return -IGC_ERR_CONFIG; + + pcie_capability_read_word(adapter->pdev, reg, value); + + return IGC_SUCCESS; +} + +s32 igc_write_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value) +{ + struct igc_adapter *adapter = hw->back; + + if (!pci_is_pcie(adapter->pdev)) + return -IGC_ERR_CONFIG; + + pcie_capability_write_word(adapter->pdev, reg, *value); + + return IGC_SUCCESS; +} + +u32 igc_rd32(struct igc_hw *hw, u32 reg) +{ + struct igc_adapter *igc = container_of(hw, struct igc_adapter, hw); + u8 __iomem *hw_addr = READ_ONCE(hw->hw_addr); + u32 value = 0; + + value = readl(&hw_addr[reg]); + + /* reads should not return all F's */ + if (!(~value) && (!reg || !(~readl(hw_addr)))) { + struct net_device *netdev = igc->netdev; + + hw->hw_addr = NULL; + netif_device_detach(netdev); + netdev_err(netdev, "PCIe link lost, device now detached\n"); + WARN(pci_device_is_present(igc->pdev), + "igc: Failed to read reg 0x%x!\n", reg); + } + + return value; +} + +int igc_set_spd_dplx(struct igc_adapter *adapter, u32 spd, u8 dplx) +{ + struct igc_mac_info *mac = &adapter->hw.mac; + + mac->autoneg = 0; + + /* Make sure dplx is at most 1 bit and lsb of speed is not set + * for the switch() below to work + */ + if ((spd & 1) || (dplx & ~1)) + goto err_inval; + + switch (spd + dplx) { + case SPEED_10 + DUPLEX_HALF: + mac->forced_speed_duplex = ADVERTISE_10_HALF; + break; + case SPEED_10 + DUPLEX_FULL: + mac->forced_speed_duplex = ADVERTISE_10_FULL; + break; + case SPEED_100 + DUPLEX_HALF: + mac->forced_speed_duplex = ADVERTISE_100_HALF; + break; + case SPEED_100 + DUPLEX_FULL: + mac->forced_speed_duplex = ADVERTISE_100_FULL; + break; + case SPEED_1000 + DUPLEX_FULL: + mac->autoneg = 1; + adapter->hw.phy.autoneg_advertised = ADVERTISE_1000_FULL; + break; + case SPEED_1000 + DUPLEX_HALF: /* not supported */ + goto err_inval; + case SPEED_2500 + DUPLEX_FULL: + mac->autoneg = 1; + adapter->hw.phy.autoneg_advertised = ADVERTISE_2500_FULL; + break; + case SPEED_2500 + DUPLEX_HALF: /* not supported */ + default: + goto err_inval; + } + + /* clear MDI, MDI(-X) override is only allowed when autoneg enabled */ + adapter->hw.phy.mdix = AUTO_ALL_MODES; + + return 0; + +err_inval: + netdev_err(adapter->netdev, "Unsupported Speed/Duplex configuration\n"); + return -EINVAL; +} + +/** + * igc_probe - Device Initialization Routine + * @pdev: PCI device information struct + * @ent: entry in igc_pci_tbl + * + * Returns 0 on success, negative on failure + * + * igc_probe initializes an adapter identified by a pci_dev structure. + * The OS initialization, configuring the adapter private structure, + * and a hardware reset occur. + */ +static int igc_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct igc_adapter *adapter; + struct net_device *netdev; + struct igc_hw *hw; + const struct igc_info *ei = igc_info_tbl[ent->driver_data]; + int err, pci_using_dac; + + err = pci_enable_device_mem(pdev); + if (err) + return err; + + pci_using_dac = 0; + err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (!err) { + pci_using_dac = 1; + } else { + err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + if (err) { + dev_err(&pdev->dev, + "No usable DMA configuration, aborting\n"); + goto err_dma; + } + } + + err = pci_request_mem_regions(pdev, igc_driver_name); + if (err) + goto err_pci_reg; + + pci_enable_pcie_error_reporting(pdev); + + pci_set_master(pdev); + + err = -ENOMEM; + netdev = alloc_etherdev_mq(sizeof(struct igc_adapter), + IGC_MAX_TX_QUEUES); + + if (!netdev) + goto err_alloc_etherdev; + + SET_NETDEV_DEV(netdev, &pdev->dev); + + pci_set_drvdata(pdev, netdev); + adapter = netdev_priv(netdev); + adapter->netdev = netdev; + adapter->pdev = pdev; + hw = &adapter->hw; + hw->back = adapter; + adapter->port_num = hw->bus.func; + adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); + + err = pci_save_state(pdev); + if (err) + goto err_ioremap; + + err = -EIO; + adapter->io_addr = ioremap(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + if (!adapter->io_addr) + goto err_ioremap; + + /* hw->hw_addr can be zeroed, so use adapter->io_addr for unmap */ + hw->hw_addr = adapter->io_addr; + + netdev->netdev_ops = &igc_netdev_ops; + igc_ethtool_set_ops(netdev); + netdev->watchdog_timeo = 5 * HZ; + + netdev->mem_start = pci_resource_start(pdev, 0); + netdev->mem_end = pci_resource_end(pdev, 0); + + /* PCI config space info */ + hw->vendor_id = pdev->vendor; + hw->device_id = pdev->device; + hw->revision_id = pdev->revision; + hw->subsystem_vendor_id = pdev->subsystem_vendor; + hw->subsystem_device_id = pdev->subsystem_device; + + /* Copy the default MAC and PHY function pointers */ + memcpy(&hw->mac.ops, ei->mac_ops, sizeof(hw->mac.ops)); + memcpy(&hw->phy.ops, ei->phy_ops, sizeof(hw->phy.ops)); + + /* Initialize skew-specific constants */ + err = ei->get_invariants(hw); + if (err) + goto err_sw_init; + + /* Add supported features to the features list*/ + netdev->features |= NETIF_F_SG; + netdev->features |= NETIF_F_TSO; + netdev->features |= NETIF_F_TSO6; + netdev->features |= NETIF_F_TSO_ECN; + netdev->features |= NETIF_F_RXCSUM; + netdev->features |= NETIF_F_HW_CSUM; + netdev->features |= NETIF_F_SCTP_CRC; + netdev->features |= NETIF_F_HW_TC; + +#define IGC_GSO_PARTIAL_FEATURES (NETIF_F_GSO_GRE | \ + NETIF_F_GSO_GRE_CSUM | \ + NETIF_F_GSO_IPXIP4 | \ + NETIF_F_GSO_IPXIP6 | \ + NETIF_F_GSO_UDP_TUNNEL | \ + NETIF_F_GSO_UDP_TUNNEL_CSUM) + + netdev->gso_partial_features = IGC_GSO_PARTIAL_FEATURES; + netdev->features |= NETIF_F_GSO_PARTIAL | IGC_GSO_PARTIAL_FEATURES; + + /* setup the private structure */ + err = igc_sw_init(adapter); + if (err) + goto err_sw_init; + + /* copy netdev features into list of user selectable features */ + netdev->hw_features |= NETIF_F_NTUPLE; + netdev->hw_features |= netdev->features; + + if (pci_using_dac) + netdev->features |= NETIF_F_HIGHDMA; + + /* MTU range: 68 - 9216 */ + netdev->min_mtu = ETH_MIN_MTU; + netdev->max_mtu = MAX_STD_JUMBO_FRAME_SIZE; + + /* before reading the NVM, reset the controller to put the device in a + * known good starting state + */ + hw->mac.ops.reset_hw(hw); + + if (igc_get_flash_presence_i225(hw)) { + if (hw->nvm.ops.validate(hw) < 0) { + dev_err(&pdev->dev, "The NVM Checksum Is Not Valid\n"); + err = -EIO; + goto err_eeprom; + } + } + + if (eth_platform_get_mac_address(&pdev->dev, hw->mac.addr)) { + /* copy the MAC address out of the NVM */ + if (hw->mac.ops.read_mac_addr(hw)) + dev_err(&pdev->dev, "NVM Read Error\n"); + } + + memcpy(netdev->dev_addr, hw->mac.addr, netdev->addr_len); + + if (!is_valid_ether_addr(netdev->dev_addr)) { + dev_err(&pdev->dev, "Invalid MAC Address\n"); + err = -EIO; + goto err_eeprom; + } + + /* configure RXPBSIZE and TXPBSIZE */ + wr32(IGC_RXPBS, I225_RXPBSIZE_DEFAULT); + wr32(IGC_TXPBS, I225_TXPBSIZE_DEFAULT); + + timer_setup(&adapter->watchdog_timer, igc_watchdog, 0); + timer_setup(&adapter->phy_info_timer, igc_update_phy_info, 0); + + INIT_WORK(&adapter->reset_task, igc_reset_task); + INIT_WORK(&adapter->watchdog_task, igc_watchdog_task); + + /* Initialize link properties that are user-changeable */ + adapter->fc_autoneg = true; + hw->mac.autoneg = true; + hw->phy.autoneg_advertised = 0xaf; + + hw->fc.requested_mode = igc_fc_default; + hw->fc.current_mode = igc_fc_default; + + /* By default, support wake on port A */ + adapter->flags |= IGC_FLAG_WOL_SUPPORTED; + + /* initialize the wol settings based on the eeprom settings */ + if (adapter->flags & IGC_FLAG_WOL_SUPPORTED) + adapter->wol |= IGC_WUFC_MAG; + + device_set_wakeup_enable(&adapter->pdev->dev, + adapter->flags & IGC_FLAG_WOL_SUPPORTED); + + igc_ptp_init(adapter); + + /* reset the hardware with the new settings */ + igc_reset(adapter); + + /* let the f/w know that the h/w is now under the control of the + * driver. + */ + igc_get_hw_control(adapter); + + strncpy(netdev->name, "eth%d", IFNAMSIZ); + err = register_netdev(netdev); + if (err) + goto err_register; + + /* carrier off reporting is important to ethtool even BEFORE open */ + netif_carrier_off(netdev); + + /* Check if Media Autosense is enabled */ + adapter->ei = *ei; + + /* print pcie link status and MAC address */ + pcie_print_link_status(pdev); + netdev_info(netdev, "MAC: %pM\n", netdev->dev_addr); + + dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_NEVER_SKIP); + /* Disable EEE for internal PHY devices */ + hw->dev_spec._base.eee_enable = false; + adapter->flags &= ~IGC_FLAG_EEE; + igc_set_eee_i225(hw, false, false, false); + + pm_runtime_put_noidle(&pdev->dev); + + return 0; + +err_register: + igc_release_hw_control(adapter); +err_eeprom: + if (!igc_check_reset_block(hw)) + igc_reset_phy(hw); +err_sw_init: + igc_clear_interrupt_scheme(adapter); + iounmap(adapter->io_addr); +err_ioremap: + free_netdev(netdev); +err_alloc_etherdev: + pci_disable_pcie_error_reporting(pdev); + pci_release_mem_regions(pdev); +err_pci_reg: +err_dma: + pci_disable_device(pdev); + return err; +} + +/** + * igc_remove - Device Removal Routine + * @pdev: PCI device information struct + * + * igc_remove is called by the PCI subsystem to alert the driver + * that it should release a PCI device. This could be caused by a + * Hot-Plug event, or because the driver is going to be removed from + * memory. + */ +static void igc_remove(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct igc_adapter *adapter = netdev_priv(netdev); + + pm_runtime_get_noresume(&pdev->dev); + + igc_flush_nfc_rules(adapter); + + igc_ptp_stop(adapter); + + set_bit(__IGC_DOWN, &adapter->state); + + del_timer_sync(&adapter->watchdog_timer); + del_timer_sync(&adapter->phy_info_timer); + + cancel_work_sync(&adapter->reset_task); + cancel_work_sync(&adapter->watchdog_task); + + /* Release control of h/w to f/w. If f/w is AMT enabled, this + * would have already happened in close and is redundant. + */ + igc_release_hw_control(adapter); + unregister_netdev(netdev); + + igc_clear_interrupt_scheme(adapter); + pci_iounmap(pdev, adapter->io_addr); + pci_release_mem_regions(pdev); + + free_netdev(netdev); + + pci_disable_pcie_error_reporting(pdev); + + pci_disable_device(pdev); +} + +static int __igc_shutdown(struct pci_dev *pdev, bool *enable_wake, + bool runtime) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct igc_adapter *adapter = netdev_priv(netdev); + u32 wufc = runtime ? IGC_WUFC_LNKC : adapter->wol; + struct igc_hw *hw = &adapter->hw; + u32 ctrl, rctl, status; + bool wake; + + rtnl_lock(); + netif_device_detach(netdev); + + if (netif_running(netdev)) + __igc_close(netdev, true); + + igc_ptp_suspend(adapter); + + igc_clear_interrupt_scheme(adapter); + rtnl_unlock(); + + status = rd32(IGC_STATUS); + if (status & IGC_STATUS_LU) + wufc &= ~IGC_WUFC_LNKC; + + if (wufc) { + igc_setup_rctl(adapter); + igc_set_rx_mode(netdev); + + /* turn on all-multi mode if wake on multicast is enabled */ + if (wufc & IGC_WUFC_MC) { + rctl = rd32(IGC_RCTL); + rctl |= IGC_RCTL_MPE; + wr32(IGC_RCTL, rctl); + } + + ctrl = rd32(IGC_CTRL); + ctrl |= IGC_CTRL_ADVD3WUC; + wr32(IGC_CTRL, ctrl); + + /* Allow time for pending master requests to run */ + igc_disable_pcie_master(hw); + + wr32(IGC_WUC, IGC_WUC_PME_EN); + wr32(IGC_WUFC, wufc); + } else { + wr32(IGC_WUC, 0); + wr32(IGC_WUFC, 0); + } + + wake = wufc || adapter->en_mng_pt; + if (!wake) + igc_power_down_phy_copper_base(&adapter->hw); + else + igc_power_up_link(adapter); + + if (enable_wake) + *enable_wake = wake; + + /* Release control of h/w to f/w. If f/w is AMT enabled, this + * would have already happened in close and is redundant. + */ + igc_release_hw_control(adapter); + + pci_disable_device(pdev); + + return 0; +} + +#ifdef CONFIG_PM +static int __maybe_unused igc_runtime_suspend(struct device *dev) +{ + return __igc_shutdown(to_pci_dev(dev), NULL, 1); +} + +static void igc_deliver_wake_packet(struct net_device *netdev) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct igc_hw *hw = &adapter->hw; + struct sk_buff *skb; + u32 wupl; + + wupl = rd32(IGC_WUPL) & IGC_WUPL_MASK; + + /* WUPM stores only the first 128 bytes of the wake packet. + * Read the packet only if we have the whole thing. + */ + if (wupl == 0 || wupl > IGC_WUPM_BYTES) + return; + + skb = netdev_alloc_skb_ip_align(netdev, IGC_WUPM_BYTES); + if (!skb) + return; + + skb_put(skb, wupl); + + /* Ensure reads are 32-bit aligned */ + wupl = roundup(wupl, 4); + + memcpy_fromio(skb->data, hw->hw_addr + IGC_WUPM_REG(0), wupl); + + skb->protocol = eth_type_trans(skb, netdev); + netif_rx(skb); +} + +static int __maybe_unused igc_resume(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct net_device *netdev = pci_get_drvdata(pdev); + struct igc_adapter *adapter = netdev_priv(netdev); + struct igc_hw *hw = &adapter->hw; + u32 err, val; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + pci_save_state(pdev); + + if (!pci_device_is_present(pdev)) + return -ENODEV; + err = pci_enable_device_mem(pdev); + if (err) { + netdev_err(netdev, "Cannot enable PCI device from suspend\n"); + return err; + } + pci_set_master(pdev); + + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_enable_wake(pdev, PCI_D3cold, 0); + + if (igc_init_interrupt_scheme(adapter, true)) { + netdev_err(netdev, "Unable to allocate memory for queues\n"); + return -ENOMEM; + } + + igc_reset(adapter); + + /* let the f/w know that the h/w is now under the control of the + * driver. + */ + igc_get_hw_control(adapter); + + val = rd32(IGC_WUS); + if (val & WAKE_PKT_WUS) + igc_deliver_wake_packet(netdev); + + wr32(IGC_WUS, ~0); + + rtnl_lock(); + if (!err && netif_running(netdev)) + err = __igc_open(netdev, true); + + if (!err) + netif_device_attach(netdev); + rtnl_unlock(); + + return err; +} + +static int __maybe_unused igc_runtime_resume(struct device *dev) +{ + return igc_resume(dev); +} + +static int __maybe_unused igc_suspend(struct device *dev) +{ + return __igc_shutdown(to_pci_dev(dev), NULL, 0); +} + +static int __maybe_unused igc_runtime_idle(struct device *dev) +{ + struct net_device *netdev = dev_get_drvdata(dev); + struct igc_adapter *adapter = netdev_priv(netdev); + + if (!igc_has_link(adapter)) + pm_schedule_suspend(dev, MSEC_PER_SEC * 5); + + return -EBUSY; +} +#endif /* CONFIG_PM */ + +static void igc_shutdown(struct pci_dev *pdev) +{ + bool wake; + + __igc_shutdown(pdev, &wake, 0); + + if (system_state == SYSTEM_POWER_OFF) { + pci_wake_from_d3(pdev, wake); + pci_set_power_state(pdev, PCI_D3hot); + } +} + +/** + * igc_io_error_detected - called when PCI error is detected + * @pdev: Pointer to PCI device + * @state: The current PCI connection state + * + * This function is called after a PCI bus error affecting + * this device has been detected. + **/ +static pci_ers_result_t igc_io_error_detected(struct pci_dev *pdev, + pci_channel_state_t state) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct igc_adapter *adapter = netdev_priv(netdev); + + netif_device_detach(netdev); + + if (state == pci_channel_io_perm_failure) + return PCI_ERS_RESULT_DISCONNECT; + + if (netif_running(netdev)) + igc_down(adapter); + pci_disable_device(pdev); + + /* Request a slot reset. */ + return PCI_ERS_RESULT_NEED_RESET; +} + +/** + * igc_io_slot_reset - called after the PCI bus has been reset. + * @pdev: Pointer to PCI device + * + * Restart the card from scratch, as if from a cold-boot. Implementation + * resembles the first-half of the igc_resume routine. + **/ +static pci_ers_result_t igc_io_slot_reset(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct igc_adapter *adapter = netdev_priv(netdev); + struct igc_hw *hw = &adapter->hw; + pci_ers_result_t result; + + if (pci_enable_device_mem(pdev)) { + netdev_err(netdev, "Could not re-enable PCI device after reset\n"); + result = PCI_ERS_RESULT_DISCONNECT; + } else { + pci_set_master(pdev); + pci_restore_state(pdev); + pci_save_state(pdev); + + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_enable_wake(pdev, PCI_D3cold, 0); + + /* In case of PCI error, adapter loses its HW address + * so we should re-assign it here. + */ + hw->hw_addr = adapter->io_addr; + + igc_reset(adapter); + wr32(IGC_WUS, ~0); + result = PCI_ERS_RESULT_RECOVERED; + } + + return result; +} + +/** + * igc_io_resume - called when traffic can start to flow again. + * @pdev: Pointer to PCI device + * + * This callback is called when the error recovery driver tells us that + * its OK to resume normal operation. Implementation resembles the + * second-half of the igc_resume routine. + */ +static void igc_io_resume(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct igc_adapter *adapter = netdev_priv(netdev); + + rtnl_lock(); + if (netif_running(netdev)) { + if (igc_open(netdev)) { + netdev_err(netdev, "igc_open failed after reset\n"); + return; + } + } + + netif_device_attach(netdev); + + /* let the f/w know that the h/w is now under the control of the + * driver. + */ + igc_get_hw_control(adapter); + rtnl_unlock(); +} + +static const struct pci_error_handlers igc_err_handler = { + .error_detected = igc_io_error_detected, + .slot_reset = igc_io_slot_reset, + .resume = igc_io_resume, +}; + +#ifdef CONFIG_PM +static const struct dev_pm_ops igc_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(igc_suspend, igc_resume) + SET_RUNTIME_PM_OPS(igc_runtime_suspend, igc_runtime_resume, + igc_runtime_idle) +}; +#endif + +static struct pci_driver igc_driver = { + .name = igc_driver_name, + .id_table = igc_pci_tbl, + .probe = igc_probe, + .remove = igc_remove, +#ifdef CONFIG_PM + .driver.pm = &igc_pm_ops, +#endif + .shutdown = igc_shutdown, + .err_handler = &igc_err_handler, +}; + +/** + * igc_reinit_queues - return error + * @adapter: pointer to adapter structure + */ +int igc_reinit_queues(struct igc_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + int err = 0; + + if (netif_running(netdev)) + igc_close(netdev); + + igc_reset_interrupt_capability(adapter); + + if (igc_init_interrupt_scheme(adapter, true)) { + netdev_err(netdev, "Unable to allocate memory for queues\n"); + return -ENOMEM; + } + + if (netif_running(netdev)) + err = igc_open(netdev); + + return err; +} + +/** + * igc_get_hw_dev - return device + * @hw: pointer to hardware structure + * + * used by hardware layer to print debugging information + */ +struct net_device *igc_get_hw_dev(struct igc_hw *hw) +{ + struct igc_adapter *adapter = hw->back; + + return adapter->netdev; +} + +/** + * igc_init_module - Driver Registration Routine + * + * igc_init_module is the first routine called when the driver is + * loaded. All it does is register with the PCI subsystem. + */ +static int __init igc_init_module(void) +{ + int ret; + + pr_info("%s\n", igc_driver_string); + pr_info("%s\n", igc_copyright); + + ret = pci_register_driver(&igc_driver); + return ret; +} + +module_init(igc_init_module); + +/** + * igc_exit_module - Driver Exit Cleanup Routine + * + * igc_exit_module is called just before the driver is removed + * from memory. + */ +static void __exit igc_exit_module(void) +{ + pci_unregister_driver(&igc_driver); +} + +module_exit(igc_exit_module); +/* igc_main.c */ diff --git a/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_nvm.c b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_nvm.c new file mode 100644 index 00000000..58f81aba --- /dev/null +++ b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_nvm.c @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2018 Intel Corporation */ + +#include "igc_mac.h" +#include "igc_nvm.h" + +/** + * igc_poll_eerd_eewr_done - Poll for EEPROM read/write completion + * @hw: pointer to the HW structure + * @ee_reg: EEPROM flag for polling + * + * Polls the EEPROM status bit for either read or write completion based + * upon the value of 'ee_reg'. + */ +static s32 igc_poll_eerd_eewr_done(struct igc_hw *hw, int ee_reg) +{ + s32 ret_val = -IGC_ERR_NVM; + u32 attempts = 100000; + u32 i, reg = 0; + + for (i = 0; i < attempts; i++) { + if (ee_reg == IGC_NVM_POLL_READ) + reg = rd32(IGC_EERD); + else + reg = rd32(IGC_EEWR); + + if (reg & IGC_NVM_RW_REG_DONE) { + ret_val = 0; + break; + } + + udelay(5); + } + + return ret_val; +} + +/** + * igc_acquire_nvm - Generic request for access to EEPROM + * @hw: pointer to the HW structure + * + * Set the EEPROM access request bit and wait for EEPROM access grant bit. + * Return successful if access grant bit set, else clear the request for + * EEPROM access and return -IGC_ERR_NVM (-1). + */ +s32 igc_acquire_nvm(struct igc_hw *hw) +{ + s32 timeout = IGC_NVM_GRANT_ATTEMPTS; + u32 eecd = rd32(IGC_EECD); + s32 ret_val = 0; + + wr32(IGC_EECD, eecd | IGC_EECD_REQ); + eecd = rd32(IGC_EECD); + + while (timeout) { + if (eecd & IGC_EECD_GNT) + break; + udelay(5); + eecd = rd32(IGC_EECD); + timeout--; + } + + if (!timeout) { + eecd &= ~IGC_EECD_REQ; + wr32(IGC_EECD, eecd); + hw_dbg("Could not acquire NVM grant\n"); + ret_val = -IGC_ERR_NVM; + } + + return ret_val; +} + +/** + * igc_release_nvm - Release exclusive access to EEPROM + * @hw: pointer to the HW structure + * + * Stop any current commands to the EEPROM and clear the EEPROM request bit. + */ +void igc_release_nvm(struct igc_hw *hw) +{ + u32 eecd; + + eecd = rd32(IGC_EECD); + eecd &= ~IGC_EECD_REQ; + wr32(IGC_EECD, eecd); +} + +/** + * igc_read_nvm_eerd - Reads EEPROM using EERD register + * @hw: pointer to the HW structure + * @offset: offset of word in the EEPROM to read + * @words: number of words to read + * @data: word read from the EEPROM + * + * Reads a 16 bit word from the EEPROM using the EERD register. + */ +s32 igc_read_nvm_eerd(struct igc_hw *hw, u16 offset, u16 words, u16 *data) +{ + struct igc_nvm_info *nvm = &hw->nvm; + u32 i, eerd = 0; + s32 ret_val = 0; + + /* A check for invalid values: offset too large, too many words, + * and not enough words. + */ + if (offset >= nvm->word_size || (words > (nvm->word_size - offset)) || + words == 0) { + hw_dbg("nvm parameter(s) out of bounds\n"); + ret_val = -IGC_ERR_NVM; + goto out; + } + + for (i = 0; i < words; i++) { + eerd = ((offset + i) << IGC_NVM_RW_ADDR_SHIFT) + + IGC_NVM_RW_REG_START; + + wr32(IGC_EERD, eerd); + ret_val = igc_poll_eerd_eewr_done(hw, IGC_NVM_POLL_READ); + if (ret_val) + break; + + data[i] = (rd32(IGC_EERD) >> IGC_NVM_RW_REG_DATA); + } + +out: + return ret_val; +} + +/** + * igc_read_mac_addr - Read device MAC address + * @hw: pointer to the HW structure + */ +s32 igc_read_mac_addr(struct igc_hw *hw) +{ + u32 rar_high; + u32 rar_low; + u16 i; + + rar_high = rd32(IGC_RAH(0)); + rar_low = rd32(IGC_RAL(0)); + + for (i = 0; i < IGC_RAL_MAC_ADDR_LEN; i++) + hw->mac.perm_addr[i] = (u8)(rar_low >> (i * 8)); + + for (i = 0; i < IGC_RAH_MAC_ADDR_LEN; i++) + hw->mac.perm_addr[i + 4] = (u8)(rar_high >> (i * 8)); + + for (i = 0; i < ETH_ALEN; i++) + hw->mac.addr[i] = hw->mac.perm_addr[i]; + + return 0; +} + +/** + * igc_validate_nvm_checksum - Validate EEPROM checksum + * @hw: pointer to the HW structure + * + * Calculates the EEPROM checksum by reading/adding each word of the EEPROM + * and then verifies that the sum of the EEPROM is equal to 0xBABA. + */ +s32 igc_validate_nvm_checksum(struct igc_hw *hw) +{ + u16 checksum = 0; + u16 i, nvm_data; + s32 ret_val = 0; + + for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { + ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); + if (ret_val) { + hw_dbg("NVM Read Error\n"); + goto out; + } + checksum += nvm_data; + } + + if (checksum != (u16)NVM_SUM) { + hw_dbg("NVM Checksum Invalid\n"); + ret_val = -IGC_ERR_NVM; + goto out; + } + +out: + return ret_val; +} + +/** + * igc_update_nvm_checksum - Update EEPROM checksum + * @hw: pointer to the HW structure + * + * Updates the EEPROM checksum by reading/adding each word of the EEPROM + * up to the checksum. Then calculates the EEPROM checksum and writes the + * value to the EEPROM. + */ +s32 igc_update_nvm_checksum(struct igc_hw *hw) +{ + u16 checksum = 0; + u16 i, nvm_data; + s32 ret_val; + + for (i = 0; i < NVM_CHECKSUM_REG; i++) { + ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); + if (ret_val) { + hw_dbg("NVM Read Error while updating checksum.\n"); + goto out; + } + checksum += nvm_data; + } + checksum = (u16)NVM_SUM - checksum; + ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum); + if (ret_val) + hw_dbg("NVM Write Error while updating checksum.\n"); + +out: + return ret_val; +} diff --git a/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_nvm.h b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_nvm.h new file mode 100644 index 00000000..f9fc2e9c --- /dev/null +++ b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_nvm.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2018 Intel Corporation */ + +#ifndef _IGC_NVM_H_ +#define _IGC_NVM_H_ + +s32 igc_acquire_nvm(struct igc_hw *hw); +void igc_release_nvm(struct igc_hw *hw); +s32 igc_read_mac_addr(struct igc_hw *hw); +s32 igc_read_nvm_eerd(struct igc_hw *hw, u16 offset, u16 words, u16 *data); +s32 igc_validate_nvm_checksum(struct igc_hw *hw); +s32 igc_update_nvm_checksum(struct igc_hw *hw); + +#endif diff --git a/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_phy.c b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_phy.c new file mode 100644 index 00000000..3a103406 --- /dev/null +++ b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_phy.c @@ -0,0 +1,787 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2018 Intel Corporation */ + +#include "igc_phy.h" + +/** + * igc_check_reset_block - Check if PHY reset is blocked + * @hw: pointer to the HW structure + * + * Read the PHY management control register and check whether a PHY reset + * is blocked. If a reset is not blocked return 0, otherwise + * return IGC_ERR_BLK_PHY_RESET (12). + */ +s32 igc_check_reset_block(struct igc_hw *hw) +{ + u32 manc; + + manc = rd32(IGC_MANC); + + return (manc & IGC_MANC_BLK_PHY_RST_ON_IDE) ? + IGC_ERR_BLK_PHY_RESET : 0; +} + +/** + * igc_get_phy_id - Retrieve the PHY ID and revision + * @hw: pointer to the HW structure + * + * Reads the PHY registers and stores the PHY ID and possibly the PHY + * revision in the hardware structure. + */ +s32 igc_get_phy_id(struct igc_hw *hw) +{ + struct igc_phy_info *phy = &hw->phy; + s32 ret_val = 0; + u16 phy_id; + + ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id); + if (ret_val) + goto out; + + phy->id = (u32)(phy_id << 16); + usleep_range(200, 500); + ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id); + if (ret_val) + goto out; + + phy->id |= (u32)(phy_id & PHY_REVISION_MASK); + phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK); + +out: + return ret_val; +} + +/** + * igc_phy_has_link - Polls PHY for link + * @hw: pointer to the HW structure + * @iterations: number of times to poll for link + * @usec_interval: delay between polling attempts + * @success: pointer to whether polling was successful or not + * + * Polls the PHY status register for link, 'iterations' number of times. + */ +s32 igc_phy_has_link(struct igc_hw *hw, u32 iterations, + u32 usec_interval, bool *success) +{ + u16 i, phy_status; + s32 ret_val = 0; + + for (i = 0; i < iterations; i++) { + /* Some PHYs require the PHY_STATUS register to be read + * twice due to the link bit being sticky. No harm doing + * it across the board. + */ + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); + if (ret_val && usec_interval > 0) { + /* If the first read fails, another entity may have + * ownership of the resources, wait and try again to + * see if they have relinquished the resources yet. + */ + if (usec_interval >= 1000) + mdelay(usec_interval / 1000); + else + udelay(usec_interval); + } + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); + if (ret_val) + break; + if (phy_status & MII_SR_LINK_STATUS) + break; + if (usec_interval >= 1000) + mdelay(usec_interval / 1000); + else + udelay(usec_interval); + } + + *success = (i < iterations) ? true : false; + + return ret_val; +} + +/** + * igc_power_up_phy_copper - Restore copper link in case of PHY power down + * @hw: pointer to the HW structure + * + * In the case of a PHY power down to save power, or to turn off link during a + * driver unload, restore the link to previous settings. + */ +void igc_power_up_phy_copper(struct igc_hw *hw) +{ + u16 mii_reg = 0; + + /* The PHY will retain its settings across a power down/up cycle */ + hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); + mii_reg &= ~MII_CR_POWER_DOWN; + hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); +} + +/** + * igc_power_down_phy_copper - Power down copper PHY + * @hw: pointer to the HW structure + * + * Power down PHY to save power when interface is down and wake on lan + * is not enabled. + */ +void igc_power_down_phy_copper(struct igc_hw *hw) +{ + u16 mii_reg = 0; + + /* The PHY will retain its settings across a power down/up cycle */ + hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); + mii_reg |= MII_CR_POWER_DOWN; + + /* Temporary workaround - should be removed when PHY will implement + * IEEE registers as properly + */ + /* hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);*/ + usleep_range(1000, 2000); +} + +/** + * igc_check_downshift - Checks whether a downshift in speed occurred + * @hw: pointer to the HW structure + * + * Success returns 0, Failure returns 1 + * + * A downshift is detected by querying the PHY link health. + */ +s32 igc_check_downshift(struct igc_hw *hw) +{ + struct igc_phy_info *phy = &hw->phy; + s32 ret_val; + + switch (phy->type) { + case igc_phy_i225: + default: + /* speed downshift not supported */ + phy->speed_downgraded = false; + ret_val = 0; + } + + return ret_val; +} + +/** + * igc_phy_hw_reset - PHY hardware reset + * @hw: pointer to the HW structure + * + * Verify the reset block is not blocking us from resetting. Acquire + * semaphore (if necessary) and read/set/write the device control reset + * bit in the PHY. Wait the appropriate delay time for the device to + * reset and release the semaphore (if necessary). + */ +s32 igc_phy_hw_reset(struct igc_hw *hw) +{ + struct igc_phy_info *phy = &hw->phy; + u32 phpm = 0, timeout = 10000; + s32 ret_val; + u32 ctrl; + + ret_val = igc_check_reset_block(hw); + if (ret_val) { + ret_val = 0; + goto out; + } + + ret_val = phy->ops.acquire(hw); + if (ret_val) + goto out; + + phpm = rd32(IGC_I225_PHPM); + + ctrl = rd32(IGC_CTRL); + wr32(IGC_CTRL, ctrl | IGC_CTRL_PHY_RST); + wrfl(); + + udelay(phy->reset_delay_us); + + wr32(IGC_CTRL, ctrl); + wrfl(); + + /* SW should guarantee 100us for the completion of the PHY reset */ + usleep_range(100, 150); + do { + phpm = rd32(IGC_I225_PHPM); + timeout--; + udelay(1); + } while (!(phpm & IGC_PHY_RST_COMP) && timeout); + + if (!timeout) + hw_dbg("Timeout is expired after a phy reset\n"); + + usleep_range(100, 150); + + phy->ops.release(hw); + +out: + return ret_val; +} + +/** + * igc_phy_setup_autoneg - Configure PHY for auto-negotiation + * @hw: pointer to the HW structure + * + * Reads the MII auto-neg advertisement register and/or the 1000T control + * register and if the PHY is already setup for auto-negotiation, then + * return successful. Otherwise, setup advertisement and flow control to + * the appropriate values for the wanted auto-negotiation. + */ +static s32 igc_phy_setup_autoneg(struct igc_hw *hw) +{ + struct igc_phy_info *phy = &hw->phy; + u16 aneg_multigbt_an_ctrl = 0; + u16 mii_1000t_ctrl_reg = 0; + u16 mii_autoneg_adv_reg; + s32 ret_val; + + phy->autoneg_advertised &= phy->autoneg_mask; + + /* Read the MII Auto-Neg Advertisement Register (Address 4). */ + ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg); + if (ret_val) + return ret_val; + + if (phy->autoneg_mask & ADVERTISE_1000_FULL) { + /* Read the MII 1000Base-T Control Register (Address 9). */ + ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, + &mii_1000t_ctrl_reg); + if (ret_val) + return ret_val; + } + + if (phy->autoneg_mask & ADVERTISE_2500_FULL) { + /* Read the MULTI GBT AN Control Register - reg 7.32 */ + ret_val = phy->ops.read_reg(hw, (STANDARD_AN_REG_MASK << + MMD_DEVADDR_SHIFT) | + ANEG_MULTIGBT_AN_CTRL, + &aneg_multigbt_an_ctrl); + + if (ret_val) + return ret_val; + } + + /* Need to parse both autoneg_advertised and fc and set up + * the appropriate PHY registers. First we will parse for + * autoneg_advertised software override. Since we can advertise + * a plethora of combinations, we need to check each bit + * individually. + */ + + /* First we clear all the 10/100 mb speed bits in the Auto-Neg + * Advertisement Register (Address 4) and the 1000 mb speed bits in + * the 1000Base-T Control Register (Address 9). + */ + mii_autoneg_adv_reg &= ~(NWAY_AR_100TX_FD_CAPS | + NWAY_AR_100TX_HD_CAPS | + NWAY_AR_10T_FD_CAPS | + NWAY_AR_10T_HD_CAPS); + mii_1000t_ctrl_reg &= ~(CR_1000T_HD_CAPS | CR_1000T_FD_CAPS); + + hw_dbg("autoneg_advertised %x\n", phy->autoneg_advertised); + + /* Do we want to advertise 10 Mb Half Duplex? */ + if (phy->autoneg_advertised & ADVERTISE_10_HALF) { + hw_dbg("Advertise 10mb Half duplex\n"); + mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS; + } + + /* Do we want to advertise 10 Mb Full Duplex? */ + if (phy->autoneg_advertised & ADVERTISE_10_FULL) { + hw_dbg("Advertise 10mb Full duplex\n"); + mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS; + } + + /* Do we want to advertise 100 Mb Half Duplex? */ + if (phy->autoneg_advertised & ADVERTISE_100_HALF) { + hw_dbg("Advertise 100mb Half duplex\n"); + mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS; + } + + /* Do we want to advertise 100 Mb Full Duplex? */ + if (phy->autoneg_advertised & ADVERTISE_100_FULL) { + hw_dbg("Advertise 100mb Full duplex\n"); + mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS; + } + + /* We do not allow the Phy to advertise 1000 Mb Half Duplex */ + if (phy->autoneg_advertised & ADVERTISE_1000_HALF) + hw_dbg("Advertise 1000mb Half duplex request denied!\n"); + + /* Do we want to advertise 1000 Mb Full Duplex? */ + if (phy->autoneg_advertised & ADVERTISE_1000_FULL) { + hw_dbg("Advertise 1000mb Full duplex\n"); + mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS; + } + + /* We do not allow the Phy to advertise 2500 Mb Half Duplex */ + if (phy->autoneg_advertised & ADVERTISE_2500_HALF) + hw_dbg("Advertise 2500mb Half duplex request denied!\n"); + + /* Do we want to advertise 2500 Mb Full Duplex? */ + if (phy->autoneg_advertised & ADVERTISE_2500_FULL) { + hw_dbg("Advertise 2500mb Full duplex\n"); + aneg_multigbt_an_ctrl |= CR_2500T_FD_CAPS; + } else { + aneg_multigbt_an_ctrl &= ~CR_2500T_FD_CAPS; + } + + /* Check for a software override of the flow control settings, and + * setup the PHY advertisement registers accordingly. If + * auto-negotiation is enabled, then software will have to set the + * "PAUSE" bits to the correct value in the Auto-Negotiation + * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto- + * negotiation. + * + * The possible values of the "fc" parameter are: + * 0: Flow control is completely disabled + * 1: Rx flow control is enabled (we can receive pause frames + * but not send pause frames). + * 2: Tx flow control is enabled (we can send pause frames + * but we do not support receiving pause frames). + * 3: Both Rx and Tx flow control (symmetric) are enabled. + * other: No software override. The flow control configuration + * in the EEPROM is used. + */ + switch (hw->fc.current_mode) { + case igc_fc_none: + /* Flow control (Rx & Tx) is completely disabled by a + * software over-ride. + */ + mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); + break; + case igc_fc_rx_pause: + /* Rx Flow control is enabled, and Tx Flow control is + * disabled, by a software over-ride. + * + * Since there really isn't a way to advertise that we are + * capable of Rx Pause ONLY, we will advertise that we + * support both symmetric and asymmetric Rx PAUSE. Later + * (in igc_config_fc_after_link_up) we will disable the + * hw's ability to send PAUSE frames. + */ + mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); + break; + case igc_fc_tx_pause: + /* Tx Flow control is enabled, and Rx Flow control is + * disabled, by a software over-ride. + */ + mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR; + mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE; + break; + case igc_fc_full: + /* Flow control (both Rx and Tx) is enabled by a software + * over-ride. + */ + mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); + break; + default: + hw_dbg("Flow control param set incorrectly\n"); + return -IGC_ERR_CONFIG; + } + + ret_val = phy->ops.write_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg); + if (ret_val) + return ret_val; + + hw_dbg("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg); + + if (phy->autoneg_mask & ADVERTISE_1000_FULL) + ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, + mii_1000t_ctrl_reg); + + if (phy->autoneg_mask & ADVERTISE_2500_FULL) + ret_val = phy->ops.write_reg(hw, + (STANDARD_AN_REG_MASK << + MMD_DEVADDR_SHIFT) | + ANEG_MULTIGBT_AN_CTRL, + aneg_multigbt_an_ctrl); + + return ret_val; +} + +/** + * igc_wait_autoneg - Wait for auto-neg completion + * @hw: pointer to the HW structure + * + * Waits for auto-negotiation to complete or for the auto-negotiation time + * limit to expire, which ever happens first. + */ +static s32 igc_wait_autoneg(struct igc_hw *hw) +{ + u16 i, phy_status; + s32 ret_val = 0; + + /* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */ + for (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) { + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); + if (ret_val) + break; + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); + if (ret_val) + break; + if (phy_status & MII_SR_AUTONEG_COMPLETE) + break; + msleep(100); + } + + /* PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation + * has completed. + */ + return ret_val; +} + +/** + * igc_copper_link_autoneg - Setup/Enable autoneg for copper link + * @hw: pointer to the HW structure + * + * Performs initial bounds checking on autoneg advertisement parameter, then + * configure to advertise the full capability. Setup the PHY to autoneg + * and restart the negotiation process between the link partner. If + * autoneg_wait_to_complete, then wait for autoneg to complete before exiting. + */ +static s32 igc_copper_link_autoneg(struct igc_hw *hw) +{ + struct igc_phy_info *phy = &hw->phy; + u16 phy_ctrl; + s32 ret_val; + + /* Perform some bounds checking on the autoneg advertisement + * parameter. + */ + phy->autoneg_advertised &= phy->autoneg_mask; + + /* If autoneg_advertised is zero, we assume it was not defaulted + * by the calling code so we set to advertise full capability. + */ + if (phy->autoneg_advertised == 0) + phy->autoneg_advertised = phy->autoneg_mask; + + hw_dbg("Reconfiguring auto-neg advertisement params\n"); + ret_val = igc_phy_setup_autoneg(hw); + if (ret_val) { + hw_dbg("Error Setting up Auto-Negotiation\n"); + goto out; + } + hw_dbg("Restarting Auto-Neg\n"); + + /* Restart auto-negotiation by setting the Auto Neg Enable bit and + * the Auto Neg Restart bit in the PHY control register. + */ + ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl); + if (ret_val) + goto out; + + phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); + ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl); + if (ret_val) + goto out; + + /* Does the user want to wait for Auto-Neg to complete here, or + * check at a later time (for example, callback routine). + */ + if (phy->autoneg_wait_to_complete) { + ret_val = igc_wait_autoneg(hw); + if (ret_val) { + hw_dbg("Error while waiting for autoneg to complete\n"); + goto out; + } + } + + hw->mac.get_link_status = true; + +out: + return ret_val; +} + +/** + * igc_setup_copper_link - Configure copper link settings + * @hw: pointer to the HW structure + * + * Calls the appropriate function to configure the link for auto-neg or forced + * speed and duplex. Then we check for link, once link is established calls + * to configure collision distance and flow control are called. If link is + * not established, we return -IGC_ERR_PHY (-2). + */ +s32 igc_setup_copper_link(struct igc_hw *hw) +{ + s32 ret_val = 0; + bool link; + + if (hw->mac.autoneg) { + /* Setup autoneg and flow control advertisement and perform + * autonegotiation. + */ + ret_val = igc_copper_link_autoneg(hw); + if (ret_val) + goto out; + } else { + /* PHY will be set to 10H, 10F, 100H or 100F + * depending on user settings. + */ + hw_dbg("Forcing Speed and Duplex\n"); + ret_val = hw->phy.ops.force_speed_duplex(hw); + if (ret_val) { + hw_dbg("Error Forcing Speed and Duplex\n"); + goto out; + } + } + + /* Check link status. Wait up to 100 microseconds for link to become + * valid. + */ + ret_val = igc_phy_has_link(hw, COPPER_LINK_UP_LIMIT, 10, &link); + if (ret_val) + goto out; + + if (link) { + hw_dbg("Valid link established!!!\n"); + igc_config_collision_dist(hw); + ret_val = igc_config_fc_after_link_up(hw); + } else { + hw_dbg("Unable to establish link!!!\n"); + } + +out: + return ret_val; +} + +/** + * igc_read_phy_reg_mdic - Read MDI control register + * @hw: pointer to the HW structure + * @offset: register offset to be read + * @data: pointer to the read data + * + * Reads the MDI control register in the PHY at offset and stores the + * information read to data. + */ +static s32 igc_read_phy_reg_mdic(struct igc_hw *hw, u32 offset, u16 *data) +{ + struct igc_phy_info *phy = &hw->phy; + u32 i, mdic = 0; + s32 ret_val = 0; + + if (offset > MAX_PHY_REG_ADDRESS) { + hw_dbg("PHY Address %d is out of range\n", offset); + ret_val = -IGC_ERR_PARAM; + goto out; + } + + /* Set up Op-code, Phy Address, and register offset in the MDI + * Control register. The MAC will take care of interfacing with the + * PHY to retrieve the desired data. + */ + mdic = ((offset << IGC_MDIC_REG_SHIFT) | + (phy->addr << IGC_MDIC_PHY_SHIFT) | + (IGC_MDIC_OP_READ)); + + wr32(IGC_MDIC, mdic); + + /* Poll the ready bit to see if the MDI read completed + * Increasing the time out as testing showed failures with + * the lower time out + */ + for (i = 0; i < IGC_GEN_POLL_TIMEOUT; i++) { + udelay(50); + mdic = rd32(IGC_MDIC); + if (mdic & IGC_MDIC_READY) + break; + } + if (!(mdic & IGC_MDIC_READY)) { + hw_dbg("MDI Read did not complete\n"); + ret_val = -IGC_ERR_PHY; + goto out; + } + if (mdic & IGC_MDIC_ERROR) { + hw_dbg("MDI Error\n"); + ret_val = -IGC_ERR_PHY; + goto out; + } + *data = (u16)mdic; + +out: + return ret_val; +} + +/** + * igc_write_phy_reg_mdic - Write MDI control register + * @hw: pointer to the HW structure + * @offset: register offset to write to + * @data: data to write to register at offset + * + * Writes data to MDI control register in the PHY at offset. + */ +static s32 igc_write_phy_reg_mdic(struct igc_hw *hw, u32 offset, u16 data) +{ + struct igc_phy_info *phy = &hw->phy; + u32 i, mdic = 0; + s32 ret_val = 0; + + if (offset > MAX_PHY_REG_ADDRESS) { + hw_dbg("PHY Address %d is out of range\n", offset); + ret_val = -IGC_ERR_PARAM; + goto out; + } + + /* Set up Op-code, Phy Address, and register offset in the MDI + * Control register. The MAC will take care of interfacing with the + * PHY to write the desired data. + */ + mdic = (((u32)data) | + (offset << IGC_MDIC_REG_SHIFT) | + (phy->addr << IGC_MDIC_PHY_SHIFT) | + (IGC_MDIC_OP_WRITE)); + + wr32(IGC_MDIC, mdic); + + /* Poll the ready bit to see if the MDI read completed + * Increasing the time out as testing showed failures with + * the lower time out + */ + for (i = 0; i < IGC_GEN_POLL_TIMEOUT; i++) { + udelay(50); + mdic = rd32(IGC_MDIC); + if (mdic & IGC_MDIC_READY) + break; + } + if (!(mdic & IGC_MDIC_READY)) { + hw_dbg("MDI Write did not complete\n"); + ret_val = -IGC_ERR_PHY; + goto out; + } + if (mdic & IGC_MDIC_ERROR) { + hw_dbg("MDI Error\n"); + ret_val = -IGC_ERR_PHY; + goto out; + } + +out: + return ret_val; +} + +/** + * __igc_access_xmdio_reg - Read/write XMDIO register + * @hw: pointer to the HW structure + * @address: XMDIO address to program + * @dev_addr: device address to program + * @data: pointer to value to read/write from/to the XMDIO address + * @read: boolean flag to indicate read or write + */ +static s32 __igc_access_xmdio_reg(struct igc_hw *hw, u16 address, + u8 dev_addr, u16 *data, bool read) +{ + s32 ret_val; + + ret_val = hw->phy.ops.write_reg(hw, IGC_MMDAC, dev_addr); + if (ret_val) + return ret_val; + + ret_val = hw->phy.ops.write_reg(hw, IGC_MMDAAD, address); + if (ret_val) + return ret_val; + + ret_val = hw->phy.ops.write_reg(hw, IGC_MMDAC, IGC_MMDAC_FUNC_DATA | + dev_addr); + if (ret_val) + return ret_val; + + if (read) + ret_val = hw->phy.ops.read_reg(hw, IGC_MMDAAD, data); + else + ret_val = hw->phy.ops.write_reg(hw, IGC_MMDAAD, *data); + if (ret_val) + return ret_val; + + /* Recalibrate the device back to 0 */ + ret_val = hw->phy.ops.write_reg(hw, IGC_MMDAC, 0); + if (ret_val) + return ret_val; + + return ret_val; +} + +/** + * igc_read_xmdio_reg - Read XMDIO register + * @hw: pointer to the HW structure + * @addr: XMDIO address to program + * @dev_addr: device address to program + * @data: value to be read from the EMI address + */ +static s32 igc_read_xmdio_reg(struct igc_hw *hw, u16 addr, + u8 dev_addr, u16 *data) +{ + return __igc_access_xmdio_reg(hw, addr, dev_addr, data, true); +} + +/** + * igc_write_xmdio_reg - Write XMDIO register + * @hw: pointer to the HW structure + * @addr: XMDIO address to program + * @dev_addr: device address to program + * @data: value to be written to the XMDIO address + */ +static s32 igc_write_xmdio_reg(struct igc_hw *hw, u16 addr, + u8 dev_addr, u16 data) +{ + return __igc_access_xmdio_reg(hw, addr, dev_addr, &data, false); +} + +/** + * igc_write_phy_reg_gpy - Write GPY PHY register + * @hw: pointer to the HW structure + * @offset: register offset to write to + * @data: data to write at register offset + * + * Acquires semaphore, if necessary, then writes the data to PHY register + * at the offset. Release any acquired semaphores before exiting. + */ +s32 igc_write_phy_reg_gpy(struct igc_hw *hw, u32 offset, u16 data) +{ + u8 dev_addr = (offset & GPY_MMD_MASK) >> GPY_MMD_SHIFT; + s32 ret_val; + + offset = offset & GPY_REG_MASK; + + if (!dev_addr) { + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + return ret_val; + ret_val = igc_write_phy_reg_mdic(hw, offset, data); + hw->phy.ops.release(hw); + } else { + ret_val = igc_write_xmdio_reg(hw, (u16)offset, dev_addr, + data); + } + + return ret_val; +} + +/** + * igc_read_phy_reg_gpy - Read GPY PHY register + * @hw: pointer to the HW structure + * @offset: lower half is register offset to read to + * upper half is MMD to use. + * @data: data to read at register offset + * + * Acquires semaphore, if necessary, then reads the data in the PHY register + * at the offset. Release any acquired semaphores before exiting. + */ +s32 igc_read_phy_reg_gpy(struct igc_hw *hw, u32 offset, u16 *data) +{ + u8 dev_addr = (offset & GPY_MMD_MASK) >> GPY_MMD_SHIFT; + s32 ret_val; + + offset = offset & GPY_REG_MASK; + + if (!dev_addr) { + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + return ret_val; + ret_val = igc_read_phy_reg_mdic(hw, offset, data); + hw->phy.ops.release(hw); + } else { + ret_val = igc_read_xmdio_reg(hw, (u16)offset, dev_addr, + data); + } + + return ret_val; +} diff --git a/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_phy.h b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_phy.h new file mode 100644 index 00000000..25cba33d --- /dev/null +++ b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_phy.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2018 Intel Corporation */ + +#ifndef _IGC_PHY_H_ +#define _IGC_PHY_H_ + +#include "igc_mac.h" + +s32 igc_check_reset_block(struct igc_hw *hw); +s32 igc_phy_hw_reset(struct igc_hw *hw); +s32 igc_get_phy_id(struct igc_hw *hw); +s32 igc_phy_has_link(struct igc_hw *hw, u32 iterations, + u32 usec_interval, bool *success); +s32 igc_check_downshift(struct igc_hw *hw); +s32 igc_setup_copper_link(struct igc_hw *hw); +void igc_power_up_phy_copper(struct igc_hw *hw); +void igc_power_down_phy_copper(struct igc_hw *hw); +s32 igc_write_phy_reg_gpy(struct igc_hw *hw, u32 offset, u16 data); +s32 igc_read_phy_reg_gpy(struct igc_hw *hw, u32 offset, u16 *data); + +#endif diff --git a/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_ptp.c b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_ptp.c new file mode 100644 index 00000000..4ab46eee --- /dev/null +++ b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_ptp.c @@ -0,0 +1,620 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2019 Intel Corporation */ + +#include "igc.h" + +#include +#include +#include +#include +#include +#include + +#define INCVALUE_MASK 0x7fffffff +#define ISGN 0x80000000 + +#define IGC_SYSTIM_OVERFLOW_PERIOD (HZ * 60 * 9) +#define IGC_PTP_TX_TIMEOUT (HZ * 15) + +/* SYSTIM read access for I225 */ +void igc_ptp_read(struct igc_adapter *adapter, struct timespec64 *ts) +{ + struct igc_hw *hw = &adapter->hw; + u32 sec, nsec; + + /* The timestamp is latched when SYSTIML is read. */ + nsec = rd32(IGC_SYSTIML); + sec = rd32(IGC_SYSTIMH); + + ts->tv_sec = sec; + ts->tv_nsec = nsec; +} + +static void igc_ptp_write_i225(struct igc_adapter *adapter, + const struct timespec64 *ts) +{ + struct igc_hw *hw = &adapter->hw; + + wr32(IGC_SYSTIML, ts->tv_nsec); + wr32(IGC_SYSTIMH, ts->tv_sec); +} + +static int igc_ptp_adjfine_i225(struct ptp_clock_info *ptp, long scaled_ppm) +{ + struct igc_adapter *igc = container_of(ptp, struct igc_adapter, + ptp_caps); + struct igc_hw *hw = &igc->hw; + int neg_adj = 0; + u64 rate; + u32 inca; + + if (scaled_ppm < 0) { + neg_adj = 1; + scaled_ppm = -scaled_ppm; + } + rate = scaled_ppm; + rate <<= 14; + rate = div_u64(rate, 78125); + + inca = rate & INCVALUE_MASK; + if (neg_adj) + inca |= ISGN; + + wr32(IGC_TIMINCA, inca); + + return 0; +} + +static int igc_ptp_adjtime_i225(struct ptp_clock_info *ptp, s64 delta) +{ + struct igc_adapter *igc = container_of(ptp, struct igc_adapter, + ptp_caps); + struct timespec64 now, then = ns_to_timespec64(delta); + unsigned long flags; + + spin_lock_irqsave(&igc->tmreg_lock, flags); + + igc_ptp_read(igc, &now); + now = timespec64_add(now, then); + igc_ptp_write_i225(igc, (const struct timespec64 *)&now); + + spin_unlock_irqrestore(&igc->tmreg_lock, flags); + + return 0; +} + +static int igc_ptp_gettimex64_i225(struct ptp_clock_info *ptp, + struct timespec64 *ts, + struct ptp_system_timestamp *sts) +{ + struct igc_adapter *igc = container_of(ptp, struct igc_adapter, + ptp_caps); + struct igc_hw *hw = &igc->hw; + unsigned long flags; + + spin_lock_irqsave(&igc->tmreg_lock, flags); + + ptp_read_system_prets(sts); + ts->tv_nsec = rd32(IGC_SYSTIML); + ts->tv_sec = rd32(IGC_SYSTIMH); + ptp_read_system_postts(sts); + + spin_unlock_irqrestore(&igc->tmreg_lock, flags); + + return 0; +} + +static int igc_ptp_settime_i225(struct ptp_clock_info *ptp, + const struct timespec64 *ts) +{ + struct igc_adapter *igc = container_of(ptp, struct igc_adapter, + ptp_caps); + unsigned long flags; + + spin_lock_irqsave(&igc->tmreg_lock, flags); + + igc_ptp_write_i225(igc, ts); + + spin_unlock_irqrestore(&igc->tmreg_lock, flags); + + return 0; +} + +static int igc_ptp_feature_enable_i225(struct ptp_clock_info *ptp, + struct ptp_clock_request *rq, int on) +{ + return -EOPNOTSUPP; +} + +/** + * igc_ptp_systim_to_hwtstamp - convert system time value to HW timestamp + * @adapter: board private structure + * @hwtstamps: timestamp structure to update + * @systim: unsigned 64bit system time value + * + * We need to convert the system time value stored in the RX/TXSTMP registers + * into a hwtstamp which can be used by the upper level timestamping functions. + **/ +static void igc_ptp_systim_to_hwtstamp(struct igc_adapter *adapter, + struct skb_shared_hwtstamps *hwtstamps, + u64 systim) +{ + switch (adapter->hw.mac.type) { + case igc_i225: + memset(hwtstamps, 0, sizeof(*hwtstamps)); + /* Upper 32 bits contain s, lower 32 bits contain ns. */ + hwtstamps->hwtstamp = ktime_set(systim >> 32, + systim & 0xFFFFFFFF); + break; + default: + break; + } +} + +/** + * igc_ptp_rx_pktstamp - Retrieve timestamp from Rx packet buffer + * @q_vector: Pointer to interrupt specific structure + * @va: Pointer to address containing Rx buffer + * @skb: Buffer containing timestamp and packet + * + * This function retrieves the timestamp saved in the beginning of packet + * buffer. While two timestamps are available, one in timer0 reference and the + * other in timer1 reference, this function considers only the timestamp in + * timer0 reference. + */ +void igc_ptp_rx_pktstamp(struct igc_q_vector *q_vector, __le32 *va, + struct sk_buff *skb) +{ + struct igc_adapter *adapter = q_vector->adapter; + u64 regval; + int adjust; + + /* Timestamps are saved in little endian at the beginning of the packet + * buffer following the layout: + * + * DWORD: | 0 | 1 | 2 | 3 | + * Field: | Timer1 SYSTIML | Timer1 SYSTIMH | Timer0 SYSTIML | Timer0 SYSTIMH | + * + * SYSTIML holds the nanoseconds part while SYSTIMH holds the seconds + * part of the timestamp. + */ + regval = le32_to_cpu(va[2]); + regval |= (u64)le32_to_cpu(va[3]) << 32; + igc_ptp_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval); + + /* Adjust timestamp for the RX latency based on link speed */ + switch (adapter->link_speed) { + case SPEED_10: + adjust = IGC_I225_RX_LATENCY_10; + break; + case SPEED_100: + adjust = IGC_I225_RX_LATENCY_100; + break; + case SPEED_1000: + adjust = IGC_I225_RX_LATENCY_1000; + break; + case SPEED_2500: + adjust = IGC_I225_RX_LATENCY_2500; + break; + default: + adjust = 0; + netdev_warn_once(adapter->netdev, "Imprecise timestamp\n"); + break; + } + skb_hwtstamps(skb)->hwtstamp = + ktime_sub_ns(skb_hwtstamps(skb)->hwtstamp, adjust); +} + +static void igc_ptp_disable_rx_timestamp(struct igc_adapter *adapter) +{ + struct igc_hw *hw = &adapter->hw; + u32 val; + int i; + + wr32(IGC_TSYNCRXCTL, 0); + + for (i = 0; i < adapter->num_rx_queues; i++) { + val = rd32(IGC_SRRCTL(i)); + val &= ~IGC_SRRCTL_TIMESTAMP; + wr32(IGC_SRRCTL(i), val); + } + + val = rd32(IGC_RXPBS); + val &= ~IGC_RXPBS_CFG_TS_EN; + wr32(IGC_RXPBS, val); +} + +static void igc_ptp_enable_rx_timestamp(struct igc_adapter *adapter) +{ + struct igc_hw *hw = &adapter->hw; + u32 val; + int i; + + val = rd32(IGC_RXPBS); + val |= IGC_RXPBS_CFG_TS_EN; + wr32(IGC_RXPBS, val); + + for (i = 0; i < adapter->num_rx_queues; i++) { + val = rd32(IGC_SRRCTL(i)); + /* FIXME: For now, only support retrieving RX timestamps from + * timer 0. + */ + val |= IGC_SRRCTL_TIMER1SEL(0) | IGC_SRRCTL_TIMER0SEL(0) | + IGC_SRRCTL_TIMESTAMP; + wr32(IGC_SRRCTL(i), val); + } + + val = IGC_TSYNCRXCTL_ENABLED | IGC_TSYNCRXCTL_TYPE_ALL | + IGC_TSYNCRXCTL_RXSYNSIG; + wr32(IGC_TSYNCRXCTL, val); +} + +static void igc_ptp_disable_tx_timestamp(struct igc_adapter *adapter) +{ + struct igc_hw *hw = &adapter->hw; + + wr32(IGC_TSYNCTXCTL, 0); +} + +static void igc_ptp_enable_tx_timestamp(struct igc_adapter *adapter) +{ + struct igc_hw *hw = &adapter->hw; + + wr32(IGC_TSYNCTXCTL, IGC_TSYNCTXCTL_ENABLED | IGC_TSYNCTXCTL_TXSYNSIG); + + /* Read TXSTMP registers to discard any timestamp previously stored. */ + rd32(IGC_TXSTMPL); + rd32(IGC_TXSTMPH); +} + +/** + * igc_ptp_set_timestamp_mode - setup hardware for timestamping + * @adapter: networking device structure + * @config: hwtstamp configuration + * + * Return: 0 in case of success, negative errno code otherwise. + */ +static int igc_ptp_set_timestamp_mode(struct igc_adapter *adapter, + struct hwtstamp_config *config) +{ + /* reserved for future extensions */ + if (config->flags) + return -EINVAL; + + switch (config->tx_type) { + case HWTSTAMP_TX_OFF: + igc_ptp_disable_tx_timestamp(adapter); + break; + case HWTSTAMP_TX_ON: + igc_ptp_enable_tx_timestamp(adapter); + break; + default: + return -ERANGE; + } + + switch (config->rx_filter) { + case HWTSTAMP_FILTER_NONE: + igc_ptp_disable_rx_timestamp(adapter); + break; + case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: + case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V2_SYNC: + case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: + case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: + case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: + case HWTSTAMP_FILTER_NTP_ALL: + case HWTSTAMP_FILTER_ALL: + igc_ptp_enable_rx_timestamp(adapter); + config->rx_filter = HWTSTAMP_FILTER_ALL; + break; + default: + return -ERANGE; + } + + return 0; +} + +static void igc_ptp_tx_timeout(struct igc_adapter *adapter) +{ + struct igc_hw *hw = &adapter->hw; + + dev_kfree_skb_any(adapter->ptp_tx_skb); + adapter->ptp_tx_skb = NULL; + adapter->tx_hwtstamp_timeouts++; + clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state); + /* Clear the tx valid bit in TSYNCTXCTL register to enable interrupt. */ + rd32(IGC_TXSTMPH); + netdev_warn(adapter->netdev, "Tx timestamp timeout\n"); +} + +void igc_ptp_tx_hang(struct igc_adapter *adapter) +{ + bool timeout = time_is_before_jiffies(adapter->ptp_tx_start + + IGC_PTP_TX_TIMEOUT); + + if (!test_bit(__IGC_PTP_TX_IN_PROGRESS, &adapter->state)) + return; + + /* If we haven't received a timestamp within the timeout, it is + * reasonable to assume that it will never occur, so we can unlock the + * timestamp bit when this occurs. + */ + if (timeout) { + cancel_work_sync(&adapter->ptp_tx_work); + igc_ptp_tx_timeout(adapter); + } +} + +/** + * igc_ptp_tx_hwtstamp - utility function which checks for TX time stamp + * @adapter: Board private structure + * + * If we were asked to do hardware stamping and such a time stamp is + * available, then it must have been for this skb here because we only + * allow only one such packet into the queue. + */ +static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter) +{ + struct sk_buff *skb = adapter->ptp_tx_skb; + struct skb_shared_hwtstamps shhwtstamps; + struct igc_hw *hw = &adapter->hw; + int adjust = 0; + u64 regval; + + if (WARN_ON_ONCE(!skb)) + return; + + regval = rd32(IGC_TXSTMPL); + regval |= (u64)rd32(IGC_TXSTMPH) << 32; + igc_ptp_systim_to_hwtstamp(adapter, &shhwtstamps, regval); + + switch (adapter->link_speed) { + case SPEED_10: + adjust = IGC_I225_TX_LATENCY_10; + break; + case SPEED_100: + adjust = IGC_I225_TX_LATENCY_100; + break; + case SPEED_1000: + adjust = IGC_I225_TX_LATENCY_1000; + break; + case SPEED_2500: + adjust = IGC_I225_TX_LATENCY_2500; + break; + } + + shhwtstamps.hwtstamp = + ktime_add_ns(shhwtstamps.hwtstamp, adjust); + + /* Clear the lock early before calling skb_tstamp_tx so that + * applications are not woken up before the lock bit is clear. We use + * a copy of the skb pointer to ensure other threads can't change it + * while we're notifying the stack. + */ + adapter->ptp_tx_skb = NULL; + clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state); + + /* Notify the stack and free the skb after we've unlocked */ + skb_tstamp_tx(skb, &shhwtstamps); + dev_kfree_skb_any(skb); +} + +/** + * igc_ptp_tx_work + * @work: pointer to work struct + * + * This work function polls the TSYNCTXCTL valid bit to determine when a + * timestamp has been taken for the current stored skb. + */ +static void igc_ptp_tx_work(struct work_struct *work) +{ + struct igc_adapter *adapter = container_of(work, struct igc_adapter, + ptp_tx_work); + struct igc_hw *hw = &adapter->hw; + u32 tsynctxctl; + + if (!test_bit(__IGC_PTP_TX_IN_PROGRESS, &adapter->state)) + return; + + tsynctxctl = rd32(IGC_TSYNCTXCTL); + if (WARN_ON_ONCE(!(tsynctxctl & IGC_TSYNCTXCTL_TXTT_0))) + return; + + igc_ptp_tx_hwtstamp(adapter); +} + +/** + * igc_ptp_set_ts_config - set hardware time stamping config + * @netdev: network interface device structure + * @ifr: interface request data + * + **/ +int igc_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct hwtstamp_config config; + int err; + + if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) + return -EFAULT; + + err = igc_ptp_set_timestamp_mode(adapter, &config); + if (err) + return err; + + /* save these settings for future reference */ + memcpy(&adapter->tstamp_config, &config, + sizeof(adapter->tstamp_config)); + + return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? + -EFAULT : 0; +} + +/** + * igc_ptp_get_ts_config - get hardware time stamping config + * @netdev: network interface device structure + * @ifr: interface request data + * + * Get the hwtstamp_config settings to return to the user. Rather than attempt + * to deconstruct the settings from the registers, just return a shadow copy + * of the last known settings. + **/ +int igc_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct hwtstamp_config *config = &adapter->tstamp_config; + + return copy_to_user(ifr->ifr_data, config, sizeof(*config)) ? + -EFAULT : 0; +} + +/** + * igc_ptp_init - Initialize PTP functionality + * @adapter: Board private structure + * + * This function is called at device probe to initialize the PTP + * functionality. + */ +void igc_ptp_init(struct igc_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + struct igc_hw *hw = &adapter->hw; + + switch (hw->mac.type) { + case igc_i225: + snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr); + adapter->ptp_caps.owner = THIS_MODULE; + adapter->ptp_caps.max_adj = 62499999; + adapter->ptp_caps.adjfine = igc_ptp_adjfine_i225; + adapter->ptp_caps.adjtime = igc_ptp_adjtime_i225; + adapter->ptp_caps.gettimex64 = igc_ptp_gettimex64_i225; + adapter->ptp_caps.settime64 = igc_ptp_settime_i225; + adapter->ptp_caps.enable = igc_ptp_feature_enable_i225; + break; + default: + adapter->ptp_clock = NULL; + return; + } + + spin_lock_init(&adapter->tmreg_lock); + INIT_WORK(&adapter->ptp_tx_work, igc_ptp_tx_work); + + adapter->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE; + adapter->tstamp_config.tx_type = HWTSTAMP_TX_OFF; + + adapter->prev_ptp_time = ktime_to_timespec64(ktime_get_real()); + adapter->ptp_reset_start = ktime_get(); + + adapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps, + &adapter->pdev->dev); + if (IS_ERR(adapter->ptp_clock)) { + adapter->ptp_clock = NULL; + netdev_err(netdev, "ptp_clock_register failed\n"); + } else if (adapter->ptp_clock) { + netdev_info(netdev, "PHC added\n"); + adapter->ptp_flags |= IGC_PTP_ENABLED; + } +} + +static void igc_ptp_time_save(struct igc_adapter *adapter) +{ + igc_ptp_read(adapter, &adapter->prev_ptp_time); + adapter->ptp_reset_start = ktime_get(); +} + +static void igc_ptp_time_restore(struct igc_adapter *adapter) +{ + struct timespec64 ts = adapter->prev_ptp_time; + ktime_t delta; + + delta = ktime_sub(ktime_get(), adapter->ptp_reset_start); + + timespec64_add_ns(&ts, ktime_to_ns(delta)); + + igc_ptp_write_i225(adapter, &ts); +} + +/** + * igc_ptp_suspend - Disable PTP work items and prepare for suspend + * @adapter: Board private structure + * + * This function stops the overflow check work and PTP Tx timestamp work, and + * will prepare the device for OS suspend. + */ +void igc_ptp_suspend(struct igc_adapter *adapter) +{ + if (!(adapter->ptp_flags & IGC_PTP_ENABLED)) + return; + + cancel_work_sync(&adapter->ptp_tx_work); + dev_kfree_skb_any(adapter->ptp_tx_skb); + adapter->ptp_tx_skb = NULL; + clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state); + + if (pci_device_is_present(adapter->pdev)) + igc_ptp_time_save(adapter); +} + +/** + * igc_ptp_stop - Disable PTP device and stop the overflow check. + * @adapter: Board private structure. + * + * This function stops the PTP support and cancels the delayed work. + **/ +void igc_ptp_stop(struct igc_adapter *adapter) +{ + igc_ptp_suspend(adapter); + + if (adapter->ptp_clock) { + ptp_clock_unregister(adapter->ptp_clock); + netdev_info(adapter->netdev, "PHC removed\n"); + adapter->ptp_flags &= ~IGC_PTP_ENABLED; + } +} + +/** + * igc_ptp_reset - Re-enable the adapter for PTP following a reset. + * @adapter: Board private structure. + * + * This function handles the reset work required to re-enable the PTP device. + **/ +void igc_ptp_reset(struct igc_adapter *adapter) +{ + struct igc_hw *hw = &adapter->hw; + unsigned long flags; + + /* reset the tstamp_config */ + igc_ptp_set_timestamp_mode(adapter, &adapter->tstamp_config); + + spin_lock_irqsave(&adapter->tmreg_lock, flags); + + switch (adapter->hw.mac.type) { + case igc_i225: + wr32(IGC_TSAUXC, 0x0); + wr32(IGC_TSSDP, 0x0); + wr32(IGC_TSIM, IGC_TSICR_INTERRUPTS); + wr32(IGC_IMS, IGC_IMS_TS); + break; + default: + /* No work to do. */ + goto out; + } + + /* Re-initialize the timer. */ + if (hw->mac.type == igc_i225) { + igc_ptp_time_restore(adapter); + } else { + timecounter_init(&adapter->tc, &adapter->cc, + ktime_to_ns(ktime_get_real())); + } +out: + spin_unlock_irqrestore(&adapter->tmreg_lock, flags); + + wrfl(); +} diff --git a/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_regs.h b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_regs.h new file mode 100644 index 00000000..9f5fc1d4 --- /dev/null +++ b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_regs.h @@ -0,0 +1,269 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2018 Intel Corporation */ + +#ifndef _IGC_REGS_H_ +#define _IGC_REGS_H_ + +/* General Register Descriptions */ +#define IGC_CTRL 0x00000 /* Device Control - RW */ +#define IGC_STATUS 0x00008 /* Device Status - RO */ +#define IGC_EECD 0x00010 /* EEPROM/Flash Control - RW */ +#define IGC_CTRL_EXT 0x00018 /* Extended Device Control - RW */ +#define IGC_MDIC 0x00020 /* MDI Control - RW */ +#define IGC_MDICNFG 0x00E04 /* MDC/MDIO Configuration - RW */ +#define IGC_CONNSW 0x00034 /* Copper/Fiber switch control - RW */ +#define IGC_I225_PHPM 0x00E14 /* I225 PHY Power Management */ + +/* Internal Packet Buffer Size Registers */ +#define IGC_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */ +#define IGC_TXPBS 0x03404 /* Tx Packet Buffer Size - RW */ + +/* NVM Register Descriptions */ +#define IGC_EERD 0x12014 /* EEprom mode read - RW */ +#define IGC_EEWR 0x12018 /* EEprom mode write - RW */ + +/* Flow Control Register Descriptions */ +#define IGC_FCAL 0x00028 /* FC Address Low - RW */ +#define IGC_FCAH 0x0002C /* FC Address High - RW */ +#define IGC_FCT 0x00030 /* FC Type - RW */ +#define IGC_FCTTV 0x00170 /* FC Transmit Timer - RW */ +#define IGC_FCRTL 0x02160 /* FC Receive Threshold Low - RW */ +#define IGC_FCRTH 0x02168 /* FC Receive Threshold High - RW */ +#define IGC_FCRTV 0x02460 /* FC Refresh Timer Value - RW */ + +/* Semaphore registers */ +#define IGC_SW_FW_SYNC 0x05B5C /* SW-FW Synchronization - RW */ +#define IGC_SWSM 0x05B50 /* SW Semaphore */ +#define IGC_FWSM 0x05B54 /* FW Semaphore */ + +/* Function Active and Power State to MNG */ +#define IGC_FACTPS 0x05B30 + +/* Interrupt Register Description */ +#define IGC_EICR 0x01580 /* Ext. Interrupt Cause read - W0 */ +#define IGC_EICS 0x01520 /* Ext. Interrupt Cause Set - W0 */ +#define IGC_EIMS 0x01524 /* Ext. Interrupt Mask Set/Read - RW */ +#define IGC_EIMC 0x01528 /* Ext. Interrupt Mask Clear - WO */ +#define IGC_EIAC 0x0152C /* Ext. Interrupt Auto Clear - RW */ +#define IGC_EIAM 0x01530 /* Ext. Interrupt Auto Mask - RW */ +#define IGC_ICR 0x01500 /* Intr Cause Read - RC/W1C */ +#define IGC_ICS 0x01504 /* Intr Cause Set - WO */ +#define IGC_IMS 0x01508 /* Intr Mask Set/Read - RW */ +#define IGC_IMC 0x0150C /* Intr Mask Clear - WO */ +#define IGC_IAM 0x01510 /* Intr Ack Auto Mask- RW */ +/* Intr Throttle - RW */ +#define IGC_EITR(_n) (0x01680 + (0x4 * (_n))) +/* Interrupt Vector Allocation - RW */ +#define IGC_IVAR0 0x01700 +#define IGC_IVAR_MISC 0x01740 /* IVAR for "other" causes - RW */ +#define IGC_GPIE 0x01514 /* General Purpose Intr Enable - RW */ + +/* MSI-X Table Register Descriptions */ +#define IGC_PBACL 0x05B68 /* MSIx PBA Clear - R/W 1 to clear */ + +/* RSS registers */ +#define IGC_MRQC 0x05818 /* Multiple Receive Control - RW */ + +/* Filtering Registers */ +#define IGC_ETQF(_n) (0x05CB0 + (4 * (_n))) /* EType Queue Fltr */ + +/* ETQF register bit definitions */ +#define IGC_ETQF_FILTER_ENABLE BIT(26) +#define IGC_ETQF_QUEUE_ENABLE BIT(31) +#define IGC_ETQF_QUEUE_SHIFT 16 +#define IGC_ETQF_QUEUE_MASK 0x00070000 +#define IGC_ETQF_ETYPE_MASK 0x0000FFFF + +/* Redirection Table - RW Array */ +#define IGC_RETA(_i) (0x05C00 + ((_i) * 4)) +/* RSS Random Key - RW Array */ +#define IGC_RSSRK(_i) (0x05C80 + ((_i) * 4)) + +/* Receive Register Descriptions */ +#define IGC_RCTL 0x00100 /* Rx Control - RW */ +#define IGC_SRRCTL(_n) (0x0C00C + ((_n) * 0x40)) +#define IGC_PSRTYPE(_i) (0x05480 + ((_i) * 4)) +#define IGC_RDBAL(_n) (0x0C000 + ((_n) * 0x40)) +#define IGC_RDBAH(_n) (0x0C004 + ((_n) * 0x40)) +#define IGC_RDLEN(_n) (0x0C008 + ((_n) * 0x40)) +#define IGC_RDH(_n) (0x0C010 + ((_n) * 0x40)) +#define IGC_RDT(_n) (0x0C018 + ((_n) * 0x40)) +#define IGC_RXDCTL(_n) (0x0C028 + ((_n) * 0x40)) +#define IGC_RQDPC(_n) (0x0C030 + ((_n) * 0x40)) +#define IGC_RXCSUM 0x05000 /* Rx Checksum Control - RW */ +#define IGC_RLPML 0x05004 /* Rx Long Packet Max Length */ +#define IGC_RFCTL 0x05008 /* Receive Filter Control*/ +#define IGC_MTA 0x05200 /* Multicast Table Array - RW Array */ +#define IGC_RA 0x05400 /* Receive Address - RW Array */ +#define IGC_UTA 0x0A000 /* Unicast Table Array - RW */ +#define IGC_RAL(_n) (0x05400 + ((_n) * 0x08)) +#define IGC_RAH(_n) (0x05404 + ((_n) * 0x08)) +#define IGC_VLANPQF 0x055B0 /* VLAN Priority Queue Filter - RW */ + +/* Transmit Register Descriptions */ +#define IGC_TCTL 0x00400 /* Tx Control - RW */ +#define IGC_TIPG 0x00410 /* Tx Inter-packet gap - RW */ +#define IGC_TDBAL(_n) (0x0E000 + ((_n) * 0x40)) +#define IGC_TDBAH(_n) (0x0E004 + ((_n) * 0x40)) +#define IGC_TDLEN(_n) (0x0E008 + ((_n) * 0x40)) +#define IGC_TDH(_n) (0x0E010 + ((_n) * 0x40)) +#define IGC_TDT(_n) (0x0E018 + ((_n) * 0x40)) +#define IGC_TXDCTL(_n) (0x0E028 + ((_n) * 0x40)) + +/* MMD Register Descriptions */ +#define IGC_MMDAC 13 /* MMD Access Control */ +#define IGC_MMDAAD 14 /* MMD Access Address/Data */ + +/* Statistics Register Descriptions */ +#define IGC_CRCERRS 0x04000 /* CRC Error Count - R/clr */ +#define IGC_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */ +#define IGC_RXERRC 0x0400C /* Receive Error Count - R/clr */ +#define IGC_MPC 0x04010 /* Missed Packet Count - R/clr */ +#define IGC_SCC 0x04014 /* Single Collision Count - R/clr */ +#define IGC_ECOL 0x04018 /* Excessive Collision Count - R/clr */ +#define IGC_MCC 0x0401C /* Multiple Collision Count - R/clr */ +#define IGC_LATECOL 0x04020 /* Late Collision Count - R/clr */ +#define IGC_COLC 0x04028 /* Collision Count - R/clr */ +#define IGC_RERC 0x0402C /* Receive Error Count - R/clr */ +#define IGC_DC 0x04030 /* Defer Count - R/clr */ +#define IGC_TNCRS 0x04034 /* Tx-No CRS - R/clr */ +#define IGC_HTDPMC 0x0403C /* Host Transmit Discarded by MAC - R/clr */ +#define IGC_RLEC 0x04040 /* Receive Length Error Count - R/clr */ +#define IGC_XONRXC 0x04048 /* XON Rx Count - R/clr */ +#define IGC_XONTXC 0x0404C /* XON Tx Count - R/clr */ +#define IGC_XOFFRXC 0x04050 /* XOFF Rx Count - R/clr */ +#define IGC_XOFFTXC 0x04054 /* XOFF Tx Count - R/clr */ +#define IGC_FCRUC 0x04058 /* Flow Control Rx Unsupported Count- R/clr */ +#define IGC_PRC64 0x0405C /* Packets Rx (64 bytes) - R/clr */ +#define IGC_PRC127 0x04060 /* Packets Rx (65-127 bytes) - R/clr */ +#define IGC_PRC255 0x04064 /* Packets Rx (128-255 bytes) - R/clr */ +#define IGC_PRC511 0x04068 /* Packets Rx (255-511 bytes) - R/clr */ +#define IGC_PRC1023 0x0406C /* Packets Rx (512-1023 bytes) - R/clr */ +#define IGC_PRC1522 0x04070 /* Packets Rx (1024-1522 bytes) - R/clr */ +#define IGC_GPRC 0x04074 /* Good Packets Rx Count - R/clr */ +#define IGC_BPRC 0x04078 /* Broadcast Packets Rx Count - R/clr */ +#define IGC_MPRC 0x0407C /* Multicast Packets Rx Count - R/clr */ +#define IGC_GPTC 0x04080 /* Good Packets Tx Count - R/clr */ +#define IGC_GORCL 0x04088 /* Good Octets Rx Count Low - R/clr */ +#define IGC_GORCH 0x0408C /* Good Octets Rx Count High - R/clr */ +#define IGC_GOTCL 0x04090 /* Good Octets Tx Count Low - R/clr */ +#define IGC_GOTCH 0x04094 /* Good Octets Tx Count High - R/clr */ +#define IGC_RNBC 0x040A0 /* Rx No Buffers Count - R/clr */ +#define IGC_RUC 0x040A4 /* Rx Undersize Count - R/clr */ +#define IGC_RFC 0x040A8 /* Rx Fragment Count - R/clr */ +#define IGC_ROC 0x040AC /* Rx Oversize Count - R/clr */ +#define IGC_RJC 0x040B0 /* Rx Jabber Count - R/clr */ +#define IGC_MGTPRC 0x040B4 /* Management Packets Rx Count - R/clr */ +#define IGC_MGTPDC 0x040B8 /* Management Packets Dropped Count - R/clr */ +#define IGC_MGTPTC 0x040BC /* Management Packets Tx Count - R/clr */ +#define IGC_TORL 0x040C0 /* Total Octets Rx Low - R/clr */ +#define IGC_TORH 0x040C4 /* Total Octets Rx High - R/clr */ +#define IGC_TOTL 0x040C8 /* Total Octets Tx Low - R/clr */ +#define IGC_TOTH 0x040CC /* Total Octets Tx High - R/clr */ +#define IGC_TPR 0x040D0 /* Total Packets Rx - R/clr */ +#define IGC_TPT 0x040D4 /* Total Packets Tx - R/clr */ +#define IGC_PTC64 0x040D8 /* Packets Tx (64 bytes) - R/clr */ +#define IGC_PTC127 0x040DC /* Packets Tx (65-127 bytes) - R/clr */ +#define IGC_PTC255 0x040E0 /* Packets Tx (128-255 bytes) - R/clr */ +#define IGC_PTC511 0x040E4 /* Packets Tx (256-511 bytes) - R/clr */ +#define IGC_PTC1023 0x040E8 /* Packets Tx (512-1023 bytes) - R/clr */ +#define IGC_PTC1522 0x040EC /* Packets Tx (1024-1522 Bytes) - R/clr */ +#define IGC_MPTC 0x040F0 /* Multicast Packets Tx Count - R/clr */ +#define IGC_BPTC 0x040F4 /* Broadcast Packets Tx Count - R/clr */ +#define IGC_TSCTC 0x040F8 /* TCP Segmentation Context Tx - R/clr */ +#define IGC_IAC 0x04100 /* Interrupt Assertion Count */ +#define IGC_RPTHC 0x04104 /* Rx Packets To Host */ +#define IGC_TLPIC 0x04148 /* EEE Tx LPI Count */ +#define IGC_RLPIC 0x0414C /* EEE Rx LPI Count */ +#define IGC_HGPTC 0x04118 /* Host Good Packets Tx Count */ +#define IGC_RXDMTC 0x04120 /* Rx Descriptor Minimum Threshold Count */ +#define IGC_HGORCL 0x04128 /* Host Good Octets Received Count Low */ +#define IGC_HGORCH 0x0412C /* Host Good Octets Received Count High */ +#define IGC_HGOTCL 0x04130 /* Host Good Octets Transmit Count Low */ +#define IGC_HGOTCH 0x04134 /* Host Good Octets Transmit Count High */ +#define IGC_LENERRS 0x04138 /* Length Errors Count */ + +/* Time sync registers */ +#define IGC_TSICR 0x0B66C /* Time Sync Interrupt Cause */ +#define IGC_TSIM 0x0B674 /* Time Sync Interrupt Mask Register */ +#define IGC_TSAUXC 0x0B640 /* Timesync Auxiliary Control register */ +#define IGC_TSYNCRXCTL 0x0B620 /* Rx Time Sync Control register - RW */ +#define IGC_TSYNCTXCTL 0x0B614 /* Tx Time Sync Control register - RW */ +#define IGC_TSYNCRXCFG 0x05F50 /* Time Sync Rx Configuration - RW */ +#define IGC_TSSDP 0x0003C /* Time Sync SDP Configuration Register - RW */ + +#define IGC_IMIR(_i) (0x05A80 + ((_i) * 4)) /* Immediate Interrupt */ +#define IGC_IMIREXT(_i) (0x05AA0 + ((_i) * 4)) /* Immediate INTR Ext*/ + +#define IGC_FTQF(_n) (0x059E0 + (4 * (_n))) /* 5-tuple Queue Fltr */ + +/* Transmit Scheduling Registers */ +#define IGC_TQAVCTRL 0x3570 +#define IGC_TXQCTL(_n) (0x3344 + 0x4 * (_n)) +#define IGC_BASET_L 0x3314 +#define IGC_BASET_H 0x3318 +#define IGC_QBVCYCLET 0x331C +#define IGC_QBVCYCLET_S 0x3320 + +#define IGC_STQT(_n) (0x3324 + 0x4 * (_n)) +#define IGC_ENDQT(_n) (0x3334 + 0x4 * (_n)) +#define IGC_DTXMXPKTSZ 0x355C + +/* System Time Registers */ +#define IGC_SYSTIML 0x0B600 /* System time register Low - RO */ +#define IGC_SYSTIMH 0x0B604 /* System time register High - RO */ +#define IGC_SYSTIMR 0x0B6F8 /* System time register Residue */ +#define IGC_TIMINCA 0x0B608 /* Increment attributes register - RW */ + +#define IGC_TXSTMPL 0x0B618 /* Tx timestamp value Low - RO */ +#define IGC_TXSTMPH 0x0B61C /* Tx timestamp value High - RO */ + +/* Management registers */ +#define IGC_MANC 0x05820 /* Management Control - RW */ + +/* Shadow Ram Write Register - RW */ +#define IGC_SRWR 0x12018 + +/* Wake Up registers */ +#define IGC_WUC 0x05800 /* Wakeup Control - RW */ +#define IGC_WUFC 0x05808 /* Wakeup Filter Control - RW */ +#define IGC_WUS 0x05810 /* Wakeup Status - R/W1C */ +#define IGC_WUPL 0x05900 /* Wakeup Packet Length - RW */ + +/* Wake Up packet memory */ +#define IGC_WUPM_REG(_i) (0x05A00 + ((_i) * 4)) + +/* Energy Efficient Ethernet "EEE" registers */ +#define IGC_EEER 0x0E30 /* Energy Efficient Ethernet "EEE"*/ +#define IGC_IPCNFG 0x0E38 /* Internal PHY Configuration */ +#define IGC_EEE_SU 0x0E34 /* EEE Setup */ + +/* LTR registers */ +#define IGC_LTRC 0x01A0 /* Latency Tolerance Reporting Control */ +#define IGC_DMACR 0x02508 /* DMA Coalescing Control Register */ +#define IGC_LTRMINV 0x5BB0 /* LTR Minimum Value */ +#define IGC_LTRMAXV 0x5BB4 /* LTR Maximum Value */ + +/* forward declaration */ +struct igc_hw; +u32 igc_rd32(struct igc_hw *hw, u32 reg); + +/* write operations, indexed using DWORDS */ +#define wr32(reg, val) \ +do { \ + u8 __iomem *hw_addr = READ_ONCE((hw)->hw_addr); \ + writel((val), &hw_addr[(reg)]); \ +} while (0) + +#define rd32(reg) (igc_rd32(hw, reg)) + +#define wrfl() ((void)rd32(IGC_STATUS)) + +#define array_wr32(reg, offset, value) \ + wr32((reg) + ((offset) << 2), (value)) + +#define array_rd32(reg, offset) (igc_rd32(hw, (reg) + ((offset) << 2))) + +#define IGC_REMOVED(h) unlikely(!(h)) + +#endif diff --git a/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_tsn.c b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_tsn.c new file mode 100644 index 00000000..4dbbb8a3 --- /dev/null +++ b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_tsn.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2019 Intel Corporation */ + +#include "igc.h" +#include "igc_tsn.h" + +static bool is_any_launchtime(struct igc_adapter *adapter) +{ + int i; + + for (i = 0; i < adapter->num_tx_queues; i++) { + struct igc_ring *ring = adapter->tx_ring[i]; + + if (ring->launchtime_enable) + return true; + } + + return false; +} + +/* Returns the TSN specific registers to their default values after + * TSN offloading is disabled. + */ +static int igc_tsn_disable_offload(struct igc_adapter *adapter) +{ + struct igc_hw *hw = &adapter->hw; + u32 tqavctrl; + int i; + + if (!(adapter->flags & IGC_FLAG_TSN_QBV_ENABLED)) + return 0; + + adapter->cycle_time = 0; + + wr32(IGC_TXPBS, I225_TXPBSIZE_DEFAULT); + wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_DEFAULT); + + tqavctrl = rd32(IGC_TQAVCTRL); + tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN | + IGC_TQAVCTRL_ENHANCED_QAV); + wr32(IGC_TQAVCTRL, tqavctrl); + + for (i = 0; i < adapter->num_tx_queues; i++) { + struct igc_ring *ring = adapter->tx_ring[i]; + + ring->start_time = 0; + ring->end_time = 0; + ring->launchtime_enable = false; + + wr32(IGC_TXQCTL(i), 0); + wr32(IGC_STQT(i), 0); + wr32(IGC_ENDQT(i), NSEC_PER_SEC); + } + + wr32(IGC_QBVCYCLET_S, 0); + wr32(IGC_QBVCYCLET, NSEC_PER_SEC); + + adapter->flags &= ~IGC_FLAG_TSN_QBV_ENABLED; + + return 0; +} + +static int igc_tsn_enable_offload(struct igc_adapter *adapter) +{ + struct igc_hw *hw = &adapter->hw; + u32 tqavctrl, baset_l, baset_h; + u32 sec, nsec, cycle; + ktime_t base_time, systim; + int i; + + if (adapter->flags & IGC_FLAG_TSN_QBV_ENABLED) + return 0; + + cycle = adapter->cycle_time; + base_time = adapter->base_time; + + wr32(IGC_TSAUXC, 0); + wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_TSN); + wr32(IGC_TXPBS, IGC_TXPBSIZE_TSN); + + tqavctrl = rd32(IGC_TQAVCTRL); + tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV; + wr32(IGC_TQAVCTRL, tqavctrl); + + wr32(IGC_QBVCYCLET_S, cycle); + wr32(IGC_QBVCYCLET, cycle); + + for (i = 0; i < adapter->num_tx_queues; i++) { + struct igc_ring *ring = adapter->tx_ring[i]; + u32 txqctl = 0; + + wr32(IGC_STQT(i), ring->start_time); + wr32(IGC_ENDQT(i), ring->end_time); + + if (adapter->base_time) { + /* If we have a base_time we are in "taprio" + * mode and we need to be strict about the + * cycles: only transmit a packet if it can be + * completed during that cycle. + */ + txqctl |= IGC_TXQCTL_STRICT_CYCLE | + IGC_TXQCTL_STRICT_END; + } + + if (ring->launchtime_enable) + txqctl |= IGC_TXQCTL_QUEUE_MODE_LAUNCHT; + + wr32(IGC_TXQCTL(i), txqctl); + } + + nsec = rd32(IGC_SYSTIML); + sec = rd32(IGC_SYSTIMH); + + systim = ktime_set(sec, nsec); + + if (ktime_compare(systim, base_time) > 0) { + s64 n; + + n = div64_s64(ktime_sub_ns(systim, base_time), cycle); + base_time = ktime_add_ns(base_time, (n + 1) * cycle); + } + + baset_h = div_s64_rem(base_time, NSEC_PER_SEC, &baset_l); + + wr32(IGC_BASET_H, baset_h); + wr32(IGC_BASET_L, baset_l); + + adapter->flags |= IGC_FLAG_TSN_QBV_ENABLED; + + return 0; +} + +int igc_tsn_offload_apply(struct igc_adapter *adapter) +{ + bool is_any_enabled = adapter->base_time || is_any_launchtime(adapter); + + if (!(adapter->flags & IGC_FLAG_TSN_QBV_ENABLED) && !is_any_enabled) + return 0; + + if (!is_any_enabled) { + int err = igc_tsn_disable_offload(adapter); + + if (err < 0) + return err; + + /* The BASET registers aren't cleared when writing + * into them, force a reset if the interface is + * running. + */ + if (netif_running(adapter->netdev)) + schedule_work(&adapter->reset_task); + + return 0; + } + + return igc_tsn_enable_offload(adapter); +} diff --git a/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_tsn.h b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_tsn.h new file mode 100644 index 00000000..f76bc86d --- /dev/null +++ b/root/target/linux/x86/files-5.4/drivers/net/ethernet/intel/igc/igc_tsn.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2020 Intel Corporation */ + +#ifndef _IGC_TSN_H_ +#define _IGC_TSN_H_ + +int igc_tsn_offload_apply(struct igc_adapter *adapter); + +#endif /* _IGC_BASE_H */ From 209010ddd92996b7f6730324ec79b7035b9efb71 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 11 Nov 2022 11:15:00 +0100 Subject: [PATCH 035/102] Search for the kernel FS on all disk. From coolsnowwolf repo --- root/target/linux/x86/image/grub-efi.cfg | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 root/target/linux/x86/image/grub-efi.cfg diff --git a/root/target/linux/x86/image/grub-efi.cfg b/root/target/linux/x86/image/grub-efi.cfg new file mode 100644 index 00000000..bbb31f77 --- /dev/null +++ b/root/target/linux/x86/image/grub-efi.cfg @@ -0,0 +1,13 @@ +@SERIAL_CONFIG@ +@TERMINAL_CONFIG@ + +set default="0" +set timeout="@TIMEOUT@" +search -l kernel -s root + +menuentry "@TITLE@" { + linux /boot/vmlinuz @GPT_ROOTPART@ @CMDLINE@ noinitrd +} +menuentry "@TITLE@ (failsafe)" { + linux /boot/vmlinuz failsafe=true @GPT_ROOTPART@ @CMDLINE@ noinitrd +} From 7ccb368a7ab484db2e514c4537e12982965bedc4 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 16 Nov 2022 21:08:27 +0100 Subject: [PATCH 036/102] Update OpenWRT --- build.sh | 93 +++++++++++++++----------------------------------------- 1 file changed, 24 insertions(+), 69 deletions(-) diff --git a/build.sh b/build.sh index cb80f522..edf8cf5a 100755 --- a/build.sh +++ b/build.sh @@ -98,9 +98,9 @@ if [ "$OMR_OPENWRT" = "default" ]; then _get_repo feeds/${OMR_KERNEL}/packages https://github.com/openwrt/packages "6711badf079986f847da07747c95c0a74960b965" _get_repo feeds/${OMR_KERNEL}/luci https://github.com/openwrt/luci "04257f6704c1b8707ee7a58ca4ec0f18a2133611" else - _get_repo "$OMR_TARGET/${OMR_KERNEL}/source" https://github.com/openwrt/openwrt "c3322cf04a1b9ee826dcc56944750b6bbcb716ef" - _get_repo feeds/${OMR_KERNEL}/packages https://github.com/openwrt/packages "7960285c3301532e8c464fb06260ce14ae4357a0" - _get_repo feeds/${OMR_KERNEL}/luci https://github.com/openwrt/luci "9ea26a75ed44cde3def5d061a867fa513d365c27" + _get_repo "$OMR_TARGET/${OMR_KERNEL}/source" https://github.com/openwrt/openwrt "0d43c22d47b91fd64fea707290f9dce3ba2a273f" + _get_repo feeds/${OMR_KERNEL}/packages https://github.com/openwrt/packages "8762261112c8235f7f85a6f57dbf342cf17093b9" + _get_repo feeds/${OMR_KERNEL}/luci https://github.com/openwrt/luci "a1ee78fa696e13ad4e19c0252eb345500d4ab3ee" fi elif [ "$OMR_OPENWRT" = "master" ]; then _get_repo "$OMR_TARGET/${OMR_KERNEL}/source" https://github.com/openwrt/openwrt "master" @@ -136,6 +136,7 @@ rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/files" "$OMR_TARGET/${OMR_KERNEL}/sourc #rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/uboot-mediatek" #rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/arm-trusted-firmware-mediatek" rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/tools/firmware-utils" +rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/uboot-rockchip" if [ "$OMR_TARGET" != "rutx" ]; then # There is many customization to support rutx and this seems to break other ipq40xx, so dirty workaround for now mv "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx" "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx.old" @@ -453,9 +454,9 @@ if [ -f target/linux/mediatek/patches-5.4/0999-hnat.patch ]; then rm -f target/linux/mediatek/patches-5.4/0999-hnat.patch fi -if [ -f target/linux/bcm27xx/patches-5.15/950-0019-drm-vc4-select-PM.patch ]; then - rm -f target/linux/bcm27xx/patches-5.15/950-0019-drm-vc4-select-PM.patch -fi +#if [ -f target/linux/bcm27xx/patches-5.15/950-0019-drm-vc4-select-PM.patch ]; then +# rm -f target/linux/bcm27xx/patches-5.15/950-0019-drm-vc4-select-PM.patch +#fi if [ -f target/linux/ipq806x/patches-5.4/0063-2-tsens-support-configurable-interrupts.patch ]; then rm -f target/linux/ipq806x/patches-5.4/0063-* fi @@ -513,24 +514,35 @@ fi #if [ -f target/linux/generic/hack-5.4/953-net-patch-linux-kernel-to-support-shortcut-fe.patch ]; then # rm -f target/linux/generic/hack-5.4/953-net-patch-linux-kernel-to-support-shortcut-fe.patch #fi -if [ -f target/linux/bcm27xx/patches-5.4/950-1031-net-lan78xx-Ack-pending-PHY-ints-when-resetting.patch ]; then - rm -f target/linux/bcm27xx/patches-5.4/950-1031-net-lan78xx-Ack-pending-PHY-ints-when-resetting.patch -fi +#if [ -f target/linux/bcm27xx/patches-5.4/950-1031-net-lan78xx-Ack-pending-PHY-ints-when-resetting.patch ]; then +# rm -f target/linux/bcm27xx/patches-5.4/950-1031-net-lan78xx-Ack-pending-PHY-ints-when-resetting.patch +#fi #if [ -f target/linux/generic/pending-5.4/770-16-net-ethernet-mediatek-mtk_eth_soc-add-flow-offloadin.patch ]; then # rm -f target/linux/generic/pending-5.4/770-16-net-ethernet-mediatek-mtk_eth_soc-add-flow-offloadin.patch #fi #if [ -f target/linux/generic/pending-5.15/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch ]; then # rm -f target/linux/generic/pending-5.15/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch #fi -if [ -f target/linux/bcm27xx/patches-5.15/950-0448-drm-vc4-Fix-definition-of-PAL-M-mode.patch ]; then - rm -f target/linux/bcm27xx/patches-5.15/950-0448-drm-vc4-Fix-definition-of-PAL-M-mode.patch -fi +#if [ -f target/linux/bcm27xx/patches-5.15/950-0448-drm-vc4-Fix-definition-of-PAL-M-mode.patch ]; then +# rm -f target/linux/bcm27xx/patches-5.15/950-0448-drm-vc4-Fix-definition-of-PAL-M-mode.patch +#fi #if [ -f target/linux/ipq40xx/patches-5.15/707-dt-bindings-net-add-QCA807x-PHY.patch ]; then # rm -f target/linux/ipq40xx/patches-5.15/707-dt-bindings-net-add-QCA807x-PHY.patch #fi #if [ -f target/linux/ipq40xx/patches-5.15/709-arm-dts-ipq4019-QCA807x-properties.patch ]; then # rm -f target/linux/ipq40xx/patches-5.15/709-arm-dts-ipq4019-QCA807x-properties.patch #fi +#if [ -f target/linux/bcm27xx/patches-5.15/950-0556-drm-vc4-Make-VEC-progressive-modes-readily-accessibl.patch ]; then +# rm -f target/linux/bcm27xx/patches-5.15/*-drm-*.patch +# rm -f target/linux/bcm27xx/patches-5.15/*-vc4*.patch +# rm -f target/linux/bcm27xx/patches-5.15/950-0183-v3d_drv-Handle-missing-clock-more-gracefully.patch +# rm -f target/linux/bcm27xx/patches-5.15/950-0305-staging-bcm2835-audio-Add-disable-headphones-flag.patch +# rm -f target/linux/bcm27xx/patches-5.15/950-0697-dtoverlays-Add-overlays-for-Pimoroni-Hyperpixel-disp.patch +# rm -f target/linux/bcm27xx/patches-5.15/950-0785-dtoverlays-Connect-the-backlight-to-the-pitft35-disp.patch +#fi +#if [ -f target/linux/bcm27xx/patches-5.15/950-0785-dtoverlays-Connect-the-backlight-to-the-pitft35-disp.patch ]; then +# rm -f target/linux/bcm27xx/patches-5.15/950-0785-dtoverlays-Connect-the-backlight-to-the-pitft35-disp.patch +#fi if [ "$OMR_KERNEL" = "5.4" ]; then echo "Set to kernel 5.4 for rpi arch" @@ -560,63 +572,6 @@ if [ "$OMR_KERNEL" = "5.4" ]; then fi echo "CONFIG_VERSION_CODE=5.4" >> ".config" fi -if [ "$OMR_KERNEL" = "5.10" ]; then - echo "Set to kernel 5.10 for rpi arch" - find target/linux/bcm27xx -type f -name Makefile -exec sed -i 's%KERNEL_PATCHVER:=5.4%KERNEL_PATCHVER:=5.10%g' {} \; - find target/linux/bcm27xx -type f -name Makefile -exec sed -i 's%KERNEL_PATCHVER=5.4%KERNEL_PATCHVER:=5.10%g' {} \; - echo "Done" - echo "Set to kernel 5.10 for x86 arch" - find target/linux/x86 -type f -name Makefile -exec sed -i 's%KERNEL_PATCHVER:=5.4%KERNEL_PATCHVER:=5.10%g' {} \; - echo "Done" - echo "Set to kernel 5.10 for mvebu arch (WRT)" - find target/linux/mvebu -type f -name Makefile -exec sed -i 's%KERNEL_PATCHVER:=5.4%KERNEL_PATCHVER:=5.10%g' {} \; - echo "Done" - echo "Set to kernel 5.10 for mediatek arch (BPI-R2)" - find target/linux/mediatek -type f -name Makefile -exec sed -i 's%KERNEL_PATCHVER:=5.4%KERNEL_PATCHVER:=5.10%g' {} \; - echo "Done" -fi -if [ "$OMR_KERNEL" = "5.14" ]; then - echo "Set to kernel 5.14 for rpi arch" - find target/linux/bcm27xx -type f -name Makefile -exec sed -i 's%KERNEL_PATCHVER:=5.10%KERNEL_PATCHVER:=5.14%g' {} \; - find target/linux/bcm27xx -type f -name Makefile -exec sed -i 's%KERNEL_PATCHVER=5.10%KERNEL_PATCHVER:=5.14%g' {} \; - find target/linux/bcm27xx -type f -name Makefile -exec sed -i 's%KERNEL_PATCHVER=5.4%KERNEL_PATCHVER:=5.14%g' {} \; - echo "Done" - echo "Set to kernel 5.14 for x86 arch" - find target/linux/x86 -type f -name Makefile -exec sed -i 's%KERNEL_PATCHVER:=5.10%KERNEL_PATCHVER:=5.14%g' {} \; - echo "Done" - echo "Set to kernel 5.14 for mvebu arch (WRT)" - find target/linux/mvebu -type f -name Makefile -exec sed -i 's%KERNEL_PATCHVER:=5.10%KERNEL_PATCHVER:=5.14%g' {} \; - echo "Done" - echo "Set to kernel 5.14 for mediatek arch (BPI-R2)" - find target/linux/mediatek -type f -name Makefile -exec sed -i 's%KERNEL_PATCHVER:=5.10%KERNEL_PATCHVER:=5.14%g' {} \; - find target/linux/mediatek -type f -name Makefile -exec sed -i 's%KERNEL_PATCHVER:=5.4%KERNEL_PATCHVER:=5.14%g' {} \; - echo "Done" - echo "Set to kernel 5.14 for rockchip arch (R2S/R4S)" - find target/linux/rockchip -type f -name Makefile -exec sed -i 's%KERNEL_PATCHVER=5.4%KERNEL_PATCHVER:=5.14%g' {} \; - echo "Done" - echo "Set to kernel 5.14 for ramips" - find target/linux/ramips -type f -name Makefile -exec sed -i 's%KERNEL_PATCHVER:=5.4%KERNEL_PATCHVER:=5.14%g' {} \; - echo "Done" - echo "Set to kernel 5.14 for ipq806x" - find target/linux/ipq806x -type f -name Makefile -exec sed -i 's%KERNEL_PATCHVER:=5.10%KERNEL_PATCHVER:=5.14%g' {} \; - echo "Done" - echo "Set to kernel 5.14 for ipq40xx" - find target/linux/ipq40xx -type f -name Makefile -exec sed -i 's%KERNEL_PATCHVER:=5.10%KERNEL_PATCHVER:=5.14%g' {} \; - echo "Done" - #rm -rf target/linux/generic/files/drivers/net/phy/b53 - rm -f target/linux/bcm27xx/modules/sound.mk - echo "CONFIG_DEVEL=y" >> ".config" - echo "CONFIG_NEED_TOOLCHAIN=y" >> ".config" - echo "CONFIG_TOOLCHAINOPTS=y" >> ".config" - echo 'CONFIG_BINUTILS_VERSION_2_36_1=y' >> ".config" - echo 'CONFIG_BINUTILS_VERSION="2.36.1' >> ".config" - echo "CONFIG_BINUTILS_USE_VERSION_2_36_1=y" >> ".config" - echo "CONFIG_VERSION_CODE=5.14" >> ".config" - #echo "CONFIG_GCC_USE_VERSION_10=y" >> ".config" - if [ "$TARGET" = "bpi-r2" ]; then - echo "# CONFIG_VERSION_CODE_FILENAMES is not set" >> ".config" - fi -fi if [ "$OMR_KERNEL" = "5.15" ]; then echo "Set to kernel 5.15 for rpi arch" find target/linux/bcm27xx -type f -name Makefile -exec sed -i 's%KERNEL_PATCHVER:=5.10%KERNEL_PATCHVER:=5.15%g' {} \; From 8ad006978d76d03ffac9daaae2ecea7bad263a12 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 17 Nov 2022 10:39:00 +0100 Subject: [PATCH 037/102] Update 5.15 config --- root/target/linux/generic/config-5.15 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/root/target/linux/generic/config-5.15 b/root/target/linux/generic/config-5.15 index 4049fbb3..a3303d5b 100644 --- a/root/target/linux/generic/config-5.15 +++ b/root/target/linux/generic/config-5.15 @@ -337,6 +337,8 @@ CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8 # CONFIG_ARM64_ERRATUM_843419 is not set # CONFIG_ARM64_ERRATUM_845719 is not set # CONFIG_ARM64_ERRATUM_858921 is not set +# CONFIG_ARM64_ERRATUM_2441007 is not set +# CONFIG_ARM64_ERRATUM_2441009 is not set # CONFIG_ARM64_HW_AFDBM is not set # CONFIG_ARM64_LSE_ATOMICS is not set CONFIG_ARM64_MODULE_PLTS=y From 0a3b251ef9525113c7b6fccdb49e8466c0719776 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 17 Nov 2022 12:53:41 +0100 Subject: [PATCH 038/102] Remove not needed patches --- .../706-dt-bindings-net-add-QCA807x-PHY.patch | 61 ------------------ ...8-arm-dts-ipq4019-QCA807x-properties.patch | 62 ------------------- 2 files changed, 123 deletions(-) delete mode 100644 root/target/linux/ipq40xx/patches-5.15/706-dt-bindings-net-add-QCA807x-PHY.patch delete mode 100644 root/target/linux/ipq40xx/patches-5.15/708-arm-dts-ipq4019-QCA807x-properties.patch diff --git a/root/target/linux/ipq40xx/patches-5.15/706-dt-bindings-net-add-QCA807x-PHY.patch b/root/target/linux/ipq40xx/patches-5.15/706-dt-bindings-net-add-QCA807x-PHY.patch deleted file mode 100644 index dfb8d692..00000000 --- a/root/target/linux/ipq40xx/patches-5.15/706-dt-bindings-net-add-QCA807x-PHY.patch +++ /dev/null @@ -1,61 +0,0 @@ -From c66863c1ba8995b61e6d727d78a241c734f5bb57 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Thu, 1 Oct 2020 15:05:35 +0200 -Subject: [PATCH] dt-bindings: net: add QCA807x PHY - -Add DT bindings for Qualcomm QCA807x PHY series. - -Signed-off-by: Robert Marko ---- - include/dt-bindings/net/qcom-qca807x.h | 45 ++++++++++++++++++++++++++ - 1 file changed, 45 insertions(+) - create mode 100644 include/dt-bindings/net/qcom-qca807x.h - ---- /dev/null -+++ b/include/dt-bindings/net/qcom-qca807x.h -@@ -0,0 +1,45 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+/* -+ * Device Tree constants for the Qualcomm QCA807X PHYs -+ */ -+ -+#ifndef _DT_BINDINGS_QCOM_QCA807X_H -+#define _DT_BINDINGS_QCOM_QCA807X_H -+ -+#define PSGMII_QSGMII_TX_DRIVER_140MV 0 -+#define PSGMII_QSGMII_TX_DRIVER_160MV 1 -+#define PSGMII_QSGMII_TX_DRIVER_180MV 2 -+#define PSGMII_QSGMII_TX_DRIVER_200MV 3 -+#define PSGMII_QSGMII_TX_DRIVER_220MV 4 -+#define PSGMII_QSGMII_TX_DRIVER_240MV 5 -+#define PSGMII_QSGMII_TX_DRIVER_260MV 6 -+#define PSGMII_QSGMII_TX_DRIVER_280MV 7 -+#define PSGMII_QSGMII_TX_DRIVER_300MV 8 -+#define PSGMII_QSGMII_TX_DRIVER_320MV 9 -+#define PSGMII_QSGMII_TX_DRIVER_400MV 10 -+#define PSGMII_QSGMII_TX_DRIVER_500MV 11 -+/* Default value */ -+#define PSGMII_QSGMII_TX_DRIVER_600MV 12 -+ -+/* Full amplitude, full bias current */ -+#define QCA807X_CONTROL_DAC_FULL_VOLT_BIAS 0 -+/* Amplitude follow DSP (amplitude is adjusted based on cable length), half bias current */ -+#define QCA807X_CONTROL_DAC_DSP_VOLT_HALF_BIAS 1 -+/* Full amplitude, bias current follow DSP (bias current is adjusted based on cable length) */ -+#define QCA807X_CONTROL_DAC_FULL_VOLT_DSP_BIAS 2 -+/* Both amplitude and bias current follow DSP */ -+#define QCA807X_CONTROL_DAC_DSP_VOLT_BIAS 3 -+/* Full amplitude, half bias current */ -+#define QCA807X_CONTROL_DAC_FULL_VOLT_HALF_BIAS 4 -+/* Amplitude follow DSP setting; 1/4 bias current when cable<10m, -+ * otherwise half bias current -+ */ -+#define QCA807X_CONTROL_DAC_DSP_VOLT_QUARTER_BIAS 5 -+/* Full amplitude; same bias current setting with “010” and “011”, -+ * but half more bias is reduced when cable <10m -+ */ -+#define QCA807X_CONTROL_DAC_FULL_VOLT_HALF_BIAS_SHORT 6 -+/* Amplitude follow DSP; same bias current setting with “110”, default value */ -+#define QCA807X_CONTROL_DAC_DSP_VOLT_HALF_BIAS_SHORT 7 -+ -+#endif diff --git a/root/target/linux/ipq40xx/patches-5.15/708-arm-dts-ipq4019-QCA807x-properties.patch b/root/target/linux/ipq40xx/patches-5.15/708-arm-dts-ipq4019-QCA807x-properties.patch deleted file mode 100644 index c08f3a83..00000000 --- a/root/target/linux/ipq40xx/patches-5.15/708-arm-dts-ipq4019-QCA807x-properties.patch +++ /dev/null @@ -1,62 +0,0 @@ -From e0fa88eaa3c176b71e563da68949ac2ab45aaa61 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Fri, 2 Oct 2020 10:43:26 +0200 -Subject: [PATCH] arm: dts: ipq4019: QCA807x properties - -This adds necessary DT properties for QCA807x PHY-s to IPQ4019 DTSI. - -Signed-off-by: Robert Marko ---- - arch/arm/boot/dts/qcom-ipq4019.dtsi | 18 ++++++++++++++++++ - 1 file changed, 18 insertions(+) - ---- a/arch/arm/boot/dts/qcom-ipq4019.dtsi -+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi -@@ -8,6 +8,7 @@ - #include - #include - #include -+#include - - / { - #address-cells = <1>; -@@ -598,22 +599,39 @@ - - ethphy0: ethernet-phy@0 { - reg = <0>; -+ -+ qcom,control-dac = ; - }; - - ethphy1: ethernet-phy@1 { - reg = <1>; -+ -+ qcom,control-dac = ; - }; - - ethphy2: ethernet-phy@2 { - reg = <2>; -+ -+ qcom,control-dac = ; - }; - - ethphy3: ethernet-phy@3 { - reg = <3>; -+ -+ qcom,control-dac = ; - }; - - ethphy4: ethernet-phy@4 { - reg = <4>; -+ -+ qcom,control-dac = ; -+ }; -+ -+ psgmiiphy: psgmii-phy@5 { -+ reg = <5>; -+ -+ qcom,tx-driver-strength = ; -+ qcom,psgmii-az; - }; - }; - From b2687257d0bbaca8b11cb0934c974915456229f8 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Thu, 17 Nov 2022 20:57:07 +0800 Subject: [PATCH 039/102] Update build.sh --- build.sh | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/build.sh b/build.sh index d09e8c14..6a41dfec 100644 --- a/build.sh +++ b/build.sh @@ -74,6 +74,12 @@ elif [ "$OMR_TARGET" = "bpi-r2" ]; then OMR_REAL_TARGET="arm_cortex-a7_neon-vfpv4" elif [ "$OMR_TARGET" = "rutx" ]; then OMR_REAL_TARGET="arm_cortex-a7_neon-vfpv4" +elif [ "$OMR_TARGET" = "l1000" ]; then + OMR_REAL_TARGET="arm_cortex-a7_neon-vfpv4" +elif [ "$OMR_TARGET" = "zbt4019" ]; then + OMR_REAL_TARGET="arm_cortex-a7_neon-vfpv4" +elif [ "$OMR_TARGET" = "5gx3" ]; then + OMR_REAL_TARGET="arm_cortex-a7_neon-vfpv4" elif [ "$OMR_TARGET" = "bpi-r64" ]; then OMR_REAL_TARGET="aarch64_cortex-a53" elif [ "$OMR_TARGET" = "espressobin" ]; then @@ -136,16 +142,7 @@ rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/files" "$OMR_TARGET/${OMR_KERNEL}/sourc #rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/uboot-mediatek" #rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/arm-trusted-firmware-mediatek" rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/tools/firmware-utils" -rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/uboot-rockchip" -if [ "$OMR_TARGET" != "rutx" ]; then - # There is many customization to support rutx and this seems to break other ipq40xx, so dirty workaround for now - mv "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx" "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx.old" - cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" - rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx" - mv "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx.old" "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx" -else - cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" -fi +cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" cat >> "$OMR_TARGET/${OMR_KERNEL}/source/package/base-files/files/etc/banner" < Date: Thu, 17 Nov 2022 23:11:49 +0800 Subject: [PATCH 040/102] Update build.sh --- build.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/build.sh b/build.sh index 6a41dfec..ffa3d980 100644 --- a/build.sh +++ b/build.sh @@ -142,6 +142,7 @@ rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/files" "$OMR_TARGET/${OMR_KERNEL}/sourc #rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/uboot-mediatek" #rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/arm-trusted-firmware-mediatek" rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/tools/firmware-utils" +rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/uboot-rockchip" cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" cat >> "$OMR_TARGET/${OMR_KERNEL}/source/package/base-files/files/etc/banner" < Date: Fri, 18 Nov 2022 18:09:38 +0100 Subject: [PATCH 041/102] Update 5.15 kernel --- root/include/kernel-version.mk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/root/include/kernel-version.mk b/root/include/kernel-version.mk index d819822b..11732502 100644 --- a/root/include/kernel-version.mk +++ b/root/include/kernel-version.mk @@ -7,7 +7,7 @@ ifdef CONFIG_TESTING_KERNEL endif LINUX_VERSION-5.4 = .203 -LINUX_VERSION-5.15 = .77 +LINUX_VERSION-5.15 = .78 LINUX_KERNEL_HASH-5.4.132 = 8466adbfb3579e751ede683496df7bb20f258b5f882250f3dd82be63736d00ef LINUX_KERNEL_HASH-5.4.182 = b2f1201f64f010e9e3c85d6f303a559a7944a80a0244a86b8f5035bd23f1f40d @@ -22,6 +22,7 @@ LINUX_KERNEL_HASH-5.15.36 = 36345db17a937c197c72ca9c7f34c262b3a12f927c237ff77701 LINUX_KERNEL_HASH-5.15.50 = 554d507d37a23810fe8c83912761e4a4f73c40794bc685ff7ca98042fe1bd70f LINUX_KERNEL_HASH-5.15.63 = 6dd3cd1e5a629d0002bc6c6ec7e8ea96710104f38664122dd56c83dfd4eb7341 LINUX_KERNEL_HASH-5.15.77 = 142f841f33796a84c62fae2f2b96d2120bd8bbf9e0aac4ce157692cdb0afe9f9 +LINUX_KERNEL_HASH-5.15.78 = 0db99f7347a38c27b8c155f3c9c8b260011aea0a4ded85ee95e6095b1e69a499 remove_uri_prefix=$(subst git://,,$(subst http://,,$(subst https://,,$(1)))) sanitize_uri=$(call qstrip,$(subst @,_,$(subst :,_,$(subst .,_,$(subst -,_,$(subst /,_,$(1))))))) From f2bf060a044aaf7f78e12963931e0a065e04f662 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 18 Nov 2022 18:10:38 +0100 Subject: [PATCH 042/102] Update rockchip uboot --- .../Makefile | 81 + .../pack-firmware.sh | 60 + .../src/bin/rk35/rk3568_bl31_v1.28.elf | Bin 0 -> 335928 bytes .../src/trust.ini | 15 + .../arm-trusted-firmware-rockchip/Makefile | 49 + root/package/boot/uboot-rockchip/Makefile | 204 +- ...hip-rk3568-add-boot-device-detection.patch | 43 + ...01-scripts-remove-dependency-on-swig.patch | 24 - ...k3568-enable-automatic-power-savings.patch | 52 + ...-spl-remove-dtoc-of-pdata-generation.patch | 28 - ...le-rockchip-HACK-build-rk3568-images.patch | 47 + .../004-arm-dts-sync-rk3568-with-linux.patch | 3520 +++++++++++++++++ ...ckchip-rk356x-HACK-fix-sdmmc-support.patch | 50 + ...rockchip-rk356x-add-quartz64-a-board.patch | 214 + ...p-rk_gpio-support-v2-gpio-controller.patch | 755 ++++ ...8-rockchip-allow-sdmmc-at-full-speed.patch | 22 + ...ip-defconfig-add-gpio-v2-to-quartz64.patch | 25 + ...6x-enable-usb2-support-on-quartz64-a.patch | 97 + ...-rk356x-attempt-to-fix-ram-detection.patch | 173 + ...ync-rk3566-device-tree-with-mainline.patch | 1060 +++++ ...rockchip-rk356x-add-bpi-r2-pro-board.patch | 795 ++++ .../014-uboot-add-Radxa-ROCK-3A-board.patch | 690 ++++ .../015-uboot-add-NanoPi-R5S-board.patch | 247 ++ ...CONFIG_USB_OHCI_NEW-et-al-to-Kconfig.patch | 282 ++ ...104-mkimage-add-public-key-for-image.patch | 166 + .../105-Only-build-dtc-if-needed.patch | 125 + .../patches/106-no-kwbimage.patch | 10 + ...9-split-nanopi-r4s-out-of-evb_rk3399.patch | 637 --- ...9-Add-support-for-multiple-DDR-types.patch | 275 -- ...rock64pro-disable-CONFIG_USE_PREBOOT.patch | 27 + ...anopi4-unify-1GB-4GB-variants-of-R4S.patch | 89 - ...s-rockchip-Add-GuangMiao-G4C-support.patch | 740 ++++ ...328-Add-support-for-Orangepi-R1-Plus.patch | 174 + ...Add-support-for-Orangepi-R1-Plus-LTS.patch | 146 + ...Add-support-for-FriendlyARM-NanoPi-R.patch | 184 + ...Add-support-for-FriendlyARM-NanoPi-R.patch | 113 + ...399-Add-support-for-Rongpin-king3399.patch | 68 + ...68-Add-support-for-ezpro_mrkaio-m68s.patch | 406 ++ ...68-Add-support-for-radxa_rock-pi-e25.patch | 148 + ...568-Add-support-for-hinlink-opc-h68k.patch | 415 ++ ...k3568-Add-support-for-fastrhino-r66s.patch | 140 + ...ip-rk3568-Add-support-for-Station-P2.patch | 77 + .../of-platdata/nanopi-r2s-rk3328/dt-decl.h | 23 - .../of-platdata/nanopi-r2s-rk3328/dt-plat.c | 155 - .../nanopi-r2s-rk3328/dt-structs-gen.h | 51 - 45 files changed, 11398 insertions(+), 1304 deletions(-) create mode 100644 root/package/boot/arm-trusted-firmware-rockchip-vendor/Makefile create mode 100755 root/package/boot/arm-trusted-firmware-rockchip-vendor/pack-firmware.sh create mode 100644 root/package/boot/arm-trusted-firmware-rockchip-vendor/src/bin/rk35/rk3568_bl31_v1.28.elf create mode 100644 root/package/boot/arm-trusted-firmware-rockchip-vendor/src/trust.ini create mode 100644 root/package/boot/arm-trusted-firmware-rockchip/Makefile create mode 100644 root/package/boot/uboot-rockchip/patches/001-rockchip-rk3568-add-boot-device-detection.patch delete mode 100644 root/package/boot/uboot-rockchip/patches/001-scripts-remove-dependency-on-swig.patch create mode 100644 root/package/boot/uboot-rockchip/patches/002-rockchip-rk3568-enable-automatic-power-savings.patch delete mode 100644 root/package/boot/uboot-rockchip/patches/002-spl-remove-dtoc-of-pdata-generation.patch create mode 100644 root/package/boot/uboot-rockchip/patches/003-Makefile-rockchip-HACK-build-rk3568-images.patch create mode 100644 root/package/boot/uboot-rockchip/patches/004-arm-dts-sync-rk3568-with-linux.patch create mode 100644 root/package/boot/uboot-rockchip/patches/005-rockchip-rk356x-HACK-fix-sdmmc-support.patch create mode 100644 root/package/boot/uboot-rockchip/patches/006-rockchip-rk356x-add-quartz64-a-board.patch create mode 100644 root/package/boot/uboot-rockchip/patches/007-gpio-rockchip-rk_gpio-support-v2-gpio-controller.patch create mode 100644 root/package/boot/uboot-rockchip/patches/008-rockchip-allow-sdmmc-at-full-speed.patch create mode 100644 root/package/boot/uboot-rockchip/patches/009-rockchip-defconfig-add-gpio-v2-to-quartz64.patch create mode 100644 root/package/boot/uboot-rockchip/patches/010-rockchip-rk356x-enable-usb2-support-on-quartz64-a.patch create mode 100644 root/package/boot/uboot-rockchip/patches/011-rockchip-rk356x-attempt-to-fix-ram-detection.patch create mode 100644 root/package/boot/uboot-rockchip/patches/012-resync-rk3566-device-tree-with-mainline.patch create mode 100644 root/package/boot/uboot-rockchip/patches/013-rockchip-rk356x-add-bpi-r2-pro-board.patch create mode 100644 root/package/boot/uboot-rockchip/patches/014-uboot-add-Radxa-ROCK-3A-board.patch create mode 100644 root/package/boot/uboot-rockchip/patches/015-uboot-add-NanoPi-R5S-board.patch create mode 100644 root/package/boot/uboot-rockchip/patches/100-Convert-CONFIG_USB_OHCI_NEW-et-al-to-Kconfig.patch create mode 100644 root/package/boot/uboot-rockchip/patches/104-mkimage-add-public-key-for-image.patch create mode 100644 root/package/boot/uboot-rockchip/patches/105-Only-build-dtc-if-needed.patch create mode 100644 root/package/boot/uboot-rockchip/patches/106-no-kwbimage.patch delete mode 100644 root/package/boot/uboot-rockchip/patches/202-rockchip-rk3399-split-nanopi-r4s-out-of-evb_rk3399.patch delete mode 100644 root/package/boot/uboot-rockchip/patches/203-ram-rk3399-Add-support-for-multiple-DDR-types.patch create mode 100644 root/package/boot/uboot-rockchip/patches/203-rock64pro-disable-CONFIG_USE_PREBOOT.patch delete mode 100644 root/package/boot/uboot-rockchip/patches/204-board-nanopi4-unify-1GB-4GB-variants-of-R4S.patch create mode 100644 root/package/boot/uboot-rockchip/patches/301-arm64-dts-rockchip-Add-GuangMiao-G4C-support.patch create mode 100644 root/package/boot/uboot-rockchip/patches/302-rockchip-rk3328-Add-support-for-Orangepi-R1-Plus.patch create mode 100644 root/package/boot/uboot-rockchip/patches/303-rockchip-rk3328-Add-support-for-Orangepi-R1-Plus-LTS.patch create mode 100644 root/package/boot/uboot-rockchip/patches/304-rockchip-rk3328-Add-support-for-FriendlyARM-NanoPi-R.patch create mode 100644 root/package/boot/uboot-rockchip/patches/305-rockchip-rk3399-Add-support-for-FriendlyARM-NanoPi-R.patch create mode 100755 root/package/boot/uboot-rockchip/patches/306-rockchip-rk3399-Add-support-for-Rongpin-king3399.patch create mode 100644 root/package/boot/uboot-rockchip/patches/311-rockchip-rk3568-Add-support-for-ezpro_mrkaio-m68s.patch create mode 100644 root/package/boot/uboot-rockchip/patches/311-rockchip-rk3568-Add-support-for-radxa_rock-pi-e25.patch create mode 100644 root/package/boot/uboot-rockchip/patches/312-rockchip-rk3568-Add-support-for-hinlink-opc-h68k.patch create mode 100644 root/package/boot/uboot-rockchip/patches/313-rockchip-rk3568-Add-support-for-fastrhino-r66s.patch create mode 100644 root/package/boot/uboot-rockchip/patches/314-rockchip-rk3568-Add-support-for-Station-P2.patch delete mode 100644 root/package/boot/uboot-rockchip/src/of-platdata/nanopi-r2s-rk3328/dt-decl.h delete mode 100644 root/package/boot/uboot-rockchip/src/of-platdata/nanopi-r2s-rk3328/dt-plat.c delete mode 100644 root/package/boot/uboot-rockchip/src/of-platdata/nanopi-r2s-rk3328/dt-structs-gen.h diff --git a/root/package/boot/arm-trusted-firmware-rockchip-vendor/Makefile b/root/package/boot/arm-trusted-firmware-rockchip-vendor/Makefile new file mode 100644 index 00000000..88e9c070 --- /dev/null +++ b/root/package/boot/arm-trusted-firmware-rockchip-vendor/Makefile @@ -0,0 +1,81 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Copyright (C) 2022 ImmortalWrt.org + +include $(TOPDIR)/rules.mk + +PKG_NAME:=arm-trusted-firmware-rockchip-vendor +PKG_RELEASE:=$(AUTORELEASE) + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL=https://github.com/rockchip-linux/rkbin.git +PKG_SOURCE_DATE:=2022-08-01 +PKG_SOURCE_VERSION:=b0c100f1a260d807df450019774993c761beb79d +PKG_MIRROR_HASH:=17723ac8f6ec446c759444ee29ba4fe544cebb3785e26d8e10c91c54b9df3f1a + +PKG_MAINTAINER:=Tianling Shen + +MAKE_PATH:=$(PKG_NAME) + +include $(INCLUDE_DIR)/package.mk + +define Package/arm-trusted-firmware-rockchip-vendor + SECTION:=boot + CATEGORY:=Boot Loaders + TITLE:=ARM Trusted Firmware for Rockchip +endef + +define Package/arm-trusted-firmware-rk3328 + $(Package/arm-trusted-firmware-rockchip-vendor) + DEPENDS:=@TARGET_rockchip_armv8 + VARIANT:=rk3328 +endef + +define Package/arm-trusted-firmware-rk3399 + $(Package/arm-trusted-firmware-rockchip-vendor) + DEPENDS:=@TARGET_rockchip_armv8 + VARIANT:=rk3399 +endef + +define Package/arm-trusted-firmware-rk3568 + $(Package/arm-trusted-firmware-rockchip-vendor) + DEPENDS:=@TARGET_rockchip_armv8 + VARIANT:=rk3568 +endef + +define Package/arm-trusted-firmware-rk3588 + $(Package/arm-trusted-firmware-rockchip-vendor) + DEPENDS:=@TARGET_rockchip_armv8 + VARIANT:=rk3588 +endef + +define Build/Configure + $(SED) 's,$$$$(PKG_BUILD_DIR),$(PKG_BUILD_DIR),g' $(PKG_BUILD_DIR)/trust.ini + $(SED) 's,$$$$(VARIANT),$(BUILD_VARIANT),g' $(PKG_BUILD_DIR)/trust.ini + $(call Build/Configure/Default) +endef + +define Build/Compile + $(CURDIR)/pack-firmware.sh build $(BUILD_VARIANT) '$(PKG_BUILD_DIR)' +endef + +define Build/InstallDev + $(CURDIR)/pack-firmware.sh install $(BUILD_VARIANT) '$(PKG_BUILD_DIR)' '$(STAGING_DIR_IMAGE)' +endef + +define Package/arm-trusted-firmware-rk3328/install +endef + +define Package/arm-trusted-firmware-rk3399/install +endef + +define Package/arm-trusted-firmware-rk3568/install +endef + +define Package/arm-trusted-firmware-rk3588/install +endef + +$(eval $(call BuildPackage,arm-trusted-firmware-rk3328)) +$(eval $(call BuildPackage,arm-trusted-firmware-rk3399)) +$(eval $(call BuildPackage,arm-trusted-firmware-rk3568)) +$(eval $(call BuildPackage,arm-trusted-firmware-rk3588)) diff --git a/root/package/boot/arm-trusted-firmware-rockchip-vendor/pack-firmware.sh b/root/package/boot/arm-trusted-firmware-rockchip-vendor/pack-firmware.sh new file mode 100755 index 00000000..6dfb8917 --- /dev/null +++ b/root/package/boot/arm-trusted-firmware-rockchip-vendor/pack-firmware.sh @@ -0,0 +1,60 @@ +#!/bin/bash +# Copyright (C) 2021 ImmortalWrt.org + +ACTION="$1" +VARIANT="$2" +PKG_BUILD_DIR="$3" +STAGING_DIR_IMAGE="$4" + +case "$VARIANT" in +"rk3328") + ATF="rk33/rk322xh_bl31_v1.49.elf" + DDR="rk33/rk3328_ddr_333MHz_v1.19.bin" + LOADER="rk33/rk322xh_miniloader_v2.50.bin" + ;; +"rk3399") + ATF="rk33/rk3399_bl31_v1.35.elf" + DDR="rk33/rk3399_ddr_800MHz_v1.27.bin" + LOADER="rk33/rk3399_miniloader_v1.26.bin" + ;; +"rk3568") + ATF="rk35/rk3568_bl31_v1.28.elf" + DDR="rk35/rk3568_ddr_1560MHz_v1.13.bin" + ;; +"rk3588") + ATF="rk35/rk3588_bl31_v1.27.elf" + DDR="rk35/rk3588_ddr_lp4_2112MHz_lp5_2736MHz_v1.08.bin" + ;; +*) + echo -e "Not compatible with your platform: $VARIANT." + exit 1 + ;; +esac + +set -x +if [ "$ACTION" == "build" ]; then + case "$VARIANT" in + rk33*) + "$PKG_BUILD_DIR"/tools/mkimage -n "$VARIANT" -T "rksd" -d "$PKG_BUILD_DIR/bin/$DDR" "$PKG_BUILD_DIR/$VARIANT-idbloader.bin" + cat "$PKG_BUILD_DIR/bin/$LOADER" >> "$PKG_BUILD_DIR/$VARIANT-idbloader.bin" + "$PKG_BUILD_DIR/tools/trust_merger" --replace "bl31.elf" "$PKG_BUILD_DIR/bin/$ATF" "$PKG_BUILD_DIR/trust.ini" + ;; + esac +elif [ "$ACTION" == "install" ]; then + mkdir -p "$STAGING_DIR_IMAGE" + cp -fp "$PKG_BUILD_DIR/bin/$ATF" "$STAGING_DIR_IMAGE"/ + case "$VARIANT" in + rk33*) + cp -fp "$PKG_BUILD_DIR/tools/loaderimage" "$STAGING_DIR_IMAGE"/ + cp -fp "$PKG_BUILD_DIR/$VARIANT-idbloader.bin" "$STAGING_DIR_IMAGE"/ + cp -fp "$PKG_BUILD_DIR/$VARIANT-trust.bin" "$STAGING_DIR_IMAGE"/ + ;; + rk35*) + cp -fp "$PKG_BUILD_DIR/bin/$DDR" "$STAGING_DIR_IMAGE"/ + ;; + esac +else + echo -e "Unknown operation: $ACTION." + exit 1 +fi +set +x diff --git a/root/package/boot/arm-trusted-firmware-rockchip-vendor/src/bin/rk35/rk3568_bl31_v1.28.elf b/root/package/boot/arm-trusted-firmware-rockchip-vendor/src/bin/rk35/rk3568_bl31_v1.28.elf new file mode 100644 index 0000000000000000000000000000000000000000..459d0662702e4cdc614e7c652f957255b4716467 GIT binary patch literal 335928 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 literal 0 HcmV?d00001 diff --git a/root/package/boot/arm-trusted-firmware-rockchip-vendor/src/trust.ini b/root/package/boot/arm-trusted-firmware-rockchip-vendor/src/trust.ini new file mode 100644 index 00000000..17b0177b --- /dev/null +++ b/root/package/boot/arm-trusted-firmware-rockchip-vendor/src/trust.ini @@ -0,0 +1,15 @@ +[VERSION] +MAJOR=1 +MINOR=0 +[BL30_OPTION] +SEC=0 +[BL31_OPTION] +SEC=1 +PATH=bl31.elf +ADDR=0x10000 +[BL32_OPTION] +SEC=0 +[BL33_OPTION] +SEC=0 +[OUTPUT] +PATH=$(PKG_BUILD_DIR)/$(VARIANT)-trust.bin diff --git a/root/package/boot/arm-trusted-firmware-rockchip/Makefile b/root/package/boot/arm-trusted-firmware-rockchip/Makefile new file mode 100644 index 00000000..b712a353 --- /dev/null +++ b/root/package/boot/arm-trusted-firmware-rockchip/Makefile @@ -0,0 +1,49 @@ +# +# Copyright (C) 2020 Tobias Maedel +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=arm-trusted-firmware-rockchip +PKG_VERSION:=2.3 +PKG_RELEASE:=1 + +PKG_SOURCE:=atf-v$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://github.com/atf-builds/atf/releases/download/v$(PKG_VERSION)/atf-v$(PKG_VERSION).tar.gz? +PKG_HASH:=bf352298743aed594cf2958dd588e06ab6713fc514bb6f809bf55a85a87134c1 + +PKG_LICENSE:=BSD-3-Clause +PKG_LICENSE_FILES:=license.md + +PKG_MAINTAINER:=Tobias Maedel + +MAKE_PATH:=$(PKG_NAME) + +include $(INCLUDE_DIR)/package.mk + +define Package/arm-trusted-firmware-rockchip + SECTION:=boot + CATEGORY:=Boot Loaders + TITLE:=ARM Trusted Firmware for Rockchip + DEPENDS:=@TARGET_rockchip_armv8 +endef + +define Build/Prepare + $(TAR) -C $(PKG_BUILD_DIR) -xf $(DL_DIR)/$(PKG_SOURCE) +endef + +define Build/Compile +endef + +define Build/InstallDev + $(INSTALL_DIR) -p $(STAGING_DIR_IMAGE) + $(CP) $(PKG_BUILD_DIR)/rk*.elf $(STAGING_DIR_IMAGE)/ +endef + +define Package/arm-trusted-firmware-rockchip/install +endef + +$(eval $(call BuildPackage,arm-trusted-firmware-rockchip)) diff --git a/root/package/boot/uboot-rockchip/Makefile b/root/package/boot/uboot-rockchip/Makefile index 17eb2711..a1cd9051 100644 --- a/root/package/boot/uboot-rockchip/Makefile +++ b/root/package/boot/uboot-rockchip/Makefile @@ -5,10 +5,10 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk -PKG_VERSION:=2021.07 -PKG_RELEASE:=1 +PKG_VERSION:=2022.07 +PKG_RELEASE:=$(AUTORELEASE) -PKG_HASH:=312b7eeae44581d1362c3a3f02c28d806647756c82ba8c72241c7cdbe68ba77e +PKG_HASH:=92b08eb49c24da14c1adbf70a71ae8f37cc53eeb4230e859ad8b6733d13dcf5e PKG_MAINTAINER:=Tobias Maedel @@ -24,35 +24,102 @@ endef # RK3328 boards +define U-Boot/nanopi-r2c-rk3328 + BUILD_SUBTARGET:=armv8 + NAME:=NanoPi R2C + BUILD_DEVICES:= \ + friendlyarm_nanopi-r2c + DEPENDS:=+PACKAGE_u-boot-nanopi-r2c-rk3328:arm-trusted-firmware-rk3328 + PKG_BUILD_DEPENDS:=arm-trusted-firmware-rockchip-vendor + ATF:=rk322xh_bl31_v1.49.elf + USE_RKBIN:=1 +endef + define U-Boot/nanopi-r2s-rk3328 BUILD_SUBTARGET:=armv8 NAME:=NanoPi R2S BUILD_DEVICES:= \ - friendlyarm_nanopi-r2s - DEPENDS:=+PACKAGE_u-boot-nanopi-r2s-rk3328:arm-trusted-firmware-rockchip - PKG_BUILD_DEPENDS:=arm-trusted-firmware-rockchip - ATF:=rk3328_bl31.elf - OF_PLATDATA:=$(1) + friendlyarm_nanopi-r2s \ + friendlyarm_nanopi-neo3 + DEPENDS:=+PACKAGE_u-boot-nanopi-r2s-rk3328:arm-trusted-firmware-rk3328 + PKG_BUILD_DEPENDS:=arm-trusted-firmware-rockchip-vendor + ATF:=rk322xh_bl31_v1.49.elf + USE_RKBIN:=1 +endef + +define U-Boot/orangepi-r1-plus-rk3328 + BUILD_SUBTARGET:=armv8 + NAME:=Orange Pi R1 Plus + BUILD_DEVICES:= \ + xunlong_orangepi-r1-plus + DEPENDS:=+PACKAGE_u-boot-orangepi-r1-plus-rk3328:arm-trusted-firmware-rk3328 + PKG_BUILD_DEPENDS:=arm-trusted-firmware-rockchip-vendor + ATF:=rk322xh_bl31_v1.49.elf + USE_RKBIN:=1 +endef + +define U-Boot/orangepi-r1-plus-lts-rk3328 + BUILD_SUBTARGET:=armv8 + NAME:=Orange Pi R1 Plus LTS + BUILD_DEVICES:= \ + xunlong_orangepi-r1-plus-lts + DEPENDS:=+PACKAGE_u-boot-orangepi-r1-plus-lts-rk3328:arm-trusted-firmware-rk3328 + PKG_BUILD_DEPENDS:=arm-trusted-firmware-rockchip-vendor + ATF:=rk322xh_bl31_v1.49.elf + USE_RKBIN:=1 endef # RK3399 boards +define U-Boot/guangmiao-g4c-rk3399 + BUILD_SUBTARGET:=armv8 + NAME:=GuangMiao G4C + BUILD_DEVICES:= \ + sharevdi_guangmiao-g4c + DEPENDS:=+PACKAGE_u-boot-guangmiao-g4c-rk3399:arm-trusted-firmware-rockchip + PKG_BUILD_DEPENDS:=arm-trusted-firmware-rockchip + ATF:=rk3399_bl31.elf +endef + define U-Boot/nanopi-r4s-rk3399 BUILD_SUBTARGET:=armv8 NAME:=NanoPi R4S BUILD_DEVICES:= \ friendlyarm_nanopi-r4s - DEPENDS:=+PACKAGE_u-boot-nanopi-r4s-rk3399:arm-trusted-firmware-rockchip - PKG_BUILD_DEPENDS:=arm-trusted-firmware-rockchip - ATF:=rk3399_bl31.elf + DEPENDS:=+PACKAGE_u-boot-nanopi-r4s-rk3399:arm-trusted-firmware-rk3399 + PKG_BUILD_DEPENDS:=arm-trusted-firmware-rockchip-vendor + ATF:=rk3399_bl31_v1.35.elf + USE_RKBIN:=1 +endef + +define U-Boot/nanopi-r4se-rk3399 + BUILD_SUBTARGET:=armv8 + NAME:=NanoPi R4SE + BUILD_DEVICES:= \ + friendlyarm_nanopi-r4se + DEPENDS:=+PACKAGE_u-boot-nanopi-r4se-rk3399:arm-trusted-firmware-rk3399 + PKG_BUILD_DEPENDS:=arm-trusted-firmware-rockchip-vendor + ATF:=rk3399_bl31_v1.35.elf + USE_RKBIN:=1 +endef + +define U-Boot/nanopi-r5s-rk3568 + BUILD_SUBTARGET:=armv8 + NAME:=NanoPi R5S + BUILD_DEVICES:= \ + friendlyarm_nanopi-r5s + DEPENDS:=+PACKAGE_u-boot-nanopi-r5s-rk3568:arm-trusted-firmware-rk3568 + PKG_BUILD_DEPENDS:=arm-trusted-firmware-rockchip-vendor + ATF:=rk3568_bl31_v1.28.elf + DDR:=rk3568_ddr_1560MHz_v1.13.bin endef define U-Boot/rock-pi-4-rk3399 BUILD_SUBTARGET:=armv8 NAME:=Rock Pi 4 BUILD_DEVICES:= \ - radxa_rock-pi-4a + radxa_rock-pi-4 DEPENDS:=+PACKAGE_u-boot-rock-pi-4-rk3399:arm-trusted-firmware-rockchip PKG_BUILD_DEPENDS:=arm-trusted-firmware-rockchip ATF:=rk3399_bl31.elf @@ -68,11 +135,104 @@ define U-Boot/rockpro64-rk3399 ATF:=rk3399_bl31.elf endef +define U-Boot/rongpin-king3399-rk3399 + BUILD_SUBTARGET:=armv8 + NAME:=Rongpin King3399 + BUILD_DEVICES:= \ + rongpin_king3399 + DEPENDS:=+PACKAGE_u-boot-rongpin-king3399-rk3399:arm-trusted-firmware-rk3399 + PKG_BUILD_DEPENDS:=arm-trusted-firmware-rockchip-vendor + ATF:=rk3399_bl31_v1.35.elf + USE_RKBIN:=1 +endef + +# RK3568 boards + +define U-Boot/mrkaio-m68s-rk3568 + BUILD_SUBTARGET:=armv8 + NAME:=Mrkaio M68S + BUILD_DEVICES:= \ + ezpro_mrkaio-m68s + DEPENDS:=+PACKAGE_u-boot-mrkaio-m68s-rk3568:arm-trusted-firmware-rk3568 + PKG_BUILD_DEPENDS:=arm-trusted-firmware-rockchip-vendor + ATF:=rk3568_bl31_v1.28.elf + DDR:=rk3568_ddr_1560MHz_v1.13.bin +endef + +define U-Boot/opc-h68k-rk3568 + BUILD_SUBTARGET:=armv8 + NAME:=OPC-H68K Board + BUILD_DEVICES:= \ + hinlink_opc-h68k + DEPENDS:=+PACKAGE_u-boot-opc-h68k-rk3568:arm-trusted-firmware-rk3568 + PKG_BUILD_DEPENDS:=arm-trusted-firmware-rockchip-vendor + ATF:=rk3568_bl31_v1.28.elf + DDR:=rk3568_ddr_1560MHz_v1.13.bin +endef + +define U-Boot/rock-3a-rk3568 + BUILD_SUBTARGET:=armv8 + NAME:=ROCK3 Model A + BUILD_DEVICES:= \ + radxa_rock-3a + DEPENDS:=+PACKAGE_u-boot-rock-3a-rk3568:arm-trusted-firmware-rk3568 + PKG_BUILD_DEPENDS:=arm-trusted-firmware-rockchip-vendor + ATF:=rk3568_bl31_v1.28.elf + DDR:=rk3568_ddr_1560MHz_v1.13.bin +endef + +define U-Boot/rock-pi-e25-rk3568 + BUILD_SUBTARGET:=armv8 + NAME:=ROCK Pi E25 + BUILD_DEVICES:= \ + radxa_rock-pi-e25 + DEPENDS:=+PACKAGE_u-boot-rock-pi-e25-rk3568:arm-trusted-firmware-rk3568 + PKG_BUILD_DEPENDS:=arm-trusted-firmware-rockchip-vendor + ATF:=rk3568_bl31_v1.28.elf + DDR:=rk3568_ddr_1560MHz_v1.13.bin +endef + +define U-Boot/r66s-rk3568 + BUILD_SUBTARGET:=armv8 + NAME:=R66S/R68S + BUILD_DEVICES:= \ + fastrhino_r66s \ + fastrhino_r68s + DEPENDS:=+PACKAGE_u-boot-r66s-rk3568:arm-trusted-firmware-rk3568 + PKG_BUILD_DEPENDS:=arm-trusted-firmware-rockchip-vendor + ATF:=rk3568_bl31_v1.28.elf + DDR:=rk3568_ddr_1560MHz_v1.13.bin +endef + +define U-Boot/station-p2-rk3568 + BUILD_SUBTARGET:=armv8 + NAME:=StationP2 + BUILD_DEVICES:= \ + firefly_station-p2 + DEPENDS:=+PACKAGE_u-boot-station-p2-rk3568:arm-trusted-firmware-rk3568 + PKG_BUILD_DEPENDS:=arm-trusted-firmware-rockchip-vendor + ATF:=rk3568_bl31_v1.28.elf + DDR:=rk3568_ddr_1560MHz_v1.13.bin +endef + UBOOT_TARGETS := \ + mrkaio-m68s-rk3568 \ + opc-h68k-rk3568 \ + rock-3a-rk3568 \ + rock-pi-e25-rk3568 \ + r66s-rk3568 \ + station-p2-rk3568 \ + guangmiao-g4c-rk3399 \ nanopi-r4s-rk3399 \ + nanopi-r4se-rk3399 \ + nanopi-r5s-rk3568 \ rock-pi-4-rk3399 \ rockpro64-rk3399 \ - nanopi-r2s-rk3328 + rongpin-king3399-rk3399 \ + nanopi-r2c-rk3328 \ + nanopi-r2s-rk3328 \ + orangepi-r1-plus-rk3328 \ + orangepi-r1-plus-lts-rk3328 UBOOT_CONFIGURE_VARS += USE_PRIVATE_LIBGCC=yes @@ -82,23 +242,23 @@ UBOOT_MAKE_FLAGS += \ define Build/Configure $(call Build/Configure/U-Boot) -ifneq ($(OF_PLATDATA),) - mkdir -p $(PKG_BUILD_DIR)/tpl/dts - mkdir -p $(PKG_BUILD_DIR)/include/generated - - $(CP) $(PKG_BUILD_DIR)/of-platdata/$(OF_PLATDATA)/dt-plat.c $(PKG_BUILD_DIR)/tpl/dts/dt-plat.c - $(CP) $(PKG_BUILD_DIR)/of-platdata/$(OF_PLATDATA)/dt-structs-gen.h $(PKG_BUILD_DIR)/include/generated/dt-structs-gen.h - $(CP) $(PKG_BUILD_DIR)/of-platdata/$(OF_PLATDATA)/dt-decl.h $(PKG_BUILD_DIR)/include/generated/dt-decl.h -endif - + $(SED) 's/CONFIG_TOOLS_LIBCRYPTO=y/# CONFIG_TOOLS_LIBCRYPTO is not set/' $(PKG_BUILD_DIR)/.config $(SED) 's#CONFIG_MKIMAGE_DTC_PATH=.*#CONFIG_MKIMAGE_DTC_PATH="$(PKG_BUILD_DIR)/scripts/dtc/dtc"#g' $(PKG_BUILD_DIR)/.config echo 'CONFIG_IDENT_STRING=" OpenWrt"' >> $(PKG_BUILD_DIR)/.config +ifneq ($(DDR),) + $(CP) $(STAGING_DIR_IMAGE)/$(DDR) $(PKG_BUILD_DIR)/ram_init.bin +endif endef define Build/InstallDev $(INSTALL_DIR) $(STAGING_DIR_IMAGE) +ifneq ($(USE_RKBIN),) + $(STAGING_DIR_IMAGE)/loaderimage --pack --uboot $(PKG_BUILD_DIR)/u-boot-dtb.bin $(PKG_BUILD_DIR)/uboot.img 0x200000 + $(CP) $(PKG_BUILD_DIR)/uboot.img $(STAGING_DIR_IMAGE)/$(BUILD_VARIANT)-uboot.img +else $(CP) $(PKG_BUILD_DIR)/idbloader.img $(STAGING_DIR_IMAGE)/$(BUILD_VARIANT)-idbloader.img $(CP) $(PKG_BUILD_DIR)/u-boot.itb $(STAGING_DIR_IMAGE)/$(BUILD_VARIANT)-u-boot.itb +endif endef define Package/u-boot/install/default diff --git a/root/package/boot/uboot-rockchip/patches/001-rockchip-rk3568-add-boot-device-detection.patch b/root/package/boot/uboot-rockchip/patches/001-rockchip-rk3568-add-boot-device-detection.patch new file mode 100644 index 00000000..b3dd3099 --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/001-rockchip-rk3568-add-boot-device-detection.patch @@ -0,0 +1,43 @@ +From 9b92a43a4f5acf4cba14fd9d473b3120688532dc Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Sun, 19 Dec 2021 08:10:24 -0500 +Subject: [PATCH 01/11] rockchip: rk3568: add boot device detection + +Enable spl to detect which device it was booted from. + +Signed-off-by: Peter Geis +--- + arch/arm/mach-rockchip/rk3568/rk3568.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/arch/arm/mach-rockchip/rk3568/rk3568.c ++++ b/arch/arm/mach-rockchip/rk3568/rk3568.c +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -23,6 +24,7 @@ + #define SGRF_SOC_CON4 0x10 + #define EMMC_HPROT_SECURE_CTRL 0x03 + #define SDMMC0_HPROT_SECURE_CTRL 0x01 ++ + /* PMU_GRF_GPIO0D_IOMUX_L */ + enum { + GPIO0D1_SHIFT = 4, +@@ -43,6 +45,12 @@ enum { + UART2_IO_SEL_M0 = 0, + }; + ++const char * const boot_devices[BROM_LAST_BOOTSOURCE + 1] = { ++ [BROM_BOOTSOURCE_EMMC] = "/sdhci@fe310000", ++ [BROM_BOOTSOURCE_SPINOR] = "/spi@fe300000/flash@0", ++ [BROM_BOOTSOURCE_SD] = "/mmc@fe2b0000", ++}; ++ + static struct mm_region rk3568_mem_map[] = { + { + .virt = 0x0UL, diff --git a/root/package/boot/uboot-rockchip/patches/001-scripts-remove-dependency-on-swig.patch b/root/package/boot/uboot-rockchip/patches/001-scripts-remove-dependency-on-swig.patch deleted file mode 100644 index 05055893..00000000 --- a/root/package/boot/uboot-rockchip/patches/001-scripts-remove-dependency-on-swig.patch +++ /dev/null @@ -1,24 +0,0 @@ -From b137ca16b54c67d76714ea5a0138741959b0dc29 Mon Sep 17 00:00:00 2001 -From: David Bauer -Date: Mon, 13 Jul 2020 23:37:37 +0200 -Subject: [PATCH] scripts: remove dependency on swig - -Don't build the libfdt tool, as it has a dependency on swig (which -OpenWrt does not ship). - -This requires more hacks, as of-platdata generation does not work -without it. - -Signed-off-by: David Bauer ---- - scripts/dtc/Makefile | 2 -- - 1 file changed, 2 deletions(-) - ---- a/scripts/dtc/Makefile -+++ b/scripts/dtc/Makefile -@@ -18,5 +18,3 @@ HOSTCFLAGS_dtc-parser.tab.o := -I$(src) - # dependencies on generated files need to be listed explicitly - $(obj)/dtc-lexer.lex.o: $(obj)/dtc-parser.tab.h - --# Added for U-Boot --subdir-$(CONFIG_PYLIBFDT) += pylibfdt diff --git a/root/package/boot/uboot-rockchip/patches/002-rockchip-rk3568-enable-automatic-power-savings.patch b/root/package/boot/uboot-rockchip/patches/002-rockchip-rk3568-enable-automatic-power-savings.patch new file mode 100644 index 00000000..f38d9f4d --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/002-rockchip-rk3568-enable-automatic-power-savings.patch @@ -0,0 +1,52 @@ +From 09d877cf076cbb67c79054e12bbb7c63a91faa71 Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Sun, 19 Dec 2021 08:11:56 -0500 +Subject: [PATCH 02/11] rockchip: rk3568: enable automatic power savings + +Enable automatic clock gating, solves the 7c temperature difference on +SoQuartz. + +Signed-off-by: Peter Geis +--- + arch/arm/mach-rockchip/rk3568/rk3568.c | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +--- a/arch/arm/mach-rockchip/rk3568/rk3568.c ++++ b/arch/arm/mach-rockchip/rk3568/rk3568.c +@@ -25,6 +25,15 @@ + #define EMMC_HPROT_SECURE_CTRL 0x03 + #define SDMMC0_HPROT_SECURE_CTRL 0x01 + ++#define PMU_BASE_ADDR 0xfdd90000 ++#define PMU_NOC_AUTO_CON0 (0x70) ++#define PMU_NOC_AUTO_CON1 (0x74) ++#define EDP_PHY_GRF_BASE 0xfdcb0000 ++#define EDP_PHY_GRF_CON0 (EDP_PHY_GRF_BASE + 0x00) ++#define EDP_PHY_GRF_CON10 (EDP_PHY_GRF_BASE + 0x28) ++#define CPU_GRF_BASE 0xfdc30000 ++#define GRF_CORE_PVTPLL_CON0 (0x10) ++ + /* PMU_GRF_GPIO0D_IOMUX_L */ + enum { + GPIO0D1_SHIFT = 4, +@@ -99,6 +108,20 @@ void board_debug_uart_init(void) + int arch_cpu_init(void) + { + #ifdef CONFIG_SPL_BUILD ++ /* ++ * When perform idle operation, corresponding clock can ++ * be opened or gated automatically. ++ */ ++ writel(0xffffffff, PMU_BASE_ADDR + PMU_NOC_AUTO_CON0); ++ writel(0x000f000f, PMU_BASE_ADDR + PMU_NOC_AUTO_CON1); ++ ++ /* Disable eDP phy by default */ ++ writel(0x00070007, EDP_PHY_GRF_CON10); ++ writel(0x0ff10ff1, EDP_PHY_GRF_CON0); ++ ++ /* Set core pvtpll ring length */ ++ writel(0x00ff002b, CPU_GRF_BASE + GRF_CORE_PVTPLL_CON0); ++ + /* Set the emmc sdmmc0 to secure */ + rk_clrreg(SGRF_BASE + SGRF_SOC_CON4, (EMMC_HPROT_SECURE_CTRL << 11 + | SDMMC0_HPROT_SECURE_CTRL << 4)); diff --git a/root/package/boot/uboot-rockchip/patches/002-spl-remove-dtoc-of-pdata-generation.patch b/root/package/boot/uboot-rockchip/patches/002-spl-remove-dtoc-of-pdata-generation.patch deleted file mode 100644 index 14bcbfb6..00000000 --- a/root/package/boot/uboot-rockchip/patches/002-spl-remove-dtoc-of-pdata-generation.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 55273cf6079ddd3b006da69f0113c2c66c03f17e Mon Sep 17 00:00:00 2001 -From: David Bauer -Date: Tue, 14 Jul 2020 22:44:22 +0200 -Subject: [PATCH] spl: remove dtoc of-pdata generation - -Remove the dtoc of-pdata generation. This generation is dependant on -libpython-dev. As OpenWrt does not ship with this dependency, use -pre-generated pdata files and remove the generation from the -build-process. - -This only affects RK3328 boards. - -Signed-off-by: David Bauer ---- - scripts/Makefile.spl | 6 ------ - 1 file changed, 6 deletions(-) - ---- a/scripts/Makefile.spl -+++ b/scripts/Makefile.spl -@@ -354,8 +354,6 @@ $(platdata-hdr) $(u-boot-spl-platdata_c) - @# of OF_PLATDATA_INST and this might change between builds. Leaving old - @# ones around is confusing and it is possible that switching the - @# setting again will use the old one instead of regenerating it. -- @rm -f $(u-boot-spl-all-platdata_c) $(u-boot-spl-all-platdata) -- $(call if_changed,dtoc) - - ifdef CONFIG_SAMSUNG - ifdef CONFIG_VAR_SIZE_SPL diff --git a/root/package/boot/uboot-rockchip/patches/003-Makefile-rockchip-HACK-build-rk3568-images.patch b/root/package/boot/uboot-rockchip/patches/003-Makefile-rockchip-HACK-build-rk3568-images.patch new file mode 100644 index 00000000..5a817301 --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/003-Makefile-rockchip-HACK-build-rk3568-images.patch @@ -0,0 +1,47 @@ +From ddbcec939789d1f7264134b3628ffb649ec88168 Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Sun, 19 Dec 2021 08:20:33 -0500 +Subject: [PATCH 03/11] Makefile: rockchip: HACK: build rk3568 images + +This is a hack to build rk3568 images. +It seems makefile can't cope with the format mkimage expects for +multiple file entries, so hack around the situation. + +Signed-off-by: Peter Geis +--- + Makefile | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/Makefile ++++ b/Makefile +@@ -1047,6 +1047,9 @@ quiet_cmd_mkimage = MKIMAGE $@ + cmd_mkimage = $(objtree)/tools/mkimage $(MKIMAGEFLAGS_$(@F)) -d $< $@ \ + >$(MKIMAGEOUTPUT) $(if $(KBUILD_VERBOSE:0=), && cat $(MKIMAGEOUTPUT)) + ++cmd_mkimage_combined = $(objtree)/tools/mkimage $(MKIMAGEFLAGS_$(@F)) -d $(COMBINED_FILE):$< $@ \ ++ >$(MKIMAGEOUTPUT) $(if $(KBUILD_VERBOSE:0=), && cat $(MKIMAGEOUTPUT)) ++ + quiet_cmd_mkfitimage = MKIMAGE $@ + cmd_mkfitimage = $(objtree)/tools/mkimage $(MKIMAGEFLAGS_$(@F)) \ + -f $(U_BOOT_ITS) -p $(CONFIG_FIT_EXTERNAL_OFFSET) $@ \ +@@ -1491,6 +1494,7 @@ u-boot-with-spl.bin: $(SPL_IMAGE) $(SPL_ + ifeq ($(CONFIG_ARCH_ROCKCHIP),y) + + # TPL + SPL ++ifneq ($(CONFIG_SYS_SOC),$(filter $(CONFIG_SYS_SOC),"rk3568" "rk3566")) + ifeq ($(CONFIG_SPL)$(CONFIG_TPL),yy) + MKIMAGEFLAGS_u-boot-tpl-rockchip.bin = -n $(CONFIG_SYS_SOC) -T rksd + tpl/u-boot-tpl-rockchip.bin: tpl/u-boot-tpl.bin FORCE +@@ -1502,6 +1506,12 @@ MKIMAGEFLAGS_idbloader.img = -n $(CONFIG + idbloader.img: spl/u-boot-spl.bin FORCE + $(call if_changed,mkimage) + endif ++else ++MKIMAGEFLAGS_idbloader.img = -n $(CONFIG_SYS_SOC) -T rksd ++COMBINED_FILE = ram_init.bin ++idbloader.img: spl/u-boot-spl.bin FORCE ++ $(call if_changed,mkimage_combined) ++endif + + ifeq ($(CONFIG_ARM64),y) + OBJCOPYFLAGS_u-boot-rockchip.bin = -I binary -O binary \ diff --git a/root/package/boot/uboot-rockchip/patches/004-arm-dts-sync-rk3568-with-linux.patch b/root/package/boot/uboot-rockchip/patches/004-arm-dts-sync-rk3568-with-linux.patch new file mode 100644 index 00000000..422f1c4d --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/004-arm-dts-sync-rk3568-with-linux.patch @@ -0,0 +1,3520 @@ +From 25624318957d560ce58be672fe2fa8537716afc7 Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Sun, 19 Dec 2021 15:14:47 -0500 +Subject: [PATCH 04/11] arm: dts: sync rk3568 with linux + +Signed-off-by: Peter Geis +--- + arch/arm/dts/Makefile | 3 +- + arch/arm/dts/rk3566-quartz64-a-u-boot.dtsi | 24 + + arch/arm/dts/rk3566-quartz64-a.dts | 860 +++++++++++ + arch/arm/dts/rk3566.dtsi | 32 + + arch/arm/dts/rk3568-evb.dts | 5 + + arch/arm/dts/rk3568-pinctrl.dtsi | 9 + + arch/arm/dts/rk3568.dtsi | 860 ++--------- + arch/arm/dts/rk356x.dtsi | 1630 ++++++++++++++++++++ + arch/arm/mach-rockchip/rk3568/rk3568.c | 2 +- + 9 files changed, 2672 insertions(+), 753 deletions(-) + create mode 100644 arch/arm/dts/rk3566-quartz64-a-u-boot.dtsi + create mode 100644 arch/arm/dts/rk3566-quartz64-a.dts + create mode 100644 arch/arm/dts/rk3566.dtsi + create mode 100644 arch/arm/dts/rk356x.dtsi + +--- a/arch/arm/dts/Makefile ++++ b/arch/arm/dts/Makefile +@@ -164,7 +164,8 @@ dtb-$(CONFIG_ROCKCHIP_RK3399) += \ + rk3399pro-rock-pi-n10.dtb + + dtb-$(CONFIG_ROCKCHIP_RK3568) += \ +- rk3568-evb.dtb ++ rk3568-evb.dtb \ ++ rk3566-quartz64-a.dtb + + dtb-$(CONFIG_ROCKCHIP_RV1108) += \ + rv1108-elgin-r1.dtb \ +--- /dev/null ++++ b/arch/arm/dts/rk3566-quartz64-a-u-boot.dtsi +@@ -0,0 +1,24 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * (C) Copyright 2021 Rockchip Electronics Co., Ltd ++ */ ++ ++#include "rk3568-u-boot.dtsi" ++ ++/ { ++ chosen { ++ stdout-path = &uart2; ++ u-boot,spl-boot-order = "same-as-spl", &sdmmc0, &sdhci; ++ }; ++}; ++ ++&sdmmc0 { ++ u-boot,dm-spl; ++ status = "okay"; ++}; ++ ++&uart2 { ++ clock-frequency = <24000000>; ++ u-boot,dm-spl; ++ status = "okay"; ++}; +--- /dev/null ++++ b/arch/arm/dts/rk3566-quartz64-a.dts +@@ -0,0 +1,860 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++/dts-v1/; ++ ++#include ++#include ++#include "rk3566.dtsi" ++ ++/ { ++ model = "Pine64 RK3566 Quartz64-A Board"; ++ compatible = "pine64,quartz64-a", "rockchip,rk3566"; ++ ++ aliases { ++ ethernet0 = &gmac1; ++ mmc0 = &sdmmc0; ++ mmc1 = &sdhci; ++ }; ++ ++ chosen: chosen { ++ stdout-path = "serial2:1500000n8"; ++ }; ++ ++ battery_cell: battery-cell { ++ compatible = "simple-battery"; ++ charge-full-design-microamp-hours = <2500000>; ++ charge-term-current-microamp = <300000>; ++ constant-charge-current-max-microamp = <2000000>; ++ constant-charge-voltage-max-microvolt = <4200000>; ++ factory-internal-resistance-micro-ohms = <180000>; ++ voltage-max-design-microvolt = <4106000>; ++ voltage-min-design-microvolt = <3625000>; ++ ++ ocv-capacity-celsius = <20>; ++ ocv-capacity-table-0 = <4106000 100>, <4071000 95>, <4018000 90>, <3975000 85>, ++ <3946000 80>, <3908000 75>, <3877000 70>, <3853000 65>, ++ <3834000 60>, <3816000 55>, <3802000 50>, <3788000 45>, ++ <3774000 40>, <3760000 35>, <3748000 30>, <3735000 25>, ++ <3718000 20>, <3697000 15>, <3685000 10>, <3625000 0>; ++ }; ++ ++ gmac1_clkin: external-gmac1-clock { ++ compatible = "fixed-clock"; ++ clock-frequency = <125000000>; ++ clock-output-names = "gmac1_clkin"; ++ #clock-cells = <0>; ++ }; ++ ++ fan: gpio_fan { ++ compatible = "gpio-fan"; ++ gpios = <&gpio0 RK_PD5 GPIO_ACTIVE_HIGH>; ++ gpio-fan,speed-map = <0 0 ++ 4500 1>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&fan_en_h>; ++ #cooling-cells = <2>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led-work { ++ label = "work-led"; ++ default-state = "off"; ++ gpios = <&gpio0 RK_PD3 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&work_led_enable_h>; ++ retain-state-suspended; ++ }; ++ ++ led-diy { ++ label = "diy-led"; ++ default-state = "on"; ++ gpios = <&gpio0 RK_PD4 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "heartbeat"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&diy_led_enable_h>; ++ retain-state-suspended; ++ }; ++ }; ++ ++ rk817-sound { ++ compatible = "simple-audio-card"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&hp_det_h>; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,hp-det-gpio = <&gpio0 RK_PC4 GPIO_ACTIVE_HIGH>; ++ simple-audio-card,name = "Analog RK817"; ++ simple-audio-card,mclk-fs = <256>; ++ simple-audio-card,widgets = ++ "Microphone", "Mic Jack", ++ "Headphone", "Headphones", ++ "Speaker", "Speaker"; ++ simple-audio-card,routing = ++ "MICL", "Mic Jack", ++ "Headphones", "HPOL", ++ "Headphones", "HPOR", ++ "Speaker", "SPKO"; ++ ++ simple-audio-card,cpu { ++ sound-dai = <&i2s1_8ch>; ++ }; ++ ++ simple-audio-card,codec { ++ sound-dai = <&rk817>; ++ }; ++ }; ++ ++ spdif_dit: spdif-dit { ++ compatible = "linux,spdif-dit"; ++ #sound-dai-cells = <0>; ++ }; ++ ++ spdif_sound: spdif-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,name = "SPDIF"; ++ ++ simple-audio-card,cpu { ++ sound-dai = <&spdif>; ++ }; ++ ++ simple-audio-card,codec { ++ sound-dai = <&spdif_dit>; ++ }; ++ }; ++ ++ sdio_pwrseq: sdio-pwrseq { ++ status = "okay"; ++ compatible = "mmc-pwrseq-simple"; ++ clocks = <&rk817 1>; ++ clock-names = "ext_clock"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&wifi_enable_h>; ++ reset-gpios = <&gpio2 RK_PC2 GPIO_ACTIVE_LOW>; ++ post-power-on-delay-ms = <100>; ++ power-off-delay-us = <5000000>; ++ }; ++ ++ spdif_sound: spdif-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,name = "SPDIF"; ++ ++ simple-audio-card,cpu { ++ sound-dai = <&spdif>; ++ }; ++ ++ simple-audio-card,codec { ++ sound-dai = <&spdif_dit>; ++ }; ++ }; ++ ++ spdif_dit: spdif-dit { ++ compatible = "linux,spdif-dit"; ++ #sound-dai-cells = <0>; ++ }; ++ ++ vcc12v_dcin: vcc12v_dcin { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc12v_dcin"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <12000000>; ++ regulator-max-microvolt = <12000000>; ++ }; ++ ++ /* vbus feeds the rk817 usb input. ++ * With no battery attached, also feeds vcc_bat+ ++ * via ON/OFF_BAT jumper ++ */ ++ vbus: vbus { ++ compatible = "regulator-fixed"; ++ regulator-name = "vbus"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc12v_dcin>; ++ }; ++ ++ vcc5v0_usb: vcc5v0_usb { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_usb"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc12v_dcin>; ++ }; ++ ++ /* all four ports are controlled by one gpio ++ * the host ports are sourced from vcc5v0_usb ++ * the otg port is sourced from vcc5v0_midu ++ */ ++ vcc5v0_usb20_host: vcc5v0_usb20_host { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_usb20_host"; ++ enable-active-high; ++ gpio = <&gpio4 RK_PB5 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&vcc5v0_usb20_host_en_h>; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc5v0_usb>; ++ }; ++ ++ vcc5v0_usb20_otg: vcc5v0_usb20_otg { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_usb20_otg"; ++ enable-active-high; ++ gpio = <&gpio4 RK_PB5 GPIO_ACTIVE_HIGH>; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&dcdc_boost>; ++ }; ++ ++ vcc3v3_pcie_p: vcc3v3_pcie_p { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio0 RK_PC6 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pcie_enable_h>; ++ regulator-name = "vcc3v3_pcie_p"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc_3v3>; ++ }; ++ ++ vcc3v3_sd: vcc3v3_sd { ++ compatible = "regulator-fixed"; ++ enable-active-low; ++ gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_LOW>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&vcc_sd_h>; ++ regulator-boot-on; ++ regulator-name = "vcc3v3_sd"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc_3v3>; ++ }; ++ ++ /* sourced from vbus and vcc_bat+ via rk817 sw5 */ ++ vcc_sys: vcc_sys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <4400000>; ++ regulator-max-microvolt = <4400000>; ++ vin-supply = <&vbus>; ++ }; ++ ++ /* sourced from vcc_sys, sdio module operates internally at 3.3v */ ++ vcc_wl: vcc_wl { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_wl"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc_sys>; ++ }; ++}; ++ ++&combphy1_usq { ++ status = "okay"; ++ rockchip,enable-ssc; ++}; ++ ++&combphy2_psq { ++ status = "okay"; ++}; ++ ++&cpu0 { ++ cpu-supply = <&vdd_cpu>; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vdd_cpu>; ++}; ++ ++&cpu2 { ++ cpu-supply = <&vdd_cpu>; ++}; ++ ++&cpu3 { ++ cpu-supply = <&vdd_cpu>; ++}; ++ ++&cpu_thermal { ++ trips { ++ cpu_hot: cpu_hot { ++ temperature = <55000>; ++ hysteresis = <2000>; ++ type = "active"; ++ }; ++ }; ++ ++ cooling-maps { ++ map1 { ++ trip = <&cpu_hot>; ++ cooling-device = <&fan THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; ++ }; ++ }; ++}; ++ ++&gmac1 { ++ assigned-clocks = <&cru SCLK_GMAC1_RX_TX>, <&cru SCLK_GMAC1_RGMII_SPEED>, <&cru SCLK_GMAC1>; ++ assigned-clock-parents = <&cru SCLK_GMAC1_RGMII_SPEED>, <&cru SCLK_GMAC1>, <&gmac1_clkin>; ++ clock_in_out = "input"; ++ phy-supply = <&vcc_3v3>; ++ phy-mode = "rgmii"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&gmac1m0_miim ++ &gmac1m0_tx_bus2 ++ &gmac1m0_rx_bus2 ++ &gmac1m0_rgmii_clk ++ &gmac1m0_clkinout ++ &gmac1m0_rgmii_bus>; ++ snps,reset-gpio = <&gpio0 RK_PC3 GPIO_ACTIVE_LOW>; ++ snps,reset-active-low; ++ /* Reset time is 20ms, 100ms for rtl8211f */ ++ snps,reset-delays-us = <0 20000 100000>; ++ tx_delay = <0x30>; ++ rx_delay = <0x10>; ++ phy-handle = <&rgmii_phy1>; ++ status = "okay"; ++}; ++ ++&hdmi { ++ status = "okay"; ++ avdd-0v9-supply = <&vdda_0v9>; ++ avdd-1v8-supply = <&vcc_1v8>; ++}; ++ ++&hdmi_in_vp0 { ++ status = "okay"; ++}; ++ ++&gpu { ++ mali-supply = <&vdd_gpu>; ++ status = "okay"; ++}; ++ ++&i2c0 { ++ status = "okay"; ++ ++ vdd_cpu: regulator@1c { ++ compatible = "tcs,tcs4525"; ++ reg = <0x1c>; ++ fcs,suspend-voltage-selector = <1>; ++ regulator-name = "vdd_cpu"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <1150000>; ++ regulator-ramp-delay = <2300>; ++ regulator-always-on; ++ regulator-boot-on; ++ vin-supply = <&vcc_sys>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ rk817: pmic@20 { ++ compatible = "rockchip,rk817"; ++ reg = <0x20>; ++ interrupt-parent = <&gpio0>; ++ interrupts = ; ++ assigned-clocks = <&cru I2S1_MCLKOUT_TX>; ++ assigned-clock-parents = <&cru CLK_I2S1_8CH_TX>; ++ clock-names = "mclk"; ++ clocks = <&cru I2S1_MCLKOUT_TX>; ++ clock-output-names = "rk808-clkout1", "rk808-clkout2"; ++ #clock-cells = <1>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_int_l>, <&i2s1m0_mclk>; ++ rockchip,system-power-controller; ++ #sound-dai-cells = <0>; ++ wakeup-source; ++ ++ vcc1-supply = <&vcc_sys>; ++ vcc2-supply = <&vcc_sys>; ++ vcc3-supply = <&vcc_sys>; ++ vcc4-supply = <&vcc_sys>; ++ vcc5-supply = <&vcc_sys>; ++ vcc6-supply = <&vcc_sys>; ++ vcc7-supply = <&vcc_sys>; ++ vcc8-supply = <&vcc_sys>; ++ vcc9-supply = <&dcdc_boost>; ++ ++ regulators { ++ vdd_logic: DCDC_REG1 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <500000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-init-microvolt = <900000>; ++ regulator-ramp-delay = <6001>; ++ regulator-initial-mode = <0x2>; ++ regulator-name = "vdd_logic"; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <900000>; ++ }; ++ }; ++ ++ vdd_gpu: DCDC_REG2 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <500000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-init-microvolt = <900000>; ++ regulator-ramp-delay = <6001>; ++ regulator-initial-mode = <0x2>; ++ regulator-name = "vdd_gpu"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_ddr: DCDC_REG3 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1100000>; ++ regulator-max-microvolt = <1100000>; ++ regulator-initial-mode = <0x2>; ++ regulator-name = "vcc_ddr"; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc_3v3: DCDC_REG4 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-initial-mode = <0x2>; ++ regulator-name = "vcc_3v3"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcca1v8_pmu: LDO_REG1 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "vcca1v8_pmu"; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vdda_0v9: LDO_REG2 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <900000>; ++ regulator-max-microvolt = <900000>; ++ regulator-name = "vdda_0v9"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdda0v9_pmu: LDO_REG3 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <900000>; ++ regulator-max-microvolt = <900000>; ++ regulator-name = "vdda0v9_pmu"; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <900000>; ++ }; ++ }; ++ ++ vccio_acodec: LDO_REG4 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "vccio_acodec"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vccio_sd: LDO_REG5 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "vccio_sd"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc3v3_pmu: LDO_REG6 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "vcc3v3_pmu"; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vcc_1v8: LDO_REG7 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "vcc_1v8"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc1v8_dvp: LDO_REG8 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "vcc1v8_dvp"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc2v8_dvp: LDO_REG9 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <2800000>; ++ regulator-max-microvolt = <2800000>; ++ regulator-name = "vcc2v8_dvp"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ dcdc_boost: BOOST { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ regulator-name = "boost"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ otg_switch: OTG_SWITCH { ++ regulator-name = "otg_switch"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ }; ++ ++ rk817_battery: battery { ++ monitored-battery = <&battery_cell>; ++ rockchip,resistor-sense-micro-ohms = <10000>; ++ rockchip,sleep-enter-current-microamp = <300000>; ++ rockchip,sleep-filter-current-microamp = <100000>; ++ }; ++ }; ++}; ++ ++&i2s1_8ch { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2s1m0_sclktx ++ &i2s1m0_lrcktx ++ &i2s1m0_sdi0 ++ &i2s1m0_sdo0>; ++ rockchip,trcm-sync-tx-only; ++ status = "okay"; ++}; ++ ++&mdio1 { ++ rgmii_phy1: ethernet-phy@0 { ++ compatible = "ethernet-phy-ieee802.3-c22"; ++ reg = <0>; ++ }; ++}; ++ ++&pcie2x1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pcie_reset_h>; ++ reset-gpios = <&gpio1 RK_PB2 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++ vpcie3v3-supply = <&vcc3v3_pcie_p>; ++}; ++ ++&pinctrl { ++ bt { ++ bt_enable_h: bt-enable-h { ++ rockchip,pins = <2 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ ++ bt_host_wake_l: bt-host-wake-l { ++ rockchip,pins = <2 RK_PC0 RK_FUNC_GPIO &pcfg_pull_down>; ++ }; ++ ++ bt_wake_l: bt-wake-l { ++ rockchip,pins = <2 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ fan { ++ fan_en_h: fan-en-h { ++ rockchip,pins = <0 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ leds { ++ work_led_enable_h: work-led-enable-h { ++ rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ ++ diy_led_enable_h: diy-led-enable-h { ++ rockchip,pins = <0 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ pcie { ++ pcie_enable_h: pcie-enable-h { ++ rockchip,pins = <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ ++ pcie_reset_h: pcie-reset-h { ++ rockchip,pins = <1 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ pmic { ++ pmic_int_l: pmic-int-l { ++ rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ ++ hp_det_h: hp-det-h { ++ rockchip,pins = <0 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ sdio-pwrseq { ++ wifi_enable_h: wifi-enable-h { ++ rockchip,pins = <2 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ usb2 { ++ vcc5v0_usb20_host_en_h: vcc5v0-usb20-host-en_h { ++ rockchip,pins = <4 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ vcc_sd { ++ vcc_sd_h: vcc-sd-h { ++ rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++}; ++ ++&pmu_io_domains { ++ status = "okay"; ++ pmuio1-supply = <&vcc3v3_pmu>; ++ pmuio2-supply = <&vcc3v3_pmu>; ++ vccio1-supply = <&vccio_acodec>; ++ vccio2-supply = <&vcc_1v8>; ++ vccio3-supply = <&vccio_sd>; ++ vccio4-supply = <&vcc_1v8>; ++ vccio5-supply = <&vcc_3v3>; ++ vccio6-supply = <&vcc1v8_dvp>; ++ vccio7-supply = <&vcc_3v3>; ++}; ++ ++/* sata1 is muxed with the usb3 port */ ++&sata1 { ++ status = "okay"; ++}; ++ ++/* sata2 is muxed with the pcie2 slot*/ ++&sata2 { ++ status = "disabled"; ++}; ++ ++&sdhci { ++ bus-width = <8>; ++ mmc-hs200-1_8v; ++ non-removable; ++ vmmc-supply = <&vcc_3v3>; ++ vqmmc-supply = <&vcc_1v8>; ++ status = "okay"; ++}; ++ ++&sdmmc0 { ++ bus-width = <4>; ++ cap-sd-highspeed; ++ cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>; ++ disable-wp; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc0_bus4 &sdmmc0_clk &sdmmc0_cmd &sdmmc0_det>; ++ sd-uhs-sdr104; ++ vmmc-supply = <&vcc3v3_sd>; ++ vqmmc-supply = <&vccio_sd>; ++ status = "okay"; ++}; ++ ++&spdif { ++ status = "okay"; ++}; ++ ++&sdmmc1 { ++ bus-width = <4>; ++ cap-sd-highspeed; ++ cap-sdio-irq; ++ disable-wp; ++ keep-power-in-suspend; ++ mmc-pwrseq = <&sdio_pwrseq>; ++ non-removable; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc1_bus4 &sdmmc1_cmd &sdmmc1_clk>; ++ sd-uhs-sdr104; ++ vmmc-supply = <&vcc_wl>; ++ vqmmc-supply = <&vcc_1v8>; ++ status = "okay"; ++}; ++ ++&sfc { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ ++ flash@0 { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <108000000>; ++ spi-rx-bus-width = <4>; ++ spi-tx-bus-width = <1>; ++ }; ++}; ++ ++&tsadc { ++ /* tshut mode 0:CRU 1:GPIO */ ++ rockchip,hw-tshut-mode = <1>; ++ /* tshut polarity 0:LOW 1:HIGH */ ++ rockchip,hw-tshut-polarity = <0>; ++ status = "okay"; ++}; ++ ++&uart0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_xfer>; ++ status = "okay"; ++}; ++ ++&uart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1m0_xfer &uart1m0_ctsn>; ++ status = "okay"; ++ uart-has-rtscts; ++ ++ bluetooth { ++ compatible = "brcm,bcm43438-bt"; ++ clocks = <&rk817 1>; ++ clock-names = "lpo"; ++ device-wake-gpios = <&gpio2 RK_PC1 GPIO_ACTIVE_HIGH>; ++ host-wake-gpios = <&gpio2 RK_PC0 GPIO_ACTIVE_HIGH>; ++ shutdown-gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bt_host_wake_l &bt_wake_l &bt_enable_h>; ++ vbat-supply = <&vcc_sys>; ++ vddio-supply = <&vcca1v8_pmu>; ++ }; ++}; ++ ++&uart2 { ++ status = "okay"; ++}; ++ ++&u2phy0_host { ++ phy-supply = <&vcc5v0_usb20_host>; ++ status = "okay"; ++}; ++ ++&u2phy0_otg { ++ phy-supply = <&vcc5v0_usb20_otg>; ++ status = "okay"; ++}; ++ ++&u2phy1_host { ++ phy-supply = <&vcc5v0_usb20_host>; ++ status = "okay"; ++}; ++ ++&u2phy1_otg { ++ phy-supply = <&vcc5v0_usb20_host>; ++ status = "okay"; ++}; ++ ++&usb2phy0 { ++ status = "okay"; ++}; ++ ++&usb2phy1 { ++ status = "okay"; ++}; ++ ++&usbdrd_dwc3 { ++ status = "okay"; ++}; ++ ++&usbdrd30 { ++ status = "okay"; ++}; ++ ++/* usb3 controller is muxed with sata1 */ ++&usbhost_dwc3 { ++ status = "disabled"; ++}; ++ ++/* usb3 controller is muxed with sata1 */ ++&usbhost30 { ++ status = "disabled"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usb_host1_ehci { ++ status = "okay"; ++}; ++ ++&usb_host1_ohci { ++ status = "okay"; ++}; ++ ++&vop { ++ status = "okay"; ++ assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>; ++ assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>; ++}; ++ ++&vop_mmu { ++ status = "okay"; ++}; ++ ++&vp0_out_hdmi { ++ status = "okay"; ++}; +--- /dev/null ++++ b/arch/arm/dts/rk3566.dtsi +@@ -0,0 +1,32 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++#include "rk356x.dtsi" ++ ++/ { ++ compatible = "rockchip,rk3566"; ++}; ++ ++&pipegrf { ++ compatible = "rockchip,rk3566-pipegrf", "syscon"; ++}; ++ ++&power { ++ power-domain@RK3568_PD_PIPE { ++ reg = ; ++ clocks = <&cru PCLK_PIPE>; ++ pm_qos = <&qos_pcie2x1>, ++ <&qos_sata1>, ++ <&qos_sata2>, ++ <&qos_usb3_0>, ++ <&qos_usb3_1>; ++ #power-domain-cells = <0>; ++ }; ++}; ++ ++&usbdrd_dwc3 { ++ phys = <&u2phy0_otg>; ++ phy-names = "usb2-phy"; ++ extcon = <&usb2phy0>; ++ maximum-speed = "high-speed"; ++ snps,dis_u2_susphy_quirk; ++}; +--- a/arch/arm/dts/rk3568-evb.dts ++++ b/arch/arm/dts/rk3568-evb.dts +@@ -74,6 +74,11 @@ + status = "okay"; + }; + ++&sdmmc0 { ++ status = "okay"; ++ max-frequency = <52000000>; ++}; ++ + &uart2 { + status = "okay"; + }; +--- a/arch/arm/dts/rk3568-pinctrl.dtsi ++++ b/arch/arm/dts/rk3568-pinctrl.dtsi +@@ -3108,4 +3108,13 @@ + <4 RK_PA0 3 &pcfg_pull_none_drv_level_2>; + }; + }; ++ ++ tsadc { ++ /omit-if-no-ref/ ++ tsadc_pin: tsadc-pin { ++ rockchip,pins = ++ /* tsadc_pin */ ++ <0 RK_PA1 0 &pcfg_pull_none>; ++ }; ++ }; + }; +--- a/arch/arm/dts/rk3568.dtsi ++++ b/arch/arm/dts/rk3568.dtsi +@@ -3,777 +3,135 @@ + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + */ + +-#include +-#include +-#include +-#include +-#include +-#include +-#include ++#include "rk356x.dtsi" + + / { + compatible = "rockchip,rk3568"; + +- interrupt-parent = <&gic>; +- #address-cells = <2>; +- #size-cells = <2>; +- +- aliases { +- gpio0 = &gpio0; +- gpio1 = &gpio1; +- gpio2 = &gpio2; +- gpio3 = &gpio3; +- gpio4 = &gpio4; +- i2c0 = &i2c0; +- i2c1 = &i2c1; +- i2c2 = &i2c2; +- i2c3 = &i2c3; +- i2c4 = &i2c4; +- i2c5 = &i2c5; +- serial0 = &uart0; +- serial1 = &uart1; +- serial2 = &uart2; +- serial3 = &uart3; +- serial4 = &uart4; +- serial5 = &uart5; +- serial6 = &uart6; +- serial7 = &uart7; +- serial8 = &uart8; +- serial9 = &uart9; +- }; +- +- cpus { +- #address-cells = <2>; +- #size-cells = <0>; +- +- cpu0: cpu@0 { +- device_type = "cpu"; +- compatible = "arm,cortex-a55"; +- reg = <0x0 0x0>; +- clocks = <&scmi_clk 0>; +- enable-method = "psci"; +- operating-points-v2 = <&cpu0_opp_table>; +- }; +- +- cpu1: cpu@100 { +- device_type = "cpu"; +- compatible = "arm,cortex-a55"; +- reg = <0x0 0x100>; +- enable-method = "psci"; +- operating-points-v2 = <&cpu0_opp_table>; +- }; +- +- cpu2: cpu@200 { +- device_type = "cpu"; +- compatible = "arm,cortex-a55"; +- reg = <0x0 0x200>; +- enable-method = "psci"; +- operating-points-v2 = <&cpu0_opp_table>; +- }; +- +- cpu3: cpu@300 { +- device_type = "cpu"; +- compatible = "arm,cortex-a55"; +- reg = <0x0 0x300>; +- enable-method = "psci"; +- operating-points-v2 = <&cpu0_opp_table>; +- }; ++ sata0: sata@fc000000 { ++ compatible = "snps,dwc-ahci"; ++ reg = <0 0xfc000000 0 0x1000>; ++ clocks = <&cru ACLK_SATA0>, <&cru CLK_SATA0_PMALIVE>, ++ <&cru CLK_SATA0_RXOOB>; ++ clock-names = "sata", "pmalive", "rxoob"; ++ interrupts = ; ++ interrupt-names = "hostc"; ++ phys = <&combphy0_us PHY_TYPE_SATA>; ++ phy-names = "sata-phy"; ++ ports-implemented = <0x1>; ++ power-domains = <&power RK3568_PD_PIPE>; ++ status = "disabled"; + }; + +- cpu0_opp_table: cpu0-opp-table { +- compatible = "operating-points-v2"; +- opp-shared; +- +- opp-408000000 { +- opp-hz = /bits/ 64 <408000000>; +- opp-microvolt = <900000 900000 1150000>; +- clock-latency-ns = <40000>; +- }; +- +- opp-600000000 { +- opp-hz = /bits/ 64 <600000000>; +- opp-microvolt = <900000 900000 1150000>; +- }; +- +- opp-816000000 { +- opp-hz = /bits/ 64 <816000000>; +- opp-microvolt = <900000 900000 1150000>; +- opp-suspend; +- }; +- +- opp-1104000000 { +- opp-hz = /bits/ 64 <1104000000>; +- opp-microvolt = <900000 900000 1150000>; +- }; +- +- opp-1416000000 { +- opp-hz = /bits/ 64 <1416000000>; +- opp-microvolt = <900000 900000 1150000>; +- }; +- +- opp-1608000000 { +- opp-hz = /bits/ 64 <1608000000>; +- opp-microvolt = <975000 975000 1150000>; +- }; ++ qos_pcie3x1: qos@fe190080 { ++ compatible = "rockchip,rk3568-qos", "syscon"; ++ reg = <0x0 0xfe190080 0x0 0x20>; ++ }; ++ ++ qos_pcie3x2: qos@fe190100 { ++ compatible = "rockchip,rk3568-qos", "syscon"; ++ reg = <0x0 0xfe190100 0x0 0x20>; ++ }; ++ ++ qos_sata0: qos@fe190200 { ++ compatible = "rockchip,rk3568-qos", "syscon"; ++ reg = <0x0 0xfe190200 0x0 0x20>; ++ }; ++ ++ gmac0: ethernet@fe2a0000 { ++ compatible = "rockchip,rk3568-gmac", "snps,dwmac-4.20a"; ++ reg = <0x0 0xfe2a0000 0x0 0x10000>; ++ interrupts = , ++ ; ++ interrupt-names = "macirq", "eth_wake_irq"; ++ clocks = <&cru SCLK_GMAC0>, <&cru SCLK_GMAC0_RX_TX>, ++ <&cru SCLK_GMAC0_RX_TX>, <&cru CLK_MAC0_REFOUT>, ++ <&cru ACLK_GMAC0>, <&cru PCLK_GMAC0>, ++ <&cru SCLK_GMAC0_RX_TX>, <&cru CLK_GMAC0_PTP_REF>, ++ <&cru PCLK_XPCS>; ++ clock-names = "stmmaceth", "mac_clk_rx", ++ "mac_clk_tx", "clk_mac_refout", ++ "aclk_mac", "pclk_mac", ++ "clk_mac_speed", "ptp_ref", ++ "pclk_xpcs"; ++ resets = <&cru SRST_A_GMAC0>; ++ reset-names = "stmmaceth"; ++ rockchip,grf = <&grf>; ++ snps,axi-config = <&gmac0_stmmac_axi_setup>; ++ snps,mixed-burst; ++ snps,mtl-rx-config = <&gmac0_mtl_rx_setup>; ++ snps,mtl-tx-config = <&gmac0_mtl_tx_setup>; ++ snps,tso; ++ status = "disabled"; + +- opp-1800000000 { +- opp-hz = /bits/ 64 <1800000000>; +- opp-microvolt = <1050000 1050000 1150000>; ++ mdio0: mdio { ++ compatible = "snps,dwmac-mdio"; ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; + }; + +- opp-1992000000 { +- opp-hz = /bits/ 64 <1992000000>; +- opp-microvolt = <1150000 1150000 1150000>; ++ gmac0_stmmac_axi_setup: stmmac-axi-config { ++ snps,blen = <0 0 0 0 16 8 4>; ++ snps,rd_osr_lmt = <8>; ++ snps,wr_osr_lmt = <4>; + }; +- }; + +- firmware { +- scmi: scmi { +- compatible = "arm,scmi-smc"; +- arm,smc-id = <0x82000010>; +- shmem = <&scmi_shmem>; +- #address-cells = <1>; +- #size-cells = <0>; +- +- scmi_clk: protocol@14 { +- reg = <0x14>; +- #clock-cells = <1>; +- }; ++ gmac0_mtl_rx_setup: rx-queues-config { ++ snps,rx-queues-to-use = <1>; ++ queue0 {}; + }; + +- }; +- +- pmu { +- compatible = "arm,cortex-a55-pmu"; +- interrupts = , +- , +- , +- ; +- interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>; +- }; +- +- psci { +- compatible = "arm,psci-1.0"; +- method = "smc"; +- }; +- +- timer { +- compatible = "arm,armv8-timer"; +- interrupts = , +- , +- , +- ; +- arm,no-tick-in-suspend; +- }; +- +- xin24m: xin24m { +- compatible = "fixed-clock"; +- clock-frequency = <24000000>; +- clock-output-names = "xin24m"; +- #clock-cells = <0>; +- }; +- +- xin32k: xin32k { +- compatible = "fixed-clock"; +- clock-frequency = <32768>; +- clock-output-names = "xin32k"; +- pinctrl-0 = <&clk32k_out0>; +- pinctrl-names = "default"; +- #clock-cells = <0>; +- }; +- +- sram@10f000 { +- compatible = "mmio-sram"; +- reg = <0x0 0x0010f000 0x0 0x100>; +- +- #address-cells = <1>; +- #size-cells = <1>; +- ranges = <0 0x0 0x0010f000 0x100>; +- +- scmi_shmem: sram@0 { +- compatible = "arm,scmi-shmem"; +- reg = <0x0 0x100>; ++ gmac0_mtl_tx_setup: tx-queues-config { ++ snps,tx-queues-to-use = <1>; ++ queue0 {}; + }; + }; + +- gic: interrupt-controller@fd400000 { +- compatible = "arm,gic-v3"; +- reg = <0x0 0xfd400000 0 0x10000>, /* GICD */ +- <0x0 0xfd460000 0 0x80000>; /* GICR */ +- interrupts = ; +- interrupt-controller; +- #interrupt-cells = <3>; +- mbi-alias = <0x0 0xfd100000>; +- mbi-ranges = <296 24>; +- msi-controller; +- }; +- +- pmugrf: syscon@fdc20000 { +- compatible = "rockchip,rk3568-pmugrf", "syscon", "simple-mfd"; +- reg = <0x0 0xfdc20000 0x0 0x10000>; +- }; +- +- grf: syscon@fdc60000 { +- compatible = "rockchip,rk3568-grf", "syscon", "simple-mfd"; +- reg = <0x0 0xfdc60000 0x0 0x10000>; +- }; +- +- pmucru: clock-controller@fdd00000 { +- compatible = "rockchip,rk3568-pmucru"; +- reg = <0x0 0xfdd00000 0x0 0x1000>; +- #clock-cells = <1>; +- #reset-cells = <1>; +- }; +- +- cru: clock-controller@fdd20000 { +- compatible = "rockchip,rk3568-cru"; +- reg = <0x0 0xfdd20000 0x0 0x1000>; +- #clock-cells = <1>; +- #reset-cells = <1>; +- }; +- +- i2c0: i2c@fdd40000 { +- compatible = "rockchip,rk3568-i2c", "rockchip,rk3399-i2c"; +- reg = <0x0 0xfdd40000 0x0 0x1000>; +- interrupts = ; +- clocks = <&pmucru CLK_I2C0>, <&pmucru PCLK_I2C0>; +- clock-names = "i2c", "pclk"; +- pinctrl-0 = <&i2c0_xfer>; +- pinctrl-names = "default"; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- }; +- +- uart0: serial@fdd50000 { +- compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; +- reg = <0x0 0xfdd50000 0x0 0x100>; +- interrupts = ; +- clocks = <&pmucru SCLK_UART0>, <&pmucru PCLK_UART0>; +- clock-names = "baudclk", "apb_pclk"; +- dmas = <&dmac0 0>, <&dmac0 1>; +- pinctrl-0 = <&uart0_xfer>; +- pinctrl-names = "default"; +- reg-io-width = <4>; +- reg-shift = <2>; +- status = "disabled"; +- }; +- +- pwm0: pwm@fdd70000 { +- compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; +- reg = <0x0 0xfdd70000 0x0 0x10>; +- clocks = <&pmucru CLK_PWM0>, <&pmucru PCLK_PWM0>; +- clock-names = "pwm", "pclk"; +- pinctrl-0 = <&pwm0m0_pins>; +- pinctrl-names = "active"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- pwm1: pwm@fdd70010 { +- compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; +- reg = <0x0 0xfdd70010 0x0 0x10>; +- clocks = <&pmucru CLK_PWM0>, <&pmucru PCLK_PWM0>; +- clock-names = "pwm", "pclk"; +- pinctrl-0 = <&pwm1m0_pins>; +- pinctrl-names = "active"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- pwm2: pwm@fdd70020 { +- compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; +- reg = <0x0 0xfdd70020 0x0 0x10>; +- clocks = <&pmucru CLK_PWM0>, <&pmucru PCLK_PWM0>; +- clock-names = "pwm", "pclk"; +- pinctrl-0 = <&pwm2m0_pins>; +- pinctrl-names = "active"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- pwm3: pwm@fdd70030 { +- compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; +- reg = <0x0 0xfdd70030 0x0 0x10>; +- clocks = <&pmucru CLK_PWM0>, <&pmucru PCLK_PWM0>; +- clock-names = "pwm", "pclk"; +- pinctrl-0 = <&pwm3_pins>; +- pinctrl-names = "active"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- sdmmc2: mmc@fe000000 { +- compatible = "rockchip,rk3568-dw-mshc", "rockchip,rk3288-dw-mshc"; +- reg = <0x0 0xfe000000 0x0 0x4000>; +- interrupts = ; +- clocks = <&cru HCLK_SDMMC2>, <&cru CLK_SDMMC2>, +- <&cru SCLK_SDMMC2_DRV>, <&cru SCLK_SDMMC2_SAMPLE>; +- clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; +- fifo-depth = <0x100>; +- max-frequency = <150000000>; +- resets = <&cru SRST_SDMMC2>; +- reset-names = "reset"; +- status = "disabled"; +- }; +- +- sdmmc0: mmc@fe2b0000 { +- compatible = "rockchip,rk3568-dw-mshc", "rockchip,rk3288-dw-mshc"; +- reg = <0x0 0xfe2b0000 0x0 0x4000>; +- interrupts = ; +- clocks = <&cru HCLK_SDMMC0>, <&cru CLK_SDMMC0>, +- <&cru SCLK_SDMMC0_DRV>, <&cru SCLK_SDMMC0_SAMPLE>; +- clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; +- fifo-depth = <0x100>; +- max-frequency = <150000000>; +- resets = <&cru SRST_SDMMC0>; +- reset-names = "reset"; +- status = "disabled"; +- }; +- +- sdmmc1: mmc@fe2c0000 { +- compatible = "rockchip,rk3568-dw-mshc", "rockchip,rk3288-dw-mshc"; +- reg = <0x0 0xfe2c0000 0x0 0x4000>; +- interrupts = ; +- clocks = <&cru HCLK_SDMMC1>, <&cru CLK_SDMMC1>, +- <&cru SCLK_SDMMC1_DRV>, <&cru SCLK_SDMMC1_SAMPLE>; +- clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; +- fifo-depth = <0x100>; +- max-frequency = <150000000>; +- resets = <&cru SRST_SDMMC1>; +- reset-names = "reset"; +- status = "disabled"; +- }; +- +- sdhci: mmc@fe310000 { +- compatible = "rockchip,rk3568-dwcmshc"; +- reg = <0x0 0xfe310000 0x0 0x10000>; +- interrupts = ; +- assigned-clocks = <&cru BCLK_EMMC>, <&cru TCLK_EMMC>; +- assigned-clock-rates = <200000000>, <24000000>; +- clocks = <&cru CCLK_EMMC>, <&cru HCLK_EMMC>, +- <&cru ACLK_EMMC>, <&cru BCLK_EMMC>, +- <&cru TCLK_EMMC>; +- clock-names = "core", "bus", "axi", "block", "timer"; +- status = "disabled"; +- }; +- +- dmac0: dmac@fe530000 { +- compatible = "arm,pl330", "arm,primecell"; +- reg = <0x0 0xfe530000 0x0 0x4000>; +- interrupts = , +- ; +- arm,pl330-periph-burst; +- clocks = <&cru ACLK_BUS>; +- clock-names = "apb_pclk"; +- #dma-cells = <1>; +- }; +- +- dmac1: dmac@fe550000 { +- compatible = "arm,pl330", "arm,primecell"; +- reg = <0x0 0xfe550000 0x0 0x4000>; +- interrupts = , +- ; +- arm,pl330-periph-burst; +- clocks = <&cru ACLK_BUS>; +- clock-names = "apb_pclk"; +- #dma-cells = <1>; +- }; +- +- i2c1: i2c@fe5a0000 { +- compatible = "rockchip,rk3568-i2c", "rockchip,rk3399-i2c"; +- reg = <0x0 0xfe5a0000 0x0 0x1000>; +- interrupts = ; +- clocks = <&cru CLK_I2C1>, <&cru PCLK_I2C1>; +- clock-names = "i2c", "pclk"; +- pinctrl-0 = <&i2c1_xfer>; +- pinctrl-names = "default"; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- }; +- +- i2c2: i2c@fe5b0000 { +- compatible = "rockchip,rk3568-i2c", "rockchip,rk3399-i2c"; +- reg = <0x0 0xfe5b0000 0x0 0x1000>; +- interrupts = ; +- clocks = <&cru CLK_I2C2>, <&cru PCLK_I2C2>; +- clock-names = "i2c", "pclk"; +- pinctrl-0 = <&i2c2m0_xfer>; +- pinctrl-names = "default"; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- }; +- +- i2c3: i2c@fe5c0000 { +- compatible = "rockchip,rk3568-i2c", "rockchip,rk3399-i2c"; +- reg = <0x0 0xfe5c0000 0x0 0x1000>; +- interrupts = ; +- clocks = <&cru CLK_I2C3>, <&cru PCLK_I2C3>; +- clock-names = "i2c", "pclk"; +- pinctrl-0 = <&i2c3m0_xfer>; +- pinctrl-names = "default"; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- }; +- +- i2c4: i2c@fe5d0000 { +- compatible = "rockchip,rk3568-i2c", "rockchip,rk3399-i2c"; +- reg = <0x0 0xfe5d0000 0x0 0x1000>; +- interrupts = ; +- clocks = <&cru CLK_I2C4>, <&cru PCLK_I2C4>; +- clock-names = "i2c", "pclk"; +- pinctrl-0 = <&i2c4m0_xfer>; +- pinctrl-names = "default"; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- }; +- +- i2c5: i2c@fe5e0000 { +- compatible = "rockchip,rk3568-i2c", "rockchip,rk3399-i2c"; +- reg = <0x0 0xfe5e0000 0x0 0x1000>; +- interrupts = ; +- clocks = <&cru CLK_I2C5>, <&cru PCLK_I2C5>; +- clock-names = "i2c", "pclk"; +- pinctrl-0 = <&i2c5m0_xfer>; +- pinctrl-names = "default"; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- }; +- +- wdt: watchdog@fe600000 { +- compatible = "rockchip,rk3568-wdt", "snps,dw-wdt"; +- reg = <0x0 0xfe600000 0x0 0x100>; +- interrupts = ; +- clocks = <&cru TCLK_WDT_NS>, <&cru PCLK_WDT_NS>; +- clock-names = "tclk", "pclk"; +- }; +- +- uart1: serial@fe650000 { +- compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; +- reg = <0x0 0xfe650000 0x0 0x100>; +- interrupts = ; +- clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>; +- clock-names = "baudclk", "apb_pclk"; +- dmas = <&dmac0 2>, <&dmac0 3>; +- pinctrl-0 = <&uart1m0_xfer>; +- pinctrl-names = "default"; +- reg-io-width = <4>; +- reg-shift = <2>; +- status = "disabled"; +- }; +- +- uart2: serial@fe660000 { +- compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; +- reg = <0x0 0xfe660000 0x0 0x100>; +- interrupts = ; +- clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>; +- clock-names = "baudclk", "apb_pclk"; +- dmas = <&dmac0 4>, <&dmac0 5>; +- pinctrl-0 = <&uart2m0_xfer>; +- pinctrl-names = "default"; +- reg-io-width = <4>; +- reg-shift = <2>; +- status = "disabled"; +- }; +- +- uart3: serial@fe670000 { +- compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; +- reg = <0x0 0xfe670000 0x0 0x100>; +- interrupts = ; +- clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>; +- clock-names = "baudclk", "apb_pclk"; +- dmas = <&dmac0 6>, <&dmac0 7>; +- pinctrl-0 = <&uart3m0_xfer>; +- pinctrl-names = "default"; +- reg-io-width = <4>; +- reg-shift = <2>; +- status = "disabled"; +- }; +- +- uart4: serial@fe680000 { +- compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; +- reg = <0x0 0xfe680000 0x0 0x100>; +- interrupts = ; +- clocks = <&cru SCLK_UART4>, <&cru PCLK_UART4>; +- clock-names = "baudclk", "apb_pclk"; +- dmas = <&dmac0 8>, <&dmac0 9>; +- pinctrl-0 = <&uart4m0_xfer>; +- pinctrl-names = "default"; +- reg-io-width = <4>; +- reg-shift = <2>; +- status = "disabled"; +- }; +- +- uart5: serial@fe690000 { +- compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; +- reg = <0x0 0xfe690000 0x0 0x100>; +- interrupts = ; +- clocks = <&cru SCLK_UART5>, <&cru PCLK_UART5>; +- clock-names = "baudclk", "apb_pclk"; +- dmas = <&dmac0 10>, <&dmac0 11>; +- pinctrl-0 = <&uart5m0_xfer>; +- pinctrl-names = "default"; +- reg-io-width = <4>; +- reg-shift = <2>; +- status = "disabled"; +- }; +- +- uart6: serial@fe6a0000 { +- compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; +- reg = <0x0 0xfe6a0000 0x0 0x100>; +- interrupts = ; +- clocks = <&cru SCLK_UART6>, <&cru PCLK_UART6>; +- clock-names = "baudclk", "apb_pclk"; +- dmas = <&dmac0 12>, <&dmac0 13>; +- pinctrl-0 = <&uart6m0_xfer>; +- pinctrl-names = "default"; +- reg-io-width = <4>; +- reg-shift = <2>; +- status = "disabled"; +- }; +- +- uart7: serial@fe6b0000 { +- compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; +- reg = <0x0 0xfe6b0000 0x0 0x100>; +- interrupts = ; +- clocks = <&cru SCLK_UART7>, <&cru PCLK_UART7>; +- clock-names = "baudclk", "apb_pclk"; +- dmas = <&dmac0 14>, <&dmac0 15>; +- pinctrl-0 = <&uart7m0_xfer>; +- pinctrl-names = "default"; +- reg-io-width = <4>; +- reg-shift = <2>; +- status = "disabled"; +- }; +- +- uart8: serial@fe6c0000 { +- compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; +- reg = <0x0 0xfe6c0000 0x0 0x100>; +- interrupts = ; +- clocks = <&cru SCLK_UART8>, <&cru PCLK_UART8>; +- clock-names = "baudclk", "apb_pclk"; +- dmas = <&dmac0 16>, <&dmac0 17>; +- pinctrl-0 = <&uart8m0_xfer>; +- pinctrl-names = "default"; +- reg-io-width = <4>; +- reg-shift = <2>; +- status = "disabled"; +- }; +- +- uart9: serial@fe6d0000 { +- compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; +- reg = <0x0 0xfe6d0000 0x0 0x100>; +- interrupts = ; +- clocks = <&cru SCLK_UART9>, <&cru PCLK_UART9>; +- clock-names = "baudclk", "apb_pclk"; +- dmas = <&dmac0 18>, <&dmac0 19>; +- pinctrl-0 = <&uart9m0_xfer>; +- pinctrl-names = "default"; +- reg-io-width = <4>; +- reg-shift = <2>; +- status = "disabled"; +- }; +- +- pwm4: pwm@fe6e0000 { +- compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; +- reg = <0x0 0xfe6e0000 0x0 0x10>; +- clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>; +- clock-names = "pwm", "pclk"; +- pinctrl-0 = <&pwm4_pins>; +- pinctrl-names = "active"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- pwm5: pwm@fe6e0010 { +- compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; +- reg = <0x0 0xfe6e0010 0x0 0x10>; +- clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>; +- clock-names = "pwm", "pclk"; +- pinctrl-0 = <&pwm5_pins>; +- pinctrl-names = "active"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- pwm6: pwm@fe6e0020 { +- compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; +- reg = <0x0 0xfe6e0020 0x0 0x10>; +- clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>; +- clock-names = "pwm", "pclk"; +- pinctrl-0 = <&pwm6_pins>; +- pinctrl-names = "active"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- pwm7: pwm@fe6e0030 { +- compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; +- reg = <0x0 0xfe6e0030 0x0 0x10>; +- clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>; +- clock-names = "pwm", "pclk"; +- pinctrl-0 = <&pwm7_pins>; +- pinctrl-names = "active"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- pwm8: pwm@fe6f0000 { +- compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; +- reg = <0x0 0xfe6f0000 0x0 0x10>; +- clocks = <&cru CLK_PWM2>, <&cru PCLK_PWM2>; +- clock-names = "pwm", "pclk"; +- pinctrl-0 = <&pwm8m0_pins>; +- pinctrl-names = "active"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- pwm9: pwm@fe6f0010 { +- compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; +- reg = <0x0 0xfe6f0010 0x0 0x10>; +- clocks = <&cru CLK_PWM2>, <&cru PCLK_PWM2>; +- clock-names = "pwm", "pclk"; +- pinctrl-0 = <&pwm9m0_pins>; +- pinctrl-names = "active"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- pwm10: pwm@fe6f0020 { +- compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; +- reg = <0x0 0xfe6f0020 0x0 0x10>; +- clocks = <&cru CLK_PWM2>, <&cru PCLK_PWM2>; +- clock-names = "pwm", "pclk"; +- pinctrl-0 = <&pwm10m0_pins>; +- pinctrl-names = "active"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- pwm11: pwm@fe6f0030 { +- compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; +- reg = <0x0 0xfe6f0030 0x0 0x10>; +- clocks = <&cru CLK_PWM2>, <&cru PCLK_PWM2>; +- clock-names = "pwm", "pclk"; +- pinctrl-0 = <&pwm11m0_pins>; +- pinctrl-names = "active"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- pwm12: pwm@fe700000 { +- compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; +- reg = <0x0 0xfe700000 0x0 0x10>; +- clocks = <&cru CLK_PWM3>, <&cru PCLK_PWM3>; +- clock-names = "pwm", "pclk"; +- pinctrl-0 = <&pwm12m0_pins>; +- pinctrl-names = "active"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- pwm13: pwm@fe700010 { +- compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; +- reg = <0x0 0xfe700010 0x0 0x10>; +- clocks = <&cru CLK_PWM3>, <&cru PCLK_PWM3>; +- clock-names = "pwm", "pclk"; +- pinctrl-0 = <&pwm13m0_pins>; +- pinctrl-names = "active"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- pwm14: pwm@fe700020 { +- compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; +- reg = <0x0 0xfe700020 0x0 0x10>; +- clocks = <&cru CLK_PWM3>, <&cru PCLK_PWM3>; +- clock-names = "pwm", "pclk"; +- pinctrl-0 = <&pwm14m0_pins>; +- pinctrl-names = "active"; +- #pwm-cells = <3>; ++ combphy0_us: phy@fe820000 { ++ compatible = "rockchip,rk3568-naneng-combphy"; ++ reg = <0x0 0xfe820000 0x0 0x100>; ++ #phy-cells = <1>; ++ assigned-clocks = <&pmucru CLK_PCIEPHY0_REF>; ++ assigned-clock-rates = <100000000>; ++ clocks = <&pmucru CLK_PCIEPHY0_REF>, <&cru PCLK_PIPEPHY0>, ++ <&cru PCLK_PIPE>; ++ clock-names = "ref", "apb", "pipe"; ++ resets = <&cru SRST_P_PIPEPHY0>, <&cru SRST_PIPEPHY0>; ++ reset-names = "combphy-apb", "combphy"; ++ rockchip,pipe-grf = <&pipegrf>; ++ rockchip,pipe-phy-grf = <&pipe_phy_grf0>; + status = "disabled"; + }; ++}; + +- pwm15: pwm@fe700030 { +- compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; +- reg = <0x0 0xfe700030 0x0 0x10>; +- clocks = <&cru CLK_PWM3>, <&cru PCLK_PWM3>; +- clock-names = "pwm", "pclk"; +- pinctrl-0 = <&pwm15m0_pins>; +- pinctrl-names = "active"; +- #pwm-cells = <3>; +- status = "disabled"; ++&cpu0_opp_table { ++ opp-1992000000 { ++ opp-hz = /bits/ 64 <1992000000>; ++ opp-microvolt = <1150000 1150000 1150000>; + }; ++}; + +- pinctrl: pinctrl { +- compatible = "rockchip,rk3568-pinctrl"; +- rockchip,grf = <&grf>; +- rockchip,pmu = <&pmugrf>; +- #address-cells = <2>; +- #size-cells = <2>; +- ranges; +- +- gpio0: gpio@fdd60000 { +- compatible = "rockchip,gpio-bank"; +- reg = <0x0 0xfdd60000 0x0 0x100>; +- interrupts = ; +- clocks = <&pmucru PCLK_GPIO0>, <&pmucru DBCLK_GPIO0>; +- gpio-controller; +- #gpio-cells = <2>; +- interrupt-controller; +- #interrupt-cells = <2>; +- }; +- +- gpio1: gpio@fe740000 { +- compatible = "rockchip,gpio-bank"; +- reg = <0x0 0xfe740000 0x0 0x100>; +- interrupts = ; +- clocks = <&cru PCLK_GPIO1>, <&cru DBCLK_GPIO1>; +- gpio-controller; +- #gpio-cells = <2>; +- interrupt-controller; +- #interrupt-cells = <2>; +- }; +- +- gpio2: gpio@fe750000 { +- compatible = "rockchip,gpio-bank"; +- reg = <0x0 0xfe750000 0x0 0x100>; +- interrupts = ; +- clocks = <&cru PCLK_GPIO2>, <&cru DBCLK_GPIO2>; +- gpio-controller; +- #gpio-cells = <2>; +- interrupt-controller; +- #interrupt-cells = <2>; +- }; +- +- gpio3: gpio@fe760000 { +- compatible = "rockchip,gpio-bank"; +- reg = <0x0 0xfe760000 0x0 0x100>; +- interrupts = ; +- clocks = <&cru PCLK_GPIO3>, <&cru DBCLK_GPIO3>; +- gpio-controller; +- #gpio-cells = <2>; +- interrupt-controller; +- #interrupt-cells = <2>; +- }; ++&pipegrf { ++ compatible = "rockchip,rk3568-pipegrf", "syscon"; ++}; + +- gpio4: gpio@fe770000 { +- compatible = "rockchip,gpio-bank"; +- reg = <0x0 0xfe770000 0x0 0x100>; +- interrupts = ; +- clocks = <&cru PCLK_GPIO4>, <&cru DBCLK_GPIO4>; +- gpio-controller; +- #gpio-cells = <2>; +- interrupt-controller; +- #interrupt-cells = <2>; +- }; ++&power { ++ power-domain@RK3568_PD_PIPE { ++ reg = ; ++ clocks = <&cru PCLK_PIPE>; ++ pm_qos = <&qos_pcie2x1>, ++ <&qos_pcie3x1>, ++ <&qos_pcie3x2>, ++ <&qos_sata0>, ++ <&qos_sata1>, ++ <&qos_sata2>, ++ <&qos_usb3_0>, ++ <&qos_usb3_1>; ++ #power-domain-cells = <0>; + }; + }; + +-#include "rk3568-pinctrl.dtsi" ++&usbdrd_dwc3 { ++ phys = <&u2phy0_otg>, <&combphy0_us PHY_TYPE_USB3>; ++ phy-names = "usb2-phy", "usb3-phy"; ++}; +--- /dev/null ++++ b/arch/arm/dts/rk356x.dtsi +@@ -0,0 +1,1630 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2021 Rockchip Electronics Co., Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/ { ++ interrupt-parent = <&gic>; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ++ aliases { ++ gpio0 = &gpio0; ++ gpio1 = &gpio1; ++ gpio2 = &gpio2; ++ gpio3 = &gpio3; ++ gpio4 = &gpio4; ++ i2c0 = &i2c0; ++ i2c1 = &i2c1; ++ i2c2 = &i2c2; ++ i2c3 = &i2c3; ++ i2c4 = &i2c4; ++ i2c5 = &i2c5; ++ serial0 = &uart0; ++ serial1 = &uart1; ++ serial2 = &uart2; ++ serial3 = &uart3; ++ serial4 = &uart4; ++ serial5 = &uart5; ++ serial6 = &uart6; ++ serial7 = &uart7; ++ serial8 = &uart8; ++ serial9 = &uart9; ++ }; ++ ++ cpus { ++ #address-cells = <2>; ++ #size-cells = <0>; ++ ++ cpu0: cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a55"; ++ reg = <0x0 0x0>; ++ clocks = <&scmi_clk 0>; ++ #cooling-cells = <2>; ++ enable-method = "psci"; ++ operating-points-v2 = <&cpu0_opp_table>; ++ }; ++ ++ cpu1: cpu@100 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a55"; ++ reg = <0x0 0x100>; ++ #cooling-cells = <2>; ++ enable-method = "psci"; ++ operating-points-v2 = <&cpu0_opp_table>; ++ }; ++ ++ cpu2: cpu@200 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a55"; ++ reg = <0x0 0x200>; ++ #cooling-cells = <2>; ++ enable-method = "psci"; ++ operating-points-v2 = <&cpu0_opp_table>; ++ }; ++ ++ cpu3: cpu@300 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a55"; ++ reg = <0x0 0x300>; ++ #cooling-cells = <2>; ++ enable-method = "psci"; ++ operating-points-v2 = <&cpu0_opp_table>; ++ }; ++ }; ++ ++ cpu0_opp_table: opp-table-0 { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ ++ opp-408000000 { ++ opp-hz = /bits/ 64 <408000000>; ++ opp-microvolt = <900000 900000 1150000>; ++ clock-latency-ns = <40000>; ++ }; ++ ++ opp-600000000 { ++ opp-hz = /bits/ 64 <600000000>; ++ opp-microvolt = <900000 900000 1150000>; ++ }; ++ ++ opp-816000000 { ++ opp-hz = /bits/ 64 <816000000>; ++ opp-microvolt = <900000 900000 1150000>; ++ opp-suspend; ++ }; ++ ++ opp-1104000000 { ++ opp-hz = /bits/ 64 <1104000000>; ++ opp-microvolt = <900000 900000 1150000>; ++ }; ++ ++ opp-1416000000 { ++ opp-hz = /bits/ 64 <1416000000>; ++ opp-microvolt = <900000 900000 1150000>; ++ }; ++ ++ opp-1608000000 { ++ opp-hz = /bits/ 64 <1608000000>; ++ opp-microvolt = <975000 975000 1150000>; ++ }; ++ ++ opp-1800000000 { ++ opp-hz = /bits/ 64 <1800000000>; ++ opp-microvolt = <1050000 1050000 1150000>; ++ }; ++ }; ++ ++ gpu_opp_table: gpu-opp-table { ++ compatible = "operating-points-v2"; ++ ++ opp-200000000 { ++ opp-hz = /bits/ 64 <200000000>; ++ opp-microvolt = <825000>; ++ }; ++ ++ opp-300000000 { ++ opp-hz = /bits/ 64 <300000000>; ++ opp-microvolt = <825000>; ++ }; ++ ++ opp-400000000 { ++ opp-hz = /bits/ 64 <400000000>; ++ opp-microvolt = <825000>; ++ }; ++ ++ opp-600000000 { ++ opp-hz = /bits/ 64 <600000000>; ++ opp-microvolt = <825000>; ++ }; ++ ++ opp-700000000 { ++ opp-hz = /bits/ 64 <700000000>; ++ opp-microvolt = <900000>; ++ }; ++ ++ opp-800000000 { ++ opp-hz = /bits/ 64 <800000000>; ++ opp-microvolt = <1000000>; ++ }; ++ }; ++ ++ firmware { ++ scmi: scmi { ++ compatible = "arm,scmi-smc"; ++ arm,smc-id = <0x82000010>; ++ shmem = <&scmi_shmem>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ scmi_clk: protocol@14 { ++ reg = <0x14>; ++ #clock-cells = <1>; ++ }; ++ }; ++ }; ++ ++ pmu { ++ compatible = "arm,cortex-a55-pmu"; ++ interrupts = , ++ , ++ , ++ ; ++ interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>; ++ }; ++ ++ psci { ++ compatible = "arm,psci-1.0"; ++ method = "smc"; ++ }; ++ ++ timer { ++ compatible = "arm,armv8-timer"; ++ interrupts = , ++ , ++ , ++ ; ++ arm,no-tick-in-suspend; ++ }; ++ ++ xin24m: xin24m { ++ compatible = "fixed-clock"; ++ clock-frequency = <24000000>; ++ clock-output-names = "xin24m"; ++ #clock-cells = <0>; ++ }; ++ ++ xin32k: xin32k { ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++ clock-output-names = "xin32k"; ++ pinctrl-0 = <&clk32k_out0>; ++ pinctrl-names = "default"; ++ #clock-cells = <0>; ++ }; ++ ++ sram@10f000 { ++ compatible = "mmio-sram"; ++ reg = <0x0 0x0010f000 0x0 0x100>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0 0x0 0x0010f000 0x100>; ++ ++ scmi_shmem: sram@0 { ++ compatible = "arm,scmi-shmem"; ++ reg = <0x0 0x100>; ++ }; ++ }; ++ ++ sata1: sata@fc400000 { ++ compatible = "snps,dwc-ahci"; ++ reg = <0 0xfc400000 0 0x1000>; ++ clocks = <&cru ACLK_SATA1>, <&cru CLK_SATA1_PMALIVE>, ++ <&cru CLK_SATA1_RXOOB>; ++ clock-names = "sata", "pmalive", "rxoob"; ++ interrupts = ; ++ interrupt-names = "hostc"; ++ phys = <&combphy1_usq PHY_TYPE_SATA>; ++ phy-names = "sata-phy"; ++ ports-implemented = <0x1>; ++ power-domains = <&power RK3568_PD_PIPE>; ++ status = "disabled"; ++ }; ++ ++ sata2: sata@fc800000 { ++ compatible = "snps,dwc-ahci"; ++ reg = <0 0xfc800000 0 0x1000>; ++ clocks = <&cru ACLK_SATA2>, <&cru CLK_SATA2_PMALIVE>, ++ <&cru CLK_SATA2_RXOOB>; ++ clock-names = "sata", "pmalive", "rxoob"; ++ interrupts = ; ++ interrupt-names = "hostc"; ++ phys = <&combphy2_psq PHY_TYPE_SATA>; ++ phy-names = "sata-phy"; ++ ports-implemented = <0x1>; ++ power-domains = <&power RK3568_PD_PIPE>; ++ status = "disabled"; ++ }; ++ ++ usbdrd30: usbdrd { ++ compatible = "rockchip,rk3399-dwc3", "snps,dwc3"; ++ clocks = <&cru CLK_USB3OTG0_REF>, <&cru CLK_USB3OTG0_SUSPEND>, ++ <&cru ACLK_USB3OTG0>, <&cru PCLK_PIPE>; ++ clock-names = "ref_clk", "suspend_clk", ++ "bus_clk", "pipe_clk"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ status = "disabled"; ++ ++ usbdrd_dwc3: dwc3@fcc00000 { ++ compatible = "snps,dwc3"; ++ reg = <0x0 0xfcc00000 0x0 0x400000>; ++ interrupts = ; ++ dr_mode = "host"; ++ phys = <&u2phy0_otg>, <&combphy0_us PHY_TYPE_USB3>; ++ phy-names = "usb2-phy", "usb3-phy"; ++ phy_type = "utmi_wide"; ++ power-domains = <&power RK3568_PD_PIPE>; ++ resets = <&cru SRST_USB3OTG0>; ++ reset-names = "usb3-otg"; ++ snps,dis_enblslpm_quirk; ++ snps,dis-u2-freeclk-exists-quirk; ++ snps,dis-del-phy-power-chg-quirk; ++ snps,dis-tx-ipgap-linecheck-quirk; ++ snps,xhci-trb-ent-quirk; ++ status = "disabled"; ++ }; ++ }; ++ ++ usbhost30: usbhost { ++ compatible = "rockchip,rk3399-dwc3", "snps,dwc3"; ++ clocks = <&cru CLK_USB3OTG1_REF>, <&cru CLK_USB3OTG1_SUSPEND>, ++ <&cru ACLK_USB3OTG1>, <&cru PCLK_PIPE>; ++ clock-names = "ref_clk", "suspend_clk", ++ "bus_clk", "pipe_clk"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ assigned-clocks = <&cru CLK_PCIEPHY1_REF>; ++ assigned-clock-rates = <25000000>; ++ ranges; ++ status = "disabled"; ++ ++ usbhost_dwc3: dwc3@fd000000 { ++ compatible = "snps,dwc3"; ++ reg = <0x0 0xfd000000 0x0 0x400000>; ++ interrupts = ; ++ dr_mode = "host"; ++ phys = <&u2phy0_host>, <&combphy1_usq PHY_TYPE_USB3>; ++ phy-names = "usb2-phy", "usb3-phy"; ++ phy_type = "utmi_wide"; ++ power-domains = <&power RK3568_PD_PIPE>; ++ resets = <&cru SRST_USB3OTG1>; ++ reset-names = "usb3-host"; ++ snps,dis_enblslpm_quirk; ++ snps,dis-u2-freeclk-exists-quirk; ++ snps,dis_u2_susphy_quirk; ++ snps,dis-del-phy-power-chg-quirk; ++ snps,dis-tx-ipgap-linecheck-quirk; ++ status = "disabled"; ++ }; ++ }; ++ ++ gic: interrupt-controller@fd400000 { ++ compatible = "arm,gic-v3"; ++ reg = <0x0 0xfd400000 0 0x10000>, /* GICD */ ++ <0x0 0xfd460000 0 0x80000>; /* GICR */ ++ interrupts = ; ++ interrupt-controller; ++ #interrupt-cells = <3>; ++ mbi-alias = <0x0 0xfd410000>; ++ mbi-ranges = <296 24>; ++ msi-controller; ++ }; ++ ++ usb_host0_ehci: usb@fd800000 { ++ compatible = "generic-ehci"; ++ reg = <0x0 0xfd800000 0x0 0x40000>; ++ interrupts = ; ++ clocks = <&cru HCLK_USB2HOST0>, <&cru HCLK_USB2HOST0_ARB>, ++ <&cru PCLK_USB>; ++ phys = <&u2phy1_otg>; ++ phy-names = "usb2-phy"; ++ status = "disabled"; ++ }; ++ ++ usb_host0_ohci: usb@fd840000 { ++ compatible = "generic-ohci"; ++ reg = <0x0 0xfd840000 0x0 0x40000>; ++ interrupts = ; ++ clocks = <&cru HCLK_USB2HOST0>, <&cru HCLK_USB2HOST0_ARB>, ++ <&cru PCLK_USB>; ++ phys = <&u2phy1_otg>; ++ phy-names = "usb2-phy"; ++ status = "disabled"; ++ }; ++ ++ usb_host1_ehci: usb@fd880000 { ++ compatible = "generic-ehci"; ++ reg = <0x0 0xfd880000 0x0 0x40000>; ++ interrupts = ; ++ clocks = <&cru HCLK_USB2HOST1>, <&cru HCLK_USB2HOST1_ARB>, ++ <&cru PCLK_USB>; ++ phys = <&u2phy1_host>; ++ phy-names = "usb2-phy"; ++ status = "disabled"; ++ }; ++ ++ usb_host1_ohci: usb@fd8c0000 { ++ compatible = "generic-ohci"; ++ reg = <0x0 0xfd8c0000 0x0 0x40000>; ++ interrupts = ; ++ clocks = <&cru HCLK_USB2HOST1>, <&cru HCLK_USB2HOST1_ARB>, ++ <&cru PCLK_USB>; ++ phys = <&u2phy1_host>; ++ phy-names = "usb2-phy"; ++ status = "disabled"; ++ }; ++ ++ pmugrf: syscon@fdc20000 { ++ compatible = "rockchip,rk3568-pmugrf", "syscon", "simple-mfd"; ++ reg = <0x0 0xfdc20000 0x0 0x10000>; ++ ++ pmu_io_domains: io-domains { ++ compatible = "rockchip,rk3568-pmu-io-voltage-domain"; ++ status = "disabled"; ++ }; ++ }; ++ ++ pipegrf: syscon@fdc50000 { ++ reg = <0x0 0xfdc50000 0x0 0x1000>; ++ }; ++ ++ grf: syscon@fdc60000 { ++ compatible = "rockchip,rk3568-grf", "syscon", "simple-mfd"; ++ reg = <0x0 0xfdc60000 0x0 0x10000>; ++ }; ++ ++ pipe_phy_grf0: syscon@fdc70000 { ++ compatible = "rockchip,pipe-phy-grf", "syscon"; ++ reg = <0x0 0xfdc70000 0x0 0x1000>; ++ }; ++ ++ pipe_phy_grf1: syscon@fdc80000 { ++ compatible = "rockchip,pipe-phy-grf", "syscon"; ++ reg = <0x0 0xfdc80000 0x0 0x1000>; ++ }; ++ ++ pipe_phy_grf2: syscon@fdc90000 { ++ compatible = "rockchip,pipe-phy-grf", "syscon"; ++ reg = <0x0 0xfdc90000 0x0 0x1000>; ++ }; ++ ++ usb2phy0_grf: syscon@fdca0000 { ++ compatible = "rockchip,rk3568-usb2phy-grf", "syscon"; ++ reg = <0x0 0xfdca0000 0x0 0x8000>; ++ }; ++ ++ usb2phy1_grf: syscon@fdca8000 { ++ compatible = "rockchip,rk3568-usb2phy-grf", "syscon"; ++ reg = <0x0 0xfdca8000 0x0 0x8000>; ++ }; ++ ++ pmucru: clock-controller@fdd00000 { ++ compatible = "rockchip,rk3568-pmucru"; ++ reg = <0x0 0xfdd00000 0x0 0x1000>; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ }; ++ ++ cru: clock-controller@fdd20000 { ++ compatible = "rockchip,rk3568-cru"; ++ reg = <0x0 0xfdd20000 0x0 0x1000>; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ assigned-clocks = <&cru PLL_GPLL>, <&pmucru PLL_PPLL>; ++ assigned-clock-rates = <1200000000>, <200000000>; ++ rockchip,grf = <&grf>; ++ }; ++ ++ i2c0: i2c@fdd40000 { ++ compatible = "rockchip,rk3568-i2c", "rockchip,rk3399-i2c"; ++ reg = <0x0 0xfdd40000 0x0 0x1000>; ++ interrupts = ; ++ clocks = <&pmucru CLK_I2C0>, <&pmucru PCLK_I2C0>; ++ clock-names = "i2c", "pclk"; ++ pinctrl-0 = <&i2c0_xfer>; ++ pinctrl-names = "default"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ uart0: serial@fdd50000 { ++ compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; ++ reg = <0x0 0xfdd50000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&pmucru SCLK_UART0>, <&pmucru PCLK_UART0>; ++ clock-names = "baudclk", "apb_pclk"; ++ dmas = <&dmac0 0>, <&dmac0 1>; ++ dma-names = "tx", "rx"; ++ pinctrl-0 = <&uart0_xfer>; ++ pinctrl-names = "default"; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ pwm0: pwm@fdd70000 { ++ compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; ++ reg = <0x0 0xfdd70000 0x0 0x10>; ++ clocks = <&pmucru CLK_PWM0>, <&pmucru PCLK_PWM0>; ++ clock-names = "pwm", "pclk"; ++ pinctrl-0 = <&pwm0m0_pins>; ++ pinctrl-names = "active"; ++ #pwm-cells = <3>; ++ status = "disabled"; ++ }; ++ ++ pwm1: pwm@fdd70010 { ++ compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; ++ reg = <0x0 0xfdd70010 0x0 0x10>; ++ clocks = <&pmucru CLK_PWM0>, <&pmucru PCLK_PWM0>; ++ clock-names = "pwm", "pclk"; ++ pinctrl-0 = <&pwm1m0_pins>; ++ pinctrl-names = "active"; ++ #pwm-cells = <3>; ++ status = "disabled"; ++ }; ++ ++ pwm2: pwm@fdd70020 { ++ compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; ++ reg = <0x0 0xfdd70020 0x0 0x10>; ++ clocks = <&pmucru CLK_PWM0>, <&pmucru PCLK_PWM0>; ++ clock-names = "pwm", "pclk"; ++ pinctrl-0 = <&pwm2m0_pins>; ++ pinctrl-names = "active"; ++ #pwm-cells = <3>; ++ status = "disabled"; ++ }; ++ ++ pwm3: pwm@fdd70030 { ++ compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; ++ reg = <0x0 0xfdd70030 0x0 0x10>; ++ clocks = <&pmucru CLK_PWM0>, <&pmucru PCLK_PWM0>; ++ clock-names = "pwm", "pclk"; ++ pinctrl-0 = <&pwm3_pins>; ++ pinctrl-names = "active"; ++ #pwm-cells = <3>; ++ status = "disabled"; ++ }; ++ ++ pmu: power-management@fdd90000 { ++ compatible = "rockchip,rk3568-pmu", "syscon", "simple-mfd"; ++ reg = <0x0 0xfdd90000 0x0 0x1000>; ++ ++ power: power-controller { ++ compatible = "rockchip,rk3568-power-controller"; ++ #power-domain-cells = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* These power domains are grouped by VD_GPU */ ++ power-domain@RK3568_PD_GPU { ++ reg = ; ++ clocks = <&cru ACLK_GPU_PRE>, ++ <&cru PCLK_GPU_PRE>; ++ pm_qos = <&qos_gpu>; ++ #power-domain-cells = <0>; ++ }; ++ ++ /* These power domains are grouped by VD_LOGIC */ ++ power-domain@RK3568_PD_VI { ++ reg = ; ++ clocks = <&cru HCLK_VI>, ++ <&cru PCLK_VI>; ++ pm_qos = <&qos_isp>, ++ <&qos_vicap0>, ++ <&qos_vicap1>; ++ #power-domain-cells = <0>; ++ }; ++ ++ power-domain@RK3568_PD_VO { ++ reg = ; ++ clocks = <&cru HCLK_VO>, ++ <&cru PCLK_VO>, ++ <&cru ACLK_VOP_PRE>; ++ pm_qos = <&qos_hdcp>, ++ <&qos_vop_m0>, ++ <&qos_vop_m1>; ++ #power-domain-cells = <0>; ++ }; ++ ++ power-domain@RK3568_PD_RGA { ++ reg = ; ++ clocks = <&cru HCLK_RGA_PRE>, ++ <&cru PCLK_RGA_PRE>; ++ pm_qos = <&qos_ebc>, ++ <&qos_iep>, ++ <&qos_jpeg_dec>, ++ <&qos_jpeg_enc>, ++ <&qos_rga_rd>, ++ <&qos_rga_wr>; ++ #power-domain-cells = <0>; ++ }; ++ ++ power-domain@RK3568_PD_VPU { ++ reg = ; ++ clocks = <&cru HCLK_VPU_PRE>; ++ pm_qos = <&qos_vpu>; ++ #power-domain-cells = <0>; ++ }; ++ ++ power-domain@RK3568_PD_RKVDEC { ++ clocks = <&cru HCLK_RKVDEC_PRE>; ++ reg = ; ++ pm_qos = <&qos_rkvdec>; ++ #power-domain-cells = <0>; ++ }; ++ ++ power-domain@RK3568_PD_RKVENC { ++ reg = ; ++ clocks = <&cru HCLK_RKVENC_PRE>; ++ pm_qos = <&qos_rkvenc_rd_m0>, ++ <&qos_rkvenc_rd_m1>, ++ <&qos_rkvenc_wr_m0>; ++ #power-domain-cells = <0>; ++ }; ++ }; ++ }; ++ ++ gpu: gpu@fde60000 { ++ compatible = "rockchip,rk3568-mali", "arm,mali-bifrost"; ++ reg = <0x0 0xfde60000 0x0 0x4000>; ++ ++ interrupts = , ++ , ++ ; ++ interrupt-names = "job", "mmu", "gpu"; ++ clocks = <&scmi_clk 1>, <&cru CLK_GPU>; ++ clock-names = "core", "bus"; ++ operating-points-v2 = <&gpu_opp_table>; ++ #cooling-cells = <2>; ++ power-domains = <&power RK3568_PD_GPU>; ++ status = "disabled"; ++ }; ++ ++ sdmmc2: mmc@fe000000 { ++ compatible = "rockchip,rk3568-dw-mshc", "rockchip,rk3288-dw-mshc"; ++ reg = <0x0 0xfe000000 0x0 0x4000>; ++ interrupts = ; ++ clocks = <&cru HCLK_SDMMC2>, <&cru CLK_SDMMC2>, ++ <&cru SCLK_SDMMC2_DRV>, <&cru SCLK_SDMMC2_SAMPLE>; ++ clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; ++ fifo-depth = <0x100>; ++ max-frequency = <150000000>; ++ resets = <&cru SRST_SDMMC2>; ++ reset-names = "reset"; ++ status = "disabled"; ++ }; ++ ++ gmac1: ethernet@fe010000 { ++ compatible = "rockchip,rk3568-gmac", "snps,dwmac-4.20a"; ++ reg = <0x0 0xfe010000 0x0 0x10000>; ++ interrupts = , ++ ; ++ interrupt-names = "macirq", "eth_wake_irq"; ++ clocks = <&cru SCLK_GMAC1>, <&cru SCLK_GMAC1_RX_TX>, ++ <&cru SCLK_GMAC1_RX_TX>, <&cru CLK_MAC1_REFOUT>, ++ <&cru ACLK_GMAC1>, <&cru PCLK_GMAC1>, ++ <&cru SCLK_GMAC1_RX_TX>, <&cru CLK_GMAC1_PTP_REF>; ++ clock-names = "stmmaceth", "mac_clk_rx", ++ "mac_clk_tx", "clk_mac_refout", ++ "aclk_mac", "pclk_mac", ++ "clk_mac_speed", "ptp_ref"; ++ resets = <&cru SRST_A_GMAC1>; ++ reset-names = "stmmaceth"; ++ rockchip,grf = <&grf>; ++ snps,axi-config = <&gmac1_stmmac_axi_setup>; ++ snps,mixed-burst; ++ snps,mtl-rx-config = <&gmac1_mtl_rx_setup>; ++ snps,mtl-tx-config = <&gmac1_mtl_tx_setup>; ++ snps,tso; ++ status = "disabled"; ++ ++ mdio1: mdio { ++ compatible = "snps,dwmac-mdio"; ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ }; ++ ++ gmac1_stmmac_axi_setup: stmmac-axi-config { ++ snps,blen = <0 0 0 0 16 8 4>; ++ snps,rd_osr_lmt = <8>; ++ snps,wr_osr_lmt = <4>; ++ }; ++ ++ gmac1_mtl_rx_setup: rx-queues-config { ++ snps,rx-queues-to-use = <1>; ++ queue0 {}; ++ }; ++ ++ gmac1_mtl_tx_setup: tx-queues-config { ++ snps,tx-queues-to-use = <1>; ++ queue0 {}; ++ }; ++ }; ++ ++ display_subsystem: display-subsystem { ++ compatible = "rockchip,display-subsystem"; ++ ports = <&vop_out>; ++ }; ++ ++ vop: vop@fe040000 { ++ compatible = "rockchip,rk3568-vop"; ++ reg = <0x0 0xfe040000 0x0 0x3000>, <0x0 0xfe044000 0x0 0x1000>; ++ reg-names = "regs", "gamma_lut"; ++ rockchip,grf = <&grf>; ++ interrupts = ; ++ clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>, <&cru DCLK_VOP0>, <&cru DCLK_VOP1>, <&cru DCLK_VOP2>; ++ clock-names = "aclk_vop", "hclk_vop", "dclk_vp0", "dclk_vp1", "dclk_vp2"; ++ iommus = <&vop_mmu>; ++ power-domains = <&power RK3568_PD_VO>; ++ status = "disabled"; ++ ++ vop_out: ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ vp0: port@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ ++ vp0_out_hdmi: endpoint@0 { ++ reg = <0>; ++ remote-endpoint = <&hdmi_in_vp0>; ++ status = "disabled"; ++ }; ++ }; ++ ++ vp1: port@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ ++ vp1_out_hdmi: endpoint@0 { ++ reg = <0>; ++ remote-endpoint = <&hdmi_in_vp1>; ++ status = "disabled"; ++ }; ++ }; ++ ++ vp2: port@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ ++ vp2_out_hdmi: endpoint@0 { ++ reg = <0>; ++ remote-endpoint = <&hdmi_in_vp2>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ }; ++ ++ vop_mmu: iommu@fe043e00 { ++ compatible = "rockchip,rk3568-iommu"; ++ reg = <0x0 0xfe043e00 0x0 0x100>, <0x0 0xfe043f00 0x0 0x100>; ++ interrupts = ; ++ interrupt-names = "vop_mmu"; ++ clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>; ++ clock-names = "aclk", "iface"; ++ #iommu-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ hdmi: hdmi@fe0a0000 { ++ compatible = "rockchip,rk3568-dw-hdmi"; ++ reg = <0x0 0xfe0a0000 0x0 0x20000>; ++ interrupts = ; ++ clocks = <&cru PCLK_HDMI_HOST>, ++ <&cru CLK_HDMI_SFR>, ++ <&cru CLK_HDMI_CEC>, ++ <&cru HCLK_VOP>; ++ clock-names = "iahb", "isfr", "cec", "hclk"; ++ power-domains = <&power RK3568_PD_VO>; ++ reg-io-width = <4>; ++ rockchip,grf = <&grf>; ++ #sound-dai-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&hdmitx_scl &hdmitx_sda &hdmitxm0_cec>; ++ status = "disabled"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hdmi_in: port@0 { ++ reg = <0>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hdmi_in_vp0: endpoint@0 { ++ reg = <0>; ++ remote-endpoint = <&vp0_out_hdmi>; ++ status = "disabled"; ++ }; ++ ++ hdmi_in_vp1: endpoint@1 { ++ reg = <1>; ++ remote-endpoint = <&vp1_out_hdmi>; ++ status = "disabled"; ++ }; ++ ++ hdmi_in_vp2: endpoint@2 { ++ reg = <2>; ++ remote-endpoint = <&vp2_out_hdmi>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ }; ++ ++ qos_gpu: qos@fe128000 { ++ compatible = "rockchip,rk3568-qos", "syscon"; ++ reg = <0x0 0xfe128000 0x0 0x20>; ++ }; ++ ++ qos_rkvenc_rd_m0: qos@fe138080 { ++ compatible = "rockchip,rk3568-qos", "syscon"; ++ reg = <0x0 0xfe138080 0x0 0x20>; ++ }; ++ ++ qos_rkvenc_rd_m1: qos@fe138100 { ++ compatible = "rockchip,rk3568-qos", "syscon"; ++ reg = <0x0 0xfe138100 0x0 0x20>; ++ }; ++ ++ qos_rkvenc_wr_m0: qos@fe138180 { ++ compatible = "rockchip,rk3568-qos", "syscon"; ++ reg = <0x0 0xfe138180 0x0 0x20>; ++ }; ++ ++ qos_isp: qos@fe148000 { ++ compatible = "rockchip,rk3568-qos", "syscon"; ++ reg = <0x0 0xfe148000 0x0 0x20>; ++ }; ++ ++ qos_vicap0: qos@fe148080 { ++ compatible = "rockchip,rk3568-qos", "syscon"; ++ reg = <0x0 0xfe148080 0x0 0x20>; ++ }; ++ ++ qos_vicap1: qos@fe148100 { ++ compatible = "rockchip,rk3568-qos", "syscon"; ++ reg = <0x0 0xfe148100 0x0 0x20>; ++ }; ++ ++ qos_vpu: qos@fe150000 { ++ compatible = "rockchip,rk3568-qos", "syscon"; ++ reg = <0x0 0xfe150000 0x0 0x20>; ++ }; ++ ++ qos_ebc: qos@fe158000 { ++ compatible = "rockchip,rk3568-qos", "syscon"; ++ reg = <0x0 0xfe158000 0x0 0x20>; ++ }; ++ ++ qos_iep: qos@fe158100 { ++ compatible = "rockchip,rk3568-qos", "syscon"; ++ reg = <0x0 0xfe158100 0x0 0x20>; ++ }; ++ ++ qos_jpeg_dec: qos@fe158180 { ++ compatible = "rockchip,rk3568-qos", "syscon"; ++ reg = <0x0 0xfe158180 0x0 0x20>; ++ }; ++ ++ qos_jpeg_enc: qos@fe158200 { ++ compatible = "rockchip,rk3568-qos", "syscon"; ++ reg = <0x0 0xfe158200 0x0 0x20>; ++ }; ++ ++ qos_rga_rd: qos@fe158280 { ++ compatible = "rockchip,rk3568-qos", "syscon"; ++ reg = <0x0 0xfe158280 0x0 0x20>; ++ }; ++ ++ qos_rga_wr: qos@fe158300 { ++ compatible = "rockchip,rk3568-qos", "syscon"; ++ reg = <0x0 0xfe158300 0x0 0x20>; ++ }; ++ ++ qos_npu: qos@fe180000 { ++ compatible = "rockchip,rk3568-qos", "syscon"; ++ reg = <0x0 0xfe180000 0x0 0x20>; ++ }; ++ ++ qos_pcie2x1: qos@fe190000 { ++ compatible = "rockchip,rk3568-qos", "syscon"; ++ reg = <0x0 0xfe190000 0x0 0x20>; ++ }; ++ ++ qos_sata1: qos@fe190280 { ++ compatible = "rockchip,rk3568-qos", "syscon"; ++ reg = <0x0 0xfe190280 0x0 0x20>; ++ }; ++ ++ qos_sata2: qos@fe190300 { ++ compatible = "rockchip,rk3568-qos", "syscon"; ++ reg = <0x0 0xfe190300 0x0 0x20>; ++ }; ++ ++ qos_usb3_0: qos@fe190380 { ++ compatible = "rockchip,rk3568-qos", "syscon"; ++ reg = <0x0 0xfe190380 0x0 0x20>; ++ }; ++ ++ qos_usb3_1: qos@fe190400 { ++ compatible = "rockchip,rk3568-qos", "syscon"; ++ reg = <0x0 0xfe190400 0x0 0x20>; ++ }; ++ ++ qos_rkvdec: qos@fe198000 { ++ compatible = "rockchip,rk3568-qos", "syscon"; ++ reg = <0x0 0xfe198000 0x0 0x20>; ++ }; ++ ++ qos_hdcp: qos@fe1a8000 { ++ compatible = "rockchip,rk3568-qos", "syscon"; ++ reg = <0x0 0xfe1a8000 0x0 0x20>; ++ }; ++ ++ qos_vop_m0: qos@fe1a8080 { ++ compatible = "rockchip,rk3568-qos", "syscon"; ++ reg = <0x0 0xfe1a8080 0x0 0x20>; ++ }; ++ ++ qos_vop_m1: qos@fe1a8100 { ++ compatible = "rockchip,rk3568-qos", "syscon"; ++ reg = <0x0 0xfe1a8100 0x0 0x20>; ++ }; ++ ++ pcie2x1: pcie@fe260000 { ++ compatible = "rockchip,rk3568-pcie"; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ bus-range = <0x0 0xf>; ++ assigned-clocks = <&cru ACLK_PCIE20_MST>, <&cru ACLK_PCIE20_SLV>, ++ <&cru ACLK_PCIE20_DBI>, <&cru PCLK_PCIE20>, ++ <&cru CLK_PCIE20_AUX_NDFT>; ++ clocks = <&cru ACLK_PCIE20_MST>, <&cru ACLK_PCIE20_SLV>, ++ <&cru ACLK_PCIE20_DBI>, <&cru PCLK_PCIE20>, ++ <&cru CLK_PCIE20_AUX_NDFT>; ++ clock-names = "aclk_mst", "aclk_slv", ++ "aclk_dbi", "pclk", "aux"; ++ device_type = "pci"; ++ interrupts = , ++ , ++ , ++ , ++ ; ++ interrupt-names = "sys", "pmc", "msi", "legacy", "err"; ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 7>; ++ interrupt-map = <0 0 0 1 &pcie_intc 0>, ++ <0 0 0 2 &pcie_intc 1>, ++ <0 0 0 3 &pcie_intc 2>, ++ <0 0 0 4 &pcie_intc 3>; ++ linux,pci-domain = <0>; ++ num-ib-windows = <6>; ++ num-ob-windows = <2>; ++ max-link-speed = <2>; ++ msi-map = <0x0 &gic 0x0 0x1000>; ++ num-lanes = <1>; ++ phys = <&combphy2_psq PHY_TYPE_PCIE>; ++ phy-names = "pcie-phy"; ++ power-domains = <&power RK3568_PD_PIPE>; ++ reg = <0x3 0xc0000000 0x0 0x400000>, ++ <0x0 0xfe260000 0x0 0x10000>, ++ <0x3 0x3f800000 0x0 0x800000>; ++ ranges = <0x1000000 0x0 0x7f700000 0x3 0x3f700000 0x0 0x00100000 ++ 0x2000000 0x0 0x40000000 0x3 0x00000000 0x0 0x3f700000>; ++ reg-names = "dbi", "apb", "config"; ++ resets = <&cru SRST_PCIE20_POWERUP>; ++ reset-names = "pipe"; ++ status = "disabled"; ++ ++ pcie_intc: legacy-interrupt-controller { ++ #address-cells = <0>; ++ #interrupt-cells = <1>; ++ interrupt-controller; ++ interrupt-parent = <&gic>; ++ interrupts = ; ++ }; ++ ++ }; ++ ++ sdmmc0: mmc@fe2b0000 { ++ compatible = "rockchip,rk3568-dw-mshc", "rockchip,rk3288-dw-mshc"; ++ reg = <0x0 0xfe2b0000 0x0 0x4000>; ++ interrupts = ; ++ clocks = <&cru HCLK_SDMMC0>, <&cru CLK_SDMMC0>, ++ <&cru SCLK_SDMMC0_DRV>, <&cru SCLK_SDMMC0_SAMPLE>; ++ clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; ++ fifo-depth = <0x100>; ++ max-frequency = <150000000>; ++ resets = <&cru SRST_SDMMC0>; ++ reset-names = "reset"; ++ status = "disabled"; ++ }; ++ ++ sdmmc1: mmc@fe2c0000 { ++ compatible = "rockchip,rk3568-dw-mshc", "rockchip,rk3288-dw-mshc"; ++ reg = <0x0 0xfe2c0000 0x0 0x4000>; ++ interrupts = ; ++ clocks = <&cru HCLK_SDMMC1>, <&cru CLK_SDMMC1>, ++ <&cru SCLK_SDMMC1_DRV>, <&cru SCLK_SDMMC1_SAMPLE>; ++ clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; ++ fifo-depth = <0x100>; ++ max-frequency = <150000000>; ++ resets = <&cru SRST_SDMMC1>; ++ reset-names = "reset"; ++ status = "disabled"; ++ }; ++ ++ sfc: spi@fe300000 { ++ compatible = "rockchip,sfc"; ++ reg = <0x0 0xfe300000 0x0 0x4000>; ++ interrupts = ; ++ clocks = <&cru SCLK_SFC>, <&cru HCLK_SFC>; ++ clock-names = "clk_sfc", "hclk_sfc"; ++ pinctrl-0 = <&fspi_pins>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ }; ++ ++ sdhci: mmc@fe310000 { ++ compatible = "rockchip,rk3568-dwcmshc"; ++ reg = <0x0 0xfe310000 0x0 0x10000>; ++ interrupts = ; ++ assigned-clocks = <&cru BCLK_EMMC>, <&cru TCLK_EMMC>; ++ assigned-clock-rates = <200000000>, <24000000>; ++ clocks = <&cru CCLK_EMMC>, <&cru HCLK_EMMC>, ++ <&cru ACLK_EMMC>, <&cru BCLK_EMMC>, ++ <&cru TCLK_EMMC>; ++ clock-names = "core", "bus", "axi", "block", "timer"; ++ status = "disabled"; ++ }; ++ ++ spdif: spdif@fe460000 { ++ compatible = "rockchip,rk3568-spdif"; ++ reg = <0x0 0xfe460000 0x0 0x1000>; ++ interrupts = ; ++ clock-names = "mclk", "hclk"; ++ clocks = <&cru MCLK_SPDIF_8CH>, <&cru HCLK_SPDIF_8CH>; ++ dmas = <&dmac1 1>; ++ dma-names = "tx"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spdifm0_tx>; ++ #sound-dai-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2s1_8ch: i2s@fe410000 { ++ compatible = "rockchip,rk3568-i2s-tdm"; ++ reg = <0x0 0xfe410000 0x0 0x1000>; ++ interrupts = ; ++ assigned-clocks = <&cru CLK_I2S1_8CH_TX_SRC>, <&cru CLK_I2S1_8CH_RX_SRC>; ++ assigned-clock-rates = <1188000000>, <1188000000>; ++ clocks = <&cru MCLK_I2S1_8CH_TX>, <&cru MCLK_I2S1_8CH_RX>, ++ <&cru HCLK_I2S1_8CH>; ++ clock-names = "mclk_tx", "mclk_rx", "hclk"; ++ dmas = <&dmac1 3>, <&dmac1 2>; ++ dma-names = "rx", "tx"; ++ resets = <&cru SRST_M_I2S1_8CH_TX>, <&cru SRST_M_I2S1_8CH_RX>; ++ reset-names = "tx-m", "rx-m"; ++ rockchip,grf = <&grf>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2s1m0_sclktx &i2s1m0_sclkrx ++ &i2s1m0_lrcktx &i2s1m0_lrckrx ++ &i2s1m0_sdi0 &i2s1m0_sdi1 ++ &i2s1m0_sdi2 &i2s1m0_sdi3 ++ &i2s1m0_sdo0 &i2s1m0_sdo1 ++ &i2s1m0_sdo2 &i2s1m0_sdo3>; ++ #sound-dai-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ dmac0: dmac@fe530000 { ++ compatible = "arm,pl330", "arm,primecell"; ++ reg = <0x0 0xfe530000 0x0 0x4000>; ++ interrupts = , ++ ; ++ arm,pl330-periph-burst; ++ clocks = <&cru ACLK_BUS>; ++ clock-names = "apb_pclk"; ++ #dma-cells = <1>; ++ }; ++ ++ dmac1: dmac@fe550000 { ++ compatible = "arm,pl330", "arm,primecell"; ++ reg = <0x0 0xfe550000 0x0 0x4000>; ++ interrupts = , ++ ; ++ arm,pl330-periph-burst; ++ clocks = <&cru ACLK_BUS>; ++ clock-names = "apb_pclk"; ++ #dma-cells = <1>; ++ }; ++ ++ i2c1: i2c@fe5a0000 { ++ compatible = "rockchip,rk3568-i2c", "rockchip,rk3399-i2c"; ++ reg = <0x0 0xfe5a0000 0x0 0x1000>; ++ interrupts = ; ++ clocks = <&cru CLK_I2C1>, <&cru PCLK_I2C1>; ++ clock-names = "i2c", "pclk"; ++ pinctrl-0 = <&i2c1_xfer>; ++ pinctrl-names = "default"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c2: i2c@fe5b0000 { ++ compatible = "rockchip,rk3568-i2c", "rockchip,rk3399-i2c"; ++ reg = <0x0 0xfe5b0000 0x0 0x1000>; ++ interrupts = ; ++ clocks = <&cru CLK_I2C2>, <&cru PCLK_I2C2>; ++ clock-names = "i2c", "pclk"; ++ pinctrl-0 = <&i2c2m0_xfer>; ++ pinctrl-names = "default"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c3: i2c@fe5c0000 { ++ compatible = "rockchip,rk3568-i2c", "rockchip,rk3399-i2c"; ++ reg = <0x0 0xfe5c0000 0x0 0x1000>; ++ interrupts = ; ++ clocks = <&cru CLK_I2C3>, <&cru PCLK_I2C3>; ++ clock-names = "i2c", "pclk"; ++ pinctrl-0 = <&i2c3m0_xfer>; ++ pinctrl-names = "default"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c4: i2c@fe5d0000 { ++ compatible = "rockchip,rk3568-i2c", "rockchip,rk3399-i2c"; ++ reg = <0x0 0xfe5d0000 0x0 0x1000>; ++ interrupts = ; ++ clocks = <&cru CLK_I2C4>, <&cru PCLK_I2C4>; ++ clock-names = "i2c", "pclk"; ++ pinctrl-0 = <&i2c4m0_xfer>; ++ pinctrl-names = "default"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c5: i2c@fe5e0000 { ++ compatible = "rockchip,rk3568-i2c", "rockchip,rk3399-i2c"; ++ reg = <0x0 0xfe5e0000 0x0 0x1000>; ++ interrupts = ; ++ clocks = <&cru CLK_I2C5>, <&cru PCLK_I2C5>; ++ clock-names = "i2c", "pclk"; ++ pinctrl-0 = <&i2c5m0_xfer>; ++ pinctrl-names = "default"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ wdt: watchdog@fe600000 { ++ compatible = "rockchip,rk3568-wdt", "snps,dw-wdt"; ++ reg = <0x0 0xfe600000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&cru TCLK_WDT_NS>, <&cru PCLK_WDT_NS>; ++ clock-names = "tclk", "pclk"; ++ }; ++ ++ uart1: serial@fe650000 { ++ compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; ++ reg = <0x0 0xfe650000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>; ++ clock-names = "baudclk", "apb_pclk"; ++ dmas = <&dmac0 2>, <&dmac0 3>; ++ dma-names = "tx", "rx"; ++ pinctrl-0 = <&uart1m0_xfer>; ++ pinctrl-names = "default"; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ uart2: serial@fe660000 { ++ compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; ++ reg = <0x0 0xfe660000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>; ++ clock-names = "baudclk", "apb_pclk"; ++ dmas = <&dmac0 4>, <&dmac0 5>; ++ dma-names = "tx", "rx"; ++ pinctrl-0 = <&uart2m0_xfer>; ++ pinctrl-names = "default"; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ uart3: serial@fe670000 { ++ compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; ++ reg = <0x0 0xfe670000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>; ++ clock-names = "baudclk", "apb_pclk"; ++ dmas = <&dmac0 6>, <&dmac0 7>; ++ dma-names = "tx", "rx"; ++ pinctrl-0 = <&uart3m0_xfer>; ++ pinctrl-names = "default"; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ uart4: serial@fe680000 { ++ compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; ++ reg = <0x0 0xfe680000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&cru SCLK_UART4>, <&cru PCLK_UART4>; ++ clock-names = "baudclk", "apb_pclk"; ++ dmas = <&dmac0 8>, <&dmac0 9>; ++ dma-names = "tx", "rx"; ++ pinctrl-0 = <&uart4m0_xfer>; ++ pinctrl-names = "default"; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ uart5: serial@fe690000 { ++ compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; ++ reg = <0x0 0xfe690000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&cru SCLK_UART5>, <&cru PCLK_UART5>; ++ clock-names = "baudclk", "apb_pclk"; ++ dmas = <&dmac0 10>, <&dmac0 11>; ++ dma-names = "tx", "rx"; ++ pinctrl-0 = <&uart5m0_xfer>; ++ pinctrl-names = "default"; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ uart6: serial@fe6a0000 { ++ compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; ++ reg = <0x0 0xfe6a0000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&cru SCLK_UART6>, <&cru PCLK_UART6>; ++ clock-names = "baudclk", "apb_pclk"; ++ dmas = <&dmac0 12>, <&dmac0 13>; ++ dma-names = "tx", "rx"; ++ pinctrl-0 = <&uart6m0_xfer>; ++ pinctrl-names = "default"; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ uart7: serial@fe6b0000 { ++ compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; ++ reg = <0x0 0xfe6b0000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&cru SCLK_UART7>, <&cru PCLK_UART7>; ++ clock-names = "baudclk", "apb_pclk"; ++ dmas = <&dmac0 14>, <&dmac0 15>; ++ dma-names = "tx", "rx"; ++ pinctrl-0 = <&uart7m0_xfer>; ++ pinctrl-names = "default"; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ uart8: serial@fe6c0000 { ++ compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; ++ reg = <0x0 0xfe6c0000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&cru SCLK_UART8>, <&cru PCLK_UART8>; ++ clock-names = "baudclk", "apb_pclk"; ++ dmas = <&dmac0 16>, <&dmac0 17>; ++ dma-names = "tx", "rx"; ++ pinctrl-0 = <&uart8m0_xfer>; ++ pinctrl-names = "default"; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ uart9: serial@fe6d0000 { ++ compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; ++ reg = <0x0 0xfe6d0000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&cru SCLK_UART9>, <&cru PCLK_UART9>; ++ clock-names = "baudclk", "apb_pclk"; ++ dmas = <&dmac0 18>, <&dmac0 19>; ++ dma-names = "tx", "rx"; ++ pinctrl-0 = <&uart9m0_xfer>; ++ pinctrl-names = "default"; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ thermal_zones: thermal-zones { ++ cpu_thermal: cpu-thermal { ++ polling-delay-passive = <100>; ++ polling-delay = <1000>; ++ ++ thermal-sensors = <&tsadc 0>; ++ ++ trips { ++ cpu_alert0: cpu_alert0 { ++ temperature = <70000>; ++ hysteresis = <2000>; ++ type = "passive"; ++ }; ++ cpu_alert1: cpu_alert1 { ++ temperature = <75000>; ++ hysteresis = <2000>; ++ type = "passive"; ++ }; ++ cpu_crit: cpu_crit { ++ temperature = <95000>; ++ hysteresis = <2000>; ++ type = "critical"; ++ }; ++ }; ++ ++ cooling-maps { ++ map0 { ++ trip = <&cpu_alert0>; ++ cooling-device = ++ <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, ++ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, ++ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, ++ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; ++ }; ++ }; ++ }; ++ ++ gpu_thermal: gpu-thermal { ++ polling-delay-passive = <20>; /* milliseconds */ ++ polling-delay = <1000>; /* milliseconds */ ++ ++ thermal-sensors = <&tsadc 1>; ++ }; ++ }; ++ ++ tsadc: tsadc@fe710000 { ++ compatible = "rockchip,rk3568-tsadc"; ++ reg = <0x0 0xfe710000 0x0 0x100>; ++ interrupts = ; ++ assigned-clocks = <&cru CLK_TSADC_TSEN>, <&cru CLK_TSADC>; ++ assigned-clock-rates = <17000000>, <700000>; ++ clocks = <&cru CLK_TSADC>, <&cru PCLK_TSADC>; ++ clock-names = "tsadc", "apb_pclk"; ++ resets = <&cru SRST_P_TSADC>, <&cru SRST_TSADC>, ++ <&cru SRST_TSADCPHY>; ++ rockchip,grf = <&grf>; ++ rockchip,hw-tshut-temp = <95000>; ++ pinctrl-names = "init", "default", "sleep"; ++ pinctrl-0 = <&tsadc_pin>; ++ pinctrl-1 = <&tsadc_shutorg>; ++ pinctrl-2 = <&tsadc_pin>; ++ #thermal-sensor-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ saradc: saradc@fe720000 { ++ compatible = "rockchip,rk3568-saradc", "rockchip,rk3399-saradc"; ++ reg = <0x0 0xfe720000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&cru CLK_SARADC>, <&cru PCLK_SARADC>; ++ clock-names = "saradc", "apb_pclk"; ++ resets = <&cru SRST_P_SARADC>; ++ reset-names = "saradc-apb"; ++ #io-channel-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ pwm4: pwm@fe6e0000 { ++ compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; ++ reg = <0x0 0xfe6e0000 0x0 0x10>; ++ clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>; ++ clock-names = "pwm", "pclk"; ++ pinctrl-0 = <&pwm4_pins>; ++ pinctrl-names = "active"; ++ #pwm-cells = <3>; ++ status = "disabled"; ++ }; ++ ++ pwm5: pwm@fe6e0010 { ++ compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; ++ reg = <0x0 0xfe6e0010 0x0 0x10>; ++ clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>; ++ clock-names = "pwm", "pclk"; ++ pinctrl-0 = <&pwm5_pins>; ++ pinctrl-names = "active"; ++ #pwm-cells = <3>; ++ status = "disabled"; ++ }; ++ ++ pwm6: pwm@fe6e0020 { ++ compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; ++ reg = <0x0 0xfe6e0020 0x0 0x10>; ++ clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>; ++ clock-names = "pwm", "pclk"; ++ pinctrl-0 = <&pwm6_pins>; ++ pinctrl-names = "active"; ++ #pwm-cells = <3>; ++ status = "disabled"; ++ }; ++ ++ pwm7: pwm@fe6e0030 { ++ compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; ++ reg = <0x0 0xfe6e0030 0x0 0x10>; ++ clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>; ++ clock-names = "pwm", "pclk"; ++ pinctrl-0 = <&pwm7_pins>; ++ pinctrl-names = "active"; ++ #pwm-cells = <3>; ++ status = "disabled"; ++ }; ++ ++ pwm8: pwm@fe6f0000 { ++ compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; ++ reg = <0x0 0xfe6f0000 0x0 0x10>; ++ clocks = <&cru CLK_PWM2>, <&cru PCLK_PWM2>; ++ clock-names = "pwm", "pclk"; ++ pinctrl-0 = <&pwm8m0_pins>; ++ pinctrl-names = "active"; ++ #pwm-cells = <3>; ++ status = "disabled"; ++ }; ++ ++ pwm9: pwm@fe6f0010 { ++ compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; ++ reg = <0x0 0xfe6f0010 0x0 0x10>; ++ clocks = <&cru CLK_PWM2>, <&cru PCLK_PWM2>; ++ clock-names = "pwm", "pclk"; ++ pinctrl-0 = <&pwm9m0_pins>; ++ pinctrl-names = "active"; ++ #pwm-cells = <3>; ++ status = "disabled"; ++ }; ++ ++ pwm10: pwm@fe6f0020 { ++ compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; ++ reg = <0x0 0xfe6f0020 0x0 0x10>; ++ clocks = <&cru CLK_PWM2>, <&cru PCLK_PWM2>; ++ clock-names = "pwm", "pclk"; ++ pinctrl-0 = <&pwm10m0_pins>; ++ pinctrl-names = "active"; ++ #pwm-cells = <3>; ++ status = "disabled"; ++ }; ++ ++ pwm11: pwm@fe6f0030 { ++ compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; ++ reg = <0x0 0xfe6f0030 0x0 0x10>; ++ clocks = <&cru CLK_PWM2>, <&cru PCLK_PWM2>; ++ clock-names = "pwm", "pclk"; ++ pinctrl-0 = <&pwm11m0_pins>; ++ pinctrl-names = "active"; ++ #pwm-cells = <3>; ++ status = "disabled"; ++ }; ++ ++ pwm12: pwm@fe700000 { ++ compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; ++ reg = <0x0 0xfe700000 0x0 0x10>; ++ clocks = <&cru CLK_PWM3>, <&cru PCLK_PWM3>; ++ clock-names = "pwm", "pclk"; ++ pinctrl-0 = <&pwm12m0_pins>; ++ pinctrl-names = "active"; ++ #pwm-cells = <3>; ++ status = "disabled"; ++ }; ++ ++ pwm13: pwm@fe700010 { ++ compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; ++ reg = <0x0 0xfe700010 0x0 0x10>; ++ clocks = <&cru CLK_PWM3>, <&cru PCLK_PWM3>; ++ clock-names = "pwm", "pclk"; ++ pinctrl-0 = <&pwm13m0_pins>; ++ pinctrl-names = "active"; ++ #pwm-cells = <3>; ++ status = "disabled"; ++ }; ++ ++ pwm14: pwm@fe700020 { ++ compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; ++ reg = <0x0 0xfe700020 0x0 0x10>; ++ clocks = <&cru CLK_PWM3>, <&cru PCLK_PWM3>; ++ clock-names = "pwm", "pclk"; ++ pinctrl-0 = <&pwm14m0_pins>; ++ pinctrl-names = "active"; ++ #pwm-cells = <3>; ++ status = "disabled"; ++ }; ++ ++ pwm15: pwm@fe700030 { ++ compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; ++ reg = <0x0 0xfe700030 0x0 0x10>; ++ clocks = <&cru CLK_PWM3>, <&cru PCLK_PWM3>; ++ clock-names = "pwm", "pclk"; ++ pinctrl-0 = <&pwm15m0_pins>; ++ pinctrl-names = "active"; ++ #pwm-cells = <3>; ++ status = "disabled"; ++ }; ++ ++ combphy1_usq: phy@fe830000 { ++ compatible = "rockchip,rk3568-naneng-combphy"; ++ reg = <0x0 0xfe830000 0x0 0x100>; ++ #phy-cells = <1>; ++ assigned-clocks = <&pmucru CLK_PCIEPHY1_REF>; ++ assigned-clock-rates = <100000000>; ++ clocks = <&pmucru CLK_PCIEPHY1_REF>, <&cru PCLK_PIPEPHY1>, ++ <&cru PCLK_PIPE>; ++ clock-names = "ref", "apb", "pipe"; ++ resets = <&cru SRST_P_PIPEPHY1>, <&cru SRST_PIPEPHY1>; ++ reset-names = "combphy-apb", "combphy"; ++ rockchip,pipe-grf = <&pipegrf>; ++ rockchip,pipe-phy-grf = <&pipe_phy_grf1>; ++ status = "disabled"; ++ }; ++ ++ combphy2_psq: phy@fe840000 { ++ compatible = "rockchip,rk3568-naneng-combphy"; ++ reg = <0x0 0xfe840000 0x0 0x100>; ++ #phy-cells = <1>; ++ assigned-clocks = <&pmucru CLK_PCIEPHY2_REF>; ++ assigned-clock-rates = <100000000>; ++ clocks = <&pmucru CLK_PCIEPHY2_REF>, <&cru PCLK_PIPEPHY2>, ++ <&cru PCLK_PIPE>; ++ clock-names = "ref", "apb", "pipe"; ++ resets = <&cru SRST_P_PIPEPHY2>, <&cru SRST_PIPEPHY2>; ++ reset-names = "combphy-apb", "combphy"; ++ rockchip,pipe-grf = <&pipegrf>; ++ rockchip,pipe-phy-grf = <&pipe_phy_grf2>; ++ status = "disabled"; ++ }; ++ ++ usb2phy0: usb2-phy@fe8a0000 { ++ compatible = "rockchip,rk3568-usb2phy"; ++ reg = <0x0 0xfe8a0000 0x0 0x10000>; ++ clocks = <&pmucru CLK_USBPHY0_REF>; ++ clock-names = "phyclk"; ++ #clock-cells = <0>; ++ clock-output-names = "usb480m_phy"; ++ interrupts = ; ++ rockchip,usbgrf = <&usb2phy0_grf>; ++ status = "disabled"; ++ ++ u2phy0_host: host-port { ++ #phy-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ u2phy0_otg: otg-port { ++ #phy-cells = <0>; ++ status = "disabled"; ++ }; ++ }; ++ ++ usb2phy1: usb2-phy@fe8b0000 { ++ compatible = "rockchip,rk3568-usb2phy"; ++ reg = <0x0 0xfe8b0000 0x0 0x10000>; ++ clocks = <&pmucru CLK_USBPHY1_REF>; ++ clock-names = "phyclk"; ++ #clock-cells = <0>; ++ interrupts = ; ++ rockchip,usbgrf = <&usb2phy1_grf>; ++ status = "disabled"; ++ ++ u2phy1_host: host-port { ++ #phy-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ u2phy1_otg: otg-port { ++ #phy-cells = <0>; ++ status = "disabled"; ++ }; ++ }; ++ ++ pinctrl: pinctrl { ++ compatible = "rockchip,rk3568-pinctrl"; ++ rockchip,grf = <&grf>; ++ rockchip,pmu = <&pmugrf>; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ gpio0: gpio@fdd60000 { ++ compatible = "rockchip,gpio-bank"; ++ reg = <0x0 0xfdd60000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&pmucru PCLK_GPIO0>, <&pmucru DBCLK_GPIO0>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; ++ ++ gpio1: gpio@fe740000 { ++ compatible = "rockchip,gpio-bank"; ++ reg = <0x0 0xfe740000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&cru PCLK_GPIO1>, <&cru DBCLK_GPIO1>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; ++ ++ gpio2: gpio@fe750000 { ++ compatible = "rockchip,gpio-bank"; ++ reg = <0x0 0xfe750000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&cru PCLK_GPIO2>, <&cru DBCLK_GPIO2>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; ++ ++ gpio3: gpio@fe760000 { ++ compatible = "rockchip,gpio-bank"; ++ reg = <0x0 0xfe760000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&cru PCLK_GPIO3>, <&cru DBCLK_GPIO3>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; ++ ++ gpio4: gpio@fe770000 { ++ compatible = "rockchip,gpio-bank"; ++ reg = <0x0 0xfe770000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&cru PCLK_GPIO4>, <&cru DBCLK_GPIO4>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; ++ }; ++}; ++ ++#include "rk3568-pinctrl.dtsi" +--- a/arch/arm/mach-rockchip/rk3568/rk3568.c ++++ b/arch/arm/mach-rockchip/rk3568/rk3568.c +@@ -55,7 +55,7 @@ enum { + }; + + const char * const boot_devices[BROM_LAST_BOOTSOURCE + 1] = { +- [BROM_BOOTSOURCE_EMMC] = "/sdhci@fe310000", ++ [BROM_BOOTSOURCE_EMMC] = "/mmc@fe310000", + [BROM_BOOTSOURCE_SPINOR] = "/spi@fe300000/flash@0", + [BROM_BOOTSOURCE_SD] = "/mmc@fe2b0000", + }; diff --git a/root/package/boot/uboot-rockchip/patches/005-rockchip-rk356x-HACK-fix-sdmmc-support.patch b/root/package/boot/uboot-rockchip/patches/005-rockchip-rk356x-HACK-fix-sdmmc-support.patch new file mode 100644 index 00000000..10e4dd11 --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/005-rockchip-rk356x-HACK-fix-sdmmc-support.patch @@ -0,0 +1,50 @@ +From 01e8a38985a90043abddc5c5bcd049c74bb29a53 Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Sun, 19 Dec 2021 18:52:18 -0500 +Subject: [PATCH 05/11] rockchip: rk356x: HACK: fix sdmmc support + +HACK: lock mmc0 to initial frequency and disable dw-mmc control of power +line. + +The sdmmc on quartz64-a is powered by the sdmmc0 power line, which is +active low. +Even though it is set as a gpio, it still seems to be triggered by the +dw-mmc driver toggling the power line. +Downstream fixes this by setting this to "0" instead of "1" using +kconfigs. + +Also, for some reason the controller will only operate at initial +frequencies. + +Signed-off-by: Peter Geis +--- + arch/arm/dts/rk3566-quartz64-a-u-boot.dtsi | 4 +++- + drivers/mmc/dw_mmc.c | 3 ++- + 2 files changed, 5 insertions(+), 2 deletions(-) + +--- a/arch/arm/dts/rk3566-quartz64-a-u-boot.dtsi ++++ b/arch/arm/dts/rk3566-quartz64-a-u-boot.dtsi +@@ -13,8 +13,10 @@ + }; + + &sdmmc0 { ++ max-frequency = <400000>; ++ bus-width = <4>; + u-boot,dm-spl; +- status = "okay"; ++ u-boot,spl-fifo-mode; + }; + + &uart2 { +--- a/drivers/mmc/dw_mmc.c ++++ b/drivers/mmc/dw_mmc.c +@@ -529,7 +529,8 @@ static int dwmci_init(struct mmc *mmc) + if (host->board_init) + host->board_init(host); + +- dwmci_writel(host, DWMCI_PWREN, 1); ++// dwmci_writel(host, DWMCI_PWREN, 1); ++ dwmci_writel(host, DWMCI_PWREN, 0); + + if (!dwmci_wait_reset(host, DWMCI_RESET_ALL)) { + debug("%s[%d] Fail-reset!!\n", __func__, __LINE__); diff --git a/root/package/boot/uboot-rockchip/patches/006-rockchip-rk356x-add-quartz64-a-board.patch b/root/package/boot/uboot-rockchip/patches/006-rockchip-rk356x-add-quartz64-a-board.patch new file mode 100644 index 00000000..0a5d784b --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/006-rockchip-rk356x-add-quartz64-a-board.patch @@ -0,0 +1,214 @@ +From 9f623c0e96fc7c3b5c9b7a81f0a3017c47033ec7 Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Sun, 19 Dec 2021 18:57:36 -0500 +Subject: [PATCH 06/11] rockchip: rk356x: add quartz64-a board + +Signed-off-by: Peter Geis +--- + arch/arm/mach-rockchip/rk3568/Kconfig | 12 ++- + board/pine64/quartz64-a-rk3566/Kconfig | 15 ++++ + board/pine64/quartz64-a-rk3566/Makefile | 4 + + .../quartz64-a-rk3566/quartz64-a-rk3566.c | 1 + + configs/quartz64-a-rk3566_defconfig | 77 +++++++++++++++++++ + include/configs/quartz64-a-rk3566.h | 14 ++++ + include/dt-bindings/power/rk3568-power.h | 32 ++++++++ + 7 files changed, 154 insertions(+), 1 deletion(-) + create mode 100644 board/pine64/quartz64-a-rk3566/Kconfig + create mode 100644 board/pine64/quartz64-a-rk3566/Makefile + create mode 100644 board/pine64/quartz64-a-rk3566/quartz64-a-rk3566.c + create mode 100644 configs/quartz64-a-rk3566_defconfig + create mode 100644 include/configs/quartz64-a-rk3566.h + create mode 100644 include/dt-bindings/power/rk3568-power.h + +--- a/arch/arm/mach-rockchip/rk3568/Kconfig ++++ b/arch/arm/mach-rockchip/rk3568/Kconfig +@@ -1,11 +1,20 @@ + if ROCKCHIP_RK3568 + ++choice ++ prompt "RK3568/RK3566 board select" ++ + config TARGET_EVB_RK3568 + bool "RK3568 evaluation board" +- select BOARD_LATE_INIT + help + RK3568 EVB is a evaluation board for Rockchp RK3568. + ++config TARGET_QUARTZ64_A_RK3566 ++ bool "Quartz64 Model A RK3566 development board" ++ help ++ Quartz64 Model A RK3566 is a development board from Pine64. ++ ++endchoice ++ + config ROCKCHIP_BOOT_MODE_REG + default 0xfdc20200 + +@@ -19,5 +28,6 @@ config SYS_MALLOC_F_LEN + default 0x2000 + + source "board/rockchip/evb_rk3568/Kconfig" ++source "board/pine64/quartz64-a-rk3566/Kconfig" + + endif +--- /dev/null ++++ b/board/pine64/quartz64-a-rk3566/Kconfig +@@ -0,0 +1,15 @@ ++if TARGET_QUARTZ64_A_RK3566 ++ ++config SYS_BOARD ++ default "quartz64-a-rk3566" ++ ++config SYS_VENDOR ++ default "pine64" ++ ++config SYS_CONFIG_NAME ++ default "quartz64-a-rk3566" ++ ++config BOARD_SPECIFIC_OPTIONS # dummy ++ def_bool y ++ ++endif +--- /dev/null ++++ b/board/pine64/quartz64-a-rk3566/Makefile +@@ -0,0 +1,4 @@ ++# SPDX-License-Identifier: GPL-2.0+ ++# ++ ++obj-y += quartz64-a-rk3566.o +--- /dev/null ++++ b/board/pine64/quartz64-a-rk3566/quartz64-a-rk3566.c +@@ -0,0 +1 @@ ++// SPDX-License-Identifier: GPL-2.0+ +--- /dev/null ++++ b/configs/quartz64-a-rk3566_defconfig +@@ -0,0 +1,77 @@ ++CONFIG_ARM=y ++CONFIG_SKIP_LOWLEVEL_INIT=y ++CONFIG_ARCH_ROCKCHIP=y ++CONFIG_SYS_TEXT_BASE=0x00a00000 ++CONFIG_SPL_LIBCOMMON_SUPPORT=y ++CONFIG_SPL_LIBGENERIC_SUPPORT=y ++CONFIG_NR_DRAM_BANKS=2 ++CONFIG_DEFAULT_DEVICE_TREE="rk3566-quartz64-a" ++CONFIG_ROCKCHIP_RK3568=y ++CONFIG_SPL_ROCKCHIP_BACK_TO_BROM=y ++CONFIG_SPL_ROCKCHIP_COMMON_BOARD=y ++CONFIG_SPL_MMC=y ++CONFIG_SPL_SERIAL=y ++CONFIG_SPL_STACK_R_ADDR=0x600000 ++CONFIG_TARGET_QUARTZ64_A_RK3566=y ++CONFIG_DEBUG_UART_BASE=0xFE660000 ++CONFIG_DEBUG_UART_CLOCK=24000000 ++CONFIG_DEBUG_UART=y ++CONFIG_SYS_LOAD_ADDR=0xc00800 ++CONFIG_API=y ++CONFIG_FIT=y ++CONFIG_FIT_VERBOSE=y ++CONFIG_SPL_LOAD_FIT=y ++CONFIG_DEFAULT_FDT_FILE="rockchip/rk3566-quartz64-a.dtb" ++# CONFIG_DISPLAY_CPUINFO is not set ++CONFIG_DISPLAY_BOARDINFO_LATE=y ++# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set ++CONFIG_SPL_STACK_R=y ++CONFIG_SPL_SEPARATE_BSS=y ++CONFIG_SPL_ATF=y ++CONFIG_SPL_ATF_LOAD_IMAGE_V2=y ++CONFIG_CMD_BIND=y ++CONFIG_CMD_CLK=y ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_I2C=y ++CONFIG_CMD_MMC=y ++# CONFIG_CMD_SETEXPR is not set ++CONFIG_CMD_PMIC=y ++CONFIG_CMD_REGULATOR=y ++# CONFIG_SPL_DOS_PARTITION is not set ++CONFIG_SPL_OF_CONTROL=y ++CONFIG_OF_LIVE=y ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_SPL_REGMAP=y ++CONFIG_SPL_SYSCON=y ++CONFIG_SPL_CLK=y ++CONFIG_ROCKCHIP_GPIO=y ++CONFIG_SYS_I2C_ROCKCHIP=y ++CONFIG_MISC=y ++CONFIG_MMC_HS200_SUPPORT=y ++CONFIG_SPL_MMC_HS200_SUPPORT=y ++CONFIG_MMC_DW=y ++CONFIG_MMC_DW_ROCKCHIP=y ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_SDMA=y ++CONFIG_MMC_SDHCI_ROCKCHIP=y ++CONFIG_DM_ETH=y ++CONFIG_ETH_DESIGNWARE=y ++CONFIG_GMAC_ROCKCHIP=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_DM_PMIC=y ++CONFIG_PMIC_RK8XX=y ++CONFIG_SPL_PMIC_RK8XX=y ++CONFIG_REGULATOR_PWM=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_SPL_DM_REGULATOR_FIXED=y ++CONFIG_DM_REGULATOR_GPIO=y ++CONFIG_REGULATOR_RK8XX=y ++CONFIG_PWM_ROCKCHIP=y ++CONFIG_SPL_RAM=y ++CONFIG_DM_RESET=y ++CONFIG_BAUDRATE=1500000 ++CONFIG_DEBUG_UART_SHIFT=2 ++CONFIG_SYSRESET=y ++CONFIG_SYSRESET_PSCI=y ++CONFIG_ERRNO_STR=y +--- /dev/null ++++ b/include/configs/quartz64-a-rk3566.h +@@ -0,0 +1,14 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++ ++#ifndef __QUARTZ64_A_RK3566_H ++#define __QUARTZ64_A_RK3566_H ++ ++#include ++ ++#define CONFIG_SUPPORT_EMMC_RPMB ++ ++#define ROCKCHIP_DEVICE_SETTINGS \ ++ "stdout=serial,vidconsole\0" \ ++ "stderr=serial,vidconsole\0" ++ ++#endif +--- /dev/null ++++ b/include/dt-bindings/power/rk3568-power.h +@@ -0,0 +1,32 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++#ifndef __DT_BINDINGS_POWER_RK3568_POWER_H__ ++#define __DT_BINDINGS_POWER_RK3568_POWER_H__ ++ ++/* VD_CORE */ ++#define RK3568_PD_CPU_0 0 ++#define RK3568_PD_CPU_1 1 ++#define RK3568_PD_CPU_2 2 ++#define RK3568_PD_CPU_3 3 ++#define RK3568_PD_CORE_ALIVE 4 ++ ++/* VD_PMU */ ++#define RK3568_PD_PMU 5 ++ ++/* VD_NPU */ ++#define RK3568_PD_NPU 6 ++ ++/* VD_GPU */ ++#define RK3568_PD_GPU 7 ++ ++/* VD_LOGIC */ ++#define RK3568_PD_VI 8 ++#define RK3568_PD_VO 9 ++#define RK3568_PD_RGA 10 ++#define RK3568_PD_VPU 11 ++#define RK3568_PD_CENTER 12 ++#define RK3568_PD_RKVDEC 13 ++#define RK3568_PD_RKVENC 14 ++#define RK3568_PD_PIPE 15 ++#define RK3568_PD_LOGIC_ALIVE 16 ++ ++#endif diff --git a/root/package/boot/uboot-rockchip/patches/007-gpio-rockchip-rk_gpio-support-v2-gpio-controller.patch b/root/package/boot/uboot-rockchip/patches/007-gpio-rockchip-rk_gpio-support-v2-gpio-controller.patch new file mode 100644 index 00000000..3066eaaf --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/007-gpio-rockchip-rk_gpio-support-v2-gpio-controller.patch @@ -0,0 +1,755 @@ +From 3a4d973a743bc76cc734db9616f9053f45fa922f Mon Sep 17 00:00:00 2001 +From: Jianqun Xu +Date: Thu, 28 May 2020 11:01:58 +0800 +Subject: [PATCH 07/11] gpio/rockchip: rk_gpio support v2 gpio controller + +The v2 gpio controller add write enable bit for some register, +such as data register, data direction register and so on. + +This patch support v2 gpio controller by redefine the read and +write operation functions. + +Also adds support for the rk3568 pinctrl device. + +Squash all fixes into this commit. + +Change-Id: I2adbcca06a37c48e6f494b89833cd034ba0dae29 +Signed-off-by: Jianqun Xu +Signed-off-by: Peter Geis +--- + arch/arm/include/asm/arch-rockchip/gpio.h | 36 ++ + drivers/gpio/Kconfig | 13 + + drivers/gpio/rk_gpio.c | 89 ++++- + drivers/pinctrl/rockchip/Makefile | 1 + + drivers/pinctrl/rockchip/pinctrl-rk3568.c | 360 ++++++++++++++++++ + .../pinctrl/rockchip/pinctrl-rockchip-core.c | 11 +- + drivers/pinctrl/rockchip/pinctrl-rockchip.h | 42 ++ + 7 files changed, 530 insertions(+), 22 deletions(-) + create mode 100644 drivers/pinctrl/rockchip/pinctrl-rk3568.c + +--- a/arch/arm/include/asm/arch-rockchip/gpio.h ++++ b/arch/arm/include/asm/arch-rockchip/gpio.h +@@ -6,6 +6,7 @@ + #ifndef _ASM_ARCH_GPIO_H + #define _ASM_ARCH_GPIO_H + ++#ifndef CONFIG_ROCKCHIP_GPIO_V2 + struct rockchip_gpio_regs { + u32 swport_dr; + u32 swport_ddr; +@@ -23,6 +24,41 @@ struct rockchip_gpio_regs { + u32 ls_sync; + }; + check_member(rockchip_gpio_regs, ls_sync, 0x60); ++#else ++struct rockchip_gpio_regs { ++ u32 swport_dr_l; /* ADDRESS OFFSET: 0x0000 */ ++ u32 swport_dr_h; /* ADDRESS OFFSET: 0x0004 */ ++ u32 swport_ddr_l; /* ADDRESS OFFSET: 0x0008 */ ++ u32 swport_ddr_h; /* ADDRESS OFFSET: 0x000c */ ++ u32 int_en_l; /* ADDRESS OFFSET: 0x0010 */ ++ u32 int_en_h; /* ADDRESS OFFSET: 0x0014 */ ++ u32 int_mask_l; /* ADDRESS OFFSET: 0x0018 */ ++ u32 int_mask_h; /* ADDRESS OFFSET: 0x001c */ ++ u32 int_type_l; /* ADDRESS OFFSET: 0x0020 */ ++ u32 int_type_h; /* ADDRESS OFFSET: 0x0024 */ ++ u32 int_polarity_l; /* ADDRESS OFFSET: 0x0028 */ ++ u32 int_polarity_h; /* ADDRESS OFFSET: 0x002c */ ++ u32 int_bothedge_l; /* ADDRESS OFFSET: 0x0030 */ ++ u32 int_bothedge_h; /* ADDRESS OFFSET: 0x0034 */ ++ u32 debounce_l; /* ADDRESS OFFSET: 0x0038 */ ++ u32 debounce_h; /* ADDRESS OFFSET: 0x003c */ ++ u32 dbclk_div_en_l; /* ADDRESS OFFSET: 0x0040 */ ++ u32 dbclk_div_en_h; /* ADDRESS OFFSET: 0x0044 */ ++ u32 dbclk_div_con; /* ADDRESS OFFSET: 0x0048 */ ++ u32 reserved004c; /* ADDRESS OFFSET: 0x004c */ ++ u32 int_status; /* ADDRESS OFFSET: 0x0050 */ ++ u32 reserved0054; /* ADDRESS OFFSET: 0x0054 */ ++ u32 int_rawstatus; /* ADDRESS OFFSET: 0x0058 */ ++ u32 reserved005c; /* ADDRESS OFFSET: 0x005c */ ++ u32 port_eoi_l; /* ADDRESS OFFSET: 0x0060 */ ++ u32 port_eoi_h; /* ADDRESS OFFSET: 0x0064 */ ++ u32 reserved0068[2]; /* ADDRESS OFFSET: 0x0068 */ ++ u32 ext_port; /* ADDRESS OFFSET: 0x0070 */ ++ u32 reserved0074; /* ADDRESS OFFSET: 0x0074 */ ++ u32 ver_id; /* ADDRESS OFFSET: 0x0078 */ ++}; ++check_member(rockchip_gpio_regs, ver_id, 0x0078); ++#endif + + enum gpio_pu_pd { + GPIO_PULL_NORMAL = 0, +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -341,6 +341,19 @@ config ROCKCHIP_GPIO + The GPIOs for a device are defined in the device tree with one node + for each bank. + ++config ROCKCHIP_GPIO_V2 ++ bool "Rockchip GPIO driver version 2.0" ++ depends on ROCKCHIP_GPIO ++ default n ++ help ++ Support GPIO access on Rockchip SoCs. The GPIOs are arranged into ++ a number of banks (different for each SoC type) each with 32 GPIOs. ++ The GPIOs for a device are defined in the device tree with one node ++ for each bank. ++ ++ Support version 2.0 GPIO controller, which support write enable bits ++ for some registers, such as dr, ddr. ++ + config SANDBOX_GPIO + bool "Enable sandbox GPIO driver" + depends on SANDBOX && DM && DM_GPIO +--- a/drivers/gpio/rk_gpio.c ++++ b/drivers/gpio/rk_gpio.c +@@ -2,12 +2,15 @@ + /* + * (C) Copyright 2015 Google, Inc + * +- * (C) Copyright 2008-2014 Rockchip Electronics ++ * (C) Copyright 2008-2020 Rockchip Electronics + * Peter, Software Engineering, . ++ * Jianqun Xu, Software Engineering, . + */ + + #include + #include ++#include ++#include + #include + #include + #include +@@ -17,12 +20,34 @@ + #include + #include + +-enum { +- ROCKCHIP_GPIOS_PER_BANK = 32, +-}; ++#include "../pinctrl/rockchip/pinctrl-rockchip.h" + + #define OFFSET_TO_BIT(bit) (1UL << (bit)) + ++#ifdef CONFIG_ROCKCHIP_GPIO_V2 ++#define REG_L(R) (R##_l) ++#define REG_H(R) (R##_h) ++#define READ_REG(REG) ((readl(REG_L(REG)) & 0xFFFF) | \ ++ ((readl(REG_H(REG)) & 0xFFFF) << 16)) ++#define WRITE_REG(REG, VAL) \ ++{\ ++ writel(((VAL) & 0xFFFF) | 0xFFFF0000, REG_L(REG)); \ ++ writel((((VAL) & 0xFFFF0000) >> 16) | 0xFFFF0000, REG_H(REG));\ ++} ++#define CLRBITS_LE32(REG, MASK) WRITE_REG(REG, READ_REG(REG) & ~(MASK)) ++#define SETBITS_LE32(REG, MASK) WRITE_REG(REG, READ_REG(REG) | (MASK)) ++#define CLRSETBITS_LE32(REG, MASK, VAL) WRITE_REG(REG, \ ++ (READ_REG(REG) & ~(MASK)) | (VAL)) ++ ++#else ++#define READ_REG(REG) readl(REG) ++#define WRITE_REG(REG, VAL) writel(VAL, REG) ++#define CLRBITS_LE32(REG, MASK) clrbits_le32(REG, MASK) ++#define SETBITS_LE32(REG, MASK) setbits_le32(REG, MASK) ++#define CLRSETBITS_LE32(REG, MASK, VAL) clrsetbits_le32(REG, MASK, VAL) ++#endif ++ ++ + struct rockchip_gpio_priv { + struct rockchip_gpio_regs *regs; + struct udevice *pinctrl; +@@ -35,7 +60,7 @@ static int rockchip_gpio_direction_input + struct rockchip_gpio_priv *priv = dev_get_priv(dev); + struct rockchip_gpio_regs *regs = priv->regs; + +- clrbits_le32(®s->swport_ddr, OFFSET_TO_BIT(offset)); ++ CLRBITS_LE32(®s->swport_ddr, OFFSET_TO_BIT(offset)); + + return 0; + } +@@ -47,8 +72,8 @@ static int rockchip_gpio_direction_outpu + struct rockchip_gpio_regs *regs = priv->regs; + int mask = OFFSET_TO_BIT(offset); + +- clrsetbits_le32(®s->swport_dr, mask, value ? mask : 0); +- setbits_le32(®s->swport_ddr, mask); ++ CLRSETBITS_LE32(®s->swport_dr, mask, value ? mask : 0); ++ SETBITS_LE32(®s->swport_ddr, mask); + + return 0; + } +@@ -68,7 +93,7 @@ static int rockchip_gpio_set_value(struc + struct rockchip_gpio_regs *regs = priv->regs; + int mask = OFFSET_TO_BIT(offset); + +- clrsetbits_le32(®s->swport_dr, mask, value ? mask : 0); ++ CLRSETBITS_LE32(®s->swport_dr, mask, value ? mask : 0); + + return 0; + } +@@ -86,8 +111,8 @@ static int rockchip_gpio_get_function(st + ret = pinctrl_get_gpio_mux(priv->pinctrl, priv->bank, offset); + if (ret) + return ret; +- is_output = readl(®s->swport_ddr) & OFFSET_TO_BIT(offset); +- ++ is_output = READ_REG(®s->swport_ddr) & OFFSET_TO_BIT(offset); ++ + return is_output ? GPIOF_OUTPUT : GPIOF_INPUT; + #endif + } +@@ -142,19 +167,49 @@ static int rockchip_gpio_probe(struct ud + { + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + struct rockchip_gpio_priv *priv = dev_get_priv(dev); +- char *end; +- int ret; ++ struct rockchip_pinctrl_priv *pctrl_priv; ++ struct rockchip_pin_bank *bank; ++ char *end = NULL; ++ static int gpio; ++ int id = -1, ret; + + priv->regs = dev_read_addr_ptr(dev); + ret = uclass_first_device_err(UCLASS_PINCTRL, &priv->pinctrl); +- if (ret) ++ if (ret) { ++ dev_err(dev, "failed to get pinctrl device %d\n", ret); + return ret; ++ } ++ ++ pctrl_priv = dev_get_priv(priv->pinctrl); ++ if (!pctrl_priv) { ++ dev_err(dev, "failed to get pinctrl priv\n"); ++ return -EINVAL; ++ } + +- uc_priv->gpio_count = ROCKCHIP_GPIOS_PER_BANK; + end = strrchr(dev->name, '@'); +- priv->bank = trailing_strtoln(dev->name, end); +- priv->name[0] = 'A' + priv->bank; +- uc_priv->bank_name = priv->name; ++ if (end) ++ id = trailing_strtoln(dev->name, end); ++ else ++ dev_read_alias_seq(dev, &id); ++ ++ if (id < 0) ++ id = gpio++; ++ ++ if (id >= pctrl_priv->ctrl->nr_banks) { ++ dev_err(dev, "bank id invalid\n"); ++ return -EINVAL; ++ } ++ ++ bank = &pctrl_priv->ctrl->pin_banks[id]; ++ if (bank->bank_num != id) { ++ dev_err(dev, "bank id mismatch with pinctrl\n"); ++ return -EINVAL; ++ } ++ ++ priv->bank = bank->bank_num; ++ uc_priv->gpio_count = bank->nr_pins; ++ uc_priv->gpio_base = bank->pin_base; ++ uc_priv->bank_name = bank->name; + + return 0; + } +--- a/drivers/pinctrl/rockchip/Makefile ++++ b/drivers/pinctrl/rockchip/Makefile +@@ -14,4 +14,5 @@ obj-$(CONFIG_ROCKCHIP_RK3308) += pinctrl + obj-$(CONFIG_ROCKCHIP_RK3328) += pinctrl-rk3328.o + obj-$(CONFIG_ROCKCHIP_RK3368) += pinctrl-rk3368.o + obj-$(CONFIG_ROCKCHIP_RK3399) += pinctrl-rk3399.o ++obj-$(CONFIG_ROCKCHIP_RK3568) += pinctrl-rk3568.o + obj-$(CONFIG_ROCKCHIP_RV1108) += pinctrl-rv1108.o +--- /dev/null ++++ b/drivers/pinctrl/rockchip/pinctrl-rk3568.c +@@ -0,0 +1,360 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * (C) Copyright 2020 Rockchip Electronics Co., Ltd ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "pinctrl-rockchip.h" ++ ++static struct rockchip_mux_route_data rk3568_mux_route_data[] = { ++ MR_TOPGRF(RK_GPIO0, RK_PB3, RK_FUNC_2, 0x0300, RK_GENMASK_VAL(0, 0, 0)), /* CAN0 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO2, RK_PA1, RK_FUNC_4, 0x0300, RK_GENMASK_VAL(0, 0, 1)), /* CAN0 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO1, RK_PA1, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(2, 2, 0)), /* CAN1 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO4, RK_PC3, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(2, 2, 1)), /* CAN1 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO4, RK_PB5, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(4, 4, 0)), /* CAN2 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO2, RK_PB2, RK_FUNC_4, 0x0300, RK_GENMASK_VAL(4, 4, 1)), /* CAN2 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO4, RK_PC4, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(6, 6, 0)), /* EDPDP_HPDIN IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO0, RK_PC2, RK_FUNC_2, 0x0300, RK_GENMASK_VAL(6, 6, 1)), /* EDPDP_HPDIN IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO3, RK_PB1, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(8, 8, 0)), /* GMAC1 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO4, RK_PA7, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(8, 8, 1)), /* GMAC1 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO4, RK_PD1, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(10, 10, 0)), /* HDMITX IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO0, RK_PC7, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(10, 10, 1)), /* HDMITX IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO0, RK_PB6, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(14, 14, 0)), /* I2C2 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO4, RK_PB4, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(14, 14, 1)), /* I2C2 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO1, RK_PA0, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(0, 0, 0)), /* I2C3 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO3, RK_PB6, RK_FUNC_4, 0x0304, RK_GENMASK_VAL(0, 0, 1)), /* I2C3 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO4, RK_PB2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(2, 2, 0)), /* I2C4 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO2, RK_PB1, RK_FUNC_2, 0x0304, RK_GENMASK_VAL(2, 2, 1)), /* I2C4 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO3, RK_PB4, RK_FUNC_4, 0x0304, RK_GENMASK_VAL(4, 4, 0)), /* I2C5 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO4, RK_PD0, RK_FUNC_2, 0x0304, RK_GENMASK_VAL(4, 4, 1)), /* I2C5 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(6, 6, 0)), /* PWM4 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(6, 6, 1)), /* PWM4 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(8, 8, 0)), /* PWM5 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(8, 8, 1)), /* PWM5 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(10, 10, 0)), /* PWM6 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(10, 10, 1)), /* PWM6 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(12, 12, 0)), /* PWM7 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(12, 12, 1)), /* PWM7 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(14, 14, 0)), /* PWM8 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(14, 14, 1)), /* PWM8 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(0, 0, 0)), /* PWM9 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(0, 0, 1)), /* PWM9 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(2, 2, 0)), /* PWM10 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(2, 2, 1)), /* PWM10 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(4, 4, 0)), /* PWM11 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(4, 4, 1)), /* PWM11 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(6, 6, 0)), /* PWM12 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(6, 6, 1)), /* PWM12 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(8, 8, 0)), /* PWM13 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(8, 8, 1)), /* PWM13 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(10, 10, 0)), /* PWM14 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(10, 10, 1)), /* PWM14 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(12, 12, 0)), /* PWM15 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(12, 12, 1)), /* PWM15 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_3, 0x0308, RK_GENMASK_VAL(14, 14, 0)), /* SDMMC2 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO3, RK_PA5, RK_FUNC_5, 0x0308, RK_GENMASK_VAL(14, 14, 1)), /* SDMMC2 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO0, RK_PB5, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(0, 0, 0)), /* SPI0 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO2, RK_PD3, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(0, 0, 1)), /* SPI0 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO2, RK_PB5, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(2, 2, 0)), /* SPI1 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO3, RK_PC3, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(2, 2, 1)), /* SPI1 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO2, RK_PC1, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(4, 4, 0)), /* SPI2 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO3, RK_PA0, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(4, 4, 1)), /* SPI2 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO4, RK_PB3, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(6, 6, 0)), /* SPI3 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(6, 6, 1)), /* SPI3 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO2, RK_PB4, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(8, 8, 0)), /* UART1 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO0, RK_PD1, RK_FUNC_1, 0x030c, RK_GENMASK_VAL(8, 8, 1)), /* UART1 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO0, RK_PD1, RK_FUNC_1, 0x030c, RK_GENMASK_VAL(10, 10, 0)), /* UART2 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO1, RK_PD5, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(10, 10, 1)), /* UART2 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO1, RK_PA1, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(12, 12, 0)), /* UART3 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO3, RK_PB7, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(12, 12, 1)), /* UART3 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO1, RK_PA6, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(14, 14, 0)), /* UART4 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO3, RK_PB2, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(14, 14, 1)), /* UART4 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO2, RK_PA2, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(0, 0, 0)), /* UART5 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO3, RK_PC2, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(0, 0, 1)), /* UART5 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO2, RK_PA4, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(2, 2, 0)), /* UART6 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO1, RK_PD5, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(2, 2, 1)), /* UART6 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO2, RK_PA6, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(5, 4, 0)), /* UART7 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO3, RK_PC4, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(5, 4, 1)), /* UART7 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0310, RK_GENMASK_VAL(5, 4, 2)), /* UART7 IO mux selection M2 */ ++ MR_TOPGRF(RK_GPIO2, RK_PC5, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(6, 6, 0)), /* UART8 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO2, RK_PD7, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(6, 6, 1)), /* UART8 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO2, RK_PB0, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(9, 8, 0)), /* UART9 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO4, RK_PC5, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(9, 8, 1)), /* UART9 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO4, RK_PA4, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(9, 8, 2)), /* UART9 IO mux selection M2 */ ++ MR_TOPGRF(RK_GPIO1, RK_PA2, RK_FUNC_1, 0x0310, RK_GENMASK_VAL(11, 10, 0)), /* I2S1 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO3, RK_PC6, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(11, 10, 1)), /* I2S1 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO2, RK_PD0, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(11, 10, 2)), /* I2S1 IO mux selection M2 */ ++ MR_TOPGRF(RK_GPIO2, RK_PC1, RK_FUNC_1, 0x0310, RK_GENMASK_VAL(12, 12, 0)), /* I2S2 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO4, RK_PB6, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(12, 12, 1)), /* I2S2 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO3, RK_PA2, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(14, 14, 0)), /* I2S3 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(14, 14, 1)), /* I2S3 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO1, RK_PA6, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(0, 0, 0)), /* PDM IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO3, RK_PD6, RK_FUNC_5, 0x0314, RK_GENMASK_VAL(0, 0, 1)), /* PDM IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO0, RK_PA5, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(3, 2, 0)), /* PCIE20 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO2, RK_PD0, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(3, 2, 1)), /* PCIE20 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO1, RK_PB0, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(3, 2, 2)), /* PCIE20 IO mux selection M2 */ ++ MR_TOPGRF(RK_GPIO0, RK_PA4, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(5, 4, 0)), /* PCIE30X1 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO2, RK_PD2, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(5, 4, 1)), /* PCIE30X1 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO1, RK_PA5, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(5, 4, 2)), /* PCIE30X1 IO mux selection M2 */ ++ MR_TOPGRF(RK_GPIO0, RK_PA6, RK_FUNC_2, 0x0314, RK_GENMASK_VAL(7, 6, 0)), /* PCIE30X2 IO mux selection M0 */ ++ MR_TOPGRF(RK_GPIO2, RK_PD4, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(7, 6, 1)), /* PCIE30X2 IO mux selection M1 */ ++ MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(7, 6, 2)), /* PCIE30X2 IO mux selection M2 */ ++}; ++ ++static int rk3568_set_mux(struct rockchip_pin_bank *bank, int pin, int mux) ++{ ++ struct rockchip_pinctrl_priv *priv = bank->priv; ++ int iomux_num = (pin / 8); ++ struct regmap *regmap; ++ int reg, ret, mask; ++ u8 bit; ++ u32 data; ++ ++ debug("setting mux of GPIO%d-%d to %d\n", bank->bank_num, pin, mux); ++ ++ if (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU) ++ regmap = priv->regmap_pmu; ++ else ++ regmap = priv->regmap_base; ++ ++ reg = bank->iomux[iomux_num].offset; ++ if ((pin % 8) >= 4) ++ reg += 0x4; ++ bit = (pin % 4) * 4; ++ mask = 0xf; ++ ++ data = (mask << (bit + 16)); ++ data |= (mux & mask) << bit; ++ ret = regmap_write(regmap, reg, data); ++ ++ return ret; ++} ++ ++#define RK3568_PULL_PMU_OFFSET 0x20 ++#define RK3568_PULL_GRF_OFFSET 0x80 ++#define RK3568_PULL_BITS_PER_PIN 2 ++#define RK3568_PULL_PINS_PER_REG 8 ++#define RK3568_PULL_BANK_STRIDE 0x10 ++ ++static void rk3568_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, ++ int pin_num, struct regmap **regmap, ++ int *reg, u8 *bit) ++{ ++ struct rockchip_pinctrl_priv *info = bank->priv; ++ ++ if (bank->bank_num == 0) { ++ *regmap = info->regmap_pmu; ++ *reg = RK3568_PULL_PMU_OFFSET; ++ *reg += bank->bank_num * RK3568_PULL_BANK_STRIDE; ++ } else { ++ *regmap = info->regmap_base; ++ *reg = RK3568_PULL_GRF_OFFSET; ++ *reg += (bank->bank_num - 1) * RK3568_PULL_BANK_STRIDE; ++ } ++ ++ *reg += ((pin_num / RK3568_PULL_PINS_PER_REG) * 4); ++ *bit = (pin_num % RK3568_PULL_PINS_PER_REG); ++ *bit *= RK3568_PULL_BITS_PER_PIN; ++} ++ ++#define RK3568_DRV_PMU_OFFSET 0x70 ++#define RK3568_DRV_GRF_OFFSET 0x200 ++#define RK3568_DRV_BITS_PER_PIN 8 ++#define RK3568_DRV_PINS_PER_REG 2 ++#define RK3568_DRV_BANK_STRIDE 0x40 ++ ++static void rk3568_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, ++ int pin_num, struct regmap **regmap, ++ int *reg, u8 *bit) ++{ ++ struct rockchip_pinctrl_priv *info = bank->priv; ++ ++ /* The first 32 pins of the first bank are located in PMU */ ++ if (bank->bank_num == 0) { ++ *regmap = info->regmap_pmu; ++ *reg = RK3568_DRV_PMU_OFFSET; ++ } else { ++ *regmap = info->regmap_base; ++ *reg = RK3568_DRV_GRF_OFFSET; ++ *reg += (bank->bank_num - 1) * RK3568_DRV_BANK_STRIDE; ++ } ++ ++ *reg += ((pin_num / RK3568_DRV_PINS_PER_REG) * 4); ++ *bit = (pin_num % RK3568_DRV_PINS_PER_REG); ++ *bit *= RK3568_DRV_BITS_PER_PIN; ++} ++ ++#define RK3568_SCHMITT_BITS_PER_PIN 2 ++#define RK3568_SCHMITT_PINS_PER_REG 8 ++#define RK3568_SCHMITT_BANK_STRIDE 0x10 ++#define RK3568_SCHMITT_GRF_OFFSET 0xc0 ++#define RK3568_SCHMITT_PMUGRF_OFFSET 0x30 ++ ++static int rk3568_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank, ++ int pin_num, struct regmap **regmap, ++ int *reg, u8 *bit) ++{ ++ struct rockchip_pinctrl_priv *info = bank->priv; ++ ++ if (bank->bank_num == 0) { ++ *regmap = info->regmap_pmu; ++ *reg = RK3568_SCHMITT_PMUGRF_OFFSET; ++ } else { ++ *regmap = info->regmap_base; ++ *reg = RK3568_SCHMITT_GRF_OFFSET; ++ *reg += (bank->bank_num - 1) * RK3568_SCHMITT_BANK_STRIDE; ++ } ++ ++ *reg += ((pin_num / RK3568_SCHMITT_PINS_PER_REG) * 4); ++ *bit = pin_num % RK3568_SCHMITT_PINS_PER_REG; ++ *bit *= RK3568_SCHMITT_BITS_PER_PIN; ++ ++ return 0; ++} ++ ++static int rk3568_set_pull(struct rockchip_pin_bank *bank, ++ int pin_num, int pull) ++{ ++ struct regmap *regmap; ++ int reg, ret; ++ u8 bit, type; ++ u32 data; ++ ++ if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT) ++ return -ENOTSUPP; ++ ++ rk3568_calc_pull_reg_and_bit(bank, pin_num, ®map, ®, &bit); ++ type = bank->pull_type[pin_num / 8]; ++ ret = rockchip_translate_pull_value(type, pull); ++ if (ret < 0) { ++ debug("unsupported pull setting %d\n", pull); ++ return ret; ++ } ++ ++ /* enable the write to the equivalent lower bits */ ++ data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16); ++ ++ data |= (ret << bit); ++ ret = regmap_write(regmap, reg, data); ++ ++ return ret; ++} ++ ++static int rk3568_set_drive(struct rockchip_pin_bank *bank, ++ int pin_num, int strength) ++{ ++ struct regmap *regmap; ++ int reg; ++ u32 data; ++ u8 bit; ++ int drv = (1 << (strength + 1)) - 1; ++ int ret = 0; ++ ++ rk3568_calc_drv_reg_and_bit(bank, pin_num, ®map, ®, &bit); ++ ++ /* enable the write to the equivalent lower bits */ ++ data = ((1 << RK3568_DRV_BITS_PER_PIN) - 1) << (bit + 16); ++ data |= (drv << bit); ++ ++ ret = regmap_write(regmap, reg, data); ++ if (ret) ++ return ret; ++ ++ if (bank->bank_num == 1 && pin_num == 21) ++ reg = 0x0840; ++ else if (bank->bank_num == 2 && pin_num == 2) ++ reg = 0x0844; ++ else if (bank->bank_num == 2 && pin_num == 8) ++ reg = 0x0848; ++ else if (bank->bank_num == 3 && pin_num == 0) ++ reg = 0x084c; ++ else if (bank->bank_num == 3 && pin_num == 6) ++ reg = 0x0850; ++ else if (bank->bank_num == 4 && pin_num == 0) ++ reg = 0x0854; ++ else ++ return 0; ++ ++ data = ((1 << RK3568_DRV_BITS_PER_PIN) - 1) << 16; ++ data |= drv; ++ ++ return regmap_write(regmap, reg, data); ++} ++ ++static int rk3568_set_schmitt(struct rockchip_pin_bank *bank, ++ int pin_num, int enable) ++{ ++ struct regmap *regmap; ++ int reg; ++ u32 data; ++ u8 bit; ++ ++ rk3568_calc_schmitt_reg_and_bit(bank, pin_num, ®map, ®, &bit); ++ ++ /* enable the write to the equivalent lower bits */ ++ data = ((1 << RK3568_SCHMITT_BITS_PER_PIN) - 1) << (bit + 16); ++ data |= (enable << bit); ++ ++ return regmap_write(regmap, reg, data); ++} ++static struct rockchip_pin_bank rk3568_pin_banks[] = { ++ PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT, ++ IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT, ++ IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT, ++ IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT), ++ PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", IOMUX_WIDTH_4BIT, ++ IOMUX_WIDTH_4BIT, ++ IOMUX_WIDTH_4BIT, ++ IOMUX_WIDTH_4BIT), ++ PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", IOMUX_WIDTH_4BIT, ++ IOMUX_WIDTH_4BIT, ++ IOMUX_WIDTH_4BIT, ++ IOMUX_WIDTH_4BIT), ++ PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", IOMUX_WIDTH_4BIT, ++ IOMUX_WIDTH_4BIT, ++ IOMUX_WIDTH_4BIT, ++ IOMUX_WIDTH_4BIT), ++ PIN_BANK_IOMUX_FLAGS(4, 32, "gpio4", IOMUX_WIDTH_4BIT, ++ IOMUX_WIDTH_4BIT, ++ IOMUX_WIDTH_4BIT, ++ IOMUX_WIDTH_4BIT), ++}; ++ ++static const struct rockchip_pin_ctrl rk3568_pin_ctrl = { ++ .pin_banks = rk3568_pin_banks, ++ .nr_banks = ARRAY_SIZE(rk3568_pin_banks), ++ .nr_pins = 160, ++ .grf_mux_offset = 0x0, ++ .pmu_mux_offset = 0x0, ++ .iomux_routes = rk3568_mux_route_data, ++ .niomux_routes = ARRAY_SIZE(rk3568_mux_route_data), ++ .set_mux = rk3568_set_mux, ++ .set_pull = rk3568_set_pull, ++ .set_drive = rk3568_set_drive, ++ .set_schmitt = rk3568_set_schmitt, ++}; ++ ++static const struct udevice_id rk3568_pinctrl_ids[] = { ++ { ++ .compatible = "rockchip,rk3568-pinctrl", ++ .data = (ulong)&rk3568_pin_ctrl ++ }, ++ { } ++}; ++ ++U_BOOT_DRIVER(pinctrl_rk3568) = { ++ .name = "rockchip_rk3568_pinctrl", ++ .id = UCLASS_PINCTRL, ++ .of_match = rk3568_pinctrl_ids, ++ .priv_auto = sizeof(struct rockchip_pinctrl_priv), ++ .ops = &rockchip_pinctrl_ops, ++#if !CONFIG_IS_ENABLED(OF_PLATDATA) ++ .bind = dm_scan_fdt_dev, ++#endif ++ .probe = rockchip_pinctrl_probe, ++}; +--- a/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c ++++ b/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c +@@ -400,7 +400,7 @@ static int rockchip_pinctrl_set_state(st + int prop_len, param; + const u32 *data; + ofnode node; +-#ifdef CONFIG_OF_LIVE ++#if CONFIG_IS_ENABLED(OF_LIVE) + const struct device_node *np; + struct property *pp; + #else +@@ -440,7 +440,7 @@ static int rockchip_pinctrl_set_state(st + node = ofnode_get_by_phandle(conf); + if (!ofnode_valid(node)) + return -ENODEV; +-#ifdef CONFIG_OF_LIVE ++#if CONFIG_IS_ENABLED(OF_LIVE) + np = ofnode_to_np(node); + for (pp = np->properties; pp; pp = pp->next) { + prop_name = pp->name; +@@ -515,13 +515,14 @@ static struct rockchip_pin_ctrl *rockchi + + /* preset iomux offset value, set new start value */ + if (iom->offset >= 0) { +- if (iom->type & IOMUX_SOURCE_PMU) ++ if ((iom->type & IOMUX_SOURCE_PMU) || (iom->type & IOMUX_L_SOURCE_PMU)) + pmu_offs = iom->offset; + else + grf_offs = iom->offset; + } else { /* set current iomux offset */ +- iom->offset = (iom->type & IOMUX_SOURCE_PMU) ? +- pmu_offs : grf_offs; ++ iom->offset = ((iom->type & IOMUX_SOURCE_PMU) || ++ (iom->type & IOMUX_L_SOURCE_PMU)) ? ++ pmu_offs : grf_offs; + } + + /* preset drv offset value, set new start value */ +--- a/drivers/pinctrl/rockchip/pinctrl-rockchip.h ++++ b/drivers/pinctrl/rockchip/pinctrl-rockchip.h +@@ -6,9 +6,13 @@ + #ifndef __DRIVERS_PINCTRL_ROCKCHIP_H + #define __DRIVERS_PINCTRL_ROCKCHIP_H + ++#include + #include + #include + ++#define RK_GENMASK_VAL(h, l, v) \ ++ (GENMASK(((h) + 16), ((l) + 16)) | (((v) << (l)) & GENMASK((h), (l)))) ++ + /** + * Encode variants of iomux registers into a type variable + */ +@@ -18,6 +22,8 @@ + #define IOMUX_UNROUTED BIT(3) + #define IOMUX_WIDTH_3BIT BIT(4) + #define IOMUX_8WIDTH_2BIT BIT(5) ++#define IOMUX_WRITABLE_32BIT BIT(6) ++#define IOMUX_L_SOURCE_PMU BIT(7) + + /** + * Defined some common pins constants +@@ -63,6 +69,21 @@ enum rockchip_pin_pull_type { + }; + + /** ++ * enum mux route register type, should be invalid/default/topgrf/pmugrf. ++ * INVALID: means do not need to set mux route ++ * DEFAULT: means same regmap as pin iomux ++ * TOPGRF: means mux route setting in topgrf ++ * PMUGRF: means mux route setting in pmugrf ++ */ ++enum rockchip_pin_route_type { ++ ROUTE_TYPE_DEFAULT = 0, ++ ROUTE_TYPE_TOPGRF = 1, ++ ROUTE_TYPE_PMUGRF = 2, ++ ++ ROUTE_TYPE_INVALID = -1, ++}; ++ ++/** + * @drv_type: drive strength variant using rockchip_perpin_drv_type + * @offset: if initialized to -1 it will be autocalculated, by specifying + * an initial offset value the relevant source offset can be reset +@@ -220,6 +241,25 @@ struct rockchip_pin_bank { + .pull_type[3] = pull3, \ + } + ++#define PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, FLAG) \ ++ { \ ++ .bank_num = ID, \ ++ .pin = PIN, \ ++ .func = FUNC, \ ++ .route_offset = REG, \ ++ .route_val = VAL, \ ++ .route_type = FLAG, \ ++ } ++ ++#define MR_DEFAULT(ID, PIN, FUNC, REG, VAL) \ ++ PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, ROUTE_TYPE_DEFAULT) ++ ++#define MR_TOPGRF(ID, PIN, FUNC, REG, VAL) \ ++ PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, ROUTE_TYPE_TOPGRF) ++ ++#define MR_PMUGRF(ID, PIN, FUNC, REG, VAL) \ ++ PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, ROUTE_TYPE_PMUGRF) ++ + /** + * struct rockchip_mux_recalced_data: recalculate a pin iomux data. + * @num: bank number. +@@ -241,6 +281,7 @@ struct rockchip_mux_recalced_data { + * @bank_num: bank number. + * @pin: index at register or used to calc index. + * @func: the min pin. ++ * @route_type: the register type. + * @route_offset: the max pin. + * @route_val: the register offset. + */ +@@ -248,6 +289,7 @@ struct rockchip_mux_route_data { + u8 bank_num; + u8 pin; + u8 func; ++ enum rockchip_pin_route_type route_type : 8; + u32 route_offset; + u32 route_val; + }; diff --git a/root/package/boot/uboot-rockchip/patches/008-rockchip-allow-sdmmc-at-full-speed.patch b/root/package/boot/uboot-rockchip/patches/008-rockchip-allow-sdmmc-at-full-speed.patch new file mode 100644 index 00000000..3ad9d5b8 --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/008-rockchip-allow-sdmmc-at-full-speed.patch @@ -0,0 +1,22 @@ +From 16cc17fc2cf2f308f5ac20b829d427114c6e59fa Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Mon, 20 Dec 2021 08:50:48 -0500 +Subject: [PATCH 08/11] rockchip: allow sdmmc at full speed + +Adding pinctrl and gpio support fixed quartz64-a sdmmc. + +Signed-off-by: Peter Geis +--- + arch/arm/dts/rk3566-quartz64-a-u-boot.dtsi | 1 - + 1 file changed, 1 deletion(-) + +--- a/arch/arm/dts/rk3566-quartz64-a-u-boot.dtsi ++++ b/arch/arm/dts/rk3566-quartz64-a-u-boot.dtsi +@@ -13,7 +13,6 @@ + }; + + &sdmmc0 { +- max-frequency = <400000>; + bus-width = <4>; + u-boot,dm-spl; + u-boot,spl-fifo-mode; diff --git a/root/package/boot/uboot-rockchip/patches/009-rockchip-defconfig-add-gpio-v2-to-quartz64.patch b/root/package/boot/uboot-rockchip/patches/009-rockchip-defconfig-add-gpio-v2-to-quartz64.patch new file mode 100644 index 00000000..c0ca879b --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/009-rockchip-defconfig-add-gpio-v2-to-quartz64.patch @@ -0,0 +1,25 @@ +From d3b3e9c1045e9fa0aff987a036b30cf380809e35 Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Mon, 20 Dec 2021 10:11:52 -0500 +Subject: [PATCH 09/11] rockchip: defconfig: add gpio-v2 to quartz64 + +Signed-off-by: Peter Geis +--- + configs/quartz64-a-rk3566_defconfig | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/configs/quartz64-a-rk3566_defconfig ++++ b/configs/quartz64-a-rk3566_defconfig +@@ -42,10 +42,12 @@ CONFIG_CMD_REGULATOR=y + CONFIG_SPL_OF_CONTROL=y + CONFIG_OF_LIVE=y + CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_SPL_DM_WARN=y + CONFIG_SPL_REGMAP=y + CONFIG_SPL_SYSCON=y + CONFIG_SPL_CLK=y + CONFIG_ROCKCHIP_GPIO=y ++CONFIG_ROCKCHIP_GPIO_V2=y + CONFIG_SYS_I2C_ROCKCHIP=y + CONFIG_MISC=y + CONFIG_MMC_HS200_SUPPORT=y diff --git a/root/package/boot/uboot-rockchip/patches/010-rockchip-rk356x-enable-usb2-support-on-quartz64-a.patch b/root/package/boot/uboot-rockchip/patches/010-rockchip-rk356x-enable-usb2-support-on-quartz64-a.patch new file mode 100644 index 00000000..a70c45a8 --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/010-rockchip-rk356x-enable-usb2-support-on-quartz64-a.patch @@ -0,0 +1,97 @@ +From 981df845d960a9078893dad88e1dd82dfcb4a148 Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Wed, 22 Dec 2021 19:40:32 -0500 +Subject: [PATCH 10/11] rockchip: rk356x: enable usb2 support on quartz64-a + +Signed-off-by: Peter Geis +--- + arch/arm/dts/rk3566-quartz64-a-u-boot.dtsi | 22 ++++++++++++++++++++++ + configs/quartz64-a-rk3566_defconfig | 17 +++++++++++++++++ + include/configs/quartz64-a-rk3566.h | 3 +++ + 3 files changed, 42 insertions(+) + +--- a/arch/arm/dts/rk3566-quartz64-a-u-boot.dtsi ++++ b/arch/arm/dts/rk3566-quartz64-a-u-boot.dtsi +@@ -12,12 +12,34 @@ + }; + }; + ++&gmac1 { ++ assigned-clocks = <&cru SCLK_GMAC1_RX_TX>, <&cru SCLK_GMAC1>; ++ assigned-clock-parents = <&cru SCLK_GMAC1_RGMII_SPEED>, <&gmac1_clkin>; ++ status = "disabled"; ++}; ++ + &sdmmc0 { + bus-width = <4>; + u-boot,dm-spl; + u-boot,spl-fifo-mode; + }; + ++&usb_host0_ehci { ++ vbus-supply = <&vcc5v0_usb20_host>; ++}; ++ ++&usb_host0_ohci { ++ vbus-supply = <&vcc5v0_usb20_host>; ++}; ++ ++&usb_host1_ehci { ++ vbus-supply = <&vcc5v0_usb20_host>; ++}; ++ ++&usb_host1_ohci { ++ vbus-supply = <&vcc5v0_usb20_host>; ++}; ++ + &uart2 { + clock-frequency = <24000000>; + u-boot,dm-spl; +--- a/configs/quartz64-a-rk3566_defconfig ++++ b/configs/quartz64-a-rk3566_defconfig +@@ -22,6 +22,7 @@ CONFIG_FIT=y + CONFIG_FIT_VERBOSE=y + CONFIG_SPL_LOAD_FIT=y + CONFIG_DEFAULT_FDT_FILE="rockchip/rk3566-quartz64-a.dtb" ++# CONFIG_SYS_DEVICE_NULLDEV is not set + # CONFIG_DISPLAY_CPUINFO is not set + CONFIG_DISPLAY_BOARDINFO_LATE=y + # CONFIG_SPL_RAW_IMAGE_SUPPORT is not set +@@ -35,6 +36,7 @@ CONFIG_CMD_GPIO=y + CONFIG_CMD_GPT=y + CONFIG_CMD_I2C=y + CONFIG_CMD_MMC=y ++CONFIG_CMD_USB=y + # CONFIG_CMD_SETEXPR is not set + CONFIG_CMD_PMIC=y + CONFIG_CMD_REGULATOR=y +@@ -76,4 +78,19 @@ CONFIG_BAUDRATE=1500000 + CONFIG_DEBUG_UART_SHIFT=2 + CONFIG_SYSRESET=y + CONFIG_SYSRESET_PSCI=y ++CONFIG_USB=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_DWC3=y ++CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_EHCI_GENERIC=y ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_GENERIC=y ++CONFIG_USB_DWC3=y ++CONFIG_USB_DWC3_GENERIC=y ++CONFIG_ROCKCHIP_USB2_PHY=y ++CONFIG_USB_KEYBOARD=y ++CONFIG_USB_HOST_ETHER=y ++CONFIG_USB_ETHER_LAN75XX=y ++CONFIG_USB_ETHER_LAN78XX=y ++CONFIG_USB_ETHER_SMSC95XX=y + CONFIG_ERRNO_STR=y +--- a/include/configs/quartz64-a-rk3566.h ++++ b/include/configs/quartz64-a-rk3566.h +@@ -11,4 +11,7 @@ + "stdout=serial,vidconsole\0" \ + "stderr=serial,vidconsole\0" + ++#define CONFIG_USB_OHCI_NEW ++#define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 2 ++ + #endif diff --git a/root/package/boot/uboot-rockchip/patches/011-rockchip-rk356x-attempt-to-fix-ram-detection.patch b/root/package/boot/uboot-rockchip/patches/011-rockchip-rk356x-attempt-to-fix-ram-detection.patch new file mode 100644 index 00000000..736de6b2 --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/011-rockchip-rk356x-attempt-to-fix-ram-detection.patch @@ -0,0 +1,173 @@ +From ea6da572fe3cee637319f1e7e588c059622c815e Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Wed, 22 Dec 2021 19:52:38 -0500 +Subject: [PATCH 11/11] rockchip: rk356x: attempt to fix ram detection + +Signed-off-by: Peter Geis +--- + arch/arm/mach-rockchip/rk3568/rk3568.c | 29 ++++++++++++++++++++++++ + arch/arm/mach-rockchip/sdram.c | 31 ++++++++++++++------------ + common/board_f.c | 7 ++++++ + configs/quartz64-a-rk3566_defconfig | 1 + + include/configs/rk3568_common.h | 5 +++++ + 5 files changed, 59 insertions(+), 14 deletions(-) + +--- a/arch/arm/mach-rockchip/rk3568/rk3568.c ++++ b/arch/arm/mach-rockchip/rk3568/rk3568.c +@@ -5,6 +5,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -135,3 +136,31 @@ int arch_cpu_init(void) + #endif + return 0; + } ++ ++#ifdef CONFIG_OF_SYSTEM_SETUP ++int ft_system_setup(void *blob, struct bd_info *bd) ++{ ++ int ret; ++ int areas = 1; ++ u64 start[2], size[2]; ++ ++ /* Reserve the io address space. */ ++ if (gd->ram_top > SDRAM_UPPER_ADDR_MIN) { ++ start[0] = gd->bd->bi_dram[0].start; ++ size[0] = SDRAM_LOWER_ADDR_MAX - gd->bd->bi_dram[0].start; ++ ++ /* Add the upper 4GB address space */ ++ start[1] = SDRAM_UPPER_ADDR_MIN; ++ size[1] = gd->ram_top - SDRAM_UPPER_ADDR_MIN; ++ areas = 2; ++ ++ ret = fdt_set_usable_memory(blob, start, size, areas); ++ if (ret) { ++ printf("Cannot set usable memory\n"); ++ return ret; ++ } ++ } ++ ++ return 0; ++}; ++#endif +--- a/arch/arm/mach-rockchip/sdram.c ++++ b/arch/arm/mach-rockchip/sdram.c +@@ -3,6 +3,8 @@ + * Copyright (C) 2017 Rockchip Electronics Co., Ltd. + */ + ++#define DEBUG ++ + #include + #include + #include +@@ -98,8 +100,7 @@ size_t rockchip_sdram_size(phys_addr_t r + SYS_REG_COL_MASK); + cs1_col = cs0_col; + bk = 3 - ((sys_reg2 >> SYS_REG_BK_SHIFT(ch)) & SYS_REG_BK_MASK); +- if ((sys_reg3 >> SYS_REG_VERSION_SHIFT & +- SYS_REG_VERSION_MASK) == 0x2) { ++ if ((sys_reg3 >> SYS_REG_VERSION_SHIFT & SYS_REG_VERSION_MASK) >= 0x2) { + cs1_col = 9 + (sys_reg3 >> SYS_REG_CS1_COL_SHIFT(ch) & + SYS_REG_CS1_COL_MASK); + if (((sys_reg3 >> SYS_REG_EXTEND_CS0_ROW_SHIFT(ch) & +@@ -136,7 +137,7 @@ size_t rockchip_sdram_size(phys_addr_t r + SYS_REG_BW_MASK)); + row_3_4 = sys_reg2 >> SYS_REG_ROW_3_4_SHIFT(ch) & + SYS_REG_ROW_3_4_MASK; +- if (dram_type == DDR4) { ++ if ((dram_type == DDR4) && (sys_reg3 >> SYS_REG_VERSION_SHIFT & SYS_REG_VERSION_MASK) != 0x3){ + dbw = (sys_reg2 >> SYS_REG_DBW_SHIFT(ch)) & + SYS_REG_DBW_MASK; + bg = (dbw == 2) ? 2 : 1; +@@ -150,15 +151,11 @@ size_t rockchip_sdram_size(phys_addr_t r + chipsize_mb = chipsize_mb * 3 / 4; + size_mb += chipsize_mb; + if (rank > 1) +- debug("rank %d cs0_col %d cs1_col %d bk %d cs0_row %d\ +- cs1_row %d bw %d row_3_4 %d\n", +- rank, cs0_col, cs1_col, bk, cs0_row, +- cs1_row, bw, row_3_4); ++ debug("rank=%d cs0_col=%d cs1_col=%d bk=%d cs0_row=%d cs1_row=%d bg=%d bw=%d row_3_4=%d\n", ++ rank, cs0_col, cs1_col, bk, cs0_row, cs1_row, bg, bw, row_3_4); + else +- debug("rank %d cs0_col %d bk %d cs0_row %d\ +- bw %d row_3_4 %d\n", +- rank, cs0_col, bk, cs0_row, +- bw, row_3_4); ++ debug("rank %d cs0_col %d bk %d cs0_row %d bw %d row_3_4 %d\n", ++ rank, cs0_col, bk, cs0_row, bw, row_3_4); + } + + /* +@@ -176,9 +173,11 @@ size_t rockchip_sdram_size(phys_addr_t r + * 2. update board_get_usable_ram_top() and dram_init_banksize() + * to reserve memory for peripheral space after previous update. + */ ++ ++#ifndef __aarch64__ + if (size_mb > (SDRAM_MAX_SIZE >> 20)) + size_mb = (SDRAM_MAX_SIZE >> 20); +- ++#endif + return (size_t)size_mb << 20; + } + +@@ -208,6 +207,10 @@ int dram_init(void) + ulong board_get_usable_ram_top(ulong total_size) + { + unsigned long top = CONFIG_SYS_SDRAM_BASE + SDRAM_MAX_SIZE; +- +- return (gd->ram_top > top) ? top : gd->ram_top; ++#ifdef SDRAM_UPPER_ADDR_MIN ++ if (gd->ram_top > SDRAM_UPPER_ADDR_MIN) ++ return gd->ram_top; ++ else ++#endif ++ return (gd->ram_top > top) ? top : gd->ram_top; + } +--- a/common/board_f.c ++++ b/common/board_f.c +@@ -345,7 +345,14 @@ static int setup_dest_addr(void) + #endif + gd->ram_top = gd->ram_base + get_effective_memsize(); + gd->ram_top = board_get_usable_ram_top(gd->mon_len); ++#ifdef SDRAM_LOWER_ADDR_MAX ++ if (gd->ram_top > SDRAM_LOWER_ADDR_MAX) ++ gd->relocaddr = SDRAM_LOWER_ADDR_MAX; ++ else ++ gd->relocaddr = gd->ram_top; ++#else + gd->relocaddr = gd->ram_top; ++#endif + debug("Ram top: %08lX\n", (ulong)gd->ram_top); + #if defined(CONFIG_MP) && (defined(CONFIG_MPC86xx) || defined(CONFIG_E500)) + /* +--- a/configs/quartz64-a-rk3566_defconfig ++++ b/configs/quartz64-a-rk3566_defconfig +@@ -21,6 +21,7 @@ CONFIG_API=y + CONFIG_FIT=y + CONFIG_FIT_VERBOSE=y + CONFIG_SPL_LOAD_FIT=y ++CONFIG_OF_SYSTEM_SETUP=y + CONFIG_DEFAULT_FDT_FILE="rockchip/rk3566-quartz64-a.dtb" + # CONFIG_SYS_DEVICE_NULLDEV is not set + # CONFIG_DISPLAY_CPUINFO is not set +--- a/include/configs/rk3568_common.h ++++ b/include/configs/rk3568_common.h +@@ -24,6 +24,11 @@ + #define CONFIG_SYS_SDRAM_BASE 0 + #define SDRAM_MAX_SIZE 0xf0000000 + ++#ifdef CONFIG_OF_SYSTEM_SETUP ++#define SDRAM_LOWER_ADDR_MAX 0xf0000000 ++#define SDRAM_UPPER_ADDR_MIN 0x100000000 ++#endif ++ + #ifndef CONFIG_SPL_BUILD + #define ENV_MEM_LAYOUT_SETTINGS \ + "scriptaddr=0x00c00000\0" \ diff --git a/root/package/boot/uboot-rockchip/patches/012-resync-rk3566-device-tree-with-mainline.patch b/root/package/boot/uboot-rockchip/patches/012-resync-rk3566-device-tree-with-mainline.patch new file mode 100644 index 00000000..11c79135 --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/012-resync-rk3566-device-tree-with-mainline.patch @@ -0,0 +1,1060 @@ +From 07cb5e592c2fe682d7f176282a16f389c94f46c8 Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Tue, 18 Jan 2022 19:20:40 -0500 +Subject: [PATCH 12/13] resync rk3566 device tree with mainline + +Signed-off-by: Peter Geis +--- + arch/arm/dts/rk3566-quartz64-a.dts | 285 ++++++++++++++++++++--- + arch/arm/dts/rk3566.dtsi | 8 +- + arch/arm/dts/rk3568.dtsi | 29 ++- + arch/arm/dts/rk356x.dtsi | 297 ++++++++++++------------ + include/dt-bindings/soc/rockchip,vop2.h | 14 ++ + 5 files changed, 442 insertions(+), 191 deletions(-) + create mode 100644 include/dt-bindings/soc/rockchip,vop2.h + +--- a/arch/arm/dts/rk3566-quartz64-a.dts ++++ b/arch/arm/dts/rk3566-quartz64-a.dts +@@ -4,6 +4,7 @@ + + #include + #include ++#include + #include "rk3566.dtsi" + + / { +@@ -55,6 +56,17 @@ + #cooling-cells = <2>; + }; + ++ hdmi-con { ++ compatible = "hdmi-connector"; ++ type = "c"; ++ ++ port { ++ hdmi_con_in: endpoint { ++ remote-endpoint = <&hdmi_out_con>; ++ }; ++ }; ++ }; ++ + leds { + compatible = "gpio-leds"; + +@@ -196,7 +208,7 @@ + enable-active-high; + gpio = <&gpio4 RK_PB5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; +- pinctrl-0 = <&vcc5v0_usb20_host_en_h>; ++ pinctrl-0 = <&vcc5v0_usb20_host_en>; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_usb>; +@@ -248,6 +260,29 @@ + vin-supply = <&vbus>; + }; + ++ vcc_sys_ebc: vcc_sys_ebc { ++ compatible = "regulator-fixed"; ++ gpio = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&vcc_sys_ebc_h>; ++ regulator-boot-on; ++ regulator-name = "vcc_sys_ebc"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ vcc_lcd_en: vcc_lcd_en { ++ compatible = "regulator-fixed"; ++// gpio = <&gpio2 RK_PC4 GPIO_ACTIVE_HIGH>; ++ regulator-always-on; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&vcc_lcd_en_h>; ++ regulator-name = "vcc_lcd_en"; ++ vin-supply = <&vcc_sys>; ++ }; ++ + /* sourced from vcc_sys, sdio module operates internally at 3.3v */ + vcc_wl: vcc_wl { + compatible = "regulator-fixed"; +@@ -258,14 +293,21 @@ + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_sys>; + }; ++ ++ backlight: backlight { ++ compatible = "pwm-backlight"; ++ pwms = <&pwm14 0 1000000 0>; ++ brightness-levels = <0 4 8 16 32 64 128 255>; ++ default-brightness-level = <6>; ++ }; + }; + +-&combphy1_usq { ++&combphy1 { + status = "okay"; + rockchip,enable-ssc; + }; + +-&combphy2_psq { ++&combphy2 { + status = "okay"; + }; + +@@ -302,6 +344,39 @@ + }; + }; + ++&ebc { ++ panel,width = <1872>; ++ panel,height = <1404>; ++ panel,vir_width = <1872>; ++ panel,vir_height = <1404>; ++ panel,sdck = <33300000>; ++ panel,lsl = <11>; ++ panel,lbl = <8>; ++ panel,ldl = <234>; ++ panel,lel = <23>; ++ panel,gdck-sta = <10>; ++ panel,lgonl = <215>; ++ panel,fsl = <1>; ++ panel,fbl = <4>; ++ panel,fdl = <1404>; ++ panel,fel = <12>; ++ panel,mirror = <1>; ++ panel,panel_16bit = <1>; ++ panel,panel_color = <0>; ++ panel,width-mm = <157>; ++ panel,height-mm = <210>; ++ ++ io-channels = <&ebc_pmic 0>; ++ panel-supply = <&v3p3>; ++ vcom-supply = <&vcom>; ++ vdrive-supply = <&vdrive>; ++ status = "okay"; ++}; ++ ++&eink { ++ status = "okay"; ++}; ++ + &gmac1 { + assigned-clocks = <&cru SCLK_GMAC1_RX_TX>, <&cru SCLK_GMAC1_RGMII_SPEED>, <&cru SCLK_GMAC1>; + assigned-clock-parents = <&cru SCLK_GMAC1_RGMII_SPEED>, <&cru SCLK_GMAC1>, <&gmac1_clkin>; +@@ -325,19 +400,28 @@ + status = "okay"; + }; + +-&hdmi { ++&gpu { ++ mali-supply = <&vdd_gpu>; + status = "okay"; ++}; ++ ++&hdmi { + avdd-0v9-supply = <&vdda_0v9>; + avdd-1v8-supply = <&vcc_1v8>; ++ status = "okay"; + }; + +-&hdmi_in_vp0 { +- status = "okay"; ++&hdmi_in { ++ hdmi_in_vp0: endpoint@0 { ++ reg = <0>; ++ remote-endpoint = <&vp0_out_hdmi>; ++ }; + }; + +-&gpu { +- mali-supply = <&vdd_gpu>; +- status = "okay"; ++&hdmi_out { ++ hdmi_out_con: endpoint { ++ remote-endpoint = <&hdmi_con_in>; ++ }; + }; + + &i2c0 { +@@ -357,6 +441,7 @@ + + regulator-state-mem { + regulator-off-in-suspend; ++ regulator-suspend-microvolt = <900000>; + }; + }; + +@@ -420,8 +505,6 @@ + vcc_ddr: DCDC_REG3 { + regulator-always-on; + regulator-boot-on; +- regulator-min-microvolt = <1100000>; +- regulator-max-microvolt = <1100000>; + regulator-initial-mode = <0x2>; + regulator-name = "vcc_ddr"; + regulator-state-mem { +@@ -571,6 +654,55 @@ + }; + }; + ++&i2c1 { ++ status = "okay"; ++ ++ ebc_pmic: pmic@68 { ++ compatible = "ti,tps65185"; ++ reg = <0x68>; ++ interrupt-parent = <&gpio4>; ++ interrupts = ; ++ #io-channel-cells = <1>; ++ pinctrl-0 = <&ebc_pmic_pins>; ++ pinctrl-names = "default"; ++ powerup-gpios = <&gpio4 RK_PC4 GPIO_ACTIVE_HIGH>; ++ pwr_good-gpios = <&gpio4 RK_PB1 GPIO_ACTIVE_HIGH>; ++ vcom_ctrl-gpios = <&gpio4 RK_PB2 GPIO_ACTIVE_HIGH>; ++ vin-supply = <&vcc_sys_ebc>; ++ vin3p3-supply = <&vcc_sys_ebc>; ++ wakeup-gpios = <&gpio4 RK_PC3 GPIO_ACTIVE_HIGH>; ++ ti,up-sequence = <1>, <0>, <2>, <3>; ++ ti,up-delay-ms = <3>, <3>, <3>, <3>; ++ ti,down-sequence = <2>, <3>, <1>, <0>; ++ ti,down-delay-ms = <3>, <6>, <6>, <6>; ++ ++ regulators { ++ v3p3: v3p3 { ++ regulator-name = "v3p3"; ++ regulator-always-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ++ vcom: vcom { ++ regulator-name = "vcom"; ++ regulator-min-microvolt = <1450000>; ++ regulator-max-microvolt = <1450000>; ++ }; ++ ++ vdrive: vdrive { ++ regulator-name = "vdrive"; ++ regulator-min-microvolt = <15000000>; ++ regulator-max-microvolt = <15000000>; ++ }; ++ }; ++ }; ++}; ++ ++&i2c3 { ++ status = "okay"; ++}; ++ + &i2s1_8ch { + pinctrl-names = "default"; + pinctrl-0 = <&i2s1m0_sclktx +@@ -611,6 +743,21 @@ + }; + }; + ++ ebc_pmic { ++ ebc_pmic_pins: ebc-pmic-pins { ++ rockchip,pins = /* wakeup */ ++ <4 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none>, ++ /* int */ ++ <4 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>, ++ /* pwr_good */ ++ <4 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>, ++ /* pwrup */ ++ <4 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>, ++ /* vcom_ctrl */ ++ <4 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ + fan { + fan_en_h: fan-en-h { + rockchip,pins = <0 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>; +@@ -654,7 +801,7 @@ + }; + + usb2 { +- vcc5v0_usb20_host_en_h: vcc5v0-usb20-host-en_h { ++ vcc5v0_usb20_host_en: vcc5v0-usb20-host-en { + rockchip,pins = <4 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +@@ -664,6 +811,18 @@ + rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; ++ ++ vcc_sys_ebc { ++ vcc_sys_ebc_h: vcc-sys-ebc-h { ++ rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ vcc_lcd_en { ++ vcc_lcd_en_h: vcc-lcd-en-h { ++ rockchip,pins = <2 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; + }; + + &pmu_io_domains { +@@ -681,12 +840,15 @@ + + /* sata1 is muxed with the usb3 port */ + &sata1 { +- status = "okay"; ++ status = "disabled"; ++// status = "okay"; + }; + + /* sata2 is muxed with the pcie2 slot*/ + &sata2 { ++ target-supply = <&vcc3v3_pcie_p>; + status = "disabled"; ++// status = "okay"; + }; + + &sdhci { +@@ -783,6 +945,10 @@ + status = "okay"; + }; + ++&u2phy0 { ++ status = "okay"; ++}; ++ + &u2phy0_host { + phy-supply = <&vcc5v0_usb20_host>; + status = "okay"; +@@ -793,25 +959,17 @@ + status = "okay"; + }; + +-&u2phy1_host { +- phy-supply = <&vcc5v0_usb20_host>; ++&u2phy1 { + status = "okay"; + }; + +-&u2phy1_otg { ++&u2phy1_host { + phy-supply = <&vcc5v0_usb20_host>; + status = "okay"; + }; + +-&usb2phy0 { +- status = "okay"; +-}; +- +-&usb2phy1 { +- status = "okay"; +-}; +- +-&usbdrd_dwc3 { ++&u2phy1_otg { ++ phy-supply = <&vcc5v0_usb20_host>; + status = "okay"; + }; + +@@ -820,13 +978,9 @@ + }; + + /* usb3 controller is muxed with sata1 */ +-&usbhost_dwc3 { +- status = "disabled"; +-}; +- +-/* usb3 controller is muxed with sata1 */ + &usbhost30 { +- status = "disabled"; ++// status = "disabled"; ++ status = "okay"; + }; + + &usb_host0_ehci { +@@ -846,15 +1000,80 @@ + }; + + &vop { +- status = "okay"; + assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>; + assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>; ++ status = "okay"; + }; + + &vop_mmu { + status = "okay"; + }; + +-&vp0_out_hdmi { ++&vp0 { ++ vp0_out_hdmi: endpoint@RK3568_VOP2_EP_HDMI { ++ reg = ; ++ remote-endpoint = <&hdmi_in_vp0>; ++ }; ++}; ++/* ++&video_phy0 { ++ status = "okay"; ++}; ++ ++&dsi0 { ++ status = "okay"; ++ clock-master; ++ ++ mipi_panel: panel@0 { ++ compatible = "feiyang,fy07024di26a30d"; ++ reg = <0>; ++ backlight = <&backlight>; ++ reset-gpios = <&gpio2 RK_PC4 GPIO_ACTIVE_HIGH>; ++ width-mm = <154>; ++ height-mm = <86>; ++ rotation = <0>; ++// avdd-supply = <&avdd>; ++// dvdd-supply = <&vcc3v3_s0>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ ++ mipi_in_panel: endpoint { ++ remote-endpoint = <&mipi_out_panel>; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&dsi0_in { ++ dsi0_in_vp1: endpoint@1 { ++ reg = <1>; ++ remote-endpoint = <&vp1_out_dsi0>; ++ }; ++}; ++ ++&dsi0_out { ++ mipi_out_panel: endpoint { ++ remote-endpoint = <&mipi_in_panel>; ++ }; ++ ++}; ++ ++&vp1 { ++ vp1_out_dsi0: endpoint@RK3568_VOP2_EP_MIPI0 { ++ reg = ; ++ remote-endpoint = <&dsi0_in_vp1>; ++ }; ++}; ++ ++&pwm14 { + status = "okay"; ++ pinctrl-0 = <&pwm14m1_pins>; ++ pinctrl-names = "default"; + }; ++*/ +--- a/arch/arm/dts/rk3566.dtsi ++++ b/arch/arm/dts/rk3566.dtsi +@@ -23,10 +23,14 @@ + }; + }; + +-&usbdrd_dwc3 { ++&usbdrd30 { + phys = <&u2phy0_otg>; + phy-names = "usb2-phy"; +- extcon = <&usb2phy0>; ++ extcon = <&u2phy0>; + maximum-speed = "high-speed"; + snps,dis_u2_susphy_quirk; + }; ++ ++&vop { ++ compatible = "rockchip,rk3566-vop"; ++}; +--- a/arch/arm/dts/rk3568.dtsi ++++ b/arch/arm/dts/rk3568.dtsi +@@ -16,13 +16,18 @@ + clock-names = "sata", "pmalive", "rxoob"; + interrupts = ; + interrupt-names = "hostc"; +- phys = <&combphy0_us PHY_TYPE_SATA>; ++ phys = <&combphy0 PHY_TYPE_SATA>; + phy-names = "sata-phy"; + ports-implemented = <0x1>; + power-domains = <&power RK3568_PD_PIPE>; + status = "disabled"; + }; + ++ pipe_phy_grf0: syscon@fdc70000 { ++ compatible = "rockchip,rk3568-pipe-phy-grf", "syscon"; ++ reg = <0x0 0xfdc70000 0x0 0x1000>; ++ }; ++ + qos_pcie3x1: qos@fe190080 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe190080 0x0 0x20>; +@@ -87,19 +92,19 @@ + }; + }; + +- combphy0_us: phy@fe820000 { ++ combphy0: phy@fe820000 { + compatible = "rockchip,rk3568-naneng-combphy"; + reg = <0x0 0xfe820000 0x0 0x100>; +- #phy-cells = <1>; +- assigned-clocks = <&pmucru CLK_PCIEPHY0_REF>; +- assigned-clock-rates = <100000000>; +- clocks = <&pmucru CLK_PCIEPHY0_REF>, <&cru PCLK_PIPEPHY0>, ++ clocks = <&pmucru CLK_PCIEPHY0_REF>, ++ <&cru PCLK_PIPEPHY0>, + <&cru PCLK_PIPE>; + clock-names = "ref", "apb", "pipe"; +- resets = <&cru SRST_P_PIPEPHY0>, <&cru SRST_PIPEPHY0>; +- reset-names = "combphy-apb", "combphy"; ++ assigned-clocks = <&pmucru CLK_PCIEPHY0_REF>; ++ assigned-clock-rates = <100000000>; ++ resets = <&cru SRST_PIPEPHY0>; + rockchip,pipe-grf = <&pipegrf>; + rockchip,pipe-phy-grf = <&pipe_phy_grf0>; ++ #phy-cells = <1>; + status = "disabled"; + }; + }; +@@ -131,7 +136,11 @@ + }; + }; + +-&usbdrd_dwc3 { +- phys = <&u2phy0_otg>, <&combphy0_us PHY_TYPE_USB3>; ++&usbdrd30 { ++ phys = <&u2phy0_otg>, <&combphy0 PHY_TYPE_USB3>; + phy-names = "usb2-phy", "usb3-phy"; + }; ++ ++&vop { ++ compatible = "rockchip,rk3568-vop"; ++}; +--- a/arch/arm/dts/rk356x.dtsi ++++ b/arch/arm/dts/rk356x.dtsi +@@ -159,6 +159,11 @@ + }; + }; + ++ display_subsystem: display-subsystem { ++ compatible = "rockchip,display-subsystem"; ++ ports = <&vop_out>; ++ }; ++ + firmware { + scmi: scmi { + compatible = "arm,scmi-smc"; +@@ -234,7 +239,7 @@ + clock-names = "sata", "pmalive", "rxoob"; + interrupts = ; + interrupt-names = "hostc"; +- phys = <&combphy1_usq PHY_TYPE_SATA>; ++ phys = <&combphy1 PHY_TYPE_SATA>; + phy-names = "sata-phy"; + ports-implemented = <0x1>; + power-domains = <&power RK3568_PD_PIPE>; +@@ -249,7 +254,7 @@ + clock-names = "sata", "pmalive", "rxoob"; + interrupts = ; + interrupt-names = "hostc"; +- phys = <&combphy2_psq PHY_TYPE_SATA>; ++ phys = <&combphy2 PHY_TYPE_SATA>; + phy-names = "sata-phy"; + ports-implemented = <0x1>; + power-domains = <&power RK3568_PD_PIPE>; +@@ -258,66 +263,46 @@ + + usbdrd30: usbdrd { + compatible = "rockchip,rk3399-dwc3", "snps,dwc3"; ++ reg = <0x0 0xfcc00000 0x0 0x400000>; ++ interrupts = ; + clocks = <&cru CLK_USB3OTG0_REF>, <&cru CLK_USB3OTG0_SUSPEND>, + <&cru ACLK_USB3OTG0>, <&cru PCLK_PIPE>; + clock-names = "ref_clk", "suspend_clk", + "bus_clk", "pipe_clk"; +- #address-cells = <2>; +- #size-cells = <2>; +- ranges; ++ dr_mode = "host"; ++ phy_type = "utmi_wide"; ++ power-domains = <&power RK3568_PD_PIPE>; ++ resets = <&cru SRST_USB3OTG0>; ++ reset-names = "usb3-otg"; ++ snps,dis_enblslpm_quirk; ++ snps,dis-u2-freeclk-exists-quirk; ++ snps,dis-del-phy-power-chg-quirk; ++ snps,dis-tx-ipgap-linecheck-quirk; ++ snps,xhci-trb-ent-quirk; + status = "disabled"; +- +- usbdrd_dwc3: dwc3@fcc00000 { +- compatible = "snps,dwc3"; +- reg = <0x0 0xfcc00000 0x0 0x400000>; +- interrupts = ; +- dr_mode = "host"; +- phys = <&u2phy0_otg>, <&combphy0_us PHY_TYPE_USB3>; +- phy-names = "usb2-phy", "usb3-phy"; +- phy_type = "utmi_wide"; +- power-domains = <&power RK3568_PD_PIPE>; +- resets = <&cru SRST_USB3OTG0>; +- reset-names = "usb3-otg"; +- snps,dis_enblslpm_quirk; +- snps,dis-u2-freeclk-exists-quirk; +- snps,dis-del-phy-power-chg-quirk; +- snps,dis-tx-ipgap-linecheck-quirk; +- snps,xhci-trb-ent-quirk; +- status = "disabled"; +- }; + }; + + usbhost30: usbhost { + compatible = "rockchip,rk3399-dwc3", "snps,dwc3"; ++ reg = <0x0 0xfd000000 0x0 0x400000>; ++ interrupts = ; + clocks = <&cru CLK_USB3OTG1_REF>, <&cru CLK_USB3OTG1_SUSPEND>, + <&cru ACLK_USB3OTG1>, <&cru PCLK_PIPE>; + clock-names = "ref_clk", "suspend_clk", + "bus_clk", "pipe_clk"; +- #address-cells = <2>; +- #size-cells = <2>; +- assigned-clocks = <&cru CLK_PCIEPHY1_REF>; +- assigned-clock-rates = <25000000>; +- ranges; +- status = "disabled"; +- +- usbhost_dwc3: dwc3@fd000000 { +- compatible = "snps,dwc3"; +- reg = <0x0 0xfd000000 0x0 0x400000>; +- interrupts = ; +- dr_mode = "host"; +- phys = <&u2phy0_host>, <&combphy1_usq PHY_TYPE_USB3>; +- phy-names = "usb2-phy", "usb3-phy"; +- phy_type = "utmi_wide"; +- power-domains = <&power RK3568_PD_PIPE>; +- resets = <&cru SRST_USB3OTG1>; +- reset-names = "usb3-host"; +- snps,dis_enblslpm_quirk; +- snps,dis-u2-freeclk-exists-quirk; +- snps,dis_u2_susphy_quirk; +- snps,dis-del-phy-power-chg-quirk; +- snps,dis-tx-ipgap-linecheck-quirk; +- status = "disabled"; +- }; ++ dr_mode = "host"; ++ phys = <&u2phy0_host>, <&combphy1 PHY_TYPE_USB3>; ++ phy-names = "usb2-phy", "usb3-phy"; ++ phy_type = "utmi_wide"; ++ power-domains = <&power RK3568_PD_PIPE>; ++ resets = <&cru SRST_USB3OTG1>; ++ reset-names = "usb3-host"; ++ snps,dis_enblslpm_quirk; ++ snps,dis-u2-freeclk-exists-quirk; ++ snps,dis_u2_susphy_quirk; ++ snps,dis-del-phy-power-chg-quirk; ++ snps,dis-tx-ipgap-linecheck-quirk; ++ status = "disabled"; + }; + + gic: interrupt-controller@fd400000 { +@@ -339,7 +324,7 @@ + clocks = <&cru HCLK_USB2HOST0>, <&cru HCLK_USB2HOST0_ARB>, + <&cru PCLK_USB>; + phys = <&u2phy1_otg>; +- phy-names = "usb2-phy"; ++ phy-names = "usb"; + status = "disabled"; + }; + +@@ -350,7 +335,7 @@ + clocks = <&cru HCLK_USB2HOST0>, <&cru HCLK_USB2HOST0_ARB>, + <&cru PCLK_USB>; + phys = <&u2phy1_otg>; +- phy-names = "usb2-phy"; ++ phy-names = "usb"; + status = "disabled"; + }; + +@@ -361,7 +346,7 @@ + clocks = <&cru HCLK_USB2HOST1>, <&cru HCLK_USB2HOST1_ARB>, + <&cru PCLK_USB>; + phys = <&u2phy1_host>; +- phy-names = "usb2-phy"; ++ phy-names = "usb"; + status = "disabled"; + }; + +@@ -372,7 +357,7 @@ + clocks = <&cru HCLK_USB2HOST1>, <&cru HCLK_USB2HOST1_ARB>, + <&cru PCLK_USB>; + phys = <&u2phy1_host>; +- phy-names = "usb2-phy"; ++ phy-names = "usb"; + status = "disabled"; + }; + +@@ -395,21 +380,17 @@ + reg = <0x0 0xfdc60000 0x0 0x10000>; + }; + +- pipe_phy_grf0: syscon@fdc70000 { +- compatible = "rockchip,pipe-phy-grf", "syscon"; +- reg = <0x0 0xfdc70000 0x0 0x1000>; +- }; +- + pipe_phy_grf1: syscon@fdc80000 { +- compatible = "rockchip,pipe-phy-grf", "syscon"; ++ compatible = "rockchip,rk3568-pipe-phy-grf", "syscon"; + reg = <0x0 0xfdc80000 0x0 0x1000>; + }; + + pipe_phy_grf2: syscon@fdc90000 { +- compatible = "rockchip,pipe-phy-grf", "syscon"; ++ compatible = "rockchip,rk3568-pipe-phy-grf", "syscon"; + reg = <0x0 0xfdc90000 0x0 0x1000>; + }; + ++ + usb2phy0_grf: syscon@fdca0000 { + compatible = "rockchip,rk3568-usb2phy-grf", "syscon"; + reg = <0x0 0xfdca0000 0x0 0x8000>; +@@ -604,6 +585,28 @@ + status = "disabled"; + }; + ++ ebc: ebc@fdec0000 { ++ compatible = "rockchip,rk3568-ebc-tcon"; ++ reg = <0x0 0xfdec0000 0x0 0x5000>; ++ interrupts = ; ++ clocks = <&cru HCLK_EBC>, <&cru DCLK_EBC>; ++ clock-names = "hclk", "dclk"; ++ pinctrl-0 = <&ebc_pins>; ++ pinctrl-names = "default"; ++ power-domains = <&power RK3568_PD_RGA>; ++ rockchip,grf = <&grf>; ++ status = "disabled"; ++ }; ++ ++ eink: eink@fdf00000 { ++ compatible = "rockchip,rk3568-eink-tcon"; ++ reg = <0x0 0xfdf00000 0x0 0x74>; ++ clocks = <&cru PCLK_EINK>, <&cru HCLK_EINK>; ++ clock-names = "pclk", "hclk"; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ + sdmmc2: mmc@fe000000 { + compatible = "rockchip,rk3568-dw-mshc", "rockchip,rk3288-dw-mshc"; + reg = <0x0 0xfe000000 0x0 0x4000>; +@@ -665,21 +668,15 @@ + }; + }; + +- display_subsystem: display-subsystem { +- compatible = "rockchip,display-subsystem"; +- ports = <&vop_out>; +- }; +- + vop: vop@fe040000 { +- compatible = "rockchip,rk3568-vop"; + reg = <0x0 0xfe040000 0x0 0x3000>, <0x0 0xfe044000 0x0 0x1000>; + reg-names = "regs", "gamma_lut"; +- rockchip,grf = <&grf>; + interrupts = ; + clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>, <&cru DCLK_VOP0>, <&cru DCLK_VOP1>, <&cru DCLK_VOP2>; + clock-names = "aclk_vop", "hclk_vop", "dclk_vp0", "dclk_vp1", "dclk_vp2"; + iommus = <&vop_mmu>; + power-domains = <&power RK3568_PD_VO>; ++ rockchip,grf = <&grf>; + status = "disabled"; + + vop_out: ports { +@@ -687,39 +684,21 @@ + #size-cells = <0>; + + vp0: port@0 { ++ reg = <0>; + #address-cells = <1>; + #size-cells = <0>; +- reg = <0>; +- +- vp0_out_hdmi: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&hdmi_in_vp0>; +- status = "disabled"; +- }; + }; + + vp1: port@1 { ++ reg = <1>; + #address-cells = <1>; + #size-cells = <0>; +- reg = <1>; +- +- vp1_out_hdmi: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&hdmi_in_vp1>; +- status = "disabled"; +- }; + }; + + vp2: port@2 { ++ reg = <2>; + #address-cells = <1>; + #size-cells = <0>; +- reg = <2>; +- +- vp2_out_hdmi: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&hdmi_in_vp2>; +- status = "disabled"; +- }; + }; + }; + }; +@@ -728,7 +707,6 @@ + compatible = "rockchip,rk3568-iommu"; + reg = <0x0 0xfe043e00 0x0 0x100>, <0x0 0xfe043f00 0x0 0x100>; + interrupts = ; +- interrupt-names = "vop_mmu"; + clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>; + clock-names = "aclk", "iface"; + #iommu-cells = <0>; +@@ -742,14 +720,15 @@ + clocks = <&cru PCLK_HDMI_HOST>, + <&cru CLK_HDMI_SFR>, + <&cru CLK_HDMI_CEC>, ++ <&pmucru CLK_HDMI_REF>, + <&cru HCLK_VOP>; +- clock-names = "iahb", "isfr", "cec", "hclk"; ++ clock-names = "iahb", "isfr", "cec", "ref", "hclk"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&hdmitx_scl &hdmitx_sda &hdmitxm0_cec>; + power-domains = <&power RK3568_PD_VO>; + reg-io-width = <4>; + rockchip,grf = <&grf>; + #sound-dai-cells = <0>; +- pinctrl-names = "default"; +- pinctrl-0 = <&hdmitx_scl &hdmitx_sda &hdmitxm0_cec>; + status = "disabled"; + + ports { +@@ -760,24 +739,12 @@ + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; ++ }; + +- hdmi_in_vp0: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&vp0_out_hdmi>; +- status = "disabled"; +- }; +- +- hdmi_in_vp1: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&vp1_out_hdmi>; +- status = "disabled"; +- }; +- +- hdmi_in_vp2: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&vp2_out_hdmi>; +- status = "disabled"; +- }; ++ hdmi_out: port@1 { ++ reg = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; + }; + }; + }; +@@ -934,7 +901,7 @@ + max-link-speed = <2>; + msi-map = <0x0 &gic 0x0 0x1000>; + num-lanes = <1>; +- phys = <&combphy2_psq PHY_TYPE_PCIE>; ++ phys = <&combphy2 PHY_TYPE_PCIE>; + phy-names = "pcie-phy"; + power-domains = <&power RK3568_PD_PIPE>; + reg = <0x3 0xc0000000 0x0 0x400000>, +@@ -1048,6 +1015,43 @@ + status = "disabled"; + }; + ++ i2s2_2ch: i2s@fe420000 { ++ compatible = "rockchip,rk3568-i2s-tdm"; ++ reg = <0x0 0xfe420000 0x0 0x1000>; ++ interrupts = ; ++ clocks = <&cru MCLK_I2S2_2CH>, <&cru MCLK_I2S2_2CH>, <&cru HCLK_I2S2_2CH>; ++ clock-names = "mclk_tx", "mclk_rx", "hclk"; ++ dmas = <&dmac1 4>, <&dmac1 5>; ++ dma-names = "tx", "rx"; ++ rockchip,cru = <&cru>; ++ rockchip,grf = <&grf>; ++ pinctrl-0 = <&i2s2m0_sclktx ++ &i2s2m0_lrcktx ++ &i2s2m0_sdi ++ &i2s2m0_sdo>; ++ pinctrl-names = "default"; ++ #sound-dai-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ pdm: pdm@fe440000 { ++ compatible = "rockchip,rk3568-pdm", "rockchip,pdm"; ++ reg = <0x0 0xfe440000 0x0 0x1000>; ++ clocks = <&cru MCLK_PDM>, <&cru HCLK_PDM>; ++ clock-names = "pdm_clk", "pdm_hclk"; ++ dmas = <&dmac1 9>; ++ dma-names = "rx"; ++ pinctrl-0 = <&pdmm0_clk ++ &pdmm0_clk1 ++ &pdmm0_sdi0 ++ &pdmm0_sdi1 ++ &pdmm0_sdi2 ++ &pdmm0_sdi3>; ++ pinctrl-names = "default"; ++ #sound-dai-cells = <0>; ++ status = "disabled"; ++ }; ++ + dmac0: dmac@fe530000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0x0 0xfe530000 0x0 0x4000>; +@@ -1487,47 +1491,15 @@ + status = "disabled"; + }; + +- combphy1_usq: phy@fe830000 { +- compatible = "rockchip,rk3568-naneng-combphy"; +- reg = <0x0 0xfe830000 0x0 0x100>; +- #phy-cells = <1>; +- assigned-clocks = <&pmucru CLK_PCIEPHY1_REF>; +- assigned-clock-rates = <100000000>; +- clocks = <&pmucru CLK_PCIEPHY1_REF>, <&cru PCLK_PIPEPHY1>, +- <&cru PCLK_PIPE>; +- clock-names = "ref", "apb", "pipe"; +- resets = <&cru SRST_P_PIPEPHY1>, <&cru SRST_PIPEPHY1>; +- reset-names = "combphy-apb", "combphy"; +- rockchip,pipe-grf = <&pipegrf>; +- rockchip,pipe-phy-grf = <&pipe_phy_grf1>; +- status = "disabled"; +- }; +- +- combphy2_psq: phy@fe840000 { +- compatible = "rockchip,rk3568-naneng-combphy"; +- reg = <0x0 0xfe840000 0x0 0x100>; +- #phy-cells = <1>; +- assigned-clocks = <&pmucru CLK_PCIEPHY2_REF>; +- assigned-clock-rates = <100000000>; +- clocks = <&pmucru CLK_PCIEPHY2_REF>, <&cru PCLK_PIPEPHY2>, +- <&cru PCLK_PIPE>; +- clock-names = "ref", "apb", "pipe"; +- resets = <&cru SRST_P_PIPEPHY2>, <&cru SRST_PIPEPHY2>; +- reset-names = "combphy-apb", "combphy"; +- rockchip,pipe-grf = <&pipegrf>; +- rockchip,pipe-phy-grf = <&pipe_phy_grf2>; +- status = "disabled"; +- }; +- +- usb2phy0: usb2-phy@fe8a0000 { ++ u2phy0: usb2phy@fe8a0000 { + compatible = "rockchip,rk3568-usb2phy"; + reg = <0x0 0xfe8a0000 0x0 0x10000>; + clocks = <&pmucru CLK_USBPHY0_REF>; + clock-names = "phyclk"; +- #clock-cells = <0>; +- clock-output-names = "usb480m_phy"; ++ clock-output-names = "clk_usbphy0_480m"; + interrupts = ; + rockchip,usbgrf = <&usb2phy0_grf>; ++ #clock-cells = <0>; + status = "disabled"; + + u2phy0_host: host-port { +@@ -1541,14 +1513,15 @@ + }; + }; + +- usb2phy1: usb2-phy@fe8b0000 { ++ u2phy1: usb2phy@fe8b0000 { + compatible = "rockchip,rk3568-usb2phy"; + reg = <0x0 0xfe8b0000 0x0 0x10000>; + clocks = <&pmucru CLK_USBPHY1_REF>; + clock-names = "phyclk"; +- #clock-cells = <0>; ++ clock-output-names = "clk_usbphy1_480m"; + interrupts = ; + rockchip,usbgrf = <&usb2phy1_grf>; ++ #clock-cells = <0>; + status = "disabled"; + + u2phy1_host: host-port { +@@ -1562,6 +1535,38 @@ + }; + }; + ++ combphy1: phy@fe830000 { ++ compatible = "rockchip,rk3568-naneng-combphy"; ++ reg = <0x0 0xfe830000 0x0 0x100>; ++ clocks = <&pmucru CLK_PCIEPHY1_REF>, ++ <&cru PCLK_PIPEPHY1>, ++ <&cru PCLK_PIPE>; ++ clock-names = "ref", "apb", "pipe"; ++ assigned-clocks = <&pmucru CLK_PCIEPHY1_REF>; ++ assigned-clock-rates = <100000000>; ++ resets = <&cru SRST_PIPEPHY1>; ++ rockchip,pipe-grf = <&pipegrf>; ++ rockchip,pipe-phy-grf = <&pipe_phy_grf1>; ++ #phy-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ combphy2: phy@fe840000 { ++ compatible = "rockchip,rk3568-naneng-combphy"; ++ reg = <0x0 0xfe840000 0x0 0x100>; ++ clocks = <&pmucru CLK_PCIEPHY2_REF>, ++ <&cru PCLK_PIPEPHY2>, ++ <&cru PCLK_PIPE>; ++ clock-names = "ref", "apb", "pipe"; ++ assigned-clocks = <&pmucru CLK_PCIEPHY2_REF>; ++ assigned-clock-rates = <100000000>; ++ resets = <&cru SRST_PIPEPHY2>; ++ rockchip,pipe-grf = <&pipegrf>; ++ rockchip,pipe-phy-grf = <&pipe_phy_grf2>; ++ #phy-cells = <1>; ++ status = "disabled"; ++ }; ++ + pinctrl: pinctrl { + compatible = "rockchip,rk3568-pinctrl"; + rockchip,grf = <&grf>; +--- /dev/null ++++ b/include/dt-bindings/soc/rockchip,vop2.h +@@ -0,0 +1,14 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ ++ ++#ifndef __DT_BINDINGS_ROCKCHIP_VOP2_H ++#define __DT_BINDINGS_ROCKCHIP_VOP2_H ++ ++#define RK3568_VOP2_EP_RGB 0 ++#define RK3568_VOP2_EP_HDMI 1 ++#define RK3568_VOP2_EP_EDP 2 ++#define RK3568_VOP2_EP_MIPI0 3 ++#define RK3568_VOP2_EP_LVDS0 4 ++#define RK3568_VOP2_EP_MIPI1 5 ++#define RK3568_VOP2_EP_LVDS1 6 ++ ++#endif /* __DT_BINDINGS_ROCKCHIP_VOP2_H */ diff --git a/root/package/boot/uboot-rockchip/patches/013-rockchip-rk356x-add-bpi-r2-pro-board.patch b/root/package/boot/uboot-rockchip/patches/013-rockchip-rk356x-add-bpi-r2-pro-board.patch new file mode 100644 index 00000000..0728caea --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/013-rockchip-rk356x-add-bpi-r2-pro-board.patch @@ -0,0 +1,795 @@ +From 89d609d74e4ef84e0e3d399d8763b268b60302fc Mon Sep 17 00:00:00 2001 +From: Marty Jones +Date: Sat, 28 May 2022 20:19:38 -0400 +Subject: [PATCH] rockchip: rk356x: add bpi r2 pro board + +Signed-off-by: Marty Jones +--- + arch/arm/dts/Makefile | 1 + + arch/arm/dts/rk3568-bpi-r2-pro-u-boot.dtsi | 47 ++ + arch/arm/dts/rk3568-bpi-r2-pro.dts | 532 ++++++++++++++++++ + arch/arm/mach-rockchip/rk3568/Kconfig | 6 + + board/rockchip/bpi-r2-pro-rk3568/Kconfig | 15 + + board/rockchip/bpi-r2-pro-rk3568/Makefile | 7 + + .../bpi-r2-pro-rk3568/bpi-r2-pro-rk3568.c | 4 + + configs/bpi-r2-pro-rk3568_defconfig | 97 ++++ + include/configs/bpi-r2-pro-rk3568.h | 15 + + 9 files changed, 724 insertions(+) + create mode 100644 arch/arm/dts/rk3568-bpi-r2-pro-u-boot.dtsi + create mode 100644 arch/arm/dts/rk3568-bpi-r2-pro.dts + create mode 100644 board/rockchip/bpi-r2-pro-rk3568/Kconfig + create mode 100644 board/rockchip/bpi-r2-pro-rk3568/Makefile + create mode 100644 board/rockchip/bpi-r2-pro-rk3568/bpi-r2-pro-rk3568.c + create mode 100644 configs/bpi-r2-pro-rk3568_defconfig + create mode 100644 include/configs/bpi-r2-pro-rk3568.h + +--- a/arch/arm/dts/Makefile ++++ b/arch/arm/dts/Makefile +@@ -164,6 +164,7 @@ dtb-$(CONFIG_ROCKCHIP_RK3399) += \ + rk3399pro-rock-pi-n10.dtb + + dtb-$(CONFIG_ROCKCHIP_RK3568) += \ ++ rk3568-bpi-r2-pro.dtb \ + rk3568-evb.dtb \ + rk3566-quartz64-a.dtb + +--- /dev/null ++++ b/arch/arm/dts/rk3568-bpi-r2-pro-u-boot.dtsi +@@ -0,0 +1,47 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * (C) Copyright 2021 Rockchip Electronics Co., Ltd ++ */ ++ ++#include "rk3568-u-boot.dtsi" ++ ++/ { ++ chosen { ++ stdout-path = &uart2; ++ u-boot,spl-boot-order = "same-as-spl", &sdmmc0, &sdhci; ++ }; ++}; ++ ++&gmac1 { ++ assigned-clocks = <&cru SCLK_GMAC1_RX_TX>, <&cru SCLK_GMAC1>; ++ assigned-clock-parents = <&cru SCLK_GMAC1_RGMII_SPEED>, <&cru CLK_MAC1_2TOP>; ++ status = "disabled"; ++}; ++ ++&sdmmc0 { ++ bus-width = <4>; ++ u-boot,dm-spl; ++ u-boot,spl-fifo-mode; ++}; ++ ++&usb_host0_ehci { ++ vbus-supply = <&vcc5v0_usb_host>; ++}; ++ ++&usb_host0_ohci { ++ vbus-supply = <&vcc5v0_usb_host>; ++}; ++ ++&usb_host1_ehci { ++ vbus-supply = <&vcc5v0_usb_host>; ++}; ++ ++&usb_host1_ohci { ++ vbus-supply = <&vcc5v0_usb_host>; ++}; ++ ++&uart2 { ++ clock-frequency = <24000000>; ++ u-boot,dm-spl; ++ status = "okay"; ++}; +--- /dev/null ++++ b/arch/arm/dts/rk3568-bpi-r2-pro.dts +@@ -0,0 +1,532 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Author: Frank Wunderlich ++ * ++ */ ++ ++/dts-v1/; ++#include ++#include ++#include ++#include "rk3568.dtsi" ++ ++/ { ++ model = "Bananapi-R2 Pro (RK3568) DDR4 Board"; ++ compatible = "rockchip,rk3568-bpi-r2pro", "rockchip,rk3568"; ++ ++ aliases { ++ ethernet0 = &gmac0; ++ ethernet1 = &gmac1; ++ mmc0 = &sdmmc0; ++ mmc1 = &sdhci; ++ }; ++ ++ chosen: chosen { ++ stdout-path = "serial2:1500000n8"; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&blue_led_pin &green_led_pin>; ++ ++ blue_led: led-0 { ++ color = ; ++ default-state = "off"; ++ function = LED_FUNCTION_STATUS; ++ gpios = <&gpio0 RK_PD6 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ green_led: led-1 { ++ color = ; ++ default-state = "on"; ++ function = LED_FUNCTION_POWER; ++ gpios = <&gpio0 RK_PD5 GPIO_ACTIVE_HIGH>; ++ }; ++ }; ++ ++ dc_12v: dc-12v { ++ compatible = "regulator-fixed"; ++ regulator-name = "dc_12v"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <12000000>; ++ regulator-max-microvolt = <12000000>; ++ }; ++ ++ vcc3v3_sys: vcc3v3-sys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc3v3_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&dc_12v>; ++ }; ++ ++ vcc5v0_sys: vcc5v0-sys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&dc_12v>; ++ }; ++ ++ vcc5v0_usb: vcc5v0_usb { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_usb"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&dc_12v>; ++ }; ++ ++ vcc5v0_usb_host: vcc5v0-usb-host { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&vcc5v0_usb_host_en>; ++ regulator-name = "vcc5v0_usb_host"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc5v0_usb>; ++ }; ++ ++ vcc5v0_usb_otg: vcc5v0-usb-otg { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&vcc5v0_usb_otg_en>; ++ regulator-name = "vcc5v0_usb_otg"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc5v0_usb>; ++ }; ++}; ++ ++&combphy0 { ++ /* used for USB3 */ ++ status = "okay"; ++}; ++ ++&combphy1 { ++ /* used for USB3 */ ++ status = "okay"; ++}; ++ ++&combphy2 { ++ /* used for SATA */ ++ status = "okay"; ++}; ++ ++&gmac0 { ++ assigned-clocks = <&cru SCLK_GMAC0_RX_TX>, <&cru SCLK_GMAC0>; ++ assigned-clock-parents = <&cru SCLK_GMAC0_RGMII_SPEED>, <&cru CLK_MAC0_2TOP>; ++ clock_in_out = "input"; ++ phy-mode = "rgmii"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&gmac0_miim ++ &gmac0_tx_bus2 ++ &gmac0_rx_bus2 ++ &gmac0_rgmii_clk ++ &gmac0_rgmii_bus>; ++ snps,reset-gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; ++ snps,reset-active-low; ++ /* Reset time is 20ms, 100ms for rtl8211f */ ++ snps,reset-delays-us = <0 20000 100000>; ++ tx_delay = <0x4f>; ++ rx_delay = <0x0f>; ++ status = "okay"; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ pause; ++ }; ++}; ++ ++&gmac1 { ++ assigned-clocks = <&cru SCLK_GMAC1_RX_TX>, <&cru SCLK_GMAC1>; ++ assigned-clock-parents = <&cru SCLK_GMAC1_RGMII_SPEED>, <&cru CLK_MAC1_2TOP>; ++ clock_in_out = "output"; ++ phy-handle = <&rgmii_phy1>; ++ phy-mode = "rgmii"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&gmac1m1_miim ++ &gmac1m1_tx_bus2 ++ &gmac1m1_rx_bus2 ++ &gmac1m1_rgmii_clk ++ &gmac1m1_rgmii_bus>; ++ ++ snps,reset-gpio = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>; ++ snps,reset-active-low; ++ /* Reset time is 20ms, 100ms for rtl8211f */ ++ snps,reset-delays-us = <0 20000 100000>; ++ ++ tx_delay = <0x3c>; ++ rx_delay = <0x2f>; ++ ++ status = "okay"; ++}; ++ ++&i2c0 { ++ status = "okay"; ++ ++ rk809: pmic@20 { ++ compatible = "rockchip,rk809"; ++ reg = <0x20>; ++ interrupt-parent = <&gpio0>; ++ interrupts = ; ++ #clock-cells = <1>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_int>; ++ rockchip,system-power-controller; ++ vcc1-supply = <&vcc3v3_sys>; ++ vcc2-supply = <&vcc3v3_sys>; ++ vcc3-supply = <&vcc3v3_sys>; ++ vcc4-supply = <&vcc3v3_sys>; ++ vcc5-supply = <&vcc3v3_sys>; ++ vcc6-supply = <&vcc3v3_sys>; ++ vcc7-supply = <&vcc3v3_sys>; ++ vcc8-supply = <&vcc3v3_sys>; ++ vcc9-supply = <&vcc3v3_sys>; ++ wakeup-source; ++ ++ regulators { ++ vdd_logic: DCDC_REG1 { ++ regulator-name = "vdd_logic"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-init-microvolt = <900000>; ++ regulator-initial-mode = <0x2>; ++ regulator-min-microvolt = <500000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-ramp-delay = <6001>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_gpu: DCDC_REG2 { ++ regulator-name = "vdd_gpu"; ++ regulator-init-microvolt = <900000>; ++ regulator-initial-mode = <0x2>; ++ regulator-min-microvolt = <500000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-ramp-delay = <6001>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_ddr: DCDC_REG3 { ++ regulator-name = "vcc_ddr"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-initial-mode = <0x2>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vdd_npu: DCDC_REG4 { ++ regulator-name = "vdd_npu"; ++ regulator-init-microvolt = <900000>; ++ regulator-initial-mode = <0x2>; ++ regulator-min-microvolt = <500000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-ramp-delay = <6001>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_1v8: DCDC_REG5 { ++ regulator-name = "vcc_1v8"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdda0v9_image: LDO_REG1 { ++ regulator-name = "vdda0v9_image"; ++ regulator-min-microvolt = <900000>; ++ regulator-max-microvolt = <900000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdda_0v9: LDO_REG2 { ++ regulator-name = "vdda_0v9"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <900000>; ++ regulator-max-microvolt = <900000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdda0v9_pmu: LDO_REG3 { ++ regulator-name = "vdda0v9_pmu"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <900000>; ++ regulator-max-microvolt = <900000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <900000>; ++ }; ++ }; ++ ++ vccio_acodec: LDO_REG4 { ++ regulator-name = "vccio_acodec"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vccio_sd: LDO_REG5 { ++ regulator-name = "vccio_sd"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc3v3_pmu: LDO_REG6 { ++ regulator-name = "vcc3v3_pmu"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vcca_1v8: LDO_REG7 { ++ regulator-name = "vcca_1v8"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcca1v8_pmu: LDO_REG8 { ++ regulator-name = "vcca1v8_pmu"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcca1v8_image: LDO_REG9 { ++ regulator-name = "vcca1v8_image"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_3v3: SWITCH_REG1 { ++ regulator-name = "vcc_3v3"; ++ regulator-always-on; ++ regulator-boot-on; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc3v3_sd: SWITCH_REG2 { ++ regulator-name = "vcc3v3_sd"; ++ regulator-always-on; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&i2c5 { ++ /* pin 3 (SDA) + 4 (SCL) of header con2 */ ++ status = "disabled"; ++}; ++ ++&mdio1 { ++ rgmii_phy1: ethernet-phy@0 { ++ compatible = "ethernet-phy-ieee802.3-c22"; ++ reg = <0x0>; ++ }; ++}; ++ ++&pinctrl { ++ leds { ++ blue_led_pin: blue-led-pin { ++ rockchip,pins = <0 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ green_led_pin: green-led-pin { ++ rockchip,pins = <0 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ pmic { ++ pmic_int: pmic_int { ++ rockchip,pins = ++ <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ usb { ++ vcc5v0_usb_host_en: vcc5v0_usb_host_en { ++ rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ ++ vcc5v0_usb_otg_en: vcc5v0_usb_otg_en { ++ rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++}; ++ ++&pmu_io_domains { ++ pmuio1-supply = <&vcc3v3_pmu>; ++ pmuio2-supply = <&vcc3v3_pmu>; ++ vccio1-supply = <&vccio_acodec>; ++ vccio3-supply = <&vccio_sd>; ++ vccio4-supply = <&vcc_3v3>; ++ vccio5-supply = <&vcc_3v3>; ++ vccio6-supply = <&vcc_1v8>; ++ vccio7-supply = <&vcc_3v3>; ++ status = "okay"; ++}; ++ ++&pwm8 { ++ /* fan 5v - gnd - pwm */ ++ status = "okay"; ++}; ++ ++&pwm10 { ++ /* pin 7 of header con2 */ ++ status = "disabled"; ++}; ++ ++&pwm11 { ++ /* pin 15 of header con2 */ ++ status = "disabled"; ++}; ++ ++ ++&pwm13 { ++ /* pin 24 of header con2 */ ++ /* shared with uart9 */ ++ pinctrl-0 = <&pwm13m1_pins>; ++ status = "disabled"; ++}; ++ ++&saradc { ++ vref-supply = <&vcca_1v8>; ++ status = "okay"; ++}; ++ ++&sata2 { ++ status = "okay"; ++}; ++ ++&sdhci { ++ bus-width = <8>; ++ max-frequency = <200000000>; ++ non-removable; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_datastrobe>; ++ status = "okay"; ++}; ++ ++&sdmmc0 { ++ bus-width = <4>; ++ cap-sd-highspeed; ++ cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>; ++ disable-wp; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc0_bus4 &sdmmc0_clk &sdmmc0_cmd &sdmmc0_det>; ++ sd-uhs-sdr104; ++ vmmc-supply = <&vcc3v3_sd>; ++ vqmmc-supply = <&vccio_sd>; ++ status = "okay"; ++}; ++ ++&tsadc { ++ status = "okay"; ++}; ++ ++&uart0 { ++ /* pin 8 (TX) + 10 (RX) (RTS:16, CTS:18) of header con2 */ ++ status = "disabled"; ++}; ++ ++&uart2 { ++ /* debug-uart */ ++ status = "okay"; ++}; ++ ++&uart7 { ++ /* pin 11 (TX) + 13 (RX) of header con2 */ ++ pinctrl-0 = <&uart7m1_xfer>; ++ status = "disabled"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usb_host1_ehci { ++ status = "okay"; ++}; ++ ++&usb_host1_ohci { ++ status = "okay"; ++}; +--- a/arch/arm/mach-rockchip/rk3568/Kconfig ++++ b/arch/arm/mach-rockchip/rk3568/Kconfig +@@ -3,6 +3,11 @@ if ROCKCHIP_RK3568 + choice + prompt "RK3568/RK3566 board select" + ++config TARGET_BPI_R2_PRO_RK3568 ++ bool "Banana Pi R2 Pro RK3566 development board" ++ help ++ Banana Pi R2 Pro is a development board Rockchp RK3568. ++ + config TARGET_EVB_RK3568 + bool "RK3568 evaluation board" + help +@@ -27,6 +32,7 @@ config SYS_SOC + config SYS_MALLOC_F_LEN + default 0x2000 + ++source "board/rockchip/bpi-r2-pro-rk3568/Kconfig" + source "board/rockchip/evb_rk3568/Kconfig" + source "board/pine64/quartz64-a-rk3566/Kconfig" + +--- /dev/null ++++ b/board/rockchip/bpi-r2-pro-rk3568/Kconfig +@@ -0,0 +1,15 @@ ++if TARGET_BPI_R2_PRO_RK3568 ++ ++config SYS_BOARD ++ default "bpi-r2-pro-rk3568" ++ ++config SYS_VENDOR ++ default "rockchip" ++ ++config SYS_CONFIG_NAME ++ default "bpi-r2-pro-rk3568" ++ ++config BOARD_SPECIFIC_OPTIONS # dummy ++ def_bool y ++ ++endif +--- /dev/null ++++ b/board/rockchip/bpi-r2-pro-rk3568/Makefile +@@ -0,0 +1,7 @@ ++# ++# (C) Copyright 2021 Rockchip Electronics Co., Ltd ++# ++# SPDX-License-Identifier: GPL-2.0+ ++# ++ ++obj-y += bpi-r2-pro-rk3568.o +--- /dev/null ++++ b/board/rockchip/bpi-r2-pro-rk3568/bpi-r2-pro-rk3568.c +@@ -0,0 +1,4 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * (C) Copyright 2021 Rockchip Electronics Co., Ltd ++ */ +--- /dev/null ++++ b/configs/bpi-r2-pro-rk3568_defconfig +@@ -0,0 +1,97 @@ ++CONFIG_ARM=y ++CONFIG_SKIP_LOWLEVEL_INIT=y ++CONFIG_ARCH_ROCKCHIP=y ++CONFIG_SYS_TEXT_BASE=0x00a00000 ++CONFIG_SPL_LIBCOMMON_SUPPORT=y ++CONFIG_SPL_LIBGENERIC_SUPPORT=y ++CONFIG_NR_DRAM_BANKS=2 ++CONFIG_DEFAULT_DEVICE_TREE="rk3568-bpi-r2-pro" ++CONFIG_ROCKCHIP_RK3568=y ++CONFIG_SPL_ROCKCHIP_BACK_TO_BROM=y ++CONFIG_SPL_ROCKCHIP_COMMON_BOARD=y ++CONFIG_SPL_MMC=y ++CONFIG_SPL_SERIAL=y ++CONFIG_SPL_STACK_R_ADDR=0x600000 ++CONFIG_TARGET_BPI_R2_PRO_RK3568=y ++CONFIG_DEBUG_UART_BASE=0xFE660000 ++CONFIG_DEBUG_UART_CLOCK=24000000 ++CONFIG_DEBUG_UART=y ++CONFIG_SYS_LOAD_ADDR=0xc00800 ++CONFIG_API=y ++CONFIG_FIT=y ++CONFIG_FIT_VERBOSE=y ++CONFIG_SPL_LOAD_FIT=y ++CONFIG_OF_SYSTEM_SETUP=y ++CONFIG_DEFAULT_FDT_FILE="rockchip/rk3568-bpi-r2-pro.dtb" ++# CONFIG_SYS_DEVICE_NULLDEV is not set ++# CONFIG_DISPLAY_CPUINFO is not set ++CONFIG_DISPLAY_BOARDINFO_LATE=y ++# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set ++CONFIG_SPL_STACK_R=y ++CONFIG_SPL_SEPARATE_BSS=y ++CONFIG_SPL_ATF=y ++CONFIG_SPL_ATF_LOAD_IMAGE_V2=y ++CONFIG_CMD_BIND=y ++CONFIG_CMD_CLK=y ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_I2C=y ++CONFIG_CMD_MMC=y ++CONFIG_CMD_USB=y ++# CONFIG_CMD_SETEXPR is not set ++CONFIG_CMD_PMIC=y ++CONFIG_CMD_REGULATOR=y ++# CONFIG_SPL_DOS_PARTITION is not set ++CONFIG_SPL_OF_CONTROL=y ++CONFIG_OF_LIVE=y ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_SPL_DM_WARN=y ++CONFIG_SPL_REGMAP=y ++CONFIG_SPL_SYSCON=y ++CONFIG_SPL_CLK=y ++CONFIG_ROCKCHIP_GPIO=y ++CONFIG_ROCKCHIP_GPIO_V2=y ++CONFIG_SYS_I2C_ROCKCHIP=y ++CONFIG_MISC=y ++CONFIG_MMC_HS200_SUPPORT=y ++CONFIG_SPL_MMC_HS200_SUPPORT=y ++CONFIG_MMC_DW=y ++CONFIG_MMC_DW_ROCKCHIP=y ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_SDMA=y ++CONFIG_MMC_SDHCI_ROCKCHIP=y ++CONFIG_DM_ETH=y ++CONFIG_ETH_DESIGNWARE=y ++CONFIG_GMAC_ROCKCHIP=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_DM_PMIC=y ++CONFIG_PMIC_RK8XX=y ++CONFIG_SPL_PMIC_RK8XX=y ++CONFIG_REGULATOR_PWM=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_SPL_DM_REGULATOR_FIXED=y ++CONFIG_DM_REGULATOR_GPIO=y ++CONFIG_REGULATOR_RK8XX=y ++CONFIG_PWM_ROCKCHIP=y ++CONFIG_SPL_RAM=y ++CONFIG_DM_RESET=y ++CONFIG_BAUDRATE=1500000 ++CONFIG_DEBUG_UART_SHIFT=2 ++CONFIG_SYSRESET=y ++CONFIG_SYSRESET_PSCI=y ++CONFIG_USB=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_DWC3=y ++CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_EHCI_GENERIC=y ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_GENERIC=y ++CONFIG_USB_DWC3=y ++CONFIG_USB_DWC3_GENERIC=y ++CONFIG_ROCKCHIP_USB2_PHY=y ++CONFIG_USB_KEYBOARD=y ++CONFIG_USB_HOST_ETHER=y ++CONFIG_USB_ETHER_LAN75XX=y ++CONFIG_USB_ETHER_LAN78XX=y ++CONFIG_USB_ETHER_SMSC95XX=y ++CONFIG_ERRNO_STR=y +--- /dev/null ++++ b/include/configs/bpi-r2-pro-rk3568.h +@@ -0,0 +1,15 @@ ++#ifndef __BPI_R2_PRO_RK3568_H ++#define __BPI_R2_PRO_RK3568_H ++ ++#include ++ ++#define CONFIG_SUPPORT_EMMC_RPMB ++ ++#define ROCKCHIP_DEVICE_SETTINGS \ ++ "stdout=serial,vidconsole\0" \ ++ "stderr=serial,vidconsole\0" ++ ++#define CONFIG_USB_OHCI_NEW ++#define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 2 ++ ++#endif diff --git a/root/package/boot/uboot-rockchip/patches/014-uboot-add-Radxa-ROCK-3A-board.patch b/root/package/boot/uboot-rockchip/patches/014-uboot-add-Radxa-ROCK-3A-board.patch new file mode 100644 index 00000000..4f38e695 --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/014-uboot-add-Radxa-ROCK-3A-board.patch @@ -0,0 +1,690 @@ +From 443eb96a82563a3b38a3c9548853a5a266dfd072 Mon Sep 17 00:00:00 2001 +From: Marty Jones +Date: Sun, 29 May 2022 06:09:59 -0400 +Subject: [PATCH] uboot: add Radxa ROCK 3A board + +Signed-off-by: Marty Jones +--- + arch/arm/dts/Makefile | 3 +- + arch/arm/dts/rk3568-rock-3a-u-boot.dtsi | 25 + + arch/arm/dts/rk3568-rock-3a.dts | 525 ++++++++++++++++++++ + arch/arm/mach-rockchip/rk3568/Kconfig | 6 + + board/radxa/rock-3a-rk3568/Kconfig | 15 + + board/radxa/rock-3a-rk3568/Makefile | 4 + + board/radxa/rock-3a-rk3568/rock-3a-rk3568.c | 1 + + configs/rock-3a-rk3568_defconfig | 97 ++++ + include/configs/rock-3a-rk3568.h | 17 + + 9 files changed, 692 insertions(+), 1 deletion(-) + create mode 100644 arch/arm/dts/rk3568-rock-3a-u-boot.dtsi + create mode 100644 arch/arm/dts/rk3568-rock-3a.dts + create mode 100644 configs/rock-3a-rk3568_defconfig + create mode 100644 include/configs/rock-3a-rk3568.h + +--- a/arch/arm/dts/Makefile ++++ b/arch/arm/dts/Makefile +@@ -166,7 +166,8 @@ dtb-$(CONFIG_ROCKCHIP_RK3399) += \ + dtb-$(CONFIG_ROCKCHIP_RK3568) += \ + rk3568-bpi-r2-pro.dtb \ + rk3568-evb.dtb \ +- rk3566-quartz64-a.dtb ++ rk3566-quartz64-a.dtb \ ++ rk3568-rock-3a.dtb + + dtb-$(CONFIG_ROCKCHIP_RV1108) += \ + rv1108-elgin-r1.dtb \ +--- /dev/null ++++ b/arch/arm/dts/rk3568-rock-3a-u-boot.dtsi +@@ -0,0 +1,24 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * (C) Copyright 2021 Rockchip Electronics Co., Ltd ++ */ ++ ++#include "rk3568-u-boot.dtsi" ++ ++/ { ++ chosen { ++ stdout-path = &uart2; ++ u-boot,spl-boot-order = "same-as-spl", &sdmmc0, &sdhci; ++ }; ++}; ++ ++&sdmmc0 { ++ bus-width = <4>; ++ u-boot,spl-fifo-mode; ++}; ++ ++&uart2 { ++ u-boot,dm-spl; ++ clock-frequency = <24000000>; ++ status = "okay"; ++}; +--- /dev/null ++++ b/arch/arm/dts/rk3568-rock-3a.dts +@@ -0,0 +1,525 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++/dts-v1/; ++#include ++#include ++#include ++#include "rk3568.dtsi" ++ ++/ { ++ model = "Radxa ROCK3 Model A"; ++ compatible = "radxa,rock3a", "rockchip,rk3568"; ++ ++ aliases { ++ ethernet0 = &gmac1; ++ mmc0 = &sdmmc0; ++ mmc1 = &sdhci; ++ }; ++ ++ chosen: chosen { ++ stdout-path = "serial2:1500000n8"; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led_user: led-0 { ++ gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>; ++ function = LED_FUNCTION_HEARTBEAT; ++ color = ; ++ linux,default-trigger = "heartbeat"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&led_user_en>; ++ }; ++ }; ++ ++ rk809-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,name = "Analog RK809"; ++ simple-audio-card,mclk-fs = <256>; ++ ++ simple-audio-card,cpu { ++ sound-dai = <&i2s1_8ch>; ++ }; ++ ++ simple-audio-card,codec { ++ sound-dai = <&rk809>; ++ }; ++ }; ++ ++ vcc12v_dcin: vcc12v-dcin { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc12v_dcin"; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ vcc3v3_sys: vcc3v3-sys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc3v3_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc12v_dcin>; ++ }; ++ ++ vcc5v0_sys: vcc5v0-sys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc12v_dcin>; ++ }; ++ ++ vcc5v0_usb: vcc5v0-usb { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_usb"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc12v_dcin>; ++ }; ++ ++ vcc5v0_usb_host: vcc5v0-usb-host { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&vcc5v0_usb_host_en>; ++ regulator-name = "vcc5v0_usb_host"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc5v0_usb>; ++ }; ++ ++ vcc5v0_usb_hub: vcc5v0-usb-hub-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio0 RK_PD5 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&vcc5v0_usb_hub_en>; ++ regulator-name = "vcc5v0_usb_hub"; ++ regulator-always-on; ++ vin-supply = <&vcc5v0_usb>; ++ }; ++ ++ vcc5v0_usb_otg: vcc5v0-usb-otg-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&vcc5v0_usb_otg_en>; ++ regulator-name = "vcc5v0_usb_otg"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc5v0_usb>; ++ }; ++}; ++ ++&combphy0 { ++ status = "okay"; ++}; ++ ++&combphy1 { ++ status = "okay"; ++}; ++ ++&cpu0 { ++ cpu-supply = <&vdd_cpu>; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vdd_cpu>; ++}; ++ ++&cpu2 { ++ cpu-supply = <&vdd_cpu>; ++}; ++ ++&cpu3 { ++ cpu-supply = <&vdd_cpu>; ++}; ++ ++&gmac1 { ++ assigned-clocks = <&cru SCLK_GMAC1_RX_TX>, <&cru SCLK_GMAC1>; ++ assigned-clock-parents = <&cru SCLK_GMAC1_RGMII_SPEED>; ++ assigned-clock-rates = <0>, <125000000>; ++ clock_in_out = "output"; ++ phy-handle = <&rgmii_phy1>; ++ phy-mode = "rgmii-id"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&gmac1m1_miim ++ &gmac1m1_tx_bus2 ++ &gmac1m1_rx_bus2 ++ &gmac1m1_rgmii_clk ++ &gmac1m1_rgmii_bus>; ++ status = "okay"; ++}; ++ ++&gpu { ++ mali-supply = <&vdd_gpu>; ++ status = "okay"; ++}; ++ ++&i2c0 { ++ status = "okay"; ++ ++ vdd_cpu: regulator@1c { ++ compatible = "tcs,tcs4525"; ++ reg = <0x1c>; ++ fcs,suspend-voltage-selector = <1>; ++ regulator-name = "vdd_cpu"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <1150000>; ++ regulator-ramp-delay = <2300>; ++ vin-supply = <&vcc5v0_sys>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ rk809: pmic@20 { ++ compatible = "rockchip,rk809"; ++ reg = <0x20>; ++ interrupt-parent = <&gpio0>; ++ interrupts = ; ++ assigned-clocks = <&cru I2S1_MCLKOUT_TX>; ++ assigned-clock-parents = <&cru CLK_I2S1_8CH_TX>; ++ #clock-cells = <1>; ++ clock-names = "mclk"; ++ clocks = <&cru I2S1_MCLKOUT_TX>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_int>, <&i2s1m0_mclk>; ++ rockchip,system-power-controller; ++ #sound-dai-cells = <0>; ++ vcc1-supply = <&vcc3v3_sys>; ++ vcc2-supply = <&vcc3v3_sys>; ++ vcc3-supply = <&vcc3v3_sys>; ++ vcc4-supply = <&vcc3v3_sys>; ++ vcc5-supply = <&vcc3v3_sys>; ++ vcc6-supply = <&vcc3v3_sys>; ++ vcc7-supply = <&vcc3v3_sys>; ++ vcc8-supply = <&vcc3v3_sys>; ++ vcc9-supply = <&vcc3v3_sys>; ++ wakeup-source; ++ ++ regulators { ++ vdd_logic: DCDC_REG1 { ++ regulator-name = "vdd_logic"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-init-microvolt = <900000>; ++ regulator-initial-mode = <0x2>; ++ regulator-min-microvolt = <500000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-ramp-delay = <6001>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_gpu: DCDC_REG2 { ++ regulator-name = "vdd_gpu"; ++ regulator-always-on; ++ regulator-init-microvolt = <900000>; ++ regulator-initial-mode = <0x2>; ++ regulator-min-microvolt = <500000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-ramp-delay = <6001>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_ddr: DCDC_REG3 { ++ regulator-name = "vcc_ddr"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-initial-mode = <0x2>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vdd_npu: DCDC_REG4 { ++ regulator-name = "vdd_npu"; ++ regulator-init-microvolt = <900000>; ++ regulator-initial-mode = <0x2>; ++ regulator-min-microvolt = <500000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-ramp-delay = <6001>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_1v8: DCDC_REG5 { ++ regulator-name = "vcc_1v8"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdda0v9_image: LDO_REG1 { ++ regulator-name = "vdda0v9_image"; ++ regulator-min-microvolt = <900000>; ++ regulator-max-microvolt = <900000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdda_0v9: LDO_REG2 { ++ regulator-name = "vdda_0v9"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <900000>; ++ regulator-max-microvolt = <900000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdda0v9_pmu: LDO_REG3 { ++ regulator-name = "vdda0v9_pmu"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <900000>; ++ regulator-max-microvolt = <900000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <900000>; ++ }; ++ }; ++ ++ vccio_acodec: LDO_REG4 { ++ regulator-name = "vccio_acodec"; ++ regulator-always-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vccio_sd: LDO_REG5 { ++ regulator-name = "vccio_sd"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc3v3_pmu: LDO_REG6 { ++ regulator-name = "vcc3v3_pmu"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vcca_1v8: LDO_REG7 { ++ regulator-name = "vcca_1v8"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcca1v8_pmu: LDO_REG8 { ++ regulator-name = "vcca1v8_pmu"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcca1v8_image: LDO_REG9 { ++ regulator-name = "vcca1v8_image"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_3v3: SWITCH_REG1 { ++ regulator-name = "vcc_3v3"; ++ regulator-always-on; ++ regulator-boot-on; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc3v3_sd: SWITCH_REG2 { ++ regulator-name = "vcc3v3_sd"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ }; ++ ++ codec { ++ mic-in-differential; ++ }; ++ }; ++}; ++ ++&i2s1_8ch { ++ rockchip,trcm-sync-tx-only; ++ status = "okay"; ++}; ++ ++&mdio1 { ++ rgmii_phy1: ethernet-phy@0 { ++ compatible = "ethernet-phy-ieee802.3-c22"; ++ reg = <0x0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <ð_phy_rst>; ++ reset-assert-us = <20000>; ++ reset-deassert-us = <100000>; ++ reset-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>; ++ }; ++}; ++ ++&pinctrl { ++ ethernet { ++ eth_phy_rst: eth_phy_rst { ++ rockchip,pins = <3 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ leds { ++ led_user_en: led_user_en { ++ rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ pmic { ++ pmic_int: pmic_int { ++ rockchip,pins = ++ <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ usb { ++ vcc5v0_usb_host_en: vcc5v0_usb_host_en { ++ rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ vcc5v0_usb_hub_en: vcc5v0_usb_hub_en { ++ rockchip,pins = <0 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ vcc5v0_usb_otg_en: vcc5v0_usb_otg_en { ++ rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++}; ++ ++&pmu_io_domains { ++ pmuio1-supply = <&vcc3v3_pmu>; ++ pmuio2-supply = <&vcc3v3_pmu>; ++ vccio1-supply = <&vccio_acodec>; ++ vccio2-supply = <&vcc_1v8>; ++ vccio3-supply = <&vccio_sd>; ++ vccio4-supply = <&vcc_1v8>; ++ vccio5-supply = <&vcc_3v3>; ++ vccio6-supply = <&vcc_1v8>; ++ vccio7-supply = <&vcc_3v3>; ++ status = "okay"; ++}; ++ ++&saradc { ++ vref-supply = <&vcca_1v8>; ++ status = "okay"; ++}; ++ ++&sdhci { ++ bus-width = <8>; ++ max-frequency = <200000000>; ++ non-removable; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_datastrobe>; ++ vmmc-supply = <&vcc_3v3>; ++ vqmmc-supply = <&vcc_1v8>; ++ status = "okay"; ++}; ++ ++&sdmmc0 { ++ bus-width = <4>; ++ cap-sd-highspeed; ++ cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>; ++ disable-wp; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc0_bus4 &sdmmc0_clk &sdmmc0_cmd &sdmmc0_det>; ++ sd-uhs-sdr104; ++ vmmc-supply = <&vcc3v3_sd>; ++ vqmmc-supply = <&vccio_sd>; ++ status = "okay"; ++}; ++ ++&tsadc { ++ rockchip,hw-tshut-mode = <1>; ++ rockchip,hw-tshut-polarity = <0>; ++ status = "okay"; ++}; ++ ++&uart2 { ++ status = "okay"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usb_host1_ehci { ++ status = "okay"; ++}; ++ ++&usb_host1_ohci { ++ status = "okay"; ++}; +--- /dev/null ++++ b/configs/rock-3a-rk3568_defconfig +@@ -0,0 +1,98 @@ ++CONFIG_ARM=y ++CONFIG_SKIP_LOWLEVEL_INIT=y ++CONFIG_ARCH_ROCKCHIP=y ++CONFIG_SYS_TEXT_BASE=0x00a00000 ++CONFIG_SPL_LIBCOMMON_SUPPORT=y ++CONFIG_SPL_LIBGENERIC_SUPPORT=y ++CONFIG_NR_DRAM_BANKS=2 ++CONFIG_DEFAULT_DEVICE_TREE="rk3568-rock-3a" ++CONFIG_ROCKCHIP_RK3568=y ++CONFIG_SPL_ROCKCHIP_BACK_TO_BROM=y ++CONFIG_SPL_ROCKCHIP_COMMON_BOARD=y ++CONFIG_SPL_MMC=y ++CONFIG_SPL_SERIAL=y ++CONFIG_SPL_STACK_R_ADDR=0x600000 ++CONFIG_TARGET_EVB_RK3568=y ++CONFIG_DEBUG_UART_BASE=0xFE660000 ++CONFIG_DEBUG_UART_CLOCK=24000000 ++CONFIG_DEBUG_UART=y ++CONFIG_SYS_LOAD_ADDR=0xc00800 ++CONFIG_API=y ++CONFIG_FIT=y ++CONFIG_FIT_VERBOSE=y ++CONFIG_SPL_LOAD_FIT=y ++CONFIG_OF_SYSTEM_SETUP=y ++CONFIG_DEFAULT_FDT_FILE="rockchip/rk3568-rock-3a.dtb" ++# CONFIG_SYS_DEVICE_NULLDEV is not set ++CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS=2 ++# CONFIG_DISPLAY_CPUINFO is not set ++CONFIG_DISPLAY_BOARDINFO_LATE=y ++# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set ++CONFIG_SPL_STACK_R=y ++CONFIG_SPL_SEPARATE_BSS=y ++CONFIG_SPL_ATF=y ++CONFIG_SPL_ATF_LOAD_IMAGE_V2=y ++CONFIG_CMD_BIND=y ++CONFIG_CMD_CLK=y ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_I2C=y ++CONFIG_CMD_MMC=y ++CONFIG_CMD_USB=y ++# CONFIG_CMD_SETEXPR is not set ++CONFIG_CMD_PMIC=y ++CONFIG_CMD_REGULATOR=y ++# CONFIG_SPL_DOS_PARTITION is not set ++CONFIG_SPL_OF_CONTROL=y ++CONFIG_OF_LIVE=y ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_SPL_DM_WARN=y ++CONFIG_SPL_REGMAP=y ++CONFIG_SPL_SYSCON=y ++CONFIG_SPL_CLK=y ++CONFIG_ROCKCHIP_GPIO=y ++CONFIG_ROCKCHIP_GPIO_V2=y ++CONFIG_SYS_I2C_ROCKCHIP=y ++CONFIG_MISC=y ++CONFIG_MMC_HS200_SUPPORT=y ++CONFIG_SPL_MMC_HS200_SUPPORT=y ++CONFIG_MMC_DW=y ++CONFIG_MMC_DW_ROCKCHIP=y ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_SDMA=y ++CONFIG_MMC_SDHCI_ROCKCHIP=y ++CONFIG_DM_ETH=y ++CONFIG_ETH_DESIGNWARE=y ++CONFIG_GMAC_ROCKCHIP=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_DM_PMIC=y ++CONFIG_PMIC_RK8XX=y ++CONFIG_SPL_PMIC_RK8XX=y ++CONFIG_REGULATOR_PWM=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_SPL_DM_REGULATOR_FIXED=y ++CONFIG_DM_REGULATOR_GPIO=y ++CONFIG_REGULATOR_RK8XX=y ++CONFIG_PWM_ROCKCHIP=y ++CONFIG_SPL_RAM=y ++CONFIG_DM_RESET=y ++CONFIG_BAUDRATE=1500000 ++CONFIG_DEBUG_UART_SHIFT=2 ++CONFIG_SYSRESET=y ++CONFIG_SYSRESET_PSCI=y ++CONFIG_USB=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_DWC3=y ++CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_EHCI_GENERIC=y ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_GENERIC=y ++CONFIG_USB_DWC3=y ++CONFIG_USB_DWC3_GENERIC=y ++CONFIG_ROCKCHIP_USB2_PHY=y ++CONFIG_USB_KEYBOARD=y ++CONFIG_USB_HOST_ETHER=y ++CONFIG_USB_ETHER_LAN75XX=y ++CONFIG_USB_ETHER_LAN78XX=y ++CONFIG_USB_ETHER_SMSC95XX=y ++CONFIG_ERRNO_STR=y diff --git a/root/package/boot/uboot-rockchip/patches/015-uboot-add-NanoPi-R5S-board.patch b/root/package/boot/uboot-rockchip/patches/015-uboot-add-NanoPi-R5S-board.patch new file mode 100644 index 00000000..b527a261 --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/015-uboot-add-NanoPi-R5S-board.patch @@ -0,0 +1,247 @@ +From 872197ee382688701f85fc486a14dc02d2113811 Mon Sep 17 00:00:00 2001 +From: Marty Jones +Date: Tue, 31 May 2022 00:51:23 -0400 +Subject: [PATCH] uboot: add NanoPi R5S board + +Signed-off-by: Marty Jones +--- + arch/arm/dts/Makefile | 1 + + arch/arm/dts/rk3568-nanopi-r5s-u-boot.dtsi | 25 +++++ + arch/arm/dts/rk3568-nanopi-r5s.dts | 9 ++ + arch/arm/mach-rockchip/rk3568/Kconfig | 6 ++ + board/friendlyelec/nanopi-r5s-rk3568/Kconfig | 15 +++ + board/friendlyelec/nanopi-r5s-rk3568/Makefile | 4 + + .../nanopi-r5s-rk3568/nanopi-r5s-rk3568.c | 4 + + configs/nanopi-r5s-rk3568_defconfig | 97 +++++++++++++++++++ + include/configs/nanopi-r5s-rk3568.h | 17 ++++ + 9 files changed, 178 insertions(+) + create mode 100644 arch/arm/dts/rk3568-nanopi-r5s-u-boot.dtsi + create mode 100644 arch/arm/dts/rk3568-nanopi-r5s.dts + create mode 100644 board/friendlyelec/nanopi-r5s-rk3568/Kconfig + create mode 100644 board/friendlyelec/nanopi-r5s-rk3568/Makefile + create mode 100644 board/friendlyelec/nanopi-r5s-rk3568/nanopi-r5s-rk3568.c + create mode 100644 configs/nanopi-r5s-rk3568_defconfig + create mode 100644 include/configs/nanopi-r5s-rk3568.h + +--- a/arch/arm/dts/Makefile ++++ b/arch/arm/dts/Makefile +@@ -166,6 +166,7 @@ dtb-$(CONFIG_ROCKCHIP_RK3399) += \ + dtb-$(CONFIG_ROCKCHIP_RK3568) += \ + rk3568-bpi-r2-pro.dtb \ + rk3568-evb.dtb \ ++ rk3568-nanopi-r5s.dtb \ + rk3566-quartz64-a.dtb \ + rk3568-rock-3a.dtb + +--- /dev/null ++++ b/arch/arm/dts/rk3568-nanopi-r5s-u-boot.dtsi +@@ -0,0 +1,25 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * (C) Copyright 2021 Rockchip Electronics Co., Ltd ++ */ ++ ++#include "rk3568-u-boot.dtsi" ++ ++/ { ++ chosen { ++ stdout-path = &uart2; ++ u-boot,spl-boot-order = "same-as-spl", &sdmmc0, &sdhci; ++ }; ++}; ++ ++&sdmmc0 { ++ bus-width = <4>; ++ u-boot,dm-spl; ++ u-boot,spl-fifo-mode; ++}; ++ ++&uart2 { ++ clock-frequency = <24000000>; ++ u-boot,dm-spl; ++ status = "okay"; ++}; +--- /dev/null ++++ b/arch/arm/dts/rk3568-nanopi-r5s.dts +@@ -0,0 +1,9 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++/dts-v1/; ++#include "rk3568-evb.dts" ++ ++/ { ++ model = "FriendlyElec NanoPi R5S"; ++ compatible = "friendlyelec,nanopi-r5s", "rockchip,rk3568"; ++}; +--- a/arch/arm/mach-rockchip/rk3568/Kconfig ++++ b/arch/arm/mach-rockchip/rk3568/Kconfig +@@ -13,6 +13,11 @@ config TARGET_EVB_RK3568 + help + RK3568 EVB is a evaluation board for Rockchp RK3568. + ++config TARGET_NANOPI_R5S_RK3568 ++ bool "NanoPi R5S board" ++ help ++ NanoPi R5S FriendlyElec is a board for Rockchp RK3568. ++ + config TARGET_QUARTZ64_A_RK3566 + bool "Quartz64 Model A RK3566 development board" + help +@@ -39,6 +44,7 @@ config SYS_MALLOC_F_LEN + + source "board/rockchip/bpi-r2-pro-rk3568/Kconfig" + source "board/rockchip/evb_rk3568/Kconfig" ++source "board/friendlyelec/nanopi-r5s-rk3568/Kconfig" + source "board/pine64/quartz64-a-rk3566/Kconfig" + source "board/radxa/rock-3a-rk3568/Kconfig" + +--- /dev/null ++++ b/board/friendlyelec/nanopi-r5s-rk3568/Kconfig +@@ -0,0 +1,15 @@ ++if TARGET_NANOPI_R5S_RK3568 ++ ++config SYS_BOARD ++ default "nanopi-r5s-rk3568" ++ ++config SYS_VENDOR ++ default "friendlyelec" ++ ++config SYS_CONFIG_NAME ++ default "nanopi-r5s-rk3568" ++ ++config BOARD_SPECIFIC_OPTIONS # dummy ++ def_bool y ++ ++endif +--- /dev/null ++++ b/board/friendlyelec/nanopi-r5s-rk3568/Makefile +@@ -0,0 +1,4 @@ ++# SPDX-License-Identifier: GPL-2.0+ ++# ++ ++obj-y += nanopi-r5s-rk3568.o +--- /dev/null ++++ b/board/friendlyelec/nanopi-r5s-rk3568/nanopi-r5s-rk3568.c +@@ -0,0 +1,4 @@ ++ // SPDX-License-Identifier: GPL-2.0+ ++/* ++ * ++ */ +--- /dev/null ++++ b/configs/nanopi-r5s-rk3568_defconfig +@@ -0,0 +1,98 @@ ++CONFIG_ARM=y ++CONFIG_SKIP_LOWLEVEL_INIT=y ++CONFIG_ARCH_ROCKCHIP=y ++CONFIG_SYS_TEXT_BASE=0x00a00000 ++CONFIG_SPL_LIBCOMMON_SUPPORT=y ++CONFIG_SPL_LIBGENERIC_SUPPORT=y ++CONFIG_NR_DRAM_BANKS=2 ++CONFIG_DEFAULT_DEVICE_TREE="rk3568-nanopi-r5s" ++CONFIG_ROCKCHIP_RK3568=y ++CONFIG_SPL_ROCKCHIP_BACK_TO_BROM=y ++CONFIG_SPL_ROCKCHIP_COMMON_BOARD=y ++CONFIG_SPL_MMC=y ++CONFIG_SPL_SERIAL=y ++CONFIG_SPL_STACK_R_ADDR=0x600000 ++CONFIG_TARGET_NANOPI_R5S_RK3568=y ++CONFIG_DEBUG_UART_BASE=0xFE660000 ++CONFIG_DEBUG_UART_CLOCK=24000000 ++CONFIG_DEBUG_UART=y ++CONFIG_SYS_LOAD_ADDR=0xc00800 ++CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS=2 ++CONFIG_API=y ++CONFIG_FIT=y ++CONFIG_FIT_VERBOSE=y ++CONFIG_SPL_LOAD_FIT=y ++CONFIG_OF_SYSTEM_SETUP=y ++CONFIG_DEFAULT_FDT_FILE="rockchip/rk3568-nanopi-r5s.dtb" ++# CONFIG_SYS_DEVICE_NULLDEV is not set ++# CONFIG_DISPLAY_CPUINFO is not set ++CONFIG_DISPLAY_BOARDINFO_LATE=y ++# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set ++CONFIG_SPL_STACK_R=y ++CONFIG_SPL_SEPARATE_BSS=y ++CONFIG_SPL_ATF=y ++CONFIG_SPL_ATF_LOAD_IMAGE_V2=y ++CONFIG_CMD_BIND=y ++CONFIG_CMD_CLK=y ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_I2C=y ++CONFIG_CMD_MMC=y ++CONFIG_CMD_USB=y ++# CONFIG_CMD_SETEXPR is not set ++CONFIG_CMD_PMIC=y ++CONFIG_CMD_REGULATOR=y ++# CONFIG_SPL_DOS_PARTITION is not set ++CONFIG_SPL_OF_CONTROL=y ++CONFIG_OF_LIVE=y ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_SPL_DM_WARN=y ++CONFIG_SPL_REGMAP=y ++CONFIG_SPL_SYSCON=y ++CONFIG_SPL_CLK=y ++CONFIG_ROCKCHIP_GPIO=y ++CONFIG_ROCKCHIP_GPIO_V2=y ++CONFIG_SYS_I2C_ROCKCHIP=y ++CONFIG_MISC=y ++CONFIG_MMC_HS200_SUPPORT=y ++CONFIG_SPL_MMC_HS200_SUPPORT=y ++CONFIG_MMC_DW=y ++CONFIG_MMC_DW_ROCKCHIP=y ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_SDMA=y ++CONFIG_MMC_SDHCI_ROCKCHIP=y ++CONFIG_DM_ETH=y ++CONFIG_ETH_DESIGNWARE=y ++CONFIG_GMAC_ROCKCHIP=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_DM_PMIC=y ++CONFIG_PMIC_RK8XX=y ++CONFIG_SPL_PMIC_RK8XX=y ++CONFIG_REGULATOR_PWM=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_SPL_DM_REGULATOR_FIXED=y ++CONFIG_DM_REGULATOR_GPIO=y ++CONFIG_REGULATOR_RK8XX=y ++CONFIG_PWM_ROCKCHIP=y ++CONFIG_SPL_RAM=y ++CONFIG_DM_RESET=y ++CONFIG_BAUDRATE=1500000 ++CONFIG_DEBUG_UART_SHIFT=2 ++CONFIG_SYSRESET=y ++CONFIG_SYSRESET_PSCI=y ++CONFIG_USB=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_DWC3=y ++CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_EHCI_GENERIC=y ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_GENERIC=y ++CONFIG_USB_DWC3=y ++CONFIG_USB_DWC3_GENERIC=y ++CONFIG_ROCKCHIP_USB2_PHY=y ++CONFIG_USB_KEYBOARD=y ++CONFIG_USB_HOST_ETHER=y ++CONFIG_USB_ETHER_LAN75XX=y ++CONFIG_USB_ETHER_LAN78XX=y ++CONFIG_USB_ETHER_SMSC95XX=y ++CONFIG_ERRNO_STR=y +--- /dev/null ++++ b/include/configs/nanopi-r5s-rk3568.h +@@ -0,0 +1,14 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++ ++#ifndef __NANOPI_R5S_RK3568_H ++#define __NANOPI_R5S_RK3568_H ++ ++#include ++ ++#define CONFIG_SUPPORT_EMMC_RPMB ++ ++#define ROCKCHIP_DEVICE_SETTINGS \ ++ "stdout=serial,vidconsole\0" \ ++ "stderr=serial,vidconsole\0" ++ ++#endif diff --git a/root/package/boot/uboot-rockchip/patches/100-Convert-CONFIG_USB_OHCI_NEW-et-al-to-Kconfig.patch b/root/package/boot/uboot-rockchip/patches/100-Convert-CONFIG_USB_OHCI_NEW-et-al-to-Kconfig.patch new file mode 100644 index 00000000..ff5a97f3 --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/100-Convert-CONFIG_USB_OHCI_NEW-et-al-to-Kconfig.patch @@ -0,0 +1,282 @@ +From cd6a45a41fb2c19884ac87afade87b4d53601929 Mon Sep 17 00:00:00 2001 +From: Tom Rini +Date: Sat, 25 Jun 2022 11:02:31 -0400 +Subject: [PATCH] Convert CONFIG_USB_OHCI_NEW et al to Kconfig + +This converts the following to Kconfig: + CONFIG_SYS_OHCI_SWAP_REG_ACCESS + CONFIG_SYS_USB_OHCI_CPU_INIT + CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS + CONFIG_SYS_USB_OHCI_SLOT_NAME + CONFIG_USB_ATMEL + CONFIG_USB_ATMEL_CLK_SEL_PLLB + CONFIG_USB_ATMEL_CLK_SEL_UPLL + CONFIG_USB_OHCI_LPC32XX + CONFIG_USB_OHCI_NEW + +Signed-off-by: Tom Rini +--- + +diff --git a/configs/evb-rk3328_defconfig b/configs/evb-rk3328_defconfig +index 4d6d235cb125..c81437300c74 100644 +--- a/configs/evb-rk3328_defconfig ++++ b/configs/evb-rk3328_defconfig +@@ -99,6 +99,7 @@ CONFIG_USB_EHCI_HCD=y + CONFIG_USB_EHCI_GENERIC=y + CONFIG_USB_OHCI_HCD=y + CONFIG_USB_OHCI_GENERIC=y ++CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS=1 + CONFIG_USB_DWC2=y + CONFIG_USB_DWC3=y + # CONFIG_USB_DWC3_GADGET is not set +diff --git a/configs/nanopi-r2s-rk3328_defconfig b/configs/nanopi-r2s-rk3328_defconfig +index 41793ca7e486..15c2e1698c20 100644 +--- a/configs/nanopi-r2s-rk3328_defconfig ++++ b/configs/nanopi-r2s-rk3328_defconfig +@@ -102,6 +102,7 @@ CONFIG_USB_EHCI_HCD=y + CONFIG_USB_EHCI_GENERIC=y + CONFIG_USB_OHCI_HCD=y + CONFIG_USB_OHCI_GENERIC=y ++CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS=1 + CONFIG_USB_DWC2=y + CONFIG_USB_DWC3=y + # CONFIG_USB_DWC3_GADGET is not set +diff --git a/configs/roc-cc-rk3328_defconfig b/configs/roc-cc-rk3328_defconfig +index ab25abc1a031..43b90c7879b7 100644 +--- a/configs/roc-cc-rk3328_defconfig ++++ b/configs/roc-cc-rk3328_defconfig +@@ -108,6 +108,7 @@ CONFIG_USB_EHCI_HCD=y + CONFIG_USB_EHCI_GENERIC=y + CONFIG_USB_OHCI_HCD=y + CONFIG_USB_OHCI_GENERIC=y ++CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS=1 + CONFIG_USB_DWC2=y + CONFIG_USB_DWC3=y + # CONFIG_USB_DWC3_GADGET is not set +diff --git a/configs/rock-pi-e-rk3328_defconfig b/configs/rock-pi-e-rk3328_defconfig +index 1d51a267b93a..7d95e171f7f4 100644 +--- a/configs/rock-pi-e-rk3328_defconfig ++++ b/configs/rock-pi-e-rk3328_defconfig +@@ -109,6 +109,7 @@ CONFIG_USB_EHCI_HCD=y + CONFIG_USB_EHCI_GENERIC=y + CONFIG_USB_OHCI_HCD=y + CONFIG_USB_OHCI_GENERIC=y ++CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS=1 + CONFIG_USB_DWC2=y + CONFIG_USB_DWC3=y + # CONFIG_USB_DWC3_GADGET is not set +diff --git a/configs/rock64-rk3328_defconfig b/configs/rock64-rk3328_defconfig +index 640fe558d414..bc333a5e2a6a 100644 +--- a/configs/rock64-rk3328_defconfig ++++ b/configs/rock64-rk3328_defconfig +@@ -106,6 +106,7 @@ CONFIG_USB_EHCI_HCD=y + CONFIG_USB_EHCI_GENERIC=y + CONFIG_USB_OHCI_HCD=y + CONFIG_USB_OHCI_GENERIC=y ++CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS=1 + CONFIG_USB_DWC2=y + CONFIG_USB_DWC3=y + # CONFIG_USB_DWC3_GADGET is not set +diff --git a/configs/rock960-rk3399_defconfig b/configs/rock960-rk3399_defconfig +index 78e50dbfbcb7..bb5b2143691d 100644 +--- a/configs/rock960-rk3399_defconfig ++++ b/configs/rock960-rk3399_defconfig +@@ -74,6 +74,7 @@ CONFIG_USB_EHCI_HCD=y + CONFIG_USB_EHCI_GENERIC=y + CONFIG_USB_OHCI_HCD=y + CONFIG_USB_OHCI_GENERIC=y ++CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS=2 + CONFIG_USB_DWC3=y + CONFIG_USB_KEYBOARD=y + CONFIG_USB_HOST_ETHER=y +diff --git a/configs/rockpro64-rk3399_defconfig b/configs/rockpro64-rk3399_defconfig +index 4d2a5b32e31c..ef28fe6a937a 100644 +--- a/configs/rockpro64-rk3399_defconfig ++++ b/configs/rockpro64-rk3399_defconfig +@@ -87,6 +87,7 @@ CONFIG_USB_EHCI_HCD=y + CONFIG_USB_EHCI_GENERIC=y + CONFIG_USB_OHCI_HCD=y + CONFIG_USB_OHCI_GENERIC=y ++CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS=2 + CONFIG_USB_DWC3=y + CONFIG_USB_DWC3_GENERIC=y + CONFIG_USB_KEYBOARD=y +diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig +index 0b82c2fdaf71..31ae9f74e7ac 100644 +--- a/drivers/usb/host/Kconfig ++++ b/drivers/usb/host/Kconfig +@@ -297,10 +297,17 @@ config USB_EHCI_TXFIFO_THRESH + Enables support for the on-chip EHCI controller on FSL chips. + endif # USB_EHCI_HCD + ++config USB_OHCI_NEW ++ bool ++ ++config SYS_USB_OHCI_CPU_INIT ++ bool ++ + config USB_OHCI_HCD + bool "OHCI HCD (USB 1.1) support" + depends on DM && OF_CONTROL + select USB_HOST ++ select USB_OHCI_NEW + ---help--- + The Open Host Controller Interface (OHCI) is a standard for accessing + USB 1.1 host controller hardware. It does more in hardware than Intel's +@@ -332,6 +339,19 @@ config USB_OHCI_DA8XX + + endif # USB_OHCI_HCD + ++config SYS_USB_OHCI_SLOT_NAME ++ string "Display name for the OHCI controller" ++ depends on USB_OHCI_NEW && !DM_USB ++ ++config SYS_USB_OHCI_MAX_ROOT_PORTS ++ int "Maximal number of ports of the root hub" ++ depends on USB_OHCI_NEW ++ default 1 if ARCH_SUNXI ++ ++config SYS_OHCI_SWAP_REG_ACCESS ++ bool "Perform byte swapping on OHCI controller register accesses" ++ depends on USB_OHCI_NEW ++ + config USB_UHCI_HCD + bool "UHCI HCD (most Intel and VIA) support" + select USB_HOST +@@ -381,3 +401,27 @@ config USB_R8A66597_HCD + ---help--- + This enables support for the on-chip Renesas R8A66597 USB 2.0 + controller, present in various RZ and SH SoCs. ++ ++config USB_ATMEL ++ bool "AT91 OHCI USB support" ++ depends on ARCH_AT91 ++ select SYS_USB_OHCI_CPU_INIT ++ select USB_OHCI_NEW ++ ++choice ++ prompt "Clock for OHCI" ++ depends on USB_ATMEL ++ ++config USB_ATMEL_CLK_SEL_PLLB ++ bool "PLLB" ++ ++config USB_ATMEL_CLK_SEL_UPLL ++ bool "UPLL" ++ ++endchoice ++ ++config USB_OHCI_LPC32XX ++ bool "LPC32xx USB OHCI support" ++ depends on ARCH_LPC32XX ++ select SYS_USB_OHCI_CPU_INIT ++ select USB_OHCI_NEW +diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c +index 8ceabaf45c1b..9b955c1bd678 100644 +--- a/drivers/usb/host/ohci-at91.c ++++ b/drivers/usb/host/ohci-at91.c +@@ -5,9 +5,6 @@ + */ + + #include +- +-#if defined(CONFIG_USB_OHCI_NEW) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT) +- + #include + + int usb_cpu_init(void) +@@ -65,5 +62,3 @@ int usb_cpu_init_fail(void) + { + return usb_cpu_stop(); + } +- +-#endif /* defined(CONFIG_USB_OHCI) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT) */ +diff --git a/drivers/usb/host/ohci-generic.c b/drivers/usb/host/ohci-generic.c +index 163f0ef17b11..5d23058aaf6a 100644 +--- a/drivers/usb/host/ohci-generic.c ++++ b/drivers/usb/host/ohci-generic.c +@@ -14,10 +14,6 @@ + #include + #include "ohci.h" + +-#if !defined(CONFIG_USB_OHCI_NEW) +-# error "Generic OHCI driver requires CONFIG_USB_OHCI_NEW" +-#endif +- + struct generic_ohci { + ohci_t ohci; + struct clk *clocks; /* clock list */ +diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h +index a38cd25eb85f..7699f2e6b15a 100644 +--- a/drivers/usb/host/ohci.h ++++ b/drivers/usb/host/ohci.h +@@ -151,7 +151,7 @@ struct ohci_hcca { + * Maximum number of root hub ports. + */ + #ifndef CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS +-# error "CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS undefined!" ++#define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 1 + #endif + + /* +diff --git a/include/configs/evb_rk3399.h b/include/configs/evb_rk3399.h +index 492b7b4df128..b7e850370b31 100644 +--- a/include/configs/evb_rk3399.h ++++ b/include/configs/evb_rk3399.h +@@ -15,7 +15,4 @@ + + #define SDRAM_BANK_SIZE (2UL << 30) + +-#define CONFIG_USB_OHCI_NEW +-#define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 2 +- + #endif +diff --git a/include/configs/gru.h b/include/configs/gru.h +index b1084bb21d4d..be2dc79968c0 100644 +--- a/include/configs/gru.h ++++ b/include/configs/gru.h +@@ -13,7 +13,4 @@ + + #include + +-#define CONFIG_USB_OHCI_NEW +-#define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 2 +- + #endif +diff --git a/include/configs/rk3328_common.h b/include/configs/rk3328_common.h +index 90183579202d..165b78ff3309 100644 +--- a/include/configs/rk3328_common.h ++++ b/include/configs/rk3328_common.h +@@ -30,8 +30,4 @@ + "partitions=" PARTS_DEFAULT \ + BOOTENV + +-/* rockchip ohci host driver */ +-#define CONFIG_USB_OHCI_NEW +-#define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 1 +- + #endif +diff --git a/include/configs/rock960_rk3399.h b/include/configs/rock960_rk3399.h +index 2edad710284f..6099d2fa55a6 100644 +--- a/include/configs/rock960_rk3399.h ++++ b/include/configs/rock960_rk3399.h +@@ -14,7 +14,4 @@ + #include + + #define SDRAM_BANK_SIZE (2UL << 30) +- +-#define CONFIG_USB_OHCI_NEW +-#define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 2 + #endif +diff --git a/include/configs/rockpro64_rk3399.h b/include/configs/rockpro64_rk3399.h +index 903e9df527c1..9195b9b99e41 100644 +--- a/include/configs/rockpro64_rk3399.h ++++ b/include/configs/rockpro64_rk3399.h +@@ -14,7 +14,4 @@ + #include + + #define SDRAM_BANK_SIZE (2UL << 30) +- +-#define CONFIG_USB_OHCI_NEW +-#define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 2 + #endif diff --git a/root/package/boot/uboot-rockchip/patches/104-mkimage-add-public-key-for-image.patch b/root/package/boot/uboot-rockchip/patches/104-mkimage-add-public-key-for-image.patch new file mode 100644 index 00000000..8c8e79cf --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/104-mkimage-add-public-key-for-image.patch @@ -0,0 +1,166 @@ +--- a/include/image.h ++++ b/include/image.h +@@ -1020,21 +1020,6 @@ int fit_image_hash_get_value(const void + + int fit_set_timestamp(void *fit, int noffset, time_t timestamp); + +-/** +- * fit_pre_load_data() - add public key to fdt blob +- * +- * Adds public key to the node pre load. +- * +- * @keydir: Directory containing keys +- * @keydest: FDT blob to write public key +- * @fit: Pointer to the FIT format image header +- * +- * returns: +- * 0, on success +- * < 0, on failure +- */ +-int fit_pre_load_data(const char *keydir, void *keydest, void *fit); +- + int fit_cipher_data(const char *keydir, void *keydest, void *fit, + const char *comment, int require_keys, + const char *engine_id, const char *cmdname); +--- a/tools/fit_image.c ++++ b/tools/fit_image.c +@@ -59,9 +59,6 @@ static int fit_add_file_data(struct imag + ret = fit_set_timestamp(ptr, 0, time); + } + +- if (!ret) +- ret = fit_pre_load_data(params->keydir, dest_blob, ptr); +- + if (!ret) { + ret = fit_cipher_data(params->keydir, dest_blob, ptr, + params->comment, +--- a/tools/image-host.c ++++ b/tools/image-host.c +@@ -14,11 +14,6 @@ + #include + #include + +-#include +-#include +- +-#define IMAGE_PRE_LOAD_PATH "/image/pre-load/sig" +- + /** + * fit_set_hash_value - set hash value in requested has node + * @fit: pointer to the FIT format image header +@@ -1116,115 +1111,6 @@ static int fit_config_add_verification_d + return 0; + } + +-/* +- * 0) open file (open) +- * 1) read certificate (PEM_read_X509) +- * 2) get public key (X509_get_pubkey) +- * 3) provide der format (d2i_RSAPublicKey) +- */ +-static int read_pub_key(const char *keydir, const void *name, +- unsigned char **pubkey, int *pubkey_len) +-{ +- char path[1024]; +- EVP_PKEY *key = NULL; +- X509 *cert; +- FILE *f; +- int ret; +- +- memset(path, 0, 1024); +- snprintf(path, sizeof(path), "%s/%s.crt", keydir, (char *)name); +- +- /* Open certificate file */ +- f = fopen(path, "r"); +- if (!f) { +- fprintf(stderr, "Couldn't open RSA certificate: '%s': %s\n", +- path, strerror(errno)); +- return -EACCES; +- } +- +- /* Read the certificate */ +- cert = NULL; +- if (!PEM_read_X509(f, &cert, NULL, NULL)) { +- printf("Couldn't read certificate"); +- ret = -EINVAL; +- goto err_cert; +- } +- +- /* Get the public key from the certificate. */ +- key = X509_get_pubkey(cert); +- if (!key) { +- printf("Couldn't read public key\n"); +- ret = -EINVAL; +- goto err_pubkey; +- } +- +- /* Get DER form */ +- ret = i2d_PublicKey(key, pubkey); +- if (ret < 0) { +- printf("Couldn't get DER form\n"); +- ret = -EINVAL; +- goto err_pubkey; +- } +- +- *pubkey_len = ret; +- ret = 0; +- +-err_pubkey: +- X509_free(cert); +-err_cert: +- fclose(f); +- return ret; +-} +- +-int fit_pre_load_data(const char *keydir, void *keydest, void *fit) +-{ +- int pre_load_noffset; +- const void *algo_name; +- const void *key_name; +- unsigned char *pubkey = NULL; +- int ret, pubkey_len; +- +- if (!keydir || !keydest || !fit) +- return 0; +- +- /* Search node pre-load sig */ +- pre_load_noffset = fdt_path_offset(keydest, IMAGE_PRE_LOAD_PATH); +- if (pre_load_noffset < 0) { +- ret = 0; +- goto out; +- } +- +- algo_name = fdt_getprop(keydest, pre_load_noffset, "algo-name", NULL); +- key_name = fdt_getprop(keydest, pre_load_noffset, "key-name", NULL); +- +- /* Check that all mandatory properties are present */ +- if (!algo_name || !key_name) { +- if (!algo_name) +- printf("The property algo-name is missing in the node %s\n", +- IMAGE_PRE_LOAD_PATH); +- if (!key_name) +- printf("The property key-name is missing in the node %s\n", +- IMAGE_PRE_LOAD_PATH); +- ret = -EINVAL; +- goto out; +- } +- +- /* Read public key */ +- ret = read_pub_key(keydir, key_name, &pubkey, &pubkey_len); +- if (ret < 0) +- goto out; +- +- /* Add the public key to the device tree */ +- ret = fdt_setprop(keydest, pre_load_noffset, "public-key", +- pubkey, pubkey_len); +- if (ret) +- printf("Can't set public-key in node %s (ret = %d)\n", +- IMAGE_PRE_LOAD_PATH, ret); +- +- out: +- return ret; +-} +- + int fit_cipher_data(const char *keydir, void *keydest, void *fit, + const char *comment, int require_keys, + const char *engine_id, const char *cmdname) diff --git a/root/package/boot/uboot-rockchip/patches/105-Only-build-dtc-if-needed.patch b/root/package/boot/uboot-rockchip/patches/105-Only-build-dtc-if-needed.patch new file mode 100644 index 00000000..ad040770 --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/105-Only-build-dtc-if-needed.patch @@ -0,0 +1,125 @@ +--- a/Makefile ++++ b/Makefile +@@ -413,13 +413,7 @@ PERL = perl + PYTHON ?= python + PYTHON2 = python2 + PYTHON3 ?= python3 +- +-# The devicetree compiler and pylibfdt are automatically built unless DTC is +-# provided. If DTC is provided, it is assumed the pylibfdt is available too. +-DTC_INTREE := $(objtree)/scripts/dtc/dtc +-DTC ?= $(DTC_INTREE) +-DTC_MIN_VERSION := 010406 +- ++DTC ?= $(objtree)/scripts/dtc/dtc + CHECK = sparse + + CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \ +@@ -2070,29 +2064,9 @@ endif + + endif + +-# Check dtc and pylibfdt, if DTC is provided, else build them + PHONY += scripts_dtc + scripts_dtc: scripts_basic +- $(Q)if test "$(DTC)" = "$(DTC_INTREE)"; then \ +- $(MAKE) $(build)=scripts/dtc; \ +- else \ +- if ! $(DTC) -v >/dev/null; then \ +- echo '*** Failed to check dtc version: $(DTC)'; \ +- false; \ +- else \ +- if test "$(call dtc-version)" -lt $(DTC_MIN_VERSION); then \ +- echo '*** Your dtc is too old, please upgrade to dtc $(DTC_MIN_VERSION) or newer'; \ +- false; \ +- else \ +- if [ -n "$(CONFIG_PYLIBFDT)" ]; then \ +- if ! echo "import libfdt" | $(PYTHON3) 2>/dev/null; then \ +- echo '*** pylibfdt does not seem to be available with $(PYTHON3)'; \ +- false; \ +- fi; \ +- fi; \ +- fi; \ +- fi; \ +- fi ++ $(Q)$(MAKE) $(build)=scripts/dtc + + # --------------------------------------------------------------------------- + quiet_cmd_cpp_lds = LDS $@ +--- a/doc/build/gcc.rst ++++ b/doc/build/gcc.rst +@@ -131,27 +131,6 @@ Further important build parameters are + * O= - generate all output files in directory , including .config + * V=1 - verbose build + +-Devicetree compiler +-~~~~~~~~~~~~~~~~~~~ +- +-Boards that use `CONFIG_OF_CONTROL` (i.e. almost all of them) need the +-devicetree compiler (dtc). Those with `CONFIG_PYLIBFDT` need pylibfdt, a Python +-library for accessing devicetree data. Suitable versions of these are included +-in the U-Boot tree in `scripts/dtc` and built automatically as needed. +- +-To use the system versions of these, use the DTC parameter, for example +- +-.. code-block:: bash +- +- DTC=/usr/bin/dtc make +- +-In this case, dtc and pylibfdt are not built. The build checks that the version +-of dtc is new enough. It also makes sure that pylibfdt is present, if needed +-(see `scripts_dtc` in the Makefile). +- +-Note that the :doc:`tools` are always built with the included version of libfdt +-so it is not possible to build U-Boot tools with a system libfdt, at present. +- + Other build targets + ~~~~~~~~~~~~~~~~~~~ + +--- a/dts/Kconfig ++++ b/dts/Kconfig +@@ -5,6 +5,9 @@ + config SUPPORT_OF_CONTROL + bool + ++config DTC ++ bool ++ + config PYLIBFDT + bool + +@@ -21,6 +24,7 @@ menu "Device Tree Control" + + config OF_CONTROL + bool "Run-time configuration via Device Tree" ++ select DTC + select OF_LIBFDT if !OF_PLATDATA + select OF_REAL if !OF_PLATDATA + help +--- a/scripts/Makefile ++++ b/scripts/Makefile +@@ -10,3 +10,4 @@ always := $(hostprogs-y) + + # Let clean descend into subdirs + subdir- += basic kconfig dtc ++subdir-$(CONFIG_DTC) += dtc +--- a/scripts/dtc-version.sh ++++ b/scripts/dtc-version.sh +@@ -10,16 +10,11 @@ + dtc="$*" + + if [ ${#dtc} -eq 0 ]; then +- echo "Error: No dtc command specified" ++ echo "Error: No dtc command specified." + printf "Usage:\n\t$0 \n" + exit 1 + fi + +-if ! which $dtc >/dev/null ; then +- echo "Error: Cannot find dtc: $dtc" +- exit 1 +-fi +- + MAJOR=$($dtc -v | head -1 | awk '{print $NF}' | cut -d . -f 1) + MINOR=$($dtc -v | head -1 | awk '{print $NF}' | cut -d . -f 2) + PATCH=$($dtc -v | head -1 | awk '{print $NF}' | cut -d . -f 3 | cut -d - -f 1) diff --git a/root/package/boot/uboot-rockchip/patches/106-no-kwbimage.patch b/root/package/boot/uboot-rockchip/patches/106-no-kwbimage.patch new file mode 100644 index 00000000..65d14f5b --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/106-no-kwbimage.patch @@ -0,0 +1,10 @@ +--- a/tools/Makefile ++++ b/tools/Makefile +@@ -119,7 +119,6 @@ dumpimage-mkimage-objs := aisimage.o \ + imximage.o \ + imx8image.o \ + imx8mimage.o \ +- kwbimage.o \ + lib/md5.o \ + lpc32xximage.o \ + mxsimage.o \ diff --git a/root/package/boot/uboot-rockchip/patches/202-rockchip-rk3399-split-nanopi-r4s-out-of-evb_rk3399.patch b/root/package/boot/uboot-rockchip/patches/202-rockchip-rk3399-split-nanopi-r4s-out-of-evb_rk3399.patch deleted file mode 100644 index ebdca081..00000000 --- a/root/package/boot/uboot-rockchip/patches/202-rockchip-rk3399-split-nanopi-r4s-out-of-evb_rk3399.patch +++ /dev/null @@ -1,637 +0,0 @@ -From 244492a7a5451eca042d3ec7ccff8de6e23dd288 Mon Sep 17 00:00:00 2001 -From: hmz007 -Date: Fri, 18 Dec 2020 17:10:35 +0800 -Subject: [PATCH 2/4] rockchip: rk3399: split nanopi-r4s out of evb_rk3399 - -Signed-off-by: hmz007 ---- - arch/arm/mach-rockchip/rk3399/Kconfig | 6 + - board/friendlyarm/nanopi4/Kconfig | 15 +++ - board/friendlyarm/nanopi4/MAINTAINERS | 6 + - board/friendlyarm/nanopi4/Makefile | 8 ++ - board/friendlyarm/nanopi4/README | 122 +++++++++++++++++++ - board/friendlyarm/nanopi4/hwrev.c | 149 ++++++++++++++++++++++++ - board/friendlyarm/nanopi4/hwrev.h | 27 +++++ - board/friendlyarm/nanopi4/nanopi4.c | 148 +++++++++++++++++++++++ - configs/nanopi-r4s-4gb-rk3399_defconfig | 4 +- - configs/nanopi-r4s-rk3399_defconfig | 4 +- - drivers/clk/rockchip/clk_rk3399.c | 2 + - include/configs/nanopi4.h | 24 ++++ - 12 files changed, 511 insertions(+), 4 deletions(-) - create mode 100644 board/friendlyarm/nanopi4/Kconfig - create mode 100644 board/friendlyarm/nanopi4/MAINTAINERS - create mode 100644 board/friendlyarm/nanopi4/Makefile - create mode 100644 board/friendlyarm/nanopi4/README - create mode 100644 board/friendlyarm/nanopi4/hwrev.c - create mode 100644 board/friendlyarm/nanopi4/hwrev.h - create mode 100644 board/friendlyarm/nanopi4/nanopi4.c - create mode 100644 include/configs/nanopi4.h - -diff --git a/arch/arm/mach-rockchip/rk3399/Kconfig b/arch/arm/mach-rockchip/rk3399/Kconfig -index 17628f9171..2a44aae43c 100644 ---- a/arch/arm/mach-rockchip/rk3399/Kconfig -+++ b/arch/arm/mach-rockchip/rk3399/Kconfig -@@ -109,6 +109,11 @@ config TARGET_ROC_PC_RK3399 - * wide voltage input(5V-15V), dual cell battery - * Wifi/BT accessible via expansion board M.2 - -+config TARGET_NANOPI4 -+ bool "FriendlyElec NanoPi 4 Series" -+ help -+ Support for FriendlyElec boards based on RK3399. -+ - endchoice - - config ROCKCHIP_BOOT_MODE_REG -@@ -152,6 +157,7 @@ config SYS_BOOTCOUNT_ADDR - endif # BOOTCOUNT_LIMIT - - source "board/firefly/roc-pc-rk3399/Kconfig" -+source "board/friendlyarm/nanopi4/Kconfig" - source "board/google/gru/Kconfig" - source "board/pine64/pinebook-pro-rk3399/Kconfig" - source "board/pine64/rockpro64_rk3399/Kconfig" -diff --git a/board/friendlyarm/nanopi4/Kconfig b/board/friendlyarm/nanopi4/Kconfig -new file mode 100644 -index 0000000000..f3f9dd7b56 ---- /dev/null -+++ b/board/friendlyarm/nanopi4/Kconfig -@@ -0,0 +1,15 @@ -+if TARGET_NANOPI4 -+ -+config SYS_BOARD -+ default "nanopi4" -+ -+config SYS_VENDOR -+ default "friendlyarm" -+ -+config SYS_CONFIG_NAME -+ default "nanopi4" -+ -+config BOARD_SPECIFIC_OPTIONS -+ def_bool y -+ -+endif -diff --git a/board/friendlyarm/nanopi4/MAINTAINERS b/board/friendlyarm/nanopi4/MAINTAINERS -new file mode 100644 -index 0000000000..b4c35701d6 ---- /dev/null -+++ b/board/friendlyarm/nanopi4/MAINTAINERS -@@ -0,0 +1,6 @@ -+NanoPi 4 Series -+M: -+S: Maintained -+F: board/friendlyarm/nanopi4/ -+F: include/configs/nanopi4.h -+F: configs/nanopi4_defconfig -diff --git a/board/friendlyarm/nanopi4/Makefile b/board/friendlyarm/nanopi4/Makefile -new file mode 100644 -index 0000000000..33a1466567 ---- /dev/null -+++ b/board/friendlyarm/nanopi4/Makefile -@@ -0,0 +1,8 @@ -+# -+# Copyright (C) Guangzhou FriendlyELEC Computer Tech. Co., Ltd. -+# (http://www.friendlyarm.com) -+# -+# SPDX-License-Identifier: GPL-2.0+ -+# -+ -+obj-y += nanopi4.o hwrev.o -diff --git a/board/friendlyarm/nanopi4/README b/board/friendlyarm/nanopi4/README -new file mode 100644 -index 0000000000..c6f58203eb ---- /dev/null -+++ b/board/friendlyarm/nanopi4/README -@@ -0,0 +1,122 @@ -+Introduction -+============ -+ -+RK3399 key features we might use in U-Boot: -+* CPU: ARMv8 64bit Big-Little architecture, -+* Big: dual-core Cortex-A72 -+* Little: quad-core Cortex-A53 -+* IRAM: 200KB -+* DRAM: 4GB-128MB dual-channel -+* eMMC: support eMMC 5.0/5.1, suport HS400, HS200, DDR50 -+* SD/MMC: support SD 3.0, MMC 4.51 -+* USB: USB3.0 type-C port *2 with dwc3 controller -+* USB2.0 EHCI host port *2 -+* Display: RGB/HDMI/DP/MIPI/EDP -+ -+evb key features: -+* regulator: pwm regulator for CPU B/L -+* PMIC: rk808 -+* debug console: UART2 -+ -+In order to support Arm Trust Firmware(ATF), we can use either SPL or -+miniloader from rockchip to do: -+* do DRAM init -+* load and verify ATF image -+* load and verify U-Boot image -+ -+Here is the step-by-step to boot to U-Boot on rk3399. -+ -+Get the Source and prebuild binary -+================================== -+ -+ > mkdir ~/evb_rk3399 -+ > cd ~/evb_rk3399 -+ > git clone https://github.com/ARM-software/arm-trusted-firmware.git -+ > git clone https://github.com/rockchip-linux/rkbin.git -+ > git clone https://github.com/rockchip-linux/rkdeveloptool.git -+ -+ -+Compile ATF -+=========== -+ -+ > cd arm-trusted-firmware -+ > make realclean -+ > make CROSS_COMPILE=aarch64-linux-gnu- PLAT=rk3399 bl31 -+ -+ Get bl31.elf in this step, copy it to U-Boot root dir: -+ > cp build/rk3399/release/bl31/bl31.elf ../u-boot/ -+ -+ Or you can get the bl31.elf directly from Rockchip: -+ > cp rkbin/rk33/rk3399_bl31_v1.00.elf ../u-boot/bl31.elf -+ -+ -+Compile U-Boot -+============== -+ -+ > cd ../u-boot -+ > export CROSS_COMPILE=aarch64-linux-gnu- -+ > make evb-rk3399_defconfig -+ for firefly-rk3399, use below instead: -+ > make firefly-rk3399_defconfig -+ > make -+ > make u-boot.itb -+ -+ Get spl/u-boot-spl.bin and u-boot.itb in this step. -+ -+Compile rkdeveloptool -+===================== -+ -+Get rkdeveloptool installed on your Host in this step. -+ -+Follow instructions in latest README, example: -+ > cd ../rkdeveloptool -+ > autoreconf -i -+ > ./configure -+ > make -+ > sudo make install -+ -+Both origin binaries and Tool are ready now, choose either option 1 or -+option 2 to deploy U-Boot. -+ -+Package the image -+================= -+ -+Package the image for U-Boot SPL(option 1) -+-------------------------------- -+ > cd .. -+ > tools/mkimage -n rk3399 -T rksd -d spl/u-boot-spl.bin idbspl.img -+ -+ Get idbspl.img in this step. -+ -+Package the image for Rockchip miniloader(option 2) -+------------------------------------------ -+ > cd .. -+ > cp arm-trusted-firmware/build/rk3399/release/bl31.elf rkbin/rk33 -+ > ./rkbin/tools/trust_merger rkbin/tools/RK3399TRUST.ini -+ > ./rkbin/tools/loaderimage --pack --uboot u-boot/u-boot-dtb.bin uboot.img -+ -+ Get trust.img and uboot.img in this step. -+ -+Flash the image to eMMC -+======================= -+ -+Flash the image with U-Boot SPL(option 1) -+------------------------------- -+Power on(or reset with RESET KEY) with MASKROM KEY preesed, and then: -+ > rkdeveloptool db rkbin/rk33/rk3399_loader_v1.08.106.bin -+ > rkdeveloptool wl 64 u-boot/idbspl.img -+ > rkdeveloptool wl 0x4000 u-boot/u-boot.itb -+ > rkdeveloptool rd -+ -+Flash the image with Rockchip miniloader(option 2) -+---------------------------------------- -+Power on(or reset with RESET KEY) with MASKROM KEY preesed, and then: -+ > rkdeveloptool db rkbin/rk33/rk3399_loader_v1.08.106.bin -+ > rkdeveloptool ul rkbin/rk33/rk3399_loader_v1.08.106.bin -+ > rkdeveloptool wl 0x4000 u-boot/uboot.img -+ > rkdeveloptool wl 0x6000 u-boot/trust.img -+ > rkdeveloptool rd -+ -+You should be able to get U-Boot log in console/UART2(baurdrate 1500000) -+For more detail, please reference to: -+http://opensource.rock-chips.com/wiki_Boot_option -diff --git a/board/friendlyarm/nanopi4/hwrev.c b/board/friendlyarm/nanopi4/hwrev.c -new file mode 100644 -index 0000000000..9199a927ee ---- /dev/null -+++ b/board/friendlyarm/nanopi4/hwrev.c -@@ -0,0 +1,149 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Copyright (c) 2020 FriendlyElec Computer Tech. Co., Ltd. -+ * (http://www.friendlyarm.com) -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* -+ * ID info: -+ * ID : Volts : ADC value : Bucket -+ * == ===== ========= =========== -+ * 0 : 0.102V: 58 : 0 - 81 -+ * 1 : 0.211V: 120 : 82 - 150 -+ * 2 : 0.319V: 181 : 151 - 211 -+ * 3 : 0.427V: 242 : 212 - 274 -+ * 4 : 0.542V: 307 : 275 - 342 -+ * 5 : 0.666V: 378 : 343 - 411 -+ * 6 : 0.781V: 444 : 412 - 477 -+ * 7 : 0.900V: 511 : 478 - 545 -+ * 8 : 1.023V: 581 : 546 - 613 -+ * 9 : 1.137V: 646 : 614 - 675 -+ * 10 : 1.240V: 704 : 676 - 733 -+ * 11 : 1.343V: 763 : 734 - 795 -+ * 12 : 1.457V: 828 : 796 - 861 -+ * 13 : 1.576V: 895 : 862 - 925 -+ * 14 : 1.684V: 956 : 926 - 989 -+ * 15 : 1.800V: 1023 : 990 - 1023 -+ */ -+static const int id_readings[] = { -+ 81, 150, 211, 274, 342, 411, 477, 545, -+ 613, 675, 733, 795, 861, 925, 989, 1023 -+}; -+ -+static int cached_board_id = -1; -+ -+#define SARADC_BASE 0xFF100000 -+#define SARADC_DATA (SARADC_BASE + 0) -+#define SARADC_CTRL (SARADC_BASE + 8) -+ -+static u32 get_saradc_value(int chn) -+{ -+ int timeout = 0; -+ u32 adc_value = 0; -+ -+ writel(0, SARADC_CTRL); -+ udelay(2); -+ -+ writel(0x28 | chn, SARADC_CTRL); -+ udelay(50); -+ -+ timeout = 0; -+ do { -+ if (readl(SARADC_CTRL) & 0x40) { -+ adc_value = readl(SARADC_DATA) & 0x3FF; -+ goto stop_adc; -+ } -+ -+ udelay(10); -+ } while (timeout++ < 100); -+ -+stop_adc: -+ writel(0, SARADC_CTRL); -+ -+ return adc_value; -+} -+ -+static uint32_t get_adc_index(int chn) -+{ -+ int i; -+ int adc_reading; -+ -+ if (cached_board_id != -1) -+ return cached_board_id; -+ -+ adc_reading = get_saradc_value(chn); -+ for (i = 0; i < ARRAY_SIZE(id_readings); i++) { -+ if (adc_reading <= id_readings[i]) { -+ debug("ADC reading %d, ID %d\n", adc_reading, i); -+ cached_board_id = i; -+ return i; -+ } -+ } -+ -+ /* should die for impossible value */ -+ return 0; -+} -+ -+/* -+ * Board revision list: -+ * 0b00 - NanoPC-T4 -+ * 0b01 - NanoPi M4 -+ * -+ * Extended by ADC_IN4 -+ * Group A: -+ * 0x04 - NanoPi NEO4 -+ * 0x06 - SOC-RK3399 -+ * -+ * Group B: -+ * 0x21 - NanoPi M4 Ver2.0 -+ */ -+static int pcb_rev = -1; -+ -+void bd_hwrev_init(void) -+{ -+#define GPIO4_BASE 0xff790000 -+ struct rockchip_gpio_regs *regs = (void *)GPIO4_BASE; -+ -+#ifdef CONFIG_SPL_BUILD -+ struct udevice *dev; -+ -+ if (uclass_get_device_by_driver(UCLASS_CLK, -+ DM_DRIVER_GET(clk_rk3399), &dev)) -+ return; -+#endif -+ -+ if (pcb_rev >= 0) -+ return; -+ -+ /* D1, D0: input mode */ -+ clrbits_le32(®s->swport_ddr, (0x3 << 24)); -+ pcb_rev = (readl(®s->ext_port) >> 24) & 0x3; -+ -+ if (pcb_rev == 0x3) { -+ /* Revision group A: 0x04 ~ 0x13 */ -+ pcb_rev = 0x4 + get_adc_index(4); -+ -+ } else if (pcb_rev == 0x1) { -+ int idx = get_adc_index(4); -+ -+ /* Revision group B: 0x21 ~ 0x2f */ -+ if (idx > 0) { -+ pcb_rev = 0x20 + idx; -+ } -+ } -+} -+ -+/* To override __weak symbols */ -+u32 get_board_rev(void) -+{ -+ return pcb_rev; -+} -+ -diff --git a/board/friendlyarm/nanopi4/hwrev.h b/board/friendlyarm/nanopi4/hwrev.h -new file mode 100644 -index 0000000000..23b3c7a557 ---- /dev/null -+++ b/board/friendlyarm/nanopi4/hwrev.h -@@ -0,0 +1,27 @@ -+/* -+ * Copyright (C) Guangzhou FriendlyARM Computer Tech. Co., Ltd. -+ * (http://www.friendlyarm.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version 2 -+ * of the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, you can access it online at -+ * http://www.gnu.org/licenses/gpl-2.0.html. -+ */ -+ -+#ifndef __BD_HW_REV_H__ -+#define __BD_HW_REV_H__ -+ -+extern void bd_hwrev_config_gpio(void); -+extern void bd_hwrev_init(void); -+extern u32 get_board_rev(void); -+ -+#endif /* __BD_HW_REV_H__ */ -diff --git a/board/friendlyarm/nanopi4/nanopi4.c b/board/friendlyarm/nanopi4/nanopi4.c -new file mode 100644 -index 0000000000..a140370ca2 ---- /dev/null -+++ b/board/friendlyarm/nanopi4/nanopi4.c -@@ -0,0 +1,148 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Copyright (c) 2020 FriendlyElec Computer Tech. Co., Ltd. -+ * (http://www.friendlyarm.com) -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CONFIG_MISC_INIT_R -+static void setup_iodomain(void) -+{ -+ struct rk3399_grf_regs *grf = -+ syscon_get_first_range(ROCKCHIP_SYSCON_GRF); -+ -+ /* BT565 and AUDIO is in 1.8v domain */ -+ rk_setreg(&grf->io_vsel, BIT(0) | BIT(1)); -+} -+ -+static int __maybe_unused mac_read_from_generic_eeprom(u8 *addr) -+{ -+ struct udevice *i2c_dev; -+ int ret; -+ -+ /* Microchip 24AA02xxx EEPROMs with EUI-48 Node Identity */ -+ ret = i2c_get_chip_for_busnum(2, 0x51, 1, &i2c_dev); -+ if (!ret) -+ ret = dm_i2c_read(i2c_dev, 0xfa, addr, 6); -+ -+ return ret; -+} -+ -+static void setup_macaddr(void) -+{ -+#if CONFIG_IS_ENABLED(CMD_NET) -+ int ret; -+ const char *cpuid = env_get("cpuid#"); -+ u8 hash[SHA256_SUM_LEN]; -+ int size = sizeof(hash); -+ u8 mac_addr[6]; -+ int from_eeprom = 0; -+ int lockdown = 0; -+ -+#ifndef CONFIG_ENV_IS_NOWHERE -+ lockdown = env_get_yesno("lockdown") == 1; -+#endif -+ if (lockdown && env_get("ethaddr")) -+ return; -+ -+ ret = mac_read_from_generic_eeprom(mac_addr); -+ if (!ret && is_valid_ethaddr(mac_addr)) { -+ eth_env_set_enetaddr("ethaddr", mac_addr); -+ from_eeprom = 1; -+ } -+ -+ if (!cpuid) { -+ debug("%s: could not retrieve 'cpuid#'\n", __func__); -+ return; -+ } -+ -+ ret = hash_block("sha256", (void *)cpuid, strlen(cpuid), hash, &size); -+ if (ret) { -+ debug("%s: failed to calculate SHA256\n", __func__); -+ return; -+ } -+ -+ /* Copy 6 bytes of the hash to base the MAC address on */ -+ memcpy(mac_addr, hash, 6); -+ -+ /* Make this a valid MAC address and set it */ -+ mac_addr[0] &= 0xfe; /* clear multicast bit */ -+ mac_addr[0] |= 0x02; /* set local assignment bit (IEEE802) */ -+ -+ if (from_eeprom) { -+ eth_env_set_enetaddr("eth1addr", mac_addr); -+ } else { -+ eth_env_set_enetaddr("ethaddr", mac_addr); -+ -+ if (lockdown && env_get("eth1addr")) -+ return; -+ -+ /* Ugly, copy another 4 bytes to generate a similar address */ -+ memcpy(mac_addr + 2, hash + 8, 4); -+ if (!memcmp(hash + 2, hash + 8, 4)) -+ mac_addr[5] ^= 0xff; -+ -+ eth_env_set_enetaddr("eth1addr", mac_addr); -+ } -+#endif -+ -+ return; -+} -+ -+int misc_init_r(void) -+{ -+ const u32 cpuid_offset = 0x7; -+ const u32 cpuid_length = 0x10; -+ u8 cpuid[cpuid_length]; -+ int ret; -+ -+ setup_iodomain(); -+ -+ ret = rockchip_cpuid_from_efuse(cpuid_offset, cpuid_length, cpuid); -+ if (ret) -+ return ret; -+ -+ ret = rockchip_cpuid_set(cpuid, cpuid_length); -+ if (ret) -+ return ret; -+ -+ setup_macaddr(); -+ bd_hwrev_init(); -+ -+ return 0; -+} -+#endif -+ -+#ifdef CONFIG_SERIAL_TAG -+void get_board_serial(struct tag_serialnr *serialnr) -+{ -+ char *serial_string; -+ u64 serial = 0; -+ -+ serial_string = env_get("serial#"); -+ -+ if (serial_string) -+ serial = simple_strtoull(serial_string, NULL, 16); -+ -+ serialnr->high = (u32)(serial >> 32); -+ serialnr->low = (u32)(serial & 0xffffffff); -+} -+#endif -diff --git a/configs/nanopi-r4s-rk3399_defconfig b/configs/nanopi-r4s-rk3399_defconfig -index 034241f209..b67f7c0dc9 100644 ---- a/configs/nanopi-r4s-rk3399_defconfig -+++ b/configs/nanopi-r4s-rk3399_defconfig -@@ -4,13 +4,13 @@ CONFIG_SYS_TEXT_BASE=0x00200000 - CONFIG_NR_DRAM_BANKS=1 - CONFIG_ENV_OFFSET=0x3F8000 --CONFIG_DEFAULT_DEVICE_TREE="rk3399-nanopi-r4s" - CONFIG_ROCKCHIP_RK3399=y --CONFIG_TARGET_EVB_RK3399=y -+CONFIG_TARGET_NANOPI4=y - CONFIG_DEBUG_UART_BASE=0xFF1A0000 - CONFIG_DEBUG_UART_CLOCK=24000000 -+CONFIG_DEFAULT_DEVICE_TREE="rk3399-nanopi-r4s" - CONFIG_DEBUG_UART=y - CONFIG_DEFAULT_FDT_FILE="rockchip/rk3399-nanopi-r4s.dtb" --CONFIG_DISPLAY_BOARDINFO_LATE=y -+CONFIG_MISC_INIT_R=y - # CONFIG_SPL_RAW_IMAGE_SUPPORT is not set - CONFIG_SPL_STACK_R=y - CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x10000 -diff --git a/drivers/clk/rockchip/clk_rk3399.c b/drivers/clk/rockchip/clk_rk3399.c -index 22c373a623..38975c0c65 100644 ---- a/drivers/clk/rockchip/clk_rk3399.c -+++ b/drivers/clk/rockchip/clk_rk3399.c -@@ -1351,6 +1351,8 @@ static void rkclk_init(struct rockchip_cru *cru) - pclk_div << PCLK_PERILP1_DIV_CON_SHIFT | - hclk_div << HCLK_PERILP1_DIV_CON_SHIFT | - HCLK_PERILP1_PLL_SEL_GPLL << HCLK_PERILP1_PLL_SEL_SHIFT); -+ -+ rk3399_saradc_set_clk(cru, 1000000); - } - #endif - -diff --git a/include/configs/nanopi4.h b/include/configs/nanopi4.h -new file mode 100644 -index 0000000000..a86d38976a ---- /dev/null -+++ b/include/configs/nanopi4.h -@@ -0,0 +1,24 @@ -+/* SPDX-License-Identifier: GPL-2.0+ */ -+/* -+ * Copyright (C) Guangzhou FriendlyELEC Computer Tech. Co., Ltd. -+ * (http://www.friendlyarm.com) -+ * -+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd -+ */ -+ -+#ifndef __CONFIG_NANOPI4_H__ -+#define __CONFIG_NANOPI4_H__ -+ -+#define ROCKCHIP_DEVICE_SETTINGS \ -+ "stdin=serial,usbkbd\0" \ -+ "stdout=serial,vidconsole\0" \ -+ "stderr=serial,vidconsole\0" -+ -+#include -+ -+#define SDRAM_BANK_SIZE (2UL << 30) -+ -+#define CONFIG_SERIAL_TAG -+#define CONFIG_REVISION_TAG -+ -+#endif --- -2.25.1 - diff --git a/root/package/boot/uboot-rockchip/patches/203-ram-rk3399-Add-support-for-multiple-DDR-types.patch b/root/package/boot/uboot-rockchip/patches/203-ram-rk3399-Add-support-for-multiple-DDR-types.patch deleted file mode 100644 index a9795849..00000000 --- a/root/package/boot/uboot-rockchip/patches/203-ram-rk3399-Add-support-for-multiple-DDR-types.patch +++ /dev/null @@ -1,275 +0,0 @@ -From 1bc90230df5cd55513268f2f7a43abdbad1161b5 Mon Sep 17 00:00:00 2001 -From: hmz007 -Date: Sat, 19 Dec 2020 19:39:14 +0800 -Subject: [PATCH 3/4] ram: rk3399: Add support for multiple DDR types - -Move rockchip,sdram-params to named subnode to include -multiple sdram parameters, and then read the parameters -(by subnode name, first subnode or current node) before -rk3399_dmc_init(). - -Signed-off-by: hmz007 ---- - arch/arm/dts/rk3399-sdram-ddr3-1333.dtsi | 6 ++- - arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi | 5 +- - arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi | 6 ++- - .../arm/dts/rk3399-sdram-lpddr3-2GB-1600.dtsi | 3 ++ - .../arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi | 3 ++ - .../rk3399-sdram-lpddr3-samsung-4GB-1866.dtsi | 3 ++ - arch/arm/dts/rk3399-sdram-lpddr4-100.dtsi | 3 ++ - drivers/ram/rockchip/sdram_rk3399.c | 49 +++++++++++++++---- - 8 files changed, 64 insertions(+), 14 deletions(-) - -diff --git a/arch/arm/dts/rk3399-sdram-ddr3-1333.dtsi b/arch/arm/dts/rk3399-sdram-ddr3-1333.dtsi -index 7fae249536..dad5b7fbd4 100644 ---- a/arch/arm/dts/rk3399-sdram-ddr3-1333.dtsi -+++ b/arch/arm/dts/rk3399-sdram-ddr3-1333.dtsi -@@ -4,7 +4,9 @@ - */ - - &dmc { -- rockchip,sdram-params = < -+ ddr3-1333 { -+ u-boot,dm-pre-reloc; -+ rockchip,sdram-params = < - 0x1 - 0xa - 0x3 -@@ -1536,5 +1538,5 @@ - 0x01010000 - 0x00000000 - >; -+ }; - }; -- -diff --git a/arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi b/arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi -index 23c7c34a9a..238f667a76 100644 ---- a/arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi -+++ b/arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi -@@ -4,7 +4,9 @@ - */ - - &dmc { -- rockchip,sdram-params = < -+ ddr3-1600 { -+ u-boot,dm-pre-reloc; -+ rockchip,sdram-params = < - 0x1 - 0xa - 0x3 -@@ -1536,4 +1538,5 @@ - 0x01010000 - 0x00000000 - >; -+ }; - }; -diff --git a/arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi b/arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi -index ea029ca90a..7f6b95fe42 100644 ---- a/arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi -+++ b/arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi -@@ -4,7 +4,9 @@ - */ - - &dmc { -- rockchip,sdram-params = < -+ ddr3-1866 { -+ u-boot,dm-pre-reloc; -+ rockchip,sdram-params = < - 0x1 - 0xa - 0x3 -@@ -1536,5 +1538,5 @@ - 0x01010000 - 0x00000000 - >; -+ }; - }; -- -diff --git a/arch/arm/dts/rk3399-sdram-lpddr3-2GB-1600.dtsi b/arch/arm/dts/rk3399-sdram-lpddr3-2GB-1600.dtsi -index 7296dbb80e..a83564794e 100644 ---- a/arch/arm/dts/rk3399-sdram-lpddr3-2GB-1600.dtsi -+++ b/arch/arm/dts/rk3399-sdram-lpddr3-2GB-1600.dtsi -@@ -5,6 +5,8 @@ - */ - - &dmc { -+ lpddr3-2GB-1600 { -+ u-boot,dm-pre-reloc; - rockchip,sdram-params = < - 0x1 - 0xa -@@ -1537,4 +1539,5 @@ - 0x01010000 - 0x00000000 - >; -+ }; - }; -diff --git a/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi b/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi -index bf429c21e4..537936c6fb 100644 ---- a/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi -+++ b/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi -@@ -4,6 +4,8 @@ - */ - - &dmc { -+ lpddr3-4GB-1600 { -+ u-boot,dm-pre-reloc; - rockchip,sdram-params = < - 0x2 - 0xa -@@ -1536,4 +1538,5 @@ - 0x01010000 - 0x00000000 - >; -+ }; - }; -diff --git a/arch/arm/dts/rk3399-sdram-lpddr3-samsung-4GB-1866.dtsi b/arch/arm/dts/rk3399-sdram-lpddr3-samsung-4GB-1866.dtsi -index 96f459fd0b..a0acdb5add 100644 ---- a/arch/arm/dts/rk3399-sdram-lpddr3-samsung-4GB-1866.dtsi -+++ b/arch/arm/dts/rk3399-sdram-lpddr3-samsung-4GB-1866.dtsi -@@ -4,6 +4,8 @@ - */ - - &dmc { -+ lpddr3-samsung-4GB-1866 { -+ u-boot,dm-pre-reloc; - rockchip,sdram-params = < - 0x2 - 0xa -@@ -1543,4 +1545,5 @@ - 0x01010000 /* DENALI_PHY_957_DATA */ - 0x00000000 /* DENALI_PHY_958_DATA */ - >; -+ }; - }; -diff --git a/arch/arm/dts/rk3399-sdram-lpddr4-100.dtsi b/arch/arm/dts/rk3399-sdram-lpddr4-100.dtsi -index f0c478d189..21d212236f 100644 ---- a/arch/arm/dts/rk3399-sdram-lpddr4-100.dtsi -+++ b/arch/arm/dts/rk3399-sdram-lpddr4-100.dtsi -@@ -6,6 +6,8 @@ - */ - - &dmc { -+ lpddr4-100 { -+ u-boot,dm-pre-reloc; - rockchip,sdram-params = < - 0x2 - 0xa -@@ -1538,4 +1540,5 @@ - 0x01010000 - 0x00000000 - >; -+ }; - }; -diff --git a/drivers/ram/rockchip/sdram_rk3399.c b/drivers/ram/rockchip/sdram_rk3399.c -index 530c8a2f40..db30105989 100644 ---- a/drivers/ram/rockchip/sdram_rk3399.c -+++ b/drivers/ram/rockchip/sdram_rk3399.c -@@ -1625,7 +1625,6 @@ static void set_ddr_stride(struct rk3399_pmusgrf_regs *pmusgrf, u32 stride) - rk_clrsetreg(&pmusgrf->soc_con4, 0x1f << 10, stride << 10); - } - --#if !defined(CONFIG_RAM_RK3399_LPDDR4) - static int data_training_first(struct dram_info *dram, u32 channel, u8 rank, - struct rk3399_sdram_params *params) - { -@@ -1715,8 +1714,8 @@ void modify_param(const struct chan_info *chan, - clrsetbits_le32(&denali_pi_params[76], 0x1 << 24, 0x1 << 24); - clrsetbits_le32(&denali_pi_params[77], 0x1, 0x1); - } --#else - -+#if defined(CONFIG_RAM_RK3399_LPDDR4) - struct rk3399_sdram_params dfs_cfgs_lpddr4[] = { - #include "sdram-rk3399-lpddr4-400.inc" - #include "sdram-rk3399-lpddr4-800.inc" -@@ -3011,20 +3010,40 @@ static int sdram_init(struct dram_info *dram, - return 0; - } - -+__weak const char *rk3399_get_ddrtype(void) -+{ -+ return NULL; -+} -+ - static int rk3399_dmc_of_to_plat(struct udevice *dev) - { - #if !CONFIG_IS_ENABLED(OF_PLATDATA) - struct rockchip_dmc_plat *plat = dev_get_plat(dev); -+ ofnode node = { .np = NULL }; -+ const char *name; - int ret; - -- ret = dev_read_u32_array(dev, "rockchip,sdram-params", -- (u32 *)&plat->sdram_params, -- sizeof(plat->sdram_params) / sizeof(u32)); -+ name = rk3399_get_ddrtype(); -+ if (name) -+ node = dev_read_subnode(dev, name); -+ if (!ofnode_valid(node)) { -+ debug("Failed to read subnode %s\n", name); -+ node = dev_read_first_subnode(dev); -+ } -+ -+ /* fallback to current node */ -+ if (!ofnode_valid(node)) -+ node = dev_ofnode(dev); -+ -+ ret = ofnode_read_u32_array(node, "rockchip,sdram-params", -+ (u32 *)&plat->sdram_params, -+ sizeof(plat->sdram_params) / sizeof(u32)); - if (ret) { - printf("%s: Cannot read rockchip,sdram-params %d\n", - __func__, ret); - return ret; - } -+ - ret = regmap_init_mem(dev_ofnode(dev), &plat->map); - if (ret) - printf("%s: regmap failed %d\n", __func__, ret); -@@ -3051,18 +3070,20 @@ static int conv_of_platdata(struct udevice *dev) - #endif - - static const struct sdram_rk3399_ops rk3399_ops = { --#if !defined(CONFIG_RAM_RK3399_LPDDR4) - .data_training_first = data_training_first, - .set_rate_index = switch_to_phy_index1, - .modify_param = modify_param, - .get_phy_index_params = get_phy_index_params, --#else -+}; -+ -+#if defined(CONFIG_RAM_RK3399_LPDDR4) -+static const struct sdram_rk3399_ops lpddr4_ops = { - .data_training_first = lpddr4_mr_detect, - .set_rate_index = lpddr4_set_rate, - .modify_param = lpddr4_modify_param, - .get_phy_index_params = lpddr4_get_phy_index_params, --#endif - }; -+#endif - - static int rk3399_dmc_init(struct udevice *dev) - { -@@ -3081,7 +3102,17 @@ static int rk3399_dmc_init(struct udevice *dev) - return ret; - #endif - -- priv->ops = &rk3399_ops; -+ if (params->base.dramtype == LPDDR4) { -+#if defined(CONFIG_RAM_RK3399_LPDDR4) -+ priv->ops = &lpddr4_ops; -+#else -+ printf("LPDDR4 support is disable\n"); -+ return -EINVAL; -+#endif -+ } else { -+ priv->ops = &rk3399_ops; -+ } -+ - priv->cic = syscon_get_first_range(ROCKCHIP_SYSCON_CIC); - priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); - priv->pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU); --- -2.25.1 - diff --git a/root/package/boot/uboot-rockchip/patches/203-rock64pro-disable-CONFIG_USE_PREBOOT.patch b/root/package/boot/uboot-rockchip/patches/203-rock64pro-disable-CONFIG_USE_PREBOOT.patch new file mode 100644 index 00000000..f6308183 --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/203-rock64pro-disable-CONFIG_USE_PREBOOT.patch @@ -0,0 +1,27 @@ +From 2114d68b3c755ec8043ae9e43ac8e9753e0cec84 Mon Sep 17 00:00:00 2001 +From: Marty Jones +Date: Sun, 17 Jan 2021 15:26:09 -0500 +Subject: [PATCH] rockpro64: disable CONFIG_USE_PREBOOT + +On commit https://github.com/u-boot/u-boot/commit/f81f9f0ebac596bae7f27db095f4f0272b606cc3 +CONFIG_USE_PREBOOT was enabled on the RockPro64. + +When the board is booting, U-Boot hangs as soon as it disables the USB +controller. This is a workaround until a final solution is deployed +upstream. + +Signed-off-by: Marty Jones +--- + configs/rockpro64-rk3399_defconfig | 1 - + 1 file changed, 1 deletion(-) + +--- a/configs/rockpro64-rk3399_defconfig ++++ b/configs/rockpro64-rk3399_defconfig +@@ -12,7 +12,6 @@ CONFIG_SPL_SPI_FLASH_SUPPORT=y + CONFIG_SPL_SPI_SUPPORT=y + CONFIG_DEFAULT_DEVICE_TREE="rk3399-rockpro64" + CONFIG_DEBUG_UART=y +-CONFIG_USE_PREBOOT=y + CONFIG_DEFAULT_FDT_FILE="rockchip/rk3399-rockpro64.dtb" + CONFIG_DISPLAY_BOARDINFO_LATE=y + CONFIG_MISC_INIT_R=y diff --git a/root/package/boot/uboot-rockchip/patches/204-board-nanopi4-unify-1GB-4GB-variants-of-R4S.patch b/root/package/boot/uboot-rockchip/patches/204-board-nanopi4-unify-1GB-4GB-variants-of-R4S.patch deleted file mode 100644 index 07ce2410..00000000 --- a/root/package/boot/uboot-rockchip/patches/204-board-nanopi4-unify-1GB-4GB-variants-of-R4S.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 317331b3d7ddcf2a5e7b5a9002ac559627000032 Mon Sep 17 00:00:00 2001 -From: hmz007 -Date: Sat, 19 Dec 2020 20:39:29 +0800 -Subject: [PATCH 4/4] board: nanopi4: unify 1GB/4GB variants of R4S - -Signed-off-by: hmz007 ---- - .../arm/dts/rk3399-nanopi-r4s-4gb-u-boot.dtsi | 8 -- - arch/arm/dts/rk3399-nanopi-r4s-4gb.dts | 114 ------------------ - arch/arm/dts/rk3399-nanopi-r4s-u-boot.dtsi | 2 + - board/friendlyarm/nanopi4/hwrev.c | 36 ++++++ - configs/nanopi-r4s-4gb-rk3399_defconfig | 63 ---------- - configs/nanopi-r4s-rk3399_defconfig | 1 + - 6 files changed, 39 insertions(+), 185 deletions(-) - delete mode 100644 arch/arm/dts/rk3399-nanopi-r4s-4gb-u-boot.dtsi - delete mode 100644 arch/arm/dts/rk3399-nanopi-r4s-4gb.dts - delete mode 100644 configs/nanopi-r4s-4gb-rk3399_defconfig - -diff --git a/arch/arm/dts/rk3399-nanopi-r4s-u-boot.dtsi b/arch/arm/dts/rk3399-nanopi-r4s-u-boot.dtsi -index eb0aca4758..9369a7022a 100644 ---- a/arch/arm/dts/rk3399-nanopi-r4s-u-boot.dtsi -+++ b/arch/arm/dts/rk3399-nanopi-r4s-u-boot.dtsi -@@ -4,4 +4,6 @@ - */ - - #include "rk3399-nanopi4-u-boot.dtsi" - #include "rk3399-sdram-lpddr4-100.dtsi" -+#include "rk3399-sdram-lpddr3-samsung-4GB-1866.dtsi" -+#include "rk3399-sdram-ddr3-1866.dtsi" -diff --git a/board/friendlyarm/nanopi4/hwrev.c b/board/friendlyarm/nanopi4/hwrev.c -index 9199a927ee..812fcef9c7 100644 ---- a/board/friendlyarm/nanopi4/hwrev.c -+++ b/board/friendlyarm/nanopi4/hwrev.c -@@ -101,9 +101,13 @@ static uint32_t get_adc_index(int chn) - * Group A: - * 0x04 - NanoPi NEO4 - * 0x06 - SOC-RK3399 -+ * 0x07 - SOC-RK3399 V2 -+ * 0x09 - NanoPi R4S 1GB -+ * 0x0A - NanoPi R4S 4GB - * - * Group B: - * 0x21 - NanoPi M4 Ver2.0 -+ * 0x22 - NanoPi M4B - */ - static int pcb_rev = -1; - -@@ -141,6 +145,38 @@ void bd_hwrev_init(void) - } - } - -+#ifdef CONFIG_SPL_BUILD -+static struct board_ddrtype { -+ int rev; -+ const char *type; -+} ddrtypes[] = { -+ { 0x00, "lpddr3-samsung-4GB-1866" }, -+ { 0x01, "lpddr3-samsung-4GB-1866" }, -+ { 0x04, "ddr3-1866" }, -+ { 0x06, "ddr3-1866" }, -+ { 0x07, "lpddr4-100" }, -+ { 0x09, "ddr3-1866" }, -+ { 0x0a, "lpddr4-100" }, -+ { 0x21, "lpddr4-100" }, -+ { 0x22, "ddr3-1866" }, -+}; -+ -+const char *rk3399_get_ddrtype(void) { -+ int i; -+ -+ bd_hwrev_init(); -+ printf("Board: rev%02x\n", pcb_rev); -+ -+ for (i = 0; i < ARRAY_SIZE(ddrtypes); i++) { -+ if (ddrtypes[i].rev == pcb_rev) -+ return ddrtypes[i].type; -+ } -+ -+ /* fallback to first subnode (ie, first included dtsi) */ -+ return NULL; -+} -+#endif -+ - /* To override __weak symbols */ - u32 get_board_rev(void) - { --- -2.25.1 - diff --git a/root/package/boot/uboot-rockchip/patches/301-arm64-dts-rockchip-Add-GuangMiao-G4C-support.patch b/root/package/boot/uboot-rockchip/patches/301-arm64-dts-rockchip-Add-GuangMiao-G4C-support.patch new file mode 100644 index 00000000..fae269b7 --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/301-arm64-dts-rockchip-Add-GuangMiao-G4C-support.patch @@ -0,0 +1,740 @@ +--- a/arch/arm/dts/Makefile ++++ b/arch/arm/dts/Makefile +@@ -124,6 +124,7 @@ dtb-$(CONFIG_ROCKCHIP_RK3399) += \ + rk3399-ficus.dtb \ + rk3399-firefly.dtb \ + rk3399-gru-bob.dtb \ ++ rk3399-guangmiao-g4c.dtb \ + rk3399-gru-kevin.dtb \ + rk3399-khadas-edge.dtb \ + rk3399-khadas-edge-captain.dtb \ +--- /dev/null ++++ b/configs/guangmiao-g4c-rk3399_defconfig +@@ -0,0 +1,57 @@ ++CONFIG_ARM=y ++CONFIG_ARCH_ROCKCHIP=y ++CONFIG_SYS_TEXT_BASE=0x00200000 ++CONFIG_ENV_OFFSET=0x3F8000 ++CONFIG_ROCKCHIP_RK3399=y ++CONFIG_TARGET_EVB_RK3399=y ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_SYS_LOAD_ADDR=0x800800 ++CONFIG_DEBUG_UART_BASE=0xFF1A0000 ++CONFIG_DEBUG_UART_CLOCK=24000000 ++CONFIG_DEBUG_UART=y ++CONFIG_DEFAULT_FDT_FILE="rockchip/rk3399-guangmiao-g4c.dtb" ++CONFIG_DISPLAY_BOARDINFO_LATE=y ++CONFIG_SPL_STACK_R=y ++CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x10000 ++CONFIG_TPL=y ++CONFIG_CMD_BOOTZ=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_MMC=y ++CONFIG_CMD_USB=y ++# CONFIG_CMD_SETEXPR is not set ++CONFIG_CMD_TIME=y ++CONFIG_SPL_OF_CONTROL=y ++CONFIG_DEFAULT_DEVICE_TREE="rk3399-guangmiao-g4c" ++CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" ++CONFIG_ENV_IS_IN_MMC=y ++CONFIG_SYS_RELOC_GD_ENV_ADDR=y ++CONFIG_ROCKCHIP_GPIO=y ++CONFIG_SYS_I2C_ROCKCHIP=y ++CONFIG_MMC_DW=y ++CONFIG_MMC_DW_ROCKCHIP=y ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_ROCKCHIP=y ++CONFIG_DM_ETH=y ++CONFIG_ETH_DESIGNWARE=y ++CONFIG_GMAC_ROCKCHIP=y ++CONFIG_PMIC_RK8XX=y ++CONFIG_REGULATOR_PWM=y ++CONFIG_REGULATOR_RK8XX=y ++CONFIG_PWM_ROCKCHIP=y ++CONFIG_RAM_RK3399_LPDDR4=y ++CONFIG_BAUDRATE=1500000 ++CONFIG_DEBUG_UART_SHIFT=2 ++CONFIG_SYSRESET=y ++CONFIG_USB=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_DWC3=y ++CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_EHCI_GENERIC=y ++CONFIG_USB_HOST_ETHER=y ++CONFIG_USB_ETHER_ASIX=y ++CONFIG_USB_ETHER_ASIX88179=y ++CONFIG_USB_ETHER_MCS7830=y ++CONFIG_USB_ETHER_RTL8152=y ++CONFIG_USB_ETHER_SMSC95XX=y ++CONFIG_SPL_TINY_MEMSET=y ++CONFIG_ERRNO_STR=y +--- /dev/null ++++ b/arch/arm/dts/rk3399-guangmiao-g4c-u-boot.dtsi +@@ -0,0 +1,18 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++ ++#include "rk3399-u-boot.dtsi" ++#include "rk3399-sdram-lpddr4-100.dtsi" ++ ++/ { ++ chosen { ++ u-boot,spl-boot-order = "same-as-spl", &sdhci, &sdmmc; ++ }; ++}; ++ ++&sdmmc { ++ pinctrl-0 = <&sdmmc_bus4 &sdmmc_clk &sdmmc_cmd &sdmmc_cd>; ++}; ++ ++&vdd_log { ++ regulator-init-microvolt = <950000>; ++}; +--- /dev/null ++++ b/arch/arm/dts/rk3399-guangmiao-g4c.dts +@@ -0,0 +1,646 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++/dts-v1/; ++#include ++#include "rk3399.dtsi" ++#include "rk3399-opp.dtsi" ++ ++/ { ++ model = "SHAREVDI GuangMiao G4C"; ++ compatible = "sharevdi,guangmiao-g4c", "rockchip,rk3399"; ++ ++ /delete-node/ display-subsystem; ++ ++ chosen { ++ stdout-path = "serial2:1500000n8"; ++ }; ++ ++ clkin_gmac: external-gmac-clock { ++ compatible = "fixed-clock"; ++ clock-frequency = <125000000>; ++ clock-output-names = "clkin_gmac"; ++ #clock-cells = <0>; ++ }; ++ ++ vcc_sys: vcc-sys { ++ compatible = "regulator-fixed"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ regulator-name = "vcc_sys"; ++ }; ++ ++ vcc3v3_sys: vcc3v3-sys { ++ compatible = "regulator-fixed"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "vcc3v3_sys"; ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ vcc_0v9: vcc-0v9 { ++ compatible = "regulator-fixed"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <900000>; ++ regulator-max-microvolt = <900000>; ++ regulator-name = "vcc_0v9"; ++ vin-supply = <&vcc3v3_sys>; ++ }; ++ ++ vcc5v0_host0: vcc5v0-host0 { ++ compatible = "regulator-fixed"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-name = "vcc5v0_host0"; ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ vdd_log: vdd-log { ++ compatible = "pwm-regulator"; ++ pwms = <&pwm2 0 25000 1>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <1400000>; ++ regulator-name = "vdd_log"; ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ autorepeat; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&reset_button_pin>; ++ ++ reset { ++ debounce-interval = <100>; ++ gpios = <&gpio0 RK_PA5 GPIO_ACTIVE_LOW>; ++ label = "reset"; ++ linux,code = ; ++ wakeup-source; ++ }; ++ }; ++ ++ gpio-leds { ++ compatible = "gpio-leds"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&lan_led_pin>, <&status_led_pin>, <&wan_led_pin>; ++ ++ lan_led: led-lan { ++ gpios = <&gpio0 RK_PA3 GPIO_ACTIVE_HIGH>; ++ label = "green:lan"; ++ }; ++ ++ status_led: led-status { ++ gpios = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>; ++ label = "green:status"; ++ }; ++ ++ wan_led: led-wan { ++ gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_HIGH>; ++ label = "green:wan"; ++ }; ++ }; ++}; ++ ++&cpu_b0 { ++ cpu-supply = <&vdd_cpu_b>; ++}; ++ ++&cpu_b1 { ++ cpu-supply = <&vdd_cpu_b>; ++}; ++ ++&cpu_l0 { ++ cpu-supply = <&vdd_cpu_l>; ++}; ++ ++&cpu_l1 { ++ cpu-supply = <&vdd_cpu_l>; ++}; ++ ++&cpu_l2 { ++ cpu-supply = <&vdd_cpu_l>; ++}; ++ ++&cpu_l3 { ++ cpu-supply = <&vdd_cpu_l>; ++}; ++ ++&emmc_phy { ++ status = "okay"; ++}; ++ ++&gmac { ++ assigned-clock-parents = <&clkin_gmac>; ++ assigned-clocks = <&cru SCLK_RMII_SRC>; ++ clock_in_out = "input"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rgmii_pins>, <&phy_intb>, <&phy_pmeb>, <&phy_rstb>; ++ phy-handle = <&rtl8211e>; ++ phy-mode = "rgmii"; ++ phy-supply = <&vcc3v3_s3>; ++ tx_delay = <0x28>; ++ rx_delay = <0x11>; ++ status = "okay"; ++ ++ mdio { ++ compatible = "snps,dwmac-mdio"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ rtl8211e: ethernet-phy@1 { ++ reg = <1>; ++ interrupt-parent = <&gpio3>; ++ interrupts = ; ++ reset-assert-us = <10000>; ++ reset-deassert-us = <30000>; ++ reset-gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; ++ ++&gpu { ++ mali-supply = <&vdd_gpu>; ++ status = "okay"; ++}; ++ ++&i2c0 { ++ clock-frequency = <400000>; ++ i2c-scl-rising-time-ns = <160>; ++ i2c-scl-falling-time-ns = <30>; ++ status = "okay"; ++ ++ vdd_cpu_b: regulator@40 { ++ compatible = "silergy,syr827"; ++ reg = <0x40>; ++ fcs,suspend-voltage-selector = <1>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&cpu_b_sleep>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1500000>; ++ regulator-name = "vdd_cpu_b"; ++ regulator-ramp-delay = <1000>; ++ vin-supply = <&vcc_sys>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_gpu: regulator@41 { ++ compatible = "silergy,syr828"; ++ reg = <0x41>; ++ fcs,suspend-voltage-selector = <1>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&gpu_sleep>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1500000>; ++ regulator-name = "vdd_gpu"; ++ regulator-ramp-delay = <1000>; ++ vin-supply = <&vcc_sys>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ rk808: pmic@1b { ++ compatible = "rockchip,rk808"; ++ reg = <0x1b>; ++ clock-output-names = "rtc_clko_soc", "rtc_clko_wifi"; ++ #clock-cells = <1>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <21 IRQ_TYPE_LEVEL_LOW>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_int_l>; ++ rockchip,system-power-controller; ++ wakeup-source; ++ ++ vcc1-supply = <&vcc_sys>; ++ vcc2-supply = <&vcc_sys>; ++ vcc3-supply = <&vcc_sys>; ++ vcc4-supply = <&vcc_sys>; ++ vcc6-supply = <&vcc_sys>; ++ vcc7-supply = <&vcc_sys>; ++ vcc8-supply = <&vcc_3v0>; ++ vcc9-supply = <&vcc_sys>; ++ vcc10-supply = <&vcc_sys>; ++ vcc11-supply = <&vcc_sys>; ++ vcc12-supply = <&vcc_sys>; ++ vddio-supply = <&vcc_3v0>; ++ ++ regulators { ++ vdd_center: DCDC_REG1 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-name = "vdd_center"; ++ regulator-ramp-delay = <6001>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_cpu_l: DCDC_REG2 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-name = "vdd_cpu_l"; ++ regulator-ramp-delay = <6001>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_ddr: DCDC_REG3 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-name = "vcc_ddr"; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc_1v8: DCDC_REG4 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "vcc_1v8"; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcc_vldo1: LDO_REG1 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "vcc_vldo1"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_vldo2: LDO_REG2 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "vcc_vldo2"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcca_1v8: LDO_REG3 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "vcca_1v8"; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcc_sdio: LDO_REG4 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "vcc_sdio"; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vcc3v0_sd: LDO_REG5 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3000000>; ++ regulator-max-microvolt = <3000000>; ++ regulator-name = "vcc3v0_sd"; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3000000>; ++ }; ++ }; ++ ++ vcc_1v5: LDO_REG6 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1500000>; ++ regulator-max-microvolt = <1500000>; ++ regulator-name = "vcc_1v5"; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1500000>; ++ }; ++ }; ++ ++ vcca1v8_codec: LDO_REG7 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "vcca1v8_codec"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_3v0: LDO_REG8 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3000000>; ++ regulator-max-microvolt = <3000000>; ++ regulator-name = "vcc_3v0"; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3000000>; ++ }; ++ }; ++ ++ vcc3v3_s3: SWITCH_REG1 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-name = "vcc3v3_s3"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc3v3_s0: SWITCH_REG2 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-name = "vcc3v3_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&i2c3 { ++ i2c-scl-rising-time-ns = <450>; ++ i2c-scl-falling-time-ns = <15>; ++ status = "okay"; ++}; ++ ++&io_domains { ++ bt656-supply = <&vcc_1v8>; ++ audio-supply = <&vcca1v8_codec>; ++ sdmmc-supply = <&vcc_sdio>; ++ gpio1830-supply = <&vcc_3v0>; ++ status = "okay"; ++}; ++ ++&pcie_phy { ++ assigned-clock-parents = <&cru SCLK_PCIEPHY_REF100M>; ++ assigned-clock-rates = <100000000>; ++ assigned-clocks = <&cru SCLK_PCIEPHY_REF>; ++ status = "okay"; ++}; ++ ++&pcie0 { ++ ep-gpios = <&gpio4 RK_PD2 GPIO_ACTIVE_HIGH>; ++ max-link-speed = <1>; ++ num-lanes = <1>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pcie_clkreqnb_cpm>; ++ vpcie0v9-supply = <&vcc_0v9>; ++ vpcie1v8-supply = <&vcca_1v8>; ++ vpcie3v3-supply = <&vcc3v3_sys>; ++ status = "okay"; ++}; ++ ++&pinctrl { ++ gpio-leds { ++ lan_led_pin: lan-led-pin { ++ rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ ++ status_led_pin: status-led-pin { ++ rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ ++ wan_led_pin: wan-led-pin { ++ rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ gmac { ++ phy_intb: phy-intb { ++ rockchip,pins = <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ ++ phy_pmeb: phy-pmeb { ++ rockchip,pins = <0 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ ++ phy_rstb: phy-rstb { ++ rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ pmic { ++ cpu_b_sleep: cpu-b-sleep { ++ rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>; ++ }; ++ ++ gpu_sleep: gpu-sleep { ++ rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; ++ }; ++ ++ pmic_int_l: pmic-int-l { ++ rockchip,pins = <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ rockchip-key { ++ reset_button_pin: reset-button-pin { ++ rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ sdio { ++ bt_reg_on_h: bt-reg-on-h { ++ /* external pullup to VCC1V8_PMUPLL */ ++ rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ sdmmc { ++ sdmmc0_det_l: sdmmc0-det-l { ++ rockchip,pins = <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++}; ++ ++&pmu_io_domains { ++ pmu1830-supply = <&vcc_3v0>; ++ status = "okay"; ++}; ++ ++&pwm0 { ++ status = "okay"; ++}; ++ ++&pwm1 { ++ status = "okay"; ++}; ++ ++&pwm2 { ++ pinctrl-names = "active"; ++ pinctrl-0 = <&pwm2_pin_pull_down>; ++ status = "okay"; ++}; ++ ++&saradc { ++ vref-supply = <&vcc_1v8>; ++ status = "okay"; ++}; ++ ++&sdhci { ++ bus-width = <8>; ++ mmc-hs200-1_8v; ++ non-removable; ++ status = "okay"; ++}; ++ ++&sdmmc { ++ bus-width = <4>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ cd-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>; ++ disable-wp; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc_bus4 &sdmmc_clk &sdmmc_cmd &sdmmc0_det_l>; ++ vqmmc-supply = <&vcc_sdio>; ++ status = "okay"; ++}; ++ ++&tcphy0 { ++ status = "okay"; ++}; ++ ++&tcphy1 { ++ status = "okay"; ++}; ++ ++&tsadc { ++ rockchip,hw-tshut-mode = <1>; ++ rockchip,hw-tshut-polarity = <1>; ++ status = "okay"; ++}; ++ ++&u2phy0 { ++ status = "okay"; ++}; ++ ++&u2phy0_host { ++ phy-supply = <&vcc5v0_host0>; ++ status = "okay"; ++}; ++ ++&u2phy0_otg { ++ status = "okay"; ++}; ++ ++&u2phy1 { ++ status = "okay"; ++}; ++ ++&u2phy1_host { ++ phy-supply = <&vcc5v0_host0>; ++ status = "okay"; ++}; ++ ++&u2phy1_otg { ++ status = "okay"; ++}; ++ ++&uart2 { ++ status = "okay"; ++}; ++ ++&usbdrd3_0 { ++ status = "okay"; ++}; ++ ++&usbdrd3_1 { ++ status = "okay"; ++}; ++ ++&usbdrd_dwc3_0 { ++ dr_mode = "host"; ++ status = "okay"; ++}; ++ ++&usbdrd_dwc3_1 { ++ dr_mode = "host"; ++ status = "okay"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usb_host1_ehci { ++ status = "okay"; ++}; ++ ++&usb_host1_ohci { ++ status = "okay"; ++}; ++ ++&vopb { ++ status = "okay"; ++}; ++ ++&vopb_mmu { ++ status = "okay"; ++}; ++ ++&vopl { ++ status = "okay"; ++}; ++ ++&vopl_mmu { ++ status = "okay"; ++}; diff --git a/root/package/boot/uboot-rockchip/patches/302-rockchip-rk3328-Add-support-for-Orangepi-R1-Plus.patch b/root/package/boot/uboot-rockchip/patches/302-rockchip-rk3328-Add-support-for-Orangepi-R1-Plus.patch new file mode 100644 index 00000000..d7940c96 --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/302-rockchip-rk3328-Add-support-for-Orangepi-R1-Plus.patch @@ -0,0 +1,174 @@ +--- a/arch/arm/dts/Makefile ++++ b/arch/arm/dts/Makefile +@@ -109,6 +109,7 @@ dtb-$(CONFIG_ROCKCHIP_RK3308) += \ + dtb-$(CONFIG_ROCKCHIP_RK3328) += \ + rk3328-evb.dtb \ + rk3328-nanopi-r2s.dtb \ ++ rk3328-orangepi-r1-plus.dtb \ + rk3328-roc-cc.dtb \ + rk3328-rock64.dtb \ + rk3328-rock-pi-e.dtb +--- /dev/null ++++ b/arch/arm/dts/rk3328-orangepi-r1-plus-u-boot.dtsi +@@ -0,0 +1,1 @@ ++#include "rk3328-nanopi-r2s-u-boot.dtsi" +--- /dev/null ++++ b/arch/arm/dts/rk3328-orangepi-r1-plus.dts +@@ -0,0 +1,38 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++#include "rk3328-nanopi-r2s.dts" ++ ++/ { ++ model = "Xunlong Orange Pi R1 Plus"; ++ compatible = "xunlong,orangepi-r1-plus", "rockchip,rk3328"; ++}; ++ ++&lan_led { ++ label = "orangepi-r1-plus:green:lan"; ++}; ++ ++&spi0 { ++ status = "okay"; ++ ++ flash@0 { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <10000000>; ++ }; ++}; ++ ++&sys_led { ++ gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; ++ label = "orangepi-r1-plus:red:sys"; ++}; ++ ++&sys_led_pin { ++ rockchip,pins = <3 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>; ++}; ++ ++&uart1 { ++ status = "okay"; ++}; ++ ++&wan_led { ++ label = "orangepi-r1-plus:green:wan"; ++}; +--- a/board/rockchip/evb_rk3328/MAINTAINERS ++++ b/board/rockchip/evb_rk3328/MAINTAINERS +@@ -12,6 +12,13 @@ F: configs/nanopi-r2s-rk3328_defconfig + F: arch/arm/dts/rk3328-nanopi-r2s-u-boot.dtsi + F: arch/arm/dts/rk3328-nanopi-r2s.dts + ++ORANGEPI-R1-PLUS-RK3328 ++M: Shenzhen Xunlong Software CO.,Limited ++S: Maintained ++F: configs/orangepi-r1-plus-rk3328_defconfig ++F: arch/arm/dts/rk3328-orangepi-r1-plus-u-boot.dtsi ++F: arch/arm/dts/rk3328-orangepi-r1-plus.dts ++ + ROC-RK3328-CC + M: Loic Devulder + M: Chen-Yu Tsai +--- /dev/null ++++ b/configs/orangepi-r1-plus-rk3328_defconfig +@@ -0,0 +1,100 @@ ++CONFIG_ARM=y ++CONFIG_ARCH_ROCKCHIP=y ++CONFIG_SYS_TEXT_BASE=0x00200000 ++CONFIG_SPL_GPIO_SUPPORT=y ++CONFIG_ENV_OFFSET=0x3F8000 ++CONFIG_ROCKCHIP_RK3328=y ++CONFIG_TPL_ROCKCHIP_COMMON_BOARD=y ++CONFIG_TPL_LIBCOMMON_SUPPORT=y ++CONFIG_TPL_LIBGENERIC_SUPPORT=y ++CONFIG_SPL_DRIVERS_MISC_SUPPORT=y ++CONFIG_SPL_STACK_R_ADDR=0x600000 ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_SYS_LOAD_ADDR=0x800800 ++CONFIG_DEBUG_UART_BASE=0xFF130000 ++CONFIG_DEBUG_UART_CLOCK=24000000 ++CONFIG_SYSINFO=y ++CONFIG_DEBUG_UART=y ++CONFIG_TPL_SYS_MALLOC_F_LEN=0x800 ++# CONFIG_ANDROID_BOOT_IMAGE is not set ++CONFIG_FIT=y ++CONFIG_FIT_VERBOSE=y ++CONFIG_SPL_LOAD_FIT=y ++CONFIG_DEFAULT_FDT_FILE="rockchip/rk3328-orangepi-r1-plus.dtb" ++CONFIG_MISC_INIT_R=y ++# CONFIG_DISPLAY_CPUINFO is not set ++CONFIG_DISPLAY_BOARDINFO_LATE=y ++# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set ++CONFIG_TPL_SYS_MALLOC_SIMPLE=y ++CONFIG_SPL_STACK_R=y ++CONFIG_SPL_I2C_SUPPORT=y ++CONFIG_SPL_POWER_SUPPORT=y ++CONFIG_SPL_ATF=y ++CONFIG_SPL_ATF_NO_PLATFORM_PARAM=y ++CONFIG_CMD_BOOTZ=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_MMC=y ++CONFIG_CMD_USB=y ++# CONFIG_CMD_SETEXPR is not set ++CONFIG_CMD_TIME=y ++CONFIG_SPL_OF_CONTROL=y ++CONFIG_TPL_OF_CONTROL=y ++CONFIG_DEFAULT_DEVICE_TREE="rk3328-orangepi-r1-plus" ++CONFIG_OF_SPL_REMOVE_PROPS="clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" ++CONFIG_TPL_OF_PLATDATA=y ++CONFIG_ENV_IS_IN_MMC=y ++CONFIG_SYS_RELOC_GD_ENV_ADDR=y ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_TPL_DM=y ++CONFIG_REGMAP=y ++CONFIG_SPL_REGMAP=y ++CONFIG_TPL_REGMAP=y ++CONFIG_SYSCON=y ++CONFIG_SPL_SYSCON=y ++CONFIG_TPL_SYSCON=y ++CONFIG_CLK=y ++CONFIG_SPL_CLK=y ++CONFIG_FASTBOOT_BUF_ADDR=0x800800 ++CONFIG_FASTBOOT_CMD_OEM_FORMAT=y ++CONFIG_ROCKCHIP_GPIO=y ++CONFIG_SYS_I2C_ROCKCHIP=y ++CONFIG_MMC_DW=y ++CONFIG_MMC_DW_ROCKCHIP=y ++CONFIG_SF_DEFAULT_SPEED=20000000 ++CONFIG_DM_ETH=y ++CONFIG_ETH_DESIGNWARE=y ++CONFIG_GMAC_ROCKCHIP=y ++CONFIG_PINCTRL=y ++CONFIG_SPL_PINCTRL=y ++CONFIG_DM_PMIC=y ++CONFIG_PMIC_RK8XX=y ++CONFIG_SPL_DM_REGULATOR=y ++CONFIG_REGULATOR_PWM=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_SPL_DM_REGULATOR_FIXED=y ++CONFIG_REGULATOR_RK8XX=y ++CONFIG_PWM_ROCKCHIP=y ++CONFIG_RAM=y ++CONFIG_SPL_RAM=y ++CONFIG_TPL_RAM=y ++CONFIG_DM_RESET=y ++CONFIG_BAUDRATE=1500000 ++CONFIG_DEBUG_UART_SHIFT=2 ++CONFIG_SYSRESET=y ++# CONFIG_TPL_SYSRESET is not set ++CONFIG_USB=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_DWC3=y ++CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_EHCI_GENERIC=y ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_GENERIC=y ++CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS=1 ++CONFIG_USB_DWC2=y ++CONFIG_USB_DWC3=y ++# CONFIG_USB_DWC3_GADGET is not set ++CONFIG_USB_GADGET=y ++CONFIG_USB_GADGET_DWC2_OTG=y ++CONFIG_SPL_TINY_MEMSET=y ++CONFIG_TPL_TINY_MEMSET=y ++CONFIG_ERRNO_STR=y diff --git a/root/package/boot/uboot-rockchip/patches/303-rockchip-rk3328-Add-support-for-Orangepi-R1-Plus-LTS.patch b/root/package/boot/uboot-rockchip/patches/303-rockchip-rk3328-Add-support-for-Orangepi-R1-Plus-LTS.patch new file mode 100644 index 00000000..0f3f17f7 --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/303-rockchip-rk3328-Add-support-for-Orangepi-R1-Plus-LTS.patch @@ -0,0 +1,146 @@ +From 68836b81f7d6328a1a5a6cce5a00bf4010f742e5 Mon Sep 17 00:00:00 2001 +From: baiywt +Date: Wed, 24 Nov 2021 19:59:38 +0800 +Subject: [PATCH] Add support for Orangepi R1 Plus LTS + +--- + arch/arm/dts/Makefile | 1 + + arch/arm/dts/rk3328-orangepi-r1-plus-lts.dts | 7 ++ + configs/orangepi-r1-plus-lts-rk3328_defconfig | 98 +++++++++++++++++++ + 3 files changed, 106 insertions(+) + create mode 100644 arch/arm/dts/rk3328-orangepi-r1-plus-lts.dts + create mode 100644 configs/orangepi-r1-plus-lts-rk3328_defconfig + +diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile +index adfe6c3f..3d4e0f59 100644 +--- a/arch/arm/dts/Makefile ++++ b/arch/arm/dts/Makefile +@@ -110,6 +110,7 @@ dtb-$(CONFIG_ROCKCHIP_RK3328) += \ + rk3328-evb.dtb \ + rk3328-nanopi-r2s.dtb \ + rk3328-orangepi-r1-plus.dtb \ ++ rk3328-orangepi-r1-plus-lts.dtb \ + rk3328-roc-cc.dtb \ + rk3328-rock64.dtb \ + rk3328-rock-pi-e.dtb +diff --git a/arch/arm/dts/rk3328-orangepi-r1-plus-lts.dts b/arch/arm/dts/rk3328-orangepi-r1-plus-lts.dts +new file mode 100644 +index 00000000..e6225b0c +--- /dev/null ++++ b/arch/arm/dts/rk3328-orangepi-r1-plus-lts.dts +@@ -0,0 +1,7 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++#include "rk3328-orangepi-r1-plus.dts" ++ ++/ { ++ model = "Xunlong Orange Pi R1 Plus LTS"; ++ compatible = "xunlong,orangepi-r1-plus-lts", "rockchip,rk3328"; ++}; +diff --git a/configs/orangepi-r1-plus-lts-rk3328_defconfig b/configs/orangepi-r1-plus-lts-rk3328_defconfig +new file mode 100644 +index 00000000..3cb3b5c3 +--- /dev/null ++++ b/configs/orangepi-r1-plus-lts-rk3328_defconfig +@@ -0,0 +1,100 @@ ++CONFIG_ARM=y ++CONFIG_ARCH_ROCKCHIP=y ++CONFIG_SYS_TEXT_BASE=0x00200000 ++CONFIG_SPL_GPIO_SUPPORT=y ++CONFIG_ENV_OFFSET=0x3F8000 ++CONFIG_ROCKCHIP_RK3328=y ++CONFIG_TPL_ROCKCHIP_COMMON_BOARD=y ++CONFIG_TPL_LIBCOMMON_SUPPORT=y ++CONFIG_TPL_LIBGENERIC_SUPPORT=y ++CONFIG_SPL_DRIVERS_MISC_SUPPORT=y ++CONFIG_SPL_STACK_R_ADDR=0x600000 ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_DEBUG_UART_BASE=0xFF130000 ++CONFIG_DEBUG_UART_CLOCK=24000000 ++CONFIG_SYSINFO=y ++CONFIG_SYS_LOAD_ADDR=0x800800 ++CONFIG_DEBUG_UART=y ++CONFIG_TPL_SYS_MALLOC_F_LEN=0x800 ++# CONFIG_ANDROID_BOOT_IMAGE is not set ++CONFIG_FIT=y ++CONFIG_FIT_VERBOSE=y ++CONFIG_SPL_LOAD_FIT=y ++CONFIG_DEFAULT_FDT_FILE="rockchip/rk3328-orangepi-r1-plus-lts.dtb" ++CONFIG_MISC_INIT_R=y ++# CONFIG_DISPLAY_CPUINFO is not set ++CONFIG_DISPLAY_BOARDINFO_LATE=y ++# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set ++CONFIG_TPL_SYS_MALLOC_SIMPLE=y ++CONFIG_SPL_STACK_R=y ++CONFIG_SPL_I2C_SUPPORT=y ++CONFIG_SPL_POWER_SUPPORT=y ++CONFIG_SPL_ATF=y ++CONFIG_SPL_ATF_NO_PLATFORM_PARAM=y ++CONFIG_CMD_BOOTZ=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_MMC=y ++CONFIG_CMD_USB=y ++# CONFIG_CMD_SETEXPR is not set ++CONFIG_CMD_TIME=y ++CONFIG_SPL_OF_CONTROL=y ++CONFIG_TPL_OF_CONTROL=y ++CONFIG_DEFAULT_DEVICE_TREE="rk3328-orangepi-r1-plus-lts" ++CONFIG_OF_SPL_REMOVE_PROPS="clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" ++CONFIG_TPL_OF_PLATDATA=y ++CONFIG_ENV_IS_IN_MMC=y ++CONFIG_SYS_RELOC_GD_ENV_ADDR=y ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_TPL_DM=y ++CONFIG_REGMAP=y ++CONFIG_SPL_REGMAP=y ++CONFIG_TPL_REGMAP=y ++CONFIG_SYSCON=y ++CONFIG_SPL_SYSCON=y ++CONFIG_TPL_SYSCON=y ++CONFIG_CLK=y ++CONFIG_SPL_CLK=y ++CONFIG_FASTBOOT_BUF_ADDR=0x800800 ++CONFIG_FASTBOOT_CMD_OEM_FORMAT=y ++CONFIG_ROCKCHIP_GPIO=y ++CONFIG_SYS_I2C_ROCKCHIP=y ++CONFIG_MMC_DW=y ++CONFIG_MMC_DW_ROCKCHIP=y ++CONFIG_SF_DEFAULT_SPEED=20000000 ++CONFIG_DM_ETH=y ++CONFIG_ETH_DESIGNWARE=y ++CONFIG_GMAC_ROCKCHIP=y ++CONFIG_PINCTRL=y ++CONFIG_SPL_PINCTRL=y ++CONFIG_DM_PMIC=y ++CONFIG_PMIC_RK8XX=y ++CONFIG_SPL_DM_REGULATOR=y ++CONFIG_REGULATOR_PWM=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_SPL_DM_REGULATOR_FIXED=y ++CONFIG_REGULATOR_RK8XX=y ++CONFIG_PWM_ROCKCHIP=y ++CONFIG_RAM=y ++CONFIG_SPL_RAM=y ++CONFIG_TPL_RAM=y ++CONFIG_DM_RESET=y ++CONFIG_BAUDRATE=1500000 ++CONFIG_DEBUG_UART_SHIFT=2 ++CONFIG_SYSRESET=y ++# CONFIG_TPL_SYSRESET is not set ++CONFIG_USB=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_DWC3=y ++CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_EHCI_GENERIC=y ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_GENERIC=y ++CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS=1 ++CONFIG_USB_DWC2=y ++CONFIG_USB_DWC3=y ++# CONFIG_USB_DWC3_GADGET is not set ++CONFIG_USB_GADGET=y ++CONFIG_USB_GADGET_DWC2_OTG=y ++CONFIG_SPL_TINY_MEMSET=y ++CONFIG_TPL_TINY_MEMSET=y ++CONFIG_ERRNO_STR=y +-- +2.25.1 diff --git a/root/package/boot/uboot-rockchip/patches/304-rockchip-rk3328-Add-support-for-FriendlyARM-NanoPi-R.patch b/root/package/boot/uboot-rockchip/patches/304-rockchip-rk3328-Add-support-for-FriendlyARM-NanoPi-R.patch new file mode 100644 index 00000000..39022fdd --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/304-rockchip-rk3328-Add-support-for-FriendlyARM-NanoPi-R.patch @@ -0,0 +1,184 @@ +diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile +index d3e89ca3ba..d5f64ac432 100644 +--- a/arch/arm/dts/Makefile ++++ b/arch/arm/dts/Makefile +@@ -108,6 +108,7 @@ dtb-$(CONFIG_ROCKCHIP_RK3308) += \ + + dtb-$(CONFIG_ROCKCHIP_RK3328) += \ + rk3328-evb.dtb \ ++ rk3328-nanopi-r2c.dtb \ + rk3328-nanopi-r2s.dtb \ + rk3328-orangepi-r1-plus.dtb \ + rk3328-roc-cc.dtb \ +diff --git a/arch/arm/dts/rk3328-nanopi-r2c-u-boot.dtsi b/arch/arm/dts/rk3328-nanopi-r2c-u-boot.dtsi +new file mode 100644 +index 0000000000..c2e86d0f0e +--- /dev/null ++++ b/arch/arm/dts/rk3328-nanopi-r2c-u-boot.dtsi +@@ -0,0 +1,7 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * (C) Copyright 2018-2019 Rockchip Electronics Co., Ltd ++ * (C) Copyright 2021 Tianling Shen ++ */ ++ ++#include "rk3328-nanopi-r2s-u-boot.dtsi" +diff --git a/arch/arm/dts/rk3328-nanopi-r2c.dts b/arch/arm/dts/rk3328-nanopi-r2c.dts +new file mode 100644 +index 0000000000..adf91a0306 +--- /dev/null ++++ b/arch/arm/dts/rk3328-nanopi-r2c.dts +@@ -0,0 +1,47 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2021 FriendlyElec Computer Tech. Co., Ltd. ++ * (http://www.friendlyarm.com) ++ * ++ * Copyright (c) 2021 Tianling Shen ++ */ ++ ++/dts-v1/; ++ ++#include "rk3328-nanopi-r2s.dts" ++ ++/ { ++ model = "FriendlyElec NanoPi R2C"; ++ compatible = "friendlyarm,nanopi-r2c", "rockchip,rk3328"; ++}; ++ ++&gmac2io { ++ phy-handle = <&yt8521s>; ++ ++ mdio { ++ /delete-node/ ethernet-phy@1; ++ ++ yt8521s: ethernet-phy@3 { ++ compatible = "ethernet-phy-id0000.011a", ++ "ethernet-phy-ieee802.3-c22"; ++ reg = <3>; ++ pinctrl-0 = <ð_phy_reset_pin>; ++ pinctrl-names = "default"; ++ reset-assert-us = <10000>; ++ reset-deassert-us = <50000>; ++ reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; ++ ++&lan_led { ++ label = "nanopi-r2c:green:lan"; ++}; ++ ++&sys_led { ++ label = "nanopi-r2c:red:sys"; ++}; ++ ++&wan_led { ++ label = "nanopi-r2c:green:wan"; ++}; +diff --git a/configs/nanopi-r2c-rk3328_defconfig b/configs/nanopi-r2c-rk3328_defconfig +new file mode 100644 +index 0000000000..7bc7a3274f +--- /dev/null ++++ b/configs/nanopi-r2c-rk3328_defconfig +@@ -0,0 +1,100 @@ ++CONFIG_ARM=y ++CONFIG_ARCH_ROCKCHIP=y ++CONFIG_SYS_TEXT_BASE=0x00200000 ++CONFIG_SPL_GPIO_SUPPORT=y ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_ENV_OFFSET=0x3F8000 ++CONFIG_DEFAULT_DEVICE_TREE="rk3328-nanopi-r2c" ++CONFIG_ROCKCHIP_RK3328=y ++CONFIG_TPL_ROCKCHIP_COMMON_BOARD=y ++CONFIG_TPL_LIBCOMMON_SUPPORT=y ++CONFIG_TPL_LIBGENERIC_SUPPORT=y ++CONFIG_SPL_DRIVERS_MISC_SUPPORT=y ++CONFIG_SPL_STACK_R_ADDR=0x600000 ++CONFIG_DEBUG_UART_BASE=0xFF130000 ++CONFIG_DEBUG_UART_CLOCK=24000000 ++CONFIG_SYS_LOAD_ADDR=0x800800 ++CONFIG_DEBUG_UART=y ++CONFIG_TPL_SYS_MALLOC_F_LEN=0x800 ++# CONFIG_ANDROID_BOOT_IMAGE is not set ++CONFIG_FIT=y ++CONFIG_FIT_VERBOSE=y ++CONFIG_SPL_LOAD_FIT=y ++CONFIG_DEFAULT_FDT_FILE="rockchip/rk3328-nanopi-r2c.dtb" ++# CONFIG_DISPLAY_CPUINFO is not set ++CONFIG_DISPLAY_BOARDINFO_LATE=y ++CONFIG_MISC_INIT_R=y ++# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set ++CONFIG_TPL_SYS_MALLOC_SIMPLE=y ++CONFIG_SPL_STACK_R=y ++CONFIG_SPL_I2C_SUPPORT=y ++CONFIG_SPL_POWER_SUPPORT=y ++CONFIG_SPL_ATF=y ++CONFIG_SPL_ATF_NO_PLATFORM_PARAM=y ++CONFIG_CMD_BOOTZ=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_MMC=y ++CONFIG_CMD_USB=y ++# CONFIG_CMD_SETEXPR is not set ++CONFIG_CMD_TIME=y ++CONFIG_SPL_OF_CONTROL=y ++CONFIG_TPL_OF_CONTROL=y ++CONFIG_OF_SPL_REMOVE_PROPS="clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" ++CONFIG_TPL_OF_PLATDATA=y ++CONFIG_ENV_IS_IN_MMC=y ++CONFIG_SYS_RELOC_GD_ENV_ADDR=y ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_TPL_DM=y ++CONFIG_REGMAP=y ++CONFIG_SPL_REGMAP=y ++CONFIG_TPL_REGMAP=y ++CONFIG_SYSCON=y ++CONFIG_SPL_SYSCON=y ++CONFIG_TPL_SYSCON=y ++CONFIG_CLK=y ++CONFIG_SPL_CLK=y ++CONFIG_FASTBOOT_BUF_ADDR=0x800800 ++CONFIG_FASTBOOT_CMD_OEM_FORMAT=y ++CONFIG_ROCKCHIP_GPIO=y ++CONFIG_SYS_I2C_ROCKCHIP=y ++CONFIG_MMC_DW=y ++CONFIG_MMC_DW_ROCKCHIP=y ++CONFIG_SF_DEFAULT_SPEED=20000000 ++CONFIG_DM_ETH=y ++CONFIG_ETH_DESIGNWARE=y ++CONFIG_GMAC_ROCKCHIP=y ++CONFIG_PINCTRL=y ++CONFIG_SPL_PINCTRL=y ++CONFIG_DM_PMIC=y ++CONFIG_PMIC_RK8XX=y ++CONFIG_SPL_DM_REGULATOR=y ++CONFIG_REGULATOR_PWM=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_SPL_DM_REGULATOR_FIXED=y ++CONFIG_REGULATOR_RK8XX=y ++CONFIG_PWM_ROCKCHIP=y ++CONFIG_RAM=y ++CONFIG_SPL_RAM=y ++CONFIG_TPL_RAM=y ++CONFIG_DM_RESET=y ++CONFIG_BAUDRATE=1500000 ++CONFIG_DEBUG_UART_SHIFT=2 ++CONFIG_SYSINFO=y ++CONFIG_SYSRESET=y ++# CONFIG_TPL_SYSRESET is not set ++CONFIG_USB=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_DWC3=y ++CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_EHCI_GENERIC=y ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_GENERIC=y ++CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS=1 ++CONFIG_USB_DWC2=y ++CONFIG_USB_DWC3=y ++# CONFIG_USB_DWC3_GADGET is not set ++CONFIG_USB_GADGET=y ++CONFIG_USB_GADGET_DWC2_OTG=y ++CONFIG_SPL_TINY_MEMSET=y ++CONFIG_TPL_TINY_MEMSET=y ++CONFIG_ERRNO_STR=y diff --git a/root/package/boot/uboot-rockchip/patches/305-rockchip-rk3399-Add-support-for-FriendlyARM-NanoPi-R.patch b/root/package/boot/uboot-rockchip/patches/305-rockchip-rk3399-Add-support-for-FriendlyARM-NanoPi-R.patch new file mode 100644 index 00000000..ca6f8095 --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/305-rockchip-rk3399-Add-support-for-FriendlyARM-NanoPi-R.patch @@ -0,0 +1,113 @@ +--- a/arch/arm/dts/Makefile ++++ b/arch/arm/dts/Makefile +@@ -157,6 +157,7 @@ + rk3399-nanopi-m4b.dtb \ + rk3399-nanopi-neo4.dtb \ + rk3399-nanopi-r4s.dtb \ ++ rk3399-nanopi-r4se.dtb \ + rk3399-orangepi.dtb \ + rk3399-pinebook-pro.dtb \ + rk3399-puma-haikou.dtb \ +--- /dev/null ++++ b/arch/arm/dts/rk3399-nanopi-r4se.dts +@@ -0,0 +1,32 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * FriendlyElec NanoPC-T4 board device tree source ++ * ++ * Copyright (c) 2020 FriendlyElec Computer Tech. Co., Ltd. ++ * (http://www.friendlyarm.com) ++ * ++ * Copyright (c) 2018 Collabora Ltd. ++ * ++ * Copyright (c) 2020 Jensen Huang ++ */ ++ ++/dts-v1/; ++#include "rk3399-nanopi-r4s.dts" ++ ++/ { ++ model = "FriendlyElec NanoPi R4SE"; ++ compatible = "friendlyarm,nanopi-r4se", "rockchip,rk3399"; ++}; ++ ++&emmc_phy { ++ status = "okay"; ++}; ++ ++&sdhci { ++ bus-width = <8>; ++ non-removable; ++ status = "okay"; ++}; ++&sdmmc { ++ pinctrl-0 = <&sdmmc_cd>; ++}; +--- /dev/null ++++ b/configs/nanopi-r4se-rk3399_defconfig +@@ -0,0 +1,65 @@ ++CONFIG_ARM=y ++CONFIG_SKIP_LOWLEVEL_INIT=y ++CONFIG_COUNTER_FREQUENCY=24000000 ++CONFIG_ARCH_ROCKCHIP=y ++CONFIG_SYS_TEXT_BASE=0x00200000 ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_ENV_OFFSET=0x3F8000 ++CONFIG_DEFAULT_DEVICE_TREE="rk3399-nanopi-r4se" ++CONFIG_ROCKCHIP_RK3399=y ++CONFIG_TARGET_EVB_RK3399=y ++CONFIG_DEBUG_UART_BASE=0xFF1A0000 ++CONFIG_DEBUG_UART_CLOCK=24000000 ++CONFIG_SYS_LOAD_ADDR=0x800800 ++CONFIG_DEBUG_UART=y ++CONFIG_DEFAULT_FDT_FILE="rockchip/rk3399-nanopi-r4se.dtb" ++CONFIG_DISPLAY_BOARDINFO_LATE=y ++# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set ++CONFIG_SPL_STACK_R=y ++CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x10000 ++CONFIG_TPL=y ++CONFIG_CMD_BOOTZ=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_MMC=y ++CONFIG_CMD_USB=y ++# CONFIG_CMD_SETEXPR is not set ++CONFIG_CMD_TIME=y ++CONFIG_SPL_OF_CONTROL=y ++CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" ++CONFIG_ENV_IS_IN_MMC=y ++CONFIG_SYS_RELOC_GD_ENV_ADDR=y ++CONFIG_ROCKCHIP_GPIO=y ++CONFIG_SYS_I2C_ROCKCHIP=y ++CONFIG_MMC_DW=y ++CONFIG_MMC_DW_ROCKCHIP=y ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_ROCKCHIP=y ++CONFIG_DM_ETH=y ++CONFIG_ETH_DESIGNWARE=y ++CONFIG_GMAC_ROCKCHIP=y ++CONFIG_PMIC_RK8XX=y ++CONFIG_REGULATOR_PWM=y ++CONFIG_REGULATOR_RK8XX=y ++CONFIG_PWM_ROCKCHIP=y ++CONFIG_RAM_RK3399_LPDDR4=y ++CONFIG_BAUDRATE=1500000 ++CONFIG_DEBUG_UART_SHIFT=2 ++CONFIG_SYSRESET=y ++CONFIG_USB=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_DWC3=y ++CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_EHCI_GENERIC=y ++CONFIG_USB_KEYBOARD=y ++CONFIG_USB_HOST_ETHER=y ++CONFIG_USB_ETHER_ASIX=y ++CONFIG_USB_ETHER_ASIX88179=y ++CONFIG_USB_ETHER_MCS7830=y ++CONFIG_USB_ETHER_RTL8152=y ++CONFIG_USB_ETHER_SMSC95XX=y ++CONFIG_DM_VIDEO=y ++CONFIG_DISPLAY=y ++CONFIG_VIDEO_ROCKCHIP=y ++CONFIG_DISPLAY_ROCKCHIP_HDMI=y ++CONFIG_SPL_TINY_MEMSET=y ++CONFIG_ERRNO_STR=y diff --git a/root/package/boot/uboot-rockchip/patches/306-rockchip-rk3399-Add-support-for-Rongpin-king3399.patch b/root/package/boot/uboot-rockchip/patches/306-rockchip-rk3399-Add-support-for-Rongpin-king3399.patch new file mode 100755 index 00000000..837f5864 --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/306-rockchip-rk3399-Add-support-for-Rongpin-king3399.patch @@ -0,0 +1,68 @@ +--- /dev/null ++++ b/configs/rongpin-king3399-rk3399_defconfig +@@ -0,0 +1,65 @@ ++CONFIG_ARM=y ++CONFIG_SKIP_LOWLEVEL_INIT=y ++CONFIG_COUNTER_FREQUENCY=24000000 ++CONFIG_ARCH_ROCKCHIP=y ++CONFIG_SYS_TEXT_BASE=0x00200000 ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_ENV_OFFSET=0x3F8000 ++CONFIG_DEFAULT_DEVICE_TREE="rk3399-nanopi-r4se" ++CONFIG_ROCKCHIP_RK3399=y ++CONFIG_TARGET_EVB_RK3399=y ++CONFIG_DEBUG_UART_BASE=0xFF1A0000 ++CONFIG_DEBUG_UART_CLOCK=24000000 ++CONFIG_SYS_LOAD_ADDR=0x800800 ++CONFIG_DEBUG_UART=y ++CONFIG_DEFAULT_FDT_FILE="rockchip/rk3399-nanopi-r4se.dtb" ++CONFIG_DISPLAY_BOARDINFO_LATE=y ++# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set ++CONFIG_SPL_STACK_R=y ++CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x10000 ++CONFIG_TPL=y ++CONFIG_CMD_BOOTZ=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_MMC=y ++CONFIG_CMD_USB=y ++# CONFIG_CMD_SETEXPR is not set ++CONFIG_CMD_TIME=y ++CONFIG_SPL_OF_CONTROL=y ++CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" ++CONFIG_ENV_IS_IN_MMC=y ++CONFIG_SYS_RELOC_GD_ENV_ADDR=y ++CONFIG_ROCKCHIP_GPIO=y ++CONFIG_SYS_I2C_ROCKCHIP=y ++CONFIG_MMC_DW=y ++CONFIG_MMC_DW_ROCKCHIP=y ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_ROCKCHIP=y ++CONFIG_DM_ETH=y ++CONFIG_ETH_DESIGNWARE=y ++CONFIG_GMAC_ROCKCHIP=y ++CONFIG_PMIC_RK8XX=y ++CONFIG_REGULATOR_PWM=y ++CONFIG_REGULATOR_RK8XX=y ++CONFIG_PWM_ROCKCHIP=y ++CONFIG_RAM_RK3399_LPDDR4=y ++CONFIG_BAUDRATE=1500000 ++CONFIG_DEBUG_UART_SHIFT=2 ++CONFIG_SYSRESET=y ++CONFIG_USB=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_DWC3=y ++CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_EHCI_GENERIC=y ++CONFIG_USB_KEYBOARD=y ++CONFIG_USB_HOST_ETHER=y ++CONFIG_USB_ETHER_ASIX=y ++CONFIG_USB_ETHER_ASIX88179=y ++CONFIG_USB_ETHER_MCS7830=y ++CONFIG_USB_ETHER_RTL8152=y ++CONFIG_USB_ETHER_SMSC95XX=y ++CONFIG_DM_VIDEO=y ++CONFIG_DISPLAY=y ++CONFIG_VIDEO_ROCKCHIP=y ++CONFIG_DISPLAY_ROCKCHIP_HDMI=y ++CONFIG_SPL_TINY_MEMSET=y ++CONFIG_ERRNO_STR=y diff --git a/root/package/boot/uboot-rockchip/patches/311-rockchip-rk3568-Add-support-for-ezpro_mrkaio-m68s.patch b/root/package/boot/uboot-rockchip/patches/311-rockchip-rk3568-Add-support-for-ezpro_mrkaio-m68s.patch new file mode 100644 index 00000000..f780ecb6 --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/311-rockchip-rk3568-Add-support-for-ezpro_mrkaio-m68s.patch @@ -0,0 +1,406 @@ +--- a/arch/arm/dts/Makefile ++++ b/arch/arm/dts/Makefile +@@ -171,6 +171,7 @@ dtb-$(CONFIG_ROCKCHIP_RK3399) += \ + dtb-$(CONFIG_ROCKCHIP_RK3568) += \ + rk3568-bpi-r2-pro.dtb \ + rk3568-evb.dtb \ ++ rk3568-mrkaio-m68s.dtb \ + rk3568-nanopi-r5s.dtb \ + rk3566-quartz64-a.dtb \ + rk3568-rock-3a.dtb +--- /dev/null ++++ b/arch/arm/dts/rk3568-mrkaio-m68s-u-boot.dtsi +@@ -0,0 +1,21 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++#include "rk3568-u-boot.dtsi" ++ ++/ { ++ chosen { ++ stdout-path = &uart2; ++ u-boot,spl-boot-order = "same-as-spl", &sdmmc0, &sdhci; ++ }; ++}; ++ ++&sdmmc0 { ++ bus-width = <4>; ++ u-boot,spl-fifo-mode; ++}; ++ ++&uart2 { ++ u-boot,dm-spl; ++ clock-frequency = <24000000>; ++ status = "okay"; ++}; +--- /dev/null ++++ b/arch/arm/dts/rk3568-mrkaio-m68s.dts +@@ -0,0 +1,268 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++#include "rk3568-evb.dts" ++ ++/ { ++ model = "EZPRO Mrkaio M68S"; ++ compatible = "ezpro,mrkaio-m68s", "rockchip,rk3568"; ++ ++ aliases { ++ mmc0 = &sdmmc0; ++ mmc1 = &sdhci; ++ }; ++}; ++ ++&cpu0 { ++ cpu-supply = <&vdd_cpu>; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vdd_cpu>; ++}; ++ ++&cpu2 { ++ cpu-supply = <&vdd_cpu>; ++}; ++ ++&cpu3 { ++ cpu-supply = <&vdd_cpu>; ++}; ++ ++&i2c0 { ++ status = "okay"; ++ ++ vdd_cpu: regulator@1c { ++ compatible = "tcs,tcs4525"; ++ reg = <0x1c>; ++ fcs,suspend-voltage-selector = <1>; ++ regulator-name = "vdd_cpu"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1150000>; ++ regulator-ramp-delay = <2300>; ++ vin-supply = <&vcc5v0_sys>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ rk809: pmic@20 { ++ compatible = "rockchip,rk809"; ++ reg = <0x20>; ++ interrupt-parent = <&gpio0>; ++ interrupts = ; ++ #clock-cells = <1>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_int>; ++ rockchip,system-power-controller; ++ ++ vcc1-supply = <&vcc3v3_sys>; ++ vcc2-supply = <&vcc3v3_sys>; ++ vcc3-supply = <&vcc3v3_sys>; ++ vcc4-supply = <&vcc3v3_sys>; ++ vcc5-supply = <&vcc3v3_sys>; ++ vcc6-supply = <&vcc3v3_sys>; ++ vcc7-supply = <&vcc3v3_sys>; ++ vcc8-supply = <&vcc3v3_sys>; ++ vcc9-supply = <&vcc3v3_sys>; ++ wakeup-source; ++ ++ regulators { ++ vdd_logic: DCDC_REG1 { ++ regulator-name = "vdd_logic"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-init-microvolt = <900000>; ++ regulator-initial-mode = <0x2>; ++ regulator-min-microvolt = <500000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-ramp-delay = <6001>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_gpu: DCDC_REG2 { ++ regulator-name = "vdd_gpu"; ++ regulator-always-on; ++ regulator-init-microvolt = <900000>; ++ regulator-initial-mode = <0x2>; ++ regulator-min-microvolt = <500000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-ramp-delay = <6001>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_ddr: DCDC_REG3 { ++ regulator-name = "vcc_ddr"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-initial-mode = <0x2>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vdd_npu: DCDC_REG4 { ++ regulator-name = "vdd_npu"; ++ regulator-init-microvolt = <900000>; ++ regulator-initial-mode = <0x2>; ++ regulator-min-microvolt = <500000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-ramp-delay = <6001>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_1v8: DCDC_REG5 { ++ regulator-name = "vcc_1v8"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdda0v9_image: LDO_REG1 { ++ regulator-name = "vdda0v9_image"; ++ regulator-min-microvolt = <900000>; ++ regulator-max-microvolt = <900000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdda_0v9: LDO_REG2 { ++ regulator-name = "vdda_0v9"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <900000>; ++ regulator-max-microvolt = <900000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdda0v9_pmu: LDO_REG3 { ++ regulator-name = "vdda0v9_pmu"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <900000>; ++ regulator-max-microvolt = <900000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <900000>; ++ }; ++ }; ++ ++ vccio_acodec: LDO_REG4 { ++ regulator-name = "vccio_acodec"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vccio_sd: LDO_REG5 { ++ regulator-name = "vccio_sd"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc3v3_pmu: LDO_REG6 { ++ regulator-name = "vcc3v3_pmu"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vcca_1v8: LDO_REG7 { ++ regulator-name = "vcca_1v8"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcca1v8_pmu: LDO_REG8 { ++ regulator-name = "vcca1v8_pmu"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcca1v8_image: LDO_REG9 { ++ regulator-name = "vcca1v8_image"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_3v3: SWITCH_REG1 { ++ regulator-name = "vcc_3v3"; ++ regulator-always-on; ++ regulator-boot-on; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc3v3_sd: SWITCH_REG2 { ++ regulator-name = "vcc3v3_sd"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&pinctrl { ++ pmic { ++ pmic_int: pmic_int { ++ rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++}; +--- /dev/null ++++ b/configs/mrkaio-m68s-rk3568_defconfig +@@ -0,0 +1,98 @@ ++CONFIG_ARM=y ++CONFIG_SKIP_LOWLEVEL_INIT=y ++CONFIG_ARCH_ROCKCHIP=y ++CONFIG_SYS_TEXT_BASE=0x00a00000 ++CONFIG_SPL_LIBCOMMON_SUPPORT=y ++CONFIG_SPL_LIBGENERIC_SUPPORT=y ++CONFIG_NR_DRAM_BANKS=2 ++CONFIG_DEFAULT_DEVICE_TREE="rk3568-mrkaio-m68s" ++CONFIG_ROCKCHIP_RK3568=y ++CONFIG_SPL_ROCKCHIP_BACK_TO_BROM=y ++CONFIG_SPL_ROCKCHIP_COMMON_BOARD=y ++CONFIG_SPL_MMC=y ++CONFIG_SPL_SERIAL=y ++CONFIG_SPL_STACK_R_ADDR=0x600000 ++CONFIG_TARGET_EVB_RK3568=y ++CONFIG_DEBUG_UART_BASE=0xFE660000 ++CONFIG_DEBUG_UART_CLOCK=24000000 ++CONFIG_DEBUG_UART=y ++CONFIG_SYS_LOAD_ADDR=0xc00800 ++CONFIG_API=y ++CONFIG_FIT=y ++CONFIG_FIT_VERBOSE=y ++CONFIG_SPL_LOAD_FIT=y ++CONFIG_OF_SYSTEM_SETUP=y ++CONFIG_DEFAULT_FDT_FILE="rockchip/rk3568-mrkaio-m68s.dtb" ++# CONFIG_SYS_DEVICE_NULLDEV is not set ++CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS=2 ++# CONFIG_DISPLAY_CPUINFO is not set ++CONFIG_DISPLAY_BOARDINFO_LATE=y ++# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set ++CONFIG_SPL_STACK_R=y ++CONFIG_SPL_SEPARATE_BSS=y ++CONFIG_SPL_ATF=y ++CONFIG_SPL_ATF_LOAD_IMAGE_V2=y ++CONFIG_CMD_BIND=y ++CONFIG_CMD_CLK=y ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_I2C=y ++CONFIG_CMD_MMC=y ++CONFIG_CMD_USB=y ++# CONFIG_CMD_SETEXPR is not set ++CONFIG_CMD_PMIC=y ++CONFIG_CMD_REGULATOR=y ++# CONFIG_SPL_DOS_PARTITION is not set ++CONFIG_SPL_OF_CONTROL=y ++CONFIG_OF_LIVE=y ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_SPL_DM_WARN=y ++CONFIG_SPL_REGMAP=y ++CONFIG_SPL_SYSCON=y ++CONFIG_SPL_CLK=y ++CONFIG_ROCKCHIP_GPIO=y ++CONFIG_ROCKCHIP_GPIO_V2=y ++CONFIG_SYS_I2C_ROCKCHIP=y ++CONFIG_MISC=y ++CONFIG_MMC_HS200_SUPPORT=y ++CONFIG_SPL_MMC_HS200_SUPPORT=y ++CONFIG_MMC_DW=y ++CONFIG_MMC_DW_ROCKCHIP=y ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_SDMA=y ++CONFIG_MMC_SDHCI_ROCKCHIP=y ++CONFIG_DM_ETH=y ++CONFIG_ETH_DESIGNWARE=y ++CONFIG_GMAC_ROCKCHIP=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_DM_PMIC=y ++CONFIG_PMIC_RK8XX=y ++CONFIG_SPL_PMIC_RK8XX=y ++CONFIG_REGULATOR_PWM=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_SPL_DM_REGULATOR_FIXED=y ++CONFIG_DM_REGULATOR_GPIO=y ++CONFIG_REGULATOR_RK8XX=y ++CONFIG_PWM_ROCKCHIP=y ++CONFIG_SPL_RAM=y ++CONFIG_DM_RESET=y ++CONFIG_BAUDRATE=1500000 ++CONFIG_DEBUG_UART_SHIFT=2 ++CONFIG_SYSRESET=y ++CONFIG_SYSRESET_PSCI=y ++CONFIG_USB=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_DWC3=y ++CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_EHCI_GENERIC=y ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_GENERIC=y ++CONFIG_USB_DWC3=y ++CONFIG_USB_DWC3_GENERIC=y ++CONFIG_ROCKCHIP_USB2_PHY=y ++CONFIG_USB_KEYBOARD=y ++CONFIG_USB_HOST_ETHER=y ++CONFIG_USB_ETHER_LAN75XX=y ++CONFIG_USB_ETHER_LAN78XX=y ++CONFIG_USB_ETHER_SMSC95XX=y ++CONFIG_ERRNO_STR=y diff --git a/root/package/boot/uboot-rockchip/patches/311-rockchip-rk3568-Add-support-for-radxa_rock-pi-e25.patch b/root/package/boot/uboot-rockchip/patches/311-rockchip-rk3568-Add-support-for-radxa_rock-pi-e25.patch new file mode 100644 index 00000000..1c1f8e5f --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/311-rockchip-rk3568-Add-support-for-radxa_rock-pi-e25.patch @@ -0,0 +1,148 @@ +--- a/arch/arm/dts/Makefile ++++ b/arch/arm/dts/Makefile +@@ -174,7 +174,8 @@ rk3568-evb.dtb \ + rk3568-mrkaio-m68s.dtb \ + rk3568-nanopi-r5s.dtb \ + rk3566-quartz64-a.dtb \ +- rk3568-rock-3a.dtb ++ rk3568-rock-3a.dtb \ ++ rk3568-rock-pi-e25.dtb + + dtb-$(CONFIG_ROCKCHIP_RV1108) += \ + rv1108-elgin-r1.dtb \ +--- /dev/null ++++ b/arch/arm/dts/rk3568-rock-pi-e25-u-boot.dtsi +@@ -0,0 +1,21 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++#include "rk3568-u-boot.dtsi" ++ ++/ { ++ chosen { ++ stdout-path = &uart2; ++ u-boot,spl-boot-order = "same-as-spl", &sdmmc0, &sdhci; ++ }; ++}; ++ ++&sdmmc0 { ++ bus-width = <4>; ++ u-boot,spl-fifo-mode; ++}; ++ ++&uart2 { ++ u-boot,dm-spl; ++ clock-frequency = <24000000>; ++ status = "okay"; ++}; +--- /dev/null ++++ b/arch/arm/dts/rk3568-rock-pi-e25.dts +@@ -0,0 +1,8 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++#include "rk3568-evb.dts" ++ ++/ { ++ model = "Radxa ROCK Pi E25"; ++ compatible = "radxa,rockpi-e25", "rockchip,rk3568"; ++}; +--- /dev/null ++++ b/configs/rock-pi-e25-rk3568_defconfig +@@ -0,0 +1,98 @@ ++CONFIG_ARM=y ++CONFIG_SKIP_LOWLEVEL_INIT=y ++CONFIG_ARCH_ROCKCHIP=y ++CONFIG_SYS_TEXT_BASE=0x00a00000 ++CONFIG_SPL_LIBCOMMON_SUPPORT=y ++CONFIG_SPL_LIBGENERIC_SUPPORT=y ++CONFIG_NR_DRAM_BANKS=2 ++CONFIG_DEFAULT_DEVICE_TREE="rk3568-rock-pi-e25" ++CONFIG_ROCKCHIP_RK3568=y ++CONFIG_SPL_ROCKCHIP_BACK_TO_BROM=y ++CONFIG_SPL_ROCKCHIP_COMMON_BOARD=y ++CONFIG_SPL_MMC=y ++CONFIG_SPL_SERIAL=y ++CONFIG_SPL_STACK_R_ADDR=0x600000 ++CONFIG_TARGET_EVB_RK3568=y ++CONFIG_DEBUG_UART_BASE=0xFE660000 ++CONFIG_DEBUG_UART_CLOCK=24000000 ++CONFIG_DEBUG_UART=y ++CONFIG_SYS_LOAD_ADDR=0xc00800 ++CONFIG_API=y ++CONFIG_FIT=y ++CONFIG_FIT_VERBOSE=y ++CONFIG_SPL_LOAD_FIT=y ++CONFIG_OF_SYSTEM_SETUP=y ++CONFIG_DEFAULT_FDT_FILE="rockchip/rk3568-rock-pi-e25.dtb" ++# CONFIG_SYS_DEVICE_NULLDEV is not set ++CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS=1 ++# CONFIG_DISPLAY_CPUINFO is not set ++CONFIG_DISPLAY_BOARDINFO_LATE=y ++# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set ++CONFIG_SPL_STACK_R=y ++CONFIG_SPL_SEPARATE_BSS=y ++CONFIG_SPL_ATF=y ++CONFIG_SPL_ATF_LOAD_IMAGE_V2=y ++CONFIG_CMD_BIND=y ++CONFIG_CMD_CLK=y ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_I2C=y ++CONFIG_CMD_MMC=y ++CONFIG_CMD_USB=y ++# CONFIG_CMD_SETEXPR is not set ++CONFIG_CMD_PMIC=y ++CONFIG_CMD_REGULATOR=y ++# CONFIG_SPL_DOS_PARTITION is not set ++CONFIG_SPL_OF_CONTROL=y ++CONFIG_OF_LIVE=y ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_SPL_DM_WARN=y ++CONFIG_SPL_REGMAP=y ++CONFIG_SPL_SYSCON=y ++CONFIG_SPL_CLK=y ++CONFIG_ROCKCHIP_GPIO=y ++CONFIG_ROCKCHIP_GPIO_V2=y ++CONFIG_SYS_I2C_ROCKCHIP=y ++CONFIG_MISC=y ++CONFIG_MMC_HS200_SUPPORT=y ++CONFIG_SPL_MMC_HS200_SUPPORT=y ++CONFIG_MMC_DW=y ++CONFIG_MMC_DW_ROCKCHIP=y ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_SDMA=y ++CONFIG_MMC_SDHCI_ROCKCHIP=y ++CONFIG_DM_ETH=y ++CONFIG_ETH_DESIGNWARE=y ++CONFIG_GMAC_ROCKCHIP=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_DM_PMIC=y ++CONFIG_PMIC_RK8XX=y ++CONFIG_SPL_PMIC_RK8XX=y ++CONFIG_REGULATOR_PWM=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_SPL_DM_REGULATOR_FIXED=y ++CONFIG_DM_REGULATOR_GPIO=y ++CONFIG_REGULATOR_RK8XX=y ++CONFIG_PWM_ROCKCHIP=y ++CONFIG_SPL_RAM=y ++CONFIG_DM_RESET=y ++CONFIG_BAUDRATE=1500000 ++CONFIG_DEBUG_UART_SHIFT=2 ++CONFIG_SYSRESET=y ++CONFIG_SYSRESET_PSCI=y ++CONFIG_USB=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_DWC3=y ++CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_EHCI_GENERIC=y ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_GENERIC=y ++CONFIG_USB_DWC3=y ++CONFIG_USB_DWC3_GENERIC=y ++CONFIG_ROCKCHIP_USB2_PHY=y ++CONFIG_USB_KEYBOARD=y ++CONFIG_USB_HOST_ETHER=y ++CONFIG_USB_ETHER_LAN75XX=y ++CONFIG_USB_ETHER_LAN78XX=y ++CONFIG_USB_ETHER_SMSC95XX=y ++CONFIG_ERRNO_STR=y diff --git a/root/package/boot/uboot-rockchip/patches/312-rockchip-rk3568-Add-support-for-hinlink-opc-h68k.patch b/root/package/boot/uboot-rockchip/patches/312-rockchip-rk3568-Add-support-for-hinlink-opc-h68k.patch new file mode 100644 index 00000000..69a685d3 --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/312-rockchip-rk3568-Add-support-for-hinlink-opc-h68k.patch @@ -0,0 +1,415 @@ +--- a/arch/arm/dts/Makefile ++++ b/arch/arm/dts/Makefile +@@ -171,6 +171,7 @@ dtb-$(CONFIG_ROCKCHIP_RK3399) += \ + dtb-$(CONFIG_ROCKCHIP_RK3568) += \ + rk3568-bpi-r2-pro.dtb \ + rk3568-evb.dtb \ ++ rk3568-opc-h68k.dtb \ + rk3568-mrkaio-m68s.dtb \ + rk3568-nanopi-r5s.dtb \ + rk3566-quartz64-a.dtb \ +--- /dev/null ++++ b/arch/arm/dts/rk3568-opc-h68k-u-boot.dtsi +@@ -0,0 +1,21 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++#include "rk3568-u-boot.dtsi" ++ ++/ { ++ chosen { ++ stdout-path = &uart2; ++ u-boot,spl-boot-order = "same-as-spl", &sdmmc0, &sdhci; ++ }; ++}; ++ ++&sdmmc0 { ++ bus-width = <4>; ++ u-boot,spl-fifo-mode; ++}; ++ ++&uart2 { ++ u-boot,dm-spl; ++ clock-frequency = <24000000>; ++ status = "okay"; ++}; +--- /dev/null ++++ b/arch/arm/dts/rk3568-opc-h68k.dts +@@ -0,0 +1,277 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++#include "rk3568-evb.dts" ++ ++/ { ++ model = "HINLINK OPC-H68K Board"; ++ compatible = "hinlink,opc-h68k", "rockchip,rk3568"; ++ ++ aliases { ++ mmc0 = &sdmmc0; ++ mmc1 = &sdhci; ++ }; ++}; ++ ++&cpu0 { ++ cpu-supply = <&vdd_cpu>; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vdd_cpu>; ++}; ++ ++&cpu2 { ++ cpu-supply = <&vdd_cpu>; ++}; ++ ++&cpu3 { ++ cpu-supply = <&vdd_cpu>; ++}; ++ ++&i2c0 { ++ status = "okay"; ++ ++ vdd_cpu: regulator@1c { ++ compatible = "tcs,tcs4525"; ++ reg = <0x1c>; ++ fcs,suspend-voltage-selector = <1>; ++ regulator-name = "vdd_cpu"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <1150000>; ++ regulator-ramp-delay = <2300>; ++ vin-supply = <&vcc5v0_sys>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ rk809: pmic@20 { ++ compatible = "rockchip,rk809"; ++ reg = <0x20>; ++ interrupt-parent = <&gpio0>; ++ interrupts = ; ++ assigned-clocks = <&cru I2S1_MCLKOUT_TX>; ++ assigned-clock-parents = <&cru CLK_I2S1_8CH_TX>; ++ #clock-cells = <1>; ++ clock-names = "mclk"; ++ clocks = <&cru I2S1_MCLKOUT_TX>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_int>, <&i2s1m0_mclk>; ++ rockchip,system-power-controller; ++ #sound-dai-cells = <0>; ++ vcc1-supply = <&vcc3v3_sys>; ++ vcc2-supply = <&vcc3v3_sys>; ++ vcc3-supply = <&vcc3v3_sys>; ++ vcc4-supply = <&vcc3v3_sys>; ++ vcc5-supply = <&vcc3v3_sys>; ++ vcc6-supply = <&vcc3v3_sys>; ++ vcc7-supply = <&vcc3v3_sys>; ++ vcc8-supply = <&vcc3v3_sys>; ++ vcc9-supply = <&vcc3v3_sys>; ++ wakeup-source; ++ ++ regulators { ++ vdd_logic: DCDC_REG1 { ++ regulator-name = "vdd_logic"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-init-microvolt = <900000>; ++ regulator-initial-mode = <0x2>; ++ regulator-min-microvolt = <500000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-ramp-delay = <6001>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_gpu: DCDC_REG2 { ++ regulator-name = "vdd_gpu"; ++ regulator-always-on; ++ regulator-init-microvolt = <900000>; ++ regulator-initial-mode = <0x2>; ++ regulator-min-microvolt = <500000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-ramp-delay = <6001>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_ddr: DCDC_REG3 { ++ regulator-name = "vcc_ddr"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-initial-mode = <0x2>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vdd_npu: DCDC_REG4 { ++ regulator-name = "vdd_npu"; ++ regulator-init-microvolt = <900000>; ++ regulator-initial-mode = <0x2>; ++ regulator-min-microvolt = <500000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-ramp-delay = <6001>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_1v8: DCDC_REG5 { ++ regulator-name = "vcc_1v8"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdda0v9_image: LDO_REG1 { ++ regulator-name = "vdda0v9_image"; ++ regulator-min-microvolt = <900000>; ++ regulator-max-microvolt = <900000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdda_0v9: LDO_REG2 { ++ regulator-name = "vdda_0v9"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <900000>; ++ regulator-max-microvolt = <900000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdda0v9_pmu: LDO_REG3 { ++ regulator-name = "vdda0v9_pmu"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <900000>; ++ regulator-max-microvolt = <900000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <900000>; ++ }; ++ }; ++ ++ vccio_acodec: LDO_REG4 { ++ regulator-name = "vccio_acodec"; ++ regulator-always-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vccio_sd: LDO_REG5 { ++ regulator-name = "vccio_sd"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc3v3_pmu: LDO_REG6 { ++ regulator-name = "vcc3v3_pmu"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vcca_1v8: LDO_REG7 { ++ regulator-name = "vcca_1v8"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcca1v8_pmu: LDO_REG8 { ++ regulator-name = "vcca1v8_pmu"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcca1v8_image: LDO_REG9 { ++ regulator-name = "vcca1v8_image"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_3v3: SWITCH_REG1 { ++ regulator-name = "vcc_3v3"; ++ regulator-always-on; ++ regulator-boot-on; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc3v3_sd: SWITCH_REG2 { ++ regulator-name = "vcc3v3_sd"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ }; ++ ++ codec { ++ mic-in-differential; ++ }; ++ }; ++}; ++ ++&pinctrl { ++ pmic { ++ pmic_int: pmic_int { ++ rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++}; +--- /dev/null ++++ b/configs/opc-h68k-rk3568_defconfig +@@ -0,0 +1,98 @@ ++CONFIG_ARM=y ++CONFIG_SKIP_LOWLEVEL_INIT=y ++CONFIG_ARCH_ROCKCHIP=y ++CONFIG_SYS_TEXT_BASE=0x00a00000 ++CONFIG_SPL_LIBCOMMON_SUPPORT=y ++CONFIG_SPL_LIBGENERIC_SUPPORT=y ++CONFIG_NR_DRAM_BANKS=2 ++CONFIG_DEFAULT_DEVICE_TREE="rk3568-opc-h68k" ++CONFIG_ROCKCHIP_RK3568=y ++CONFIG_SPL_ROCKCHIP_BACK_TO_BROM=y ++CONFIG_SPL_ROCKCHIP_COMMON_BOARD=y ++CONFIG_SPL_MMC=y ++CONFIG_SPL_SERIAL=y ++CONFIG_SPL_STACK_R_ADDR=0x600000 ++CONFIG_TARGET_EVB_RK3568=y ++CONFIG_DEBUG_UART_BASE=0xFE660000 ++CONFIG_DEBUG_UART_CLOCK=24000000 ++CONFIG_DEBUG_UART=y ++CONFIG_SYS_LOAD_ADDR=0xc00800 ++CONFIG_API=y ++CONFIG_FIT=y ++CONFIG_FIT_VERBOSE=y ++CONFIG_SPL_LOAD_FIT=y ++CONFIG_OF_SYSTEM_SETUP=y ++CONFIG_DEFAULT_FDT_FILE="rockchip/rk3568-opc-h68k.dtb" ++# CONFIG_SYS_DEVICE_NULLDEV is not set ++CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS=2 ++# CONFIG_DISPLAY_CPUINFO is not set ++CONFIG_DISPLAY_BOARDINFO_LATE=y ++# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set ++CONFIG_SPL_STACK_R=y ++CONFIG_SPL_SEPARATE_BSS=y ++CONFIG_SPL_ATF=y ++CONFIG_SPL_ATF_LOAD_IMAGE_V2=y ++CONFIG_CMD_BIND=y ++CONFIG_CMD_CLK=y ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_I2C=y ++CONFIG_CMD_MMC=y ++CONFIG_CMD_USB=y ++# CONFIG_CMD_SETEXPR is not set ++CONFIG_CMD_PMIC=y ++CONFIG_CMD_REGULATOR=y ++# CONFIG_SPL_DOS_PARTITION is not set ++CONFIG_SPL_OF_CONTROL=y ++CONFIG_OF_LIVE=y ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_SPL_DM_WARN=y ++CONFIG_SPL_REGMAP=y ++CONFIG_SPL_SYSCON=y ++CONFIG_SPL_CLK=y ++CONFIG_ROCKCHIP_GPIO=y ++CONFIG_ROCKCHIP_GPIO_V2=y ++CONFIG_SYS_I2C_ROCKCHIP=y ++CONFIG_MISC=y ++CONFIG_MMC_HS200_SUPPORT=y ++CONFIG_SPL_MMC_HS200_SUPPORT=y ++CONFIG_MMC_DW=y ++CONFIG_MMC_DW_ROCKCHIP=y ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_SDMA=y ++CONFIG_MMC_SDHCI_ROCKCHIP=y ++CONFIG_DM_ETH=y ++CONFIG_ETH_DESIGNWARE=y ++CONFIG_GMAC_ROCKCHIP=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_DM_PMIC=y ++CONFIG_PMIC_RK8XX=y ++CONFIG_SPL_PMIC_RK8XX=y ++CONFIG_REGULATOR_PWM=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_SPL_DM_REGULATOR_FIXED=y ++CONFIG_DM_REGULATOR_GPIO=y ++CONFIG_REGULATOR_RK8XX=y ++CONFIG_PWM_ROCKCHIP=y ++CONFIG_SPL_RAM=y ++CONFIG_DM_RESET=y ++CONFIG_BAUDRATE=1500000 ++CONFIG_DEBUG_UART_SHIFT=2 ++CONFIG_SYSRESET=y ++CONFIG_SYSRESET_PSCI=y ++CONFIG_USB=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_DWC3=y ++CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_EHCI_GENERIC=y ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_GENERIC=y ++CONFIG_USB_DWC3=y ++CONFIG_USB_DWC3_GENERIC=y ++CONFIG_ROCKCHIP_USB2_PHY=y ++CONFIG_USB_KEYBOARD=y ++CONFIG_USB_HOST_ETHER=y ++CONFIG_USB_ETHER_LAN75XX=y ++CONFIG_USB_ETHER_LAN78XX=y ++CONFIG_USB_ETHER_SMSC95XX=y ++CONFIG_ERRNO_STR=y diff --git a/root/package/boot/uboot-rockchip/patches/313-rockchip-rk3568-Add-support-for-fastrhino-r66s.patch b/root/package/boot/uboot-rockchip/patches/313-rockchip-rk3568-Add-support-for-fastrhino-r66s.patch new file mode 100644 index 00000000..e7f7d6ae --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/313-rockchip-rk3568-Add-support-for-fastrhino-r66s.patch @@ -0,0 +1,140 @@ +--- a/arch/arm/dts/Makefile ++++ b/arch/arm/dts/Makefile +@@ -171,6 +171,7 @@ dtb-$(CONFIG_ROCKCHIP_RK3399) += \ + dtb-$(CONFIG_ROCKCHIP_RK3568) += \ + rk3568-bpi-r2-pro.dtb \ + rk3568-evb.dtb \ ++ rk3568-r66s.dtb \ + rk3568-opc-h68k.dtb \ + rk3568-mrkaio-m68s.dtb \ + rk3568-nanopi-r5s.dtb \ +--- /dev/null ++++ b/arch/arm/dts/rk3568-r66s-u-boot.dtsi +@@ -0,0 +1,21 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++#include "rk3568-u-boot.dtsi" ++ ++/ { ++ chosen { ++ stdout-path = &uart2; ++ u-boot,spl-boot-order = "same-as-spl", &sdmmc0, &sdhci; ++ }; ++}; ++ ++&sdmmc0 { ++ bus-width = <4>; ++ u-boot,spl-fifo-mode; ++}; ++ ++&uart2 { ++ u-boot,dm-spl; ++ clock-frequency = <24000000>; ++ status = "okay"; ++}; +--- /dev/null ++++ b/arch/arm/dts/rk3568-r66s.dts +@@ -0,0 +1,2 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++#include "rk3568-evb.dts" +--- /dev/null ++++ b/configs/r66s-rk3568_defconfig +@@ -0,0 +1,98 @@ ++CONFIG_ARM=y ++CONFIG_SKIP_LOWLEVEL_INIT=y ++CONFIG_ARCH_ROCKCHIP=y ++CONFIG_SYS_TEXT_BASE=0x00a00000 ++CONFIG_SPL_LIBCOMMON_SUPPORT=y ++CONFIG_SPL_LIBGENERIC_SUPPORT=y ++CONFIG_NR_DRAM_BANKS=2 ++CONFIG_DEFAULT_DEVICE_TREE="rk3568-r66s" ++CONFIG_ROCKCHIP_RK3568=y ++CONFIG_SPL_ROCKCHIP_BACK_TO_BROM=y ++CONFIG_SPL_ROCKCHIP_COMMON_BOARD=y ++CONFIG_SPL_MMC=y ++CONFIG_SPL_SERIAL=y ++CONFIG_SPL_STACK_R_ADDR=0x600000 ++CONFIG_TARGET_EVB_RK3568=y ++CONFIG_DEBUG_UART_BASE=0xFE660000 ++CONFIG_DEBUG_UART_CLOCK=24000000 ++CONFIG_DEBUG_UART=y ++CONFIG_SYS_LOAD_ADDR=0xc00800 ++CONFIG_API=y ++CONFIG_FIT=y ++CONFIG_FIT_VERBOSE=y ++CONFIG_SPL_LOAD_FIT=y ++CONFIG_OF_SYSTEM_SETUP=y ++CONFIG_DEFAULT_FDT_FILE="rockchip/rk3568-r66s.dtb" ++# CONFIG_SYS_DEVICE_NULLDEV is not set ++CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS=2 ++# CONFIG_DISPLAY_CPUINFO is not set ++CONFIG_DISPLAY_BOARDINFO_LATE=y ++# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set ++CONFIG_SPL_STACK_R=y ++CONFIG_SPL_SEPARATE_BSS=y ++CONFIG_SPL_ATF=y ++CONFIG_SPL_ATF_LOAD_IMAGE_V2=y ++CONFIG_CMD_BIND=y ++CONFIG_CMD_CLK=y ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_I2C=y ++CONFIG_CMD_MMC=y ++CONFIG_CMD_USB=y ++# CONFIG_CMD_SETEXPR is not set ++CONFIG_CMD_PMIC=y ++CONFIG_CMD_REGULATOR=y ++# CONFIG_SPL_DOS_PARTITION is not set ++CONFIG_SPL_OF_CONTROL=y ++CONFIG_OF_LIVE=y ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_SPL_DM_WARN=y ++CONFIG_SPL_REGMAP=y ++CONFIG_SPL_SYSCON=y ++CONFIG_SPL_CLK=y ++CONFIG_ROCKCHIP_GPIO=y ++CONFIG_ROCKCHIP_GPIO_V2=y ++CONFIG_SYS_I2C_ROCKCHIP=y ++CONFIG_MISC=y ++CONFIG_MMC_HS200_SUPPORT=y ++CONFIG_SPL_MMC_HS200_SUPPORT=y ++CONFIG_MMC_DW=y ++CONFIG_MMC_DW_ROCKCHIP=y ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_SDMA=y ++CONFIG_MMC_SDHCI_ROCKCHIP=y ++CONFIG_DM_ETH=y ++CONFIG_ETH_DESIGNWARE=y ++CONFIG_GMAC_ROCKCHIP=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_DM_PMIC=y ++CONFIG_PMIC_RK8XX=y ++CONFIG_SPL_PMIC_RK8XX=y ++CONFIG_REGULATOR_PWM=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_SPL_DM_REGULATOR_FIXED=y ++CONFIG_DM_REGULATOR_GPIO=y ++CONFIG_REGULATOR_RK8XX=y ++CONFIG_PWM_ROCKCHIP=y ++CONFIG_SPL_RAM=y ++CONFIG_DM_RESET=y ++CONFIG_BAUDRATE=1500000 ++CONFIG_DEBUG_UART_SHIFT=2 ++CONFIG_SYSRESET=y ++CONFIG_SYSRESET_PSCI=y ++CONFIG_USB=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_DWC3=y ++CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_EHCI_GENERIC=y ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_GENERIC=y ++CONFIG_USB_DWC3=y ++CONFIG_USB_DWC3_GENERIC=y ++CONFIG_ROCKCHIP_USB2_PHY=y ++CONFIG_USB_KEYBOARD=y ++CONFIG_USB_HOST_ETHER=y ++CONFIG_USB_ETHER_LAN75XX=y ++CONFIG_USB_ETHER_LAN78XX=y ++CONFIG_USB_ETHER_SMSC95XX=y ++CONFIG_ERRNO_STR=y diff --git a/root/package/boot/uboot-rockchip/patches/314-rockchip-rk3568-Add-support-for-Station-P2.patch b/root/package/boot/uboot-rockchip/patches/314-rockchip-rk3568-Add-support-for-Station-P2.patch new file mode 100644 index 00000000..3df47445 --- /dev/null +++ b/root/package/boot/uboot-rockchip/patches/314-rockchip-rk3568-Add-support-for-Station-P2.patch @@ -0,0 +1,77 @@ +From 18e3719c5d5b1573c29d137c1244ca23277750b2 Mon Sep 17 00:00:00 2001 +From: huangjf +Date: Thu, 7 Apr 2022 16:22:56 +0800 +Subject: [PATCH] rockchip: rk3568: Add support for Station P2 + +--- + configs/station-p2-rk3568_defconfig | 59 +++++++++++++++++++++++++++++ + 1 file changed, 59 insertions(+) + create mode 100644 configs/station-p2-rk3568_defconfig + +diff --git a/configs/station-p2-rk3568_defconfig b/configs/station-p2-rk3568_defconfig +new file mode 100644 +index 0000000000..435be99edf +--- /dev/null ++++ b/configs/station-p2-rk3568_defconfig +@@ -0,0 +1,59 @@ ++CONFIG_ARM=y ++CONFIG_SKIP_LOWLEVEL_INIT=y ++CONFIG_ARCH_ROCKCHIP=y ++CONFIG_SYS_TEXT_BASE=0x00a00000 ++CONFIG_SPL_LIBCOMMON_SUPPORT=y ++CONFIG_SPL_LIBGENERIC_SUPPORT=y ++CONFIG_NR_DRAM_BANKS=2 ++CONFIG_DEFAULT_DEVICE_TREE="rk3568-evb" ++CONFIG_ROCKCHIP_RK3568=y ++CONFIG_SPL_ROCKCHIP_BACK_TO_BROM=y ++CONFIG_SPL_ROCKCHIP_COMMON_BOARD=y ++CONFIG_SPL_MMC=y ++CONFIG_SPL_SERIAL=y ++CONFIG_SPL_STACK_R_ADDR=0x600000 ++CONFIG_TARGET_EVB_RK3568=y ++CONFIG_DEBUG_UART_BASE=0xFE660000 ++CONFIG_DEBUG_UART_CLOCK=24000000 ++CONFIG_DEBUG_UART=y ++CONFIG_SYS_LOAD_ADDR=0xc00800 ++CONFIG_FIT=y ++CONFIG_FIT_VERBOSE=y ++CONFIG_SPL_LOAD_FIT=y ++CONFIG_DEFAULT_FDT_FILE="rockchip/rk3568-evb.dtb" ++# CONFIG_DISPLAY_CPUINFO is not set ++CONFIG_DISPLAY_BOARDINFO_LATE=y ++# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set ++CONFIG_SPL_STACK_R=y ++CONFIG_SPL_SEPARATE_BSS=y ++CONFIG_SPL_ATF=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_MMC=y ++# CONFIG_CMD_SETEXPR is not set ++# CONFIG_SPL_DOS_PARTITION is not set ++CONFIG_SPL_OF_CONTROL=y ++CONFIG_OF_LIVE=y ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_SPL_REGMAP=y ++CONFIG_SPL_SYSCON=y ++CONFIG_SPL_CLK=y ++CONFIG_ROCKCHIP_GPIO=y ++CONFIG_SYS_I2C_ROCKCHIP=y ++CONFIG_MISC=y ++CONFIG_SUPPORT_EMMC_RPMB=y ++CONFIG_MMC_DW=y ++CONFIG_MMC_DW_ROCKCHIP=y ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_SDMA=y ++CONFIG_MMC_SDHCI_ROCKCHIP=y ++CONFIG_DM_ETH=y ++CONFIG_ETH_DESIGNWARE=y ++CONFIG_GMAC_ROCKCHIP=y ++CONFIG_REGULATOR_PWM=y ++CONFIG_PWM_ROCKCHIP=y ++CONFIG_SPL_RAM=y ++CONFIG_DM_RESET=y ++CONFIG_BAUDRATE=1500000 ++CONFIG_DEBUG_UART_SHIFT=2 ++CONFIG_SYSRESET=y ++CONFIG_ERRNO_STR=y +-- +2.20.1 diff --git a/root/package/boot/uboot-rockchip/src/of-platdata/nanopi-r2s-rk3328/dt-decl.h b/root/package/boot/uboot-rockchip/src/of-platdata/nanopi-r2s-rk3328/dt-decl.h deleted file mode 100644 index 0919e4ed..00000000 --- a/root/package/boot/uboot-rockchip/src/of-platdata/nanopi-r2s-rk3328/dt-decl.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * DO NOT MODIFY - * - * Declares externs for all device/uclass instances. - * This was generated by dtoc from a .dtb (device tree binary) file. - */ - -#include -#include - -/* driver declarations - these allow DM_DRIVER_GET() to be used */ -extern U_BOOT_DRIVER(rockchip_rk3328_cru); -extern U_BOOT_DRIVER(rockchip_rk3328_dmc); -extern U_BOOT_DRIVER(rockchip_rk3288_dw_mshc); -extern U_BOOT_DRIVER(ns16550_serial); -extern U_BOOT_DRIVER(rockchip_rk3328_grf); - -/* uclass driver declarations - needed for DM_UCLASS_DRIVER_REF() */ -extern UCLASS_DRIVER(clk); -extern UCLASS_DRIVER(mmc); -extern UCLASS_DRIVER(ram); -extern UCLASS_DRIVER(serial); -extern UCLASS_DRIVER(syscon); diff --git a/root/package/boot/uboot-rockchip/src/of-platdata/nanopi-r2s-rk3328/dt-plat.c b/root/package/boot/uboot-rockchip/src/of-platdata/nanopi-r2s-rk3328/dt-plat.c deleted file mode 100644 index e5b330c9..00000000 --- a/root/package/boot/uboot-rockchip/src/of-platdata/nanopi-r2s-rk3328/dt-plat.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * DO NOT MODIFY - * - * Declares the U_BOOT_DRIVER() records and platform data. - * This was generated by dtoc from a .dtb (device tree binary) file. - */ - -/* Allow use of U_BOOT_DRVINFO() in this file */ -#define DT_PLAT_C - -#include -#include -#include - -/* - * driver_info declarations, ordered by 'struct driver_info' linker_list idx: - * - * idx driver_info driver - * --- -------------------- -------------------- - * 0: clock_controller_at_ff440000 rockchip_rk3328_cru - * 1: dmc rockchip_rk3328_dmc - * 2: mmc_at_ff500000 rockchip_rk3288_dw_mshc - * 3: serial_at_ff130000 ns16550_serial - * 4: syscon_at_ff100000 rockchip_rk3328_grf - * --- -------------------- -------------------- - */ - -/* - * Node /clock-controller@ff440000 index 0 - * driver rockchip_rk3328_cru parent None - */ -static struct dtd_rockchip_rk3328_cru dtv_clock_controller_at_ff440000 = { - .reg = {0xff440000, 0x1000}, - .rockchip_grf = 0x3a, -}; -U_BOOT_DRVINFO(clock_controller_at_ff440000) = { - .name = "rockchip_rk3328_cru", - .plat = &dtv_clock_controller_at_ff440000, - .plat_size = sizeof(dtv_clock_controller_at_ff440000), - .parent_idx = -1, -}; - -/* - * Node /dmc index 1 - * driver rockchip_rk3328_dmc parent None - */ -static struct dtd_rockchip_rk3328_dmc dtv_dmc = { - .reg = {0xff400000, 0x1000, 0xff780000, 0x3000, 0xff100000, 0x1000, 0xff440000, 0x1000, - 0xff720000, 0x1000, 0xff798000, 0x1000}, - .rockchip_sdram_params = {0x1, 0xa, 0x2, 0x1, 0x0, 0x0, 0x11, 0x0, - 0x11, 0x0, 0x0, 0x94291288, 0x0, 0x27, 0x462, 0x15, - 0x242, 0xff, 0x14d, 0x0, 0x1, 0x0, 0x0, 0x0, - 0x43049010, 0x64, 0x28003b, 0xd0, 0x20053, 0xd4, 0x220000, 0xd8, - 0x100, 0xdc, 0x40000, 0xe0, 0x0, 0xe4, 0x110000, 0xe8, - 0x420, 0xec, 0x400, 0xf4, 0xf011f, 0x100, 0x9060b06, 0x104, - 0x20209, 0x108, 0x505040a, 0x10c, 0x40400c, 0x110, 0x5030206, 0x114, - 0x3030202, 0x120, 0x3030b03, 0x124, 0x20208, 0x180, 0x1000040, 0x184, - 0x0, 0x190, 0x7030003, 0x198, 0x5001100, 0x1a0, 0xc0400003, 0x240, - 0x6000604, 0x244, 0x201, 0x250, 0xf00, 0x490, 0x1, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0x4, 0xc, 0x28, 0xa, 0x2c, - 0x0, 0x30, 0x9, 0xffffffff, 0xffffffff, 0x77, 0x88, 0x79, - 0x79, 0x87, 0x97, 0x87, 0x78, 0x77, 0x78, 0x87, - 0x88, 0x87, 0x87, 0x77, 0x78, 0x78, 0x78, 0x78, - 0x78, 0x78, 0x78, 0x78, 0x78, 0x69, 0x9, 0x77, - 0x78, 0x77, 0x78, 0x77, 0x78, 0x77, 0x78, 0x77, - 0x79, 0x9, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, - 0x78, 0x78, 0x78, 0x69, 0x9, 0x77, 0x78, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x79, 0x9, - 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, - 0x78, 0x69, 0x9, 0x77, 0x78, 0x77, 0x78, 0x77, - 0x78, 0x77, 0x78, 0x77, 0x79, 0x9, 0x78, 0x78, - 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x69, - 0x9, 0x77, 0x78, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x79, 0x9}, -}; -U_BOOT_DRVINFO(dmc) = { - .name = "rockchip_rk3328_dmc", - .plat = &dtv_dmc, - .plat_size = sizeof(dtv_dmc), - .parent_idx = -1, -}; - -/* - * Node /mmc@ff500000 index 2 - * driver rockchip_rk3288_dw_mshc parent None - */ -static struct dtd_rockchip_rk3288_dw_mshc dtv_mmc_at_ff500000 = { - .bus_width = 0x4, - .cap_sd_highspeed = true, - .clocks = { - {0, {317}}, - {0, {33}}, - {0, {74}}, - {0, {78}},}, - .disable_wp = true, - .fifo_depth = 0x100, - .interrupts = {0x0, 0xc, 0x4}, - .max_frequency = 0x8f0d180, - .pinctrl_0 = {0x47, 0x48, 0x49, 0x4a}, - .pinctrl_names = "default", - .reg = {0xff500000, 0x4000}, - .sd_uhs_sdr104 = true, - .sd_uhs_sdr12 = true, - .sd_uhs_sdr25 = true, - .sd_uhs_sdr50 = true, - .u_boot_spl_fifo_mode = true, - .vmmc_supply = 0x4b, - .vqmmc_supply = 0x1e, -}; -U_BOOT_DRVINFO(mmc_at_ff500000) = { - .name = "rockchip_rk3288_dw_mshc", - .plat = &dtv_mmc_at_ff500000, - .plat_size = sizeof(dtv_mmc_at_ff500000), - .parent_idx = -1, -}; - -/* - * Node /serial@ff130000 index 3 - * driver ns16550_serial parent None - */ -static struct dtd_ns16550_serial dtv_serial_at_ff130000 = { - .clock_frequency = 0x16e3600, - .clocks = { - {0, {40}}, - {0, {212}},}, - .dma_names = {"tx", "rx"}, - .dmas = {0x10, 0x6, 0x10, 0x7}, - .interrupts = {0x0, 0x39, 0x4}, - .pinctrl_0 = 0x26, - .pinctrl_names = "default", - .reg = {0xff130000, 0x100}, - .reg_io_width = 0x4, - .reg_shift = 0x2, -}; -U_BOOT_DRVINFO(serial_at_ff130000) = { - .name = "ns16550_serial", - .plat = &dtv_serial_at_ff130000, - .plat_size = sizeof(dtv_serial_at_ff130000), - .parent_idx = -1, -}; - -/* - * Node /syscon@ff100000 index 4 - * driver rockchip_rk3328_grf parent None - */ -static struct dtd_rockchip_rk3328_grf dtv_syscon_at_ff100000 = { - .reg = {0xff100000, 0x1000}, -}; -U_BOOT_DRVINFO(syscon_at_ff100000) = { - .name = "rockchip_rk3328_grf", - .plat = &dtv_syscon_at_ff100000, - .plat_size = sizeof(dtv_syscon_at_ff100000), - .parent_idx = -1, -}; - diff --git a/root/package/boot/uboot-rockchip/src/of-platdata/nanopi-r2s-rk3328/dt-structs-gen.h b/root/package/boot/uboot-rockchip/src/of-platdata/nanopi-r2s-rk3328/dt-structs-gen.h deleted file mode 100644 index b1ff08a9..00000000 --- a/root/package/boot/uboot-rockchip/src/of-platdata/nanopi-r2s-rk3328/dt-structs-gen.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * DO NOT MODIFY - * - * Defines the structs used to hold devicetree data. - * This was generated by dtoc from a .dtb (device tree binary) file. - */ - -#include -#include -struct dtd_ns16550_serial { - fdt32_t clock_frequency; - struct phandle_1_arg clocks[2]; - const char * dma_names[2]; - fdt32_t dmas[4]; - fdt32_t interrupts[3]; - fdt32_t pinctrl_0; - const char * pinctrl_names; - fdt64_t reg[2]; - fdt32_t reg_io_width; - fdt32_t reg_shift; -}; -struct dtd_rockchip_rk3288_dw_mshc { - fdt32_t bus_width; - bool cap_sd_highspeed; - struct phandle_1_arg clocks[4]; - bool disable_wp; - fdt32_t fifo_depth; - fdt32_t interrupts[3]; - fdt32_t max_frequency; - fdt32_t pinctrl_0[4]; - const char * pinctrl_names; - fdt64_t reg[2]; - bool sd_uhs_sdr104; - bool sd_uhs_sdr12; - bool sd_uhs_sdr25; - bool sd_uhs_sdr50; - bool u_boot_spl_fifo_mode; - fdt32_t vmmc_supply; - fdt32_t vqmmc_supply; -}; -struct dtd_rockchip_rk3328_cru { - fdt64_t reg[2]; - fdt32_t rockchip_grf; -}; -struct dtd_rockchip_rk3328_dmc { - fdt64_t reg[12]; - fdt32_t rockchip_sdram_params[196]; -}; -struct dtd_rockchip_rk3328_grf { - fdt64_t reg[2]; -}; From 2d9c2e06255cd435d6d0461b774ad540ff81aa43 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 18 Nov 2022 18:11:43 +0100 Subject: [PATCH 043/102] Add r5s support. From coolsnowwold repo --- root/target/linux/rockchip/armv8/config-5.15 | 89 +- .../boot/dts/rockchip/rk3399-rock-pi-4.dts | 19 - .../rockchip/rk3328-dram-default-timing.dtsi | 311 ++ .../rockchip/rk3328-dram-nanopi2-timing.dtsi | 311 ++ .../arch/arm64/boot/dts/rockchip/rk3368.dtsi | 1393 ++++++++ .../dts/rockchip/rk3399-guangmiao-g4c.dts | 664 ++++ .../boot/dts/rockchip/rk3399-king3399.dts | 1127 ++++++ .../boot/dts/rockchip/rk3399-nanopi-r4se.dts | 18 + .../boot/dts/rockchip/rk3568-fastrhino.dtsi | 530 +++ .../boot/dts/rockchip/rk3568-mrkaio-m68s.dts | 654 ++++ .../boot/dts/rockchip/rk3568-nanopi-r5s.dts | 710 ++++ .../boot/dts/rockchip/rk3568-opc-h68k.dts | 725 ++++ .../boot/dts/rockchip/rk3568-pinctrl.dtsi | 3120 +++++++++++++++++ .../arm64/boot/dts/rockchip/rk3568-r66s.dts | 26 + .../arm64/boot/dts/rockchip/rk3568-r68s.dts | 83 + .../arm64/boot/dts/rockchip/rk3568-roc-pc.dts | 797 +++++ .../boot/dts/rockchip/rk3568-rock-3a.dts | 766 ++++ .../boot/dts/rockchip/rk3568-rock-pi-e25.dts | 630 ++++ .../arch/arm64/boot/dts/rockchip/rk3568.dtsi | 265 ++ .../arch/arm64/boot/dts/rockchip/rk356x.dtsi | 1838 ++++++++++ .../boot/dts/rockchip/rockchip-pinconf.dtsi | 344 ++ .../drivers/char/hw_random/rockchip-rng.c | 310 ++ .../files/drivers/devfreq/rk3328_dmc.c | 852 +++++ .../include/dt-bindings/clock/rk3568-cru.h | 926 +++++ .../include/dt-bindings/clock/rockchip-ddr.h | 63 + .../include/dt-bindings/memory/rk3328-dram.h | 159 + .../include/dt-bindings/power/rk3568-power.h | 32 + root/target/linux/rockchip/image/Makefile | 82 + root/target/linux/rockchip/image/armv8.mk | 148 +- .../rockchip/image/nanopi-r5s.bootscript | 8 + ...add-compatible-to-NanoPi-R2S-etherne.patch | 25 + ...-thermal-Allow-more-resets-for-tsadc.patch | 28 + ...dd-GFP_DMA32-for-rx-buffers-if-no-64.patch | 67 + ...6-arm64-dts-rockchip-add-rk3566-dtsi.patch | 39 + ...ts-rockchip-add-gmac0-node-to-rk3568.patch | 73 + ...ockchip-drop-pclk_xpcs-from-gmac0-on.patch | 54 + ...chip-inno-usb2-support-address-cells.patch | 45 + ...no-usb2-support-standalone-phy-nodes.patch | 44 + ...p-inno-usb2-support-muxed-interrupts.patch | 237 ++ ...ockchip-inno-usb2-add-rk3568-support.patch | 104 + ...chip-add-naneng-combo-phy-for-RK3568.patch | 633 ++++ ...-use-3.0-clock-when-operating-in-2.0.patch | 46 + ...port-setting-f_min-from-host-drivers.patch | 54 + ...hip-Fix-handling-invalid-clock-rates.patch | 79 + ...8-Add-support-for-power-off-on-RK817.patch | 27 + ...-rk808-Add-reboot-support-to-rk808.c.patch | 110 + ...c-rockchip-set-dwc3-clock-for-rk3566.patch | 51 + ...kchip-dwc-Reset-core-at-driver-probe.patch | 72 + ...hip-dwc-Add-legacy-interrupt-support.patch | 163 + ...5.20-arm64-enable-THP_SWAP-for-arm64.patch | 123 + ...9-v5.19-drm-rockchip-Add-VOP2-driver.patch | 67 + ...70-v6.1-phy-rockchip-Support-PCIe-v3.patch | 394 +++ ...rockchip-Add-PCIe-v3-nodes-to-rk3568.patch | 146 + ...-rockchip-use-system-LED-for-OpenWrt.patch | 31 - ...d-OF-node-for-pcie-eth-on-NanoPi-R4S.patch | 22 + ...-initial-signal-voltage-on-power-off.patch | 35 + ...dd-support-for-Motorcomm-yt8531C-phy.patch | 141 + ...8-add-i2c0-controller-for-nanopi-r2s.patch | 22 + ...328-Add-support-for-OrangePi-R1-Plus.patch | 52 + ...Add-support-for-OrangePi-R1-Plus-LTS.patch | 79 + ...Add-support-for-FriendlyARM-NanoPi-R.patch | 64 + ...-support-for-FriendlyARM-NanoPi-Neo3.patch | 442 +++ ...ip-rk356x-add-support-for-new-boards.patch | 14 + ...399-add-support-for-Rongpin-King3399.patch | 10 + ...-for-rockchip-hardware-random-number.patch | 45 + ...ip-add-hardware-random-number-genera.patch | 69 + ...ip-add-devfreq-driver-for-rk3328-dmc.patch | 44 + ...setting-ddr-clock-via-SIP-Version-2-.patch | 210 ++ ...eq-rockchip-dfi-add-more-soc-support.patch | 662 ++++ ...m64-dts-rockchip-rk3328-add-dfi-node.patch | 27 + ...anopi-r2s-add-rk3328-dmc-relate-node.patch | 126 + ...ip-add-more-cpu-operating-points-for.patch | 44 + ...chip-rk3399-overclock-to-2.2-1.8-GHz.patch | 46 + ...4-dts-rockchip-Add-RK3328-idle-state.patch | 69 + ...-add-hwmon-support-for-SoCs-and-GPUs.patch | 53 + ...dd-support-for-FriendlyARM-NanoPi-R.patch} | 3 +- ...chip-add-EEPROM-node-for-NanoPi-R4S.patch} | 14 +- ...ync-rk3566-device-tree-with-mainline.patch | 28 + ...6-arm64-dts-rockchip-add-rk3566-dtsi.patch | 39 + ...ts-rockchip-add-gmac0-node-to-rk3568.patch | 73 + ...ockchip-drop-pclk_xpcs-from-gmac0-on.patch | 54 + ...chip-inno-usb2-support-address-cells.patch | 45 + ...no-usb2-support-standalone-phy-nodes.patch | 44 + ...p-inno-usb2-support-muxed-interrupts.patch | 237 ++ ...ockchip-inno-usb2-add-rk3568-support.patch | 104 + ...chip-add-naneng-combo-phy-for-RK3568.patch | 633 ++++ ...port-setting-f_min-from-host-drivers.patch | 54 + ...hip-Fix-handling-invalid-clock-rates.patch | 79 + ...c-rockchip-set-dwc3-clock-for-rk3566.patch | 51 + ...70-v6.1-phy-rockchip-Support-PCIe-v3.patch | 394 +++ ...rockchip-Add-PCIe-v3-nodes-to-rk3568.patch | 146 + ...dd-OF-node-for-USB-eth-on-NanoPi-R2S.patch | 17 +- ...-initial-signal-voltage-on-power-off.patch | 35 + ...d-OF-node-for-pcie-eth-on-NanoPi-R4S.patch | 22 + .../107-nanopi-r4s-sd-signalling.patch} | 2 +- ...8-add-i2c0-controller-for-nanopi-r2s.patch | 22 + ...328-Add-support-for-OrangePi-R1-Plus.patch | 52 + ...Add-support-for-OrangePi-R1-Plus-LTS.patch | 79 + ...Add-support-for-FriendlyARM-NanoPi-R.patch | 64 + ...-support-for-FriendlyARM-NanoPi-Neo3.patch | 444 +++ ...399-add-support-for-Rongpin-King3399.patch | 7 + ...ip-rk356x-add-support-for-new-boards.patch | 13 + ...Add-driver-for-Motorcomm-YT85xx-PHYs.patch | 39 + ...-for-rockchip-hardware-random-number.patch | 45 + ...ip-add-hardware-random-number-genera.patch | 69 + ...ip-add-devfreq-driver-for-rk3328-dmc.patch | 44 + ...setting-ddr-clock-via-SIP-Version-2-.patch | 210 ++ ...eq-rockchip-dfi-add-more-soc-support.patch | 663 ++++ ...m64-dts-rockchip-rk3328-add-dfi-node.patch | 27 + ...anopi-r2s-add-rk3328-dmc-relate-node.patch | 126 + ...ip-add-more-cpu-operating-points-for.patch | 44 + ...chip-rk3399-overclock-to-2.2-1.8-GHz.patch | 46 + 112 files changed, 25981 insertions(+), 75 deletions(-) delete mode 100644 root/target/linux/rockchip/files-5.14/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts create mode 100644 root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3328-dram-default-timing.dtsi create mode 100644 root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3328-dram-nanopi2-timing.dtsi create mode 100644 root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3368.dtsi create mode 100644 root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3399-guangmiao-g4c.dts create mode 100755 root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3399-king3399.dts create mode 100644 root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4se.dts create mode 100644 root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-fastrhino.dtsi create mode 100644 root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-mrkaio-m68s.dts create mode 100644 root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dts create mode 100644 root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-opc-h68k.dts create mode 100644 root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-pinctrl.dtsi create mode 100644 root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-r66s.dts create mode 100644 root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-r68s.dts create mode 100644 root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-roc-pc.dts create mode 100644 root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts create mode 100644 root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-rock-pi-e25.dts create mode 100644 root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568.dtsi create mode 100644 root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk356x.dtsi create mode 100644 root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rockchip-pinconf.dtsi create mode 100644 root/target/linux/rockchip/files/drivers/char/hw_random/rockchip-rng.c create mode 100644 root/target/linux/rockchip/files/drivers/devfreq/rk3328_dmc.c create mode 100644 root/target/linux/rockchip/files/include/dt-bindings/clock/rk3568-cru.h create mode 100644 root/target/linux/rockchip/files/include/dt-bindings/clock/rockchip-ddr.h create mode 100644 root/target/linux/rockchip/files/include/dt-bindings/memory/rk3328-dram.h create mode 100644 root/target/linux/rockchip/files/include/dt-bindings/power/rk3568-power.h create mode 100644 root/target/linux/rockchip/image/Makefile create mode 100644 root/target/linux/rockchip/image/nanopi-r5s.bootscript create mode 100644 root/target/linux/rockchip/patches-5.15/005-rockchip-rk3328-add-compatible-to-NanoPi-R2S-etherne.patch create mode 100644 root/target/linux/rockchip/patches-5.15/009-v5.16-drivers-rockchip-thermal-Allow-more-resets-for-tsadc.patch create mode 100644 root/target/linux/rockchip/patches-5.15/010-v5.16-net-stmmac-Add-GFP_DMA32-for-rx-buffers-if-no-64.patch create mode 100644 root/target/linux/rockchip/patches-5.15/015-v5.16-arm64-dts-rockchip-add-rk3566-dtsi.patch create mode 100644 root/target/linux/rockchip/patches-5.15/020-v5.16-arm64-dts-rockchip-add-gmac0-node-to-rk3568.patch create mode 100644 root/target/linux/rockchip/patches-5.15/031-v5.17-arm64-dts-rockchip-drop-pclk_xpcs-from-gmac0-on.patch create mode 100644 root/target/linux/rockchip/patches-5.15/032-v5.17-phy-rockchip-inno-usb2-support-address-cells.patch create mode 100644 root/target/linux/rockchip/patches-5.15/033-v5.17-phy-rockchip-inno-usb2-support-standalone-phy-nodes.patch create mode 100644 root/target/linux/rockchip/patches-5.15/034-v5.17-phy-rockchip-inno-usb2-support-muxed-interrupts.patch create mode 100644 root/target/linux/rockchip/patches-5.15/035-v5.17-phy-rockchip-inno-usb2-add-rk3568-support.patch create mode 100644 root/target/linux/rockchip/patches-5.15/037-v5.18-phy-rockchip-add-naneng-combo-phy-for-RK3568.patch create mode 100644 root/target/linux/rockchip/patches-5.15/040-v5.18-usb-dwc3-core-do-not-use-3.0-clock-when-operating-in-2.0.patch create mode 100644 root/target/linux/rockchip/patches-5.15/050-v5.18-mmc-dw_mmc-Support-setting-f_min-from-host-drivers.patch create mode 100644 root/target/linux/rockchip/patches-5.15/051-v5.18-mmc-dw-mmc-rockchip-Fix-handling-invalid-clock-rates.patch create mode 100644 root/target/linux/rockchip/patches-5.15/052-v5.16-mfd-rk808-Add-support-for-power-off-on-RK817.patch create mode 100644 root/target/linux/rockchip/patches-5.15/053-v5.18-mfd-rk808-Add-reboot-support-to-rk808.c.patch create mode 100644 root/target/linux/rockchip/patches-5.15/054-v5.19-soc-rockchip-set-dwc3-clock-for-rk3566.patch create mode 100644 root/target/linux/rockchip/patches-5.15/056-v5.19-PCI-rockchip-dwc-Reset-core-at-driver-probe.patch create mode 100644 root/target/linux/rockchip/patches-5.15/057-v5.19-PCI-rockchip-dwc-Add-legacy-interrupt-support.patch create mode 100644 root/target/linux/rockchip/patches-5.15/061-v5.20-arm64-enable-THP_SWAP-for-arm64.patch create mode 100644 root/target/linux/rockchip/patches-5.15/069-v5.19-drm-rockchip-Add-VOP2-driver.patch create mode 100644 root/target/linux/rockchip/patches-5.15/070-v6.1-phy-rockchip-Support-PCIe-v3.patch create mode 100644 root/target/linux/rockchip/patches-5.15/071-v6.1-arm64-dts-rockchip-Add-PCIe-v3-nodes-to-rk3568.patch delete mode 100644 root/target/linux/rockchip/patches-5.15/100-rockchip-use-system-LED-for-OpenWrt.patch create mode 100644 root/target/linux/rockchip/patches-5.15/106-arm64-rockchip-add-OF-node-for-pcie-eth-on-NanoPi-R4S.patch create mode 100644 root/target/linux/rockchip/patches-5.15/107-mmc-core-set-initial-signal-voltage-on-power-off.patch create mode 100644 root/target/linux/rockchip/patches-5.15/108-net-phy-add-support-for-Motorcomm-yt8531C-phy.patch create mode 100644 root/target/linux/rockchip/patches-5.15/201-rockchip-rk3328-add-i2c0-controller-for-nanopi-r2s.patch create mode 100644 root/target/linux/rockchip/patches-5.15/202-rockchip-rk3328-Add-support-for-OrangePi-R1-Plus.patch create mode 100644 root/target/linux/rockchip/patches-5.15/203-rockchip-rk3328-Add-support-for-OrangePi-R1-Plus-LTS.patch create mode 100644 root/target/linux/rockchip/patches-5.15/204-rockchip-rk3328-Add-support-for-FriendlyARM-NanoPi-R.patch create mode 100644 root/target/linux/rockchip/patches-5.15/205-rockchip-rk3328-add-support-for-FriendlyARM-NanoPi-Neo3.patch create mode 100644 root/target/linux/rockchip/patches-5.15/210-rockchip-rk356x-add-support-for-new-boards.patch create mode 100644 root/target/linux/rockchip/patches-5.15/211-rockchip-rk3399-add-support-for-Rongpin-King3399.patch create mode 100644 root/target/linux/rockchip/patches-5.15/801-char-add-support-for-rockchip-hardware-random-number.patch create mode 100644 root/target/linux/rockchip/patches-5.15/802-arm64-dts-rockchip-add-hardware-random-number-genera.patch create mode 100644 root/target/linux/rockchip/patches-5.15/803-PM-devfreq-rockchip-add-devfreq-driver-for-rk3328-dmc.patch create mode 100644 root/target/linux/rockchip/patches-5.15/804-clk-rockchip-support-setting-ddr-clock-via-SIP-Version-2-.patch create mode 100644 root/target/linux/rockchip/patches-5.15/805-PM-devfreq-rockchip-dfi-add-more-soc-support.patch create mode 100644 root/target/linux/rockchip/patches-5.15/806-arm64-dts-rockchip-rk3328-add-dfi-node.patch create mode 100644 root/target/linux/rockchip/patches-5.15/807-arm64-dts-nanopi-r2s-add-rk3328-dmc-relate-node.patch create mode 100644 root/target/linux/rockchip/patches-5.15/991-arm64-dts-rockchip-add-more-cpu-operating-points-for.patch create mode 100644 root/target/linux/rockchip/patches-5.15/992-rockchip-rk3399-overclock-to-2.2-1.8-GHz.patch create mode 100644 root/target/linux/rockchip/patches-5.4/007-arm64-dts-rockchip-Add-RK3328-idle-state.patch create mode 100644 root/target/linux/rockchip/patches-5.4/008-rockchip-add-hwmon-support-for-SoCs-and-GPUs.patch rename root/target/linux/rockchip/patches-5.4/{007-v5.13-rockchip-rk3399-Add-support-for-FriendlyARM-NanoPi-R.patch => 009-rockchip-rk3399-Add-support-for-FriendlyARM-NanoPi-R.patch} (97%) rename root/target/linux/rockchip/{patches-5.15/005-arm64-dts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch => patches-5.4/010-arm64-dts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch} (69%) create mode 100644 root/target/linux/rockchip/patches-5.4/012-resync-rk3566-device-tree-with-mainline.patch create mode 100644 root/target/linux/rockchip/patches-5.4/015-v5.16-arm64-dts-rockchip-add-rk3566-dtsi.patch create mode 100644 root/target/linux/rockchip/patches-5.4/020-v5.16-arm64-dts-rockchip-add-gmac0-node-to-rk3568.patch create mode 100644 root/target/linux/rockchip/patches-5.4/031-v5.17-arm64-dts-rockchip-drop-pclk_xpcs-from-gmac0-on.patch create mode 100644 root/target/linux/rockchip/patches-5.4/032-v5.17-phy-rockchip-inno-usb2-support-address-cells.patch create mode 100644 root/target/linux/rockchip/patches-5.4/033-v5.17-phy-rockchip-inno-usb2-support-standalone-phy-nodes.patch create mode 100644 root/target/linux/rockchip/patches-5.4/034-v5.17-phy-rockchip-inno-usb2-support-muxed-interrupts.patch create mode 100644 root/target/linux/rockchip/patches-5.4/035-v5.17-phy-rockchip-inno-usb2-add-rk3568-support.patch create mode 100644 root/target/linux/rockchip/patches-5.4/037-v5.18-phy-rockchip-add-naneng-combo-phy-for-RK3568.patch create mode 100644 root/target/linux/rockchip/patches-5.4/050-v5.18-mmc-dw_mmc-Support-setting-f_min-from-host-drivers.patch create mode 100644 root/target/linux/rockchip/patches-5.4/051-v5.18-mmc-dw-mmc-rockchip-Fix-handling-invalid-clock-rates.patch create mode 100644 root/target/linux/rockchip/patches-5.4/054-v5.19-soc-rockchip-set-dwc3-clock-for-rk3566.patch create mode 100644 root/target/linux/rockchip/patches-5.4/070-v6.1-phy-rockchip-Support-PCIe-v3.patch create mode 100644 root/target/linux/rockchip/patches-5.4/071-v6.1-arm64-dts-rockchip-Add-PCIe-v3-nodes-to-rk3568.patch rename root/target/linux/rockchip/{patches-5.15 => patches-5.4}/103-arm64-rockchip-add-OF-node-for-USB-eth-on-NanoPi-R2S.patch (78%) create mode 100644 root/target/linux/rockchip/patches-5.4/105-mmc-core-set-initial-signal-voltage-on-power-off.patch create mode 100644 root/target/linux/rockchip/patches-5.4/106-arm64-rockchip-add-OF-node-for-pcie-eth-on-NanoPi-R4S.patch rename root/target/linux/rockchip/{patches-5.15/105-nanopi-r4s-sd-signalling.patch => patches-5.4/107-nanopi-r4s-sd-signalling.patch} (97%) create mode 100644 root/target/linux/rockchip/patches-5.4/201-rockchip-rk3328-add-i2c0-controller-for-nanopi-r2s.patch create mode 100644 root/target/linux/rockchip/patches-5.4/202-rockchip-rk3328-Add-support-for-OrangePi-R1-Plus.patch create mode 100644 root/target/linux/rockchip/patches-5.4/203-rockchip-rk3328-Add-support-for-OrangePi-R1-Plus-LTS.patch create mode 100644 root/target/linux/rockchip/patches-5.4/204-rockchip-rk3328-Add-support-for-FriendlyARM-NanoPi-R.patch create mode 100644 root/target/linux/rockchip/patches-5.4/205-rockchip-rk3328-add-support-for-FriendlyARM-NanoPi-Neo3.patch create mode 100644 root/target/linux/rockchip/patches-5.4/206-rockchip-rk3399-add-support-for-Rongpin-King3399.patch create mode 100644 root/target/linux/rockchip/patches-5.4/210-rockchip-rk356x-add-support-for-new-boards.patch create mode 100644 root/target/linux/rockchip/patches-5.4/600-net-phy-Add-driver-for-Motorcomm-YT85xx-PHYs.patch create mode 100644 root/target/linux/rockchip/patches-5.4/801-char-add-support-for-rockchip-hardware-random-number.patch create mode 100644 root/target/linux/rockchip/patches-5.4/802-arm64-dts-rockchip-add-hardware-random-number-genera.patch create mode 100644 root/target/linux/rockchip/patches-5.4/803-PM-devfreq-rockchip-add-devfreq-driver-for-rk3328-dmc.patch create mode 100644 root/target/linux/rockchip/patches-5.4/804-clk-rockchip-support-setting-ddr-clock-via-SIP-Version-2-.patch create mode 100644 root/target/linux/rockchip/patches-5.4/805-PM-devfreq-rockchip-dfi-add-more-soc-support.patch create mode 100644 root/target/linux/rockchip/patches-5.4/806-arm64-dts-rockchip-rk3328-add-dfi-node.patch create mode 100644 root/target/linux/rockchip/patches-5.4/807-arm64-dts-nanopi-r2s-add-rk3328-dmc-relate-node.patch create mode 100644 root/target/linux/rockchip/patches-5.4/991-arm64-dts-rockchip-add-more-cpu-operating-points-for.patch create mode 100644 root/target/linux/rockchip/patches-5.4/992-rockchip-rk3399-overclock-to-2.2-1.8-GHz.patch diff --git a/root/target/linux/rockchip/armv8/config-5.15 b/root/target/linux/rockchip/armv8/config-5.15 index 2079cea4..85299456 100644 --- a/root/target/linux/rockchip/armv8/config-5.15 +++ b/root/target/linux/rockchip/armv8/config-5.15 @@ -1,5 +1,6 @@ CONFIG_64BIT=y CONFIG_AF_UNIX_OOB=y +# CONFIG_ARCH_BCM4908 is not set CONFIG_ARCH_DMA_ADDR_T_64BIT=y CONFIG_ARCH_HIBERNATION_POSSIBLE=y CONFIG_ARCH_KEEP_MEMBLOCK=y @@ -19,7 +20,11 @@ CONFIG_ARC_EMAC_CORE=y CONFIG_ARM64=y CONFIG_ARM64_4K_PAGES=y CONFIG_ARM64_CNP=y +CONFIG_ARM64_CRYPTO=y CONFIG_ARM64_EPAN=y +# CONFIG_ARM64_ERRATUM_1165522 is not set +# CONFIG_ARM64_ERRATUM_1286807 is not set +# CONFIG_ARM64_ERRATUM_1418040 is not set CONFIG_ARM64_ERRATUM_819472=y CONFIG_ARM64_ERRATUM_824069=y CONFIG_ARM64_ERRATUM_826319=y @@ -28,6 +33,7 @@ CONFIG_ARM64_ERRATUM_832075=y CONFIG_ARM64_ERRATUM_843419=y CONFIG_ARM64_ERRATUM_845719=y CONFIG_ARM64_ERRATUM_858921=y +CONFIG_ARM64_ERRATUM_1742098=y CONFIG_ARM64_HW_AFDBM=y CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y CONFIG_ARM64_MODULE_PLTS=y @@ -51,17 +57,20 @@ CONFIG_ARM_ARCH_TIMER=y CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND=y CONFIG_ARM_CPUIDLE=y +# CONFIG_ARM_FFA_TRANSPORT is not set CONFIG_ARM_GIC=y CONFIG_ARM_GIC_V2M=y CONFIG_ARM_GIC_V3=y CONFIG_ARM_GIC_V3_ITS=y CONFIG_ARM_GIC_V3_ITS_PCI=y CONFIG_ARM_MHU=y -CONFIG_ARM_MHU_V2=y +# CONFIG_ARM_MHU_V2 is not set CONFIG_ARM_PSCI_CPUIDLE=y CONFIG_ARM_PSCI_CPUIDLE_DOMAIN=y CONFIG_ARM_PSCI_FW=y +CONFIG_ARM_RK3328_DMC_DEVFREQ=y # CONFIG_ARM_RK3399_DMC_DEVFREQ is not set +CONFIG_ARM_SCMI_PROTOCOL=y CONFIG_ARM_SCPI_CPUFREQ=y CONFIG_ARM_SCPI_POWER_DOMAIN=y CONFIG_ARM_SCPI_PROTOCOL=y @@ -74,6 +83,7 @@ CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y CONFIG_BACKLIGHT_CLASS_DEVICE=y CONFIG_BACKLIGHT_GPIO=y CONFIG_BACKLIGHT_PWM=y +# CONFIG_BCM_VK is not set CONFIG_BINARY_PRINTF=y CONFIG_BLK_DEV_BSG=y CONFIG_BLK_DEV_BSGLIB=y @@ -89,6 +99,7 @@ CONFIG_BLK_MQ_PCI=y CONFIG_BLK_PM=y CONFIG_BLOCK_COMPAT=y CONFIG_BRCMSTB_GISB_ARB=y +# CONFIG_BRIDGE_CFM is not set CONFIG_BSD_PROCESS_ACCT=y CONFIG_BSD_PROCESS_ACCT_V3=y CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y @@ -104,6 +115,7 @@ CONFIG_CLONE_BACKWARDS=y CONFIG_CMA=y CONFIG_CMA_ALIGNMENT=8 CONFIG_CMA_AREAS=7 +# CONFIG_CAVIUM_TX2_ERRATUM_219 is not set # CONFIG_CMA_DEBUG is not set # CONFIG_CMA_DEBUGFS is not set CONFIG_CMA_SIZE_MBYTES=5 @@ -113,8 +125,10 @@ CONFIG_CMA_SIZE_SEL_MBYTES=y # CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set # CONFIG_CMA_SYSFS is not set CONFIG_COMMON_CLK=y +# CONFIG_COMMON_CLK_AXI_CLKGEN is not set CONFIG_COMMON_CLK_RK808=y CONFIG_COMMON_CLK_ROCKCHIP=y +CONFIG_COMMON_CLK_SCMI=y CONFIG_COMMON_CLK_SCPI=y CONFIG_COMPAT=y CONFIG_COMPAT_32BIT_TIME=y @@ -151,13 +165,25 @@ CONFIG_CRC16=y CONFIG_CRC32_SLICEBY8=y CONFIG_CRC_T10DIF=y CONFIG_CROSS_MEMORY_ATTACH=y +CONFIG_CRYPTO_AES_ARM64=y +CONFIG_CRYPTO_AES_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y CONFIG_CRYPTO_CRC32=y CONFIG_CRYPTO_CRC32C=y CONFIG_CRYPTO_CRCT10DIF=y -CONFIG_CRYPTO_DEV_ROCKCHIP=y +CONFIG_CRYPTO_CRCT10DIF_ARM64_CE=y +CONFIG_CRYPTO_CRYPTD=y +CONFIG_CRYPTO_GHASH_ARM64_CE=y +CONFIG_CRYPTO_GF128MUL=y +CONFIG_CRYPTO_LIB_SHA256=y +CONFIG_CRYPTO_NULL2=y CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_SIMD=y +# CONFIG_CXL_BUS is not set CONFIG_DCACHE_WORD_ACCESS=y CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_IRQFLAGS is not set # CONFIG_DEVFREQ_GOV_PASSIVE is not set CONFIG_DEVFREQ_GOV_PERFORMANCE=y CONFIG_DEVFREQ_GOV_POWERSAVE=y @@ -166,16 +192,21 @@ CONFIG_DEVFREQ_GOV_USERSPACE=y # CONFIG_DEVFREQ_THERMAL is not set CONFIG_DEVMEM=y # CONFIG_DEVPORT is not set +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_DMABUF_DEBUG is not set +# CONFIG_DMABUF_SYSFS_STATS is not set CONFIG_DMADEVICES=y CONFIG_DMA_CMA=y CONFIG_DMA_DIRECT_REMAP=y CONFIG_DMA_ENGINE=y +# CONFIG_DMA_MAP_BENCHMARK is not set CONFIG_DMA_OF=y CONFIG_DMA_OPS=y CONFIG_DMA_REMAP=y +# CONFIG_DMA_RESTRICTED_POOL is not set CONFIG_DMA_SHARED_BUFFER=y CONFIG_DNOTIFY=y -# CONFIG_DRM_ROCKCHIP is not set CONFIG_DTC=y CONFIG_DT_IDLE_STATES=y CONFIG_DUMMY_CONSOLE=y @@ -189,12 +220,14 @@ CONFIG_ENERGY_MODEL=y CONFIG_EXT4_FS=y CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXTCON=y +# CONFIG_EXTCON_USBC_TUSB320 is not set CONFIG_F2FS_FS=y CONFIG_FANOTIFY=y CONFIG_FHANDLE=y CONFIG_FIXED_PHY=y CONFIG_FIX_EARLYCON_MEM=y # CONFIG_FORTIFY_SOURCE is not set +# CONFIG_FUJITSU_ERRATUM_010001 is not set CONFIG_FRAME_POINTER=y CONFIG_FRAME_WARN=2048 CONFIG_FS_IOMAP=y @@ -238,6 +271,7 @@ CONFIG_GPIO_DWAPB=y CONFIG_GPIO_GENERIC=y CONFIG_GPIO_GENERIC_PLATFORM=y CONFIG_GPIO_ROCKCHIP=y +# CONFIG_GUP_TEST is not set CONFIG_HANDLE_DOMAIN_IRQ=y # CONFIG_HARDENED_USERCOPY is not set CONFIG_HARDIRQS_SW_RESEND=y @@ -256,6 +290,11 @@ CONFIG_HUGETLB_PAGE=y CONFIG_HWMON=y CONFIG_HWSPINLOCK=y CONFIG_HW_CONSOLE=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_ROCKCHIP=y +CONFIG_HZ=250 +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y CONFIG_I2C=y CONFIG_I2C_BOARDINFO=y CONFIG_I2C_CHARDEV=y @@ -271,12 +310,11 @@ CONFIG_INPUT_KEYBOARD=y CONFIG_INPUT_LEDS=y CONFIG_INPUT_MATRIXKMAP=y # CONFIG_INPUT_MISC is not set -# CONFIG_INPUT_RK805_PWRKEY is not set CONFIG_IOMMU_API=y # CONFIG_IOMMU_DEBUGFS is not set # CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set -# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set -CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y +CONFIG_IOMMU_DEFAULT_DMA_STRICT=y +# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set CONFIG_IOMMU_DMA=y CONFIG_IOMMU_IOVA=y CONFIG_IOMMU_IO_PGTABLE=y @@ -299,6 +337,8 @@ CONFIG_JUMP_LABEL=y CONFIG_KALLSYMS=y CONFIG_KEXEC_CORE=y CONFIG_KEXEC_FILE=y +# CONFIG_KEXEC_SIG is not set +# CONFIG_KFENCE is not set CONFIG_KSM=y # CONFIG_LEDS_BRIGHTNESS_HW_CHANGED is not set CONFIG_LEDS_GPIO=y @@ -306,10 +346,13 @@ CONFIG_LEDS_PWM=y CONFIG_LEDS_SYSCON=y CONFIG_LEDS_TRIGGER_CPU=y CONFIG_LEDS_TRIGGER_PANIC=y +# CONFIG_LEDS_TRIGGER_TTY is not set CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=16 CONFIG_LIBCRC32C=y CONFIG_LIBFDT=y +# CONFIG_LITEX_SOC_CONTROLLER is not set +CONFIG_LLD_VERSION=0 CONFIG_LOCALVERSION_AUTO=y CONFIG_LOCK_DEBUGGING_SUPPORT=y CONFIG_LOCK_SPIN_ON_OWNER=y @@ -328,6 +371,7 @@ CONFIG_MDIO_DEVRES=y CONFIG_MEMFD_CREATE=y CONFIG_MEMORY_ISOLATION=y CONFIG_MFD_CORE=y +# CONFIG_MFD_INTEL_PMT is not set # CONFIG_MFD_KHADAS_MCU is not set CONFIG_MFD_RK808=y CONFIG_MFD_SYSCON=y @@ -350,11 +394,16 @@ CONFIG_MMC_SDHCI_OF_DWCMSHC=y # CONFIG_MMC_SDHCI_PCI is not set CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_MOTORCOMM_PHY=y CONFIG_MQ_IOSCHED_DEADLINE=y # CONFIG_MTD_CFI is not set CONFIG_MTD_CMDLINE_PARTS=y # CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_NAND_ECC_SW_HAMMING is not set CONFIG_MTD_SPI_NOR=y +# CONFIG_MTD_SPI_NOR_SWP_DISABLE is not set +CONFIG_MTD_SPI_NOR_SWP_DISABLE_ON_VOLATILE=y +# CONFIG_MTD_SPI_NOR_SWP_KEEP is not set CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y CONFIG_MTD_SPLIT_FIRMWARE=y CONFIG_MUTEX_SPIN_ON_OWNER=y @@ -369,7 +418,9 @@ CONFIG_NOP_USB_XCEIV=y CONFIG_NO_HZ_COMMON=y CONFIG_NO_HZ_IDLE=y CONFIG_NR_CPUS=256 +# CONFIG_NVIDIA_CARMEL_CNP_ERRATUM is not set CONFIG_NVMEM=y +# CONFIG_NVMEM_RMEM is not set CONFIG_NVMEM_SYSFS=y CONFIG_NVME_CORE=y # CONFIG_NVME_HWMON is not set @@ -384,6 +435,7 @@ CONFIG_OF_IOMMU=y CONFIG_OF_IRQ=y CONFIG_OF_KOBJ=y CONFIG_OF_MDIO=y +CONFIG_OF_NET=y CONFIG_OF_OVERLAY=y CONFIG_OF_RESOLVE=y CONFIG_OLD_SIGSUSPEND3=y @@ -403,9 +455,12 @@ CONFIG_PCIEASPM_DEFAULT=y # CONFIG_PCIEASPM_POWERSAVE is not set # CONFIG_PCIEASPM_POWER_SUPERSAVE is not set CONFIG_PCIEPORTBUS=y +CONFIG_PCIE_DW=y +CONFIG_PCIE_DW_HOST=y +# CONFIG_PCIE_MICROCHIP_HOST is not set CONFIG_PCIE_PME=y CONFIG_PCIE_ROCKCHIP=y -# CONFIG_PCIE_ROCKCHIP_DW_HOST is not set +CONFIG_PCIE_ROCKCHIP_DW_HOST=y CONFIG_PCIE_ROCKCHIP_HOST=y CONFIG_PCI_DOMAINS=y CONFIG_PCI_DOMAINS_GENERIC=y @@ -424,10 +479,13 @@ CONFIG_PHY_ROCKCHIP_EMMC=y # CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY is not set # CONFIG_PHY_ROCKCHIP_INNO_HDMI is not set CONFIG_PHY_ROCKCHIP_INNO_USB2=y +CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY=y CONFIG_PHY_ROCKCHIP_PCIE=y +CONFIG_PHY_ROCKCHIP_SNPS_PCIE3=y CONFIG_PHY_ROCKCHIP_TYPEC=y CONFIG_PHY_ROCKCHIP_USB=y CONFIG_PINCTRL=y +# CONFIG_PINCTRL_MICROCHIP_SGPIO is not set # CONFIG_PINCTRL_RK805 is not set CONFIG_PINCTRL_ROCKCHIP=y # CONFIG_PINCTRL_SINGLE is not set @@ -454,6 +512,8 @@ CONFIG_PROC_PAGE_MONITOR=y CONFIG_PROC_VMCORE=y CONFIG_PTP_1588_CLOCK_OPTIONAL=y CONFIG_PWM=y +# CONFIG_PWM_ATMEL_TCB is not set +# CONFIG_PWM_DWC is not set CONFIG_PWM_ROCKCHIP=y CONFIG_PWM_SYSFS=y # CONFIG_QFMT_V1 is not set @@ -476,11 +536,14 @@ CONFIG_REGMAP_I2C=y CONFIG_REGMAP_IRQ=y CONFIG_REGMAP_MMIO=y CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DA9121 is not set CONFIG_REGULATOR_FAN53555=y CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_GPIO=y +# CONFIG_REGULATOR_PF8X00 is not set CONFIG_REGULATOR_PWM=y CONFIG_REGULATOR_RK808=y +# CONFIG_REGULATOR_RTQ6752 is not set CONFIG_RELOCATABLE=y CONFIG_RESET_CONTROLLER=y CONFIG_RFS_ACCEL=y @@ -492,7 +555,6 @@ CONFIG_ROCKCHIP_MBOX=y # CONFIG_ROCKCHIP_OTP is not set CONFIG_ROCKCHIP_PHY=y CONFIG_ROCKCHIP_PM_DOMAINS=y -# CONFIG_ROCKCHIP_SARADC is not set CONFIG_ROCKCHIP_THERMAL=y CONFIG_ROCKCHIP_TIMER=y CONFIG_RODATA_FULL_DEFAULT_ENABLED=y @@ -513,7 +575,13 @@ CONFIG_SCSI_SAS_ATTRS=y CONFIG_SCSI_SAS_HOST_SMP=y CONFIG_SCSI_SAS_LIBSAS=y # CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SENSORS_AHT10 is not set +# CONFIG_SENSORS_AQUACOMPUTER_D5NEXT is not set CONFIG_SENSORS_ARM_SCPI=y +# CONFIG_SENSORS_LTC2992 is not set +# CONFIG_SENSORS_MAX127 is not set +# CONFIG_SENSORS_SBTSI is not set +# CONFIG_SENSORS_TPS23861 is not set CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y CONFIG_SERIAL_8250_DW=y CONFIG_SERIAL_8250_DWLIB=y @@ -548,7 +616,7 @@ CONFIG_SPI_DYNAMIC=y CONFIG_SPI_MASTER=y CONFIG_SPI_MEM=y CONFIG_SPI_ROCKCHIP=y -# CONFIG_SPI_ROCKCHIP_SFC is not set +CONFIG_SPI_ROCKCHIP_SFC=y CONFIG_SPI_SPIDEV=y # CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set CONFIG_SQUASHFS_DECOMP_SINGLE=y @@ -560,6 +628,8 @@ CONFIG_SRCU=y CONFIG_STACKPROTECTOR=y CONFIG_STACKPROTECTOR_PER_TASK=y CONFIG_STACKPROTECTOR_STRONG=y +CONFIG_STACKTRACE=y +# CONFIG_STAGING is not set CONFIG_STMMAC_ETH=y CONFIG_STMMAC_PLATFORM=y # CONFIG_STMMAC_SELFTESTS is not set @@ -606,6 +676,7 @@ CONFIG_TYPEC_TCPM=y CONFIG_UNINLINE_SPIN_UNLOCK=y CONFIG_UNMAP_KERNEL_AT_EL0=y CONFIG_USB=y +# CONFIG_USB_CDNS_SUPPORT is not set CONFIG_USB_COMMON=y CONFIG_USB_DWC3=y CONFIG_USB_DWC3_HOST=y diff --git a/root/target/linux/rockchip/files-5.14/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts b/root/target/linux/rockchip/files-5.14/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts deleted file mode 100644 index f6e7710a..00000000 --- a/root/target/linux/rockchip/files-5.14/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -/* - * Copyright (c) 2019 Akash Gajjar - * Copyright (c) 2019 Pragnesh Patel - */ - -/* TODO - * Delete this file and migrate RockPi 4 to RockPi 4A after - * removing Kernel 5.4. - */ - - -/dts-v1/; -#include "rk3399-rock-pi-4.dtsi" - -/ { - model = "Radxa ROCK Pi 4"; - compatible = "radxa,rockpi4", "rockchip,rk3399"; -}; diff --git a/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3328-dram-default-timing.dtsi b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3328-dram-default-timing.dtsi new file mode 100644 index 00000000..a3f5ff4b --- /dev/null +++ b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3328-dram-default-timing.dtsi @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include +#include + +/ { + ddr_timing: ddr_timing { + compatible = "rockchip,ddr-timing"; + ddr3_speed_bin = ; + ddr4_speed_bin = ; + pd_idle = <0>; + sr_idle = <0>; + sr_mc_gate_idle = <0>; + srpd_lite_idle = <0>; + standby_idle = <0>; + + auto_pd_dis_freq = <1066>; + auto_sr_dis_freq = <800>; + ddr3_dll_dis_freq = <300>; + ddr4_dll_dis_freq = <625>; + phy_dll_dis_freq = <400>; + + ddr3_odt_dis_freq = <100>; + phy_ddr3_odt_dis_freq = <100>; + ddr3_drv = ; + ddr3_odt = ; + phy_ddr3_ca_drv = ; + phy_ddr3_ck_drv = ; + phy_ddr3_dq_drv = ; + phy_ddr3_odt = ; + + lpddr3_odt_dis_freq = <666>; + phy_lpddr3_odt_dis_freq = <666>; + lpddr3_drv = ; + lpddr3_odt = ; + phy_lpddr3_ca_drv = ; + phy_lpddr3_ck_drv = ; + phy_lpddr3_dq_drv = ; + phy_lpddr3_odt = ; + + lpddr4_odt_dis_freq = <800>; + phy_lpddr4_odt_dis_freq = <800>; + lpddr4_drv = ; + lpddr4_dq_odt = ; + lpddr4_ca_odt = ; + phy_lpddr4_ca_drv = ; + phy_lpddr4_ck_cs_drv = ; + phy_lpddr4_dq_drv = ; + phy_lpddr4_odt = ; + + ddr4_odt_dis_freq = <666>; + phy_ddr4_odt_dis_freq = <666>; + ddr4_drv = ; + ddr4_odt = ; + phy_ddr4_ca_drv = ; + phy_ddr4_ck_drv = ; + phy_ddr4_dq_drv = ; + phy_ddr4_odt = ; + + /* CA de-skew, one step is 47.8ps, range 0-15 */ + ddr3a1_ddr4a9_de-skew = <7>; + ddr3a0_ddr4a10_de-skew = <7>; + ddr3a3_ddr4a6_de-skew = <8>; + ddr3a2_ddr4a4_de-skew = <8>; + ddr3a5_ddr4a8_de-skew = <7>; + ddr3a4_ddr4a5_de-skew = <9>; + ddr3a7_ddr4a11_de-skew = <7>; + ddr3a6_ddr4a7_de-skew = <9>; + ddr3a9_ddr4a0_de-skew = <8>; + ddr3a8_ddr4a13_de-skew = <7>; + ddr3a11_ddr4a3_de-skew = <9>; + ddr3a10_ddr4cs0_de-skew = <7>; + ddr3a13_ddr4a2_de-skew = <8>; + ddr3a12_ddr4ba1_de-skew = <7>; + ddr3a15_ddr4odt0_de-skew = <7>; + ddr3a14_ddr4a1_de-skew = <8>; + ddr3ba1_ddr4a15_de-skew = <7>; + ddr3ba0_ddr4bg0_de-skew = <7>; + ddr3ras_ddr4cke_de-skew = <7>; + ddr3ba2_ddr4ba0_de-skew = <8>; + ddr3we_ddr4bg1_de-skew = <8>; + ddr3cas_ddr4a12_de-skew = <7>; + ddr3ckn_ddr4ckn_de-skew = <8>; + ddr3ckp_ddr4ckp_de-skew = <8>; + ddr3cke_ddr4a16_de-skew = <8>; + ddr3odt0_ddr4a14_de-skew = <7>; + ddr3cs0_ddr4act_de-skew = <8>; + ddr3reset_ddr4reset_de-skew = <7>; + ddr3cs1_ddr4cs1_de-skew = <7>; + ddr3odt1_ddr4odt1_de-skew = <7>; + + /* DATA de-skew + * RX one step is 25.1ps, range 0-15 + * TX one step is 47.8ps, range 0-15 + */ + cs0_dm0_rx_de-skew = <7>; + cs0_dm0_tx_de-skew = <8>; + cs0_dq0_rx_de-skew = <7>; + cs0_dq0_tx_de-skew = <8>; + cs0_dq1_rx_de-skew = <7>; + cs0_dq1_tx_de-skew = <8>; + cs0_dq2_rx_de-skew = <7>; + cs0_dq2_tx_de-skew = <8>; + cs0_dq3_rx_de-skew = <7>; + cs0_dq3_tx_de-skew = <8>; + cs0_dq4_rx_de-skew = <7>; + cs0_dq4_tx_de-skew = <8>; + cs0_dq5_rx_de-skew = <7>; + cs0_dq5_tx_de-skew = <8>; + cs0_dq6_rx_de-skew = <7>; + cs0_dq6_tx_de-skew = <8>; + cs0_dq7_rx_de-skew = <7>; + cs0_dq7_tx_de-skew = <8>; + cs0_dqs0_rx_de-skew = <6>; + cs0_dqs0p_tx_de-skew = <9>; + cs0_dqs0n_tx_de-skew = <9>; + + cs0_dm1_rx_de-skew = <7>; + cs0_dm1_tx_de-skew = <7>; + cs0_dq8_rx_de-skew = <7>; + cs0_dq8_tx_de-skew = <8>; + cs0_dq9_rx_de-skew = <7>; + cs0_dq9_tx_de-skew = <7>; + cs0_dq10_rx_de-skew = <7>; + cs0_dq10_tx_de-skew = <8>; + cs0_dq11_rx_de-skew = <7>; + cs0_dq11_tx_de-skew = <7>; + cs0_dq12_rx_de-skew = <7>; + cs0_dq12_tx_de-skew = <8>; + cs0_dq13_rx_de-skew = <7>; + cs0_dq13_tx_de-skew = <7>; + cs0_dq14_rx_de-skew = <7>; + cs0_dq14_tx_de-skew = <8>; + cs0_dq15_rx_de-skew = <7>; + cs0_dq15_tx_de-skew = <7>; + cs0_dqs1_rx_de-skew = <7>; + cs0_dqs1p_tx_de-skew = <9>; + cs0_dqs1n_tx_de-skew = <9>; + + cs0_dm2_rx_de-skew = <7>; + cs0_dm2_tx_de-skew = <8>; + cs0_dq16_rx_de-skew = <7>; + cs0_dq16_tx_de-skew = <8>; + cs0_dq17_rx_de-skew = <7>; + cs0_dq17_tx_de-skew = <8>; + cs0_dq18_rx_de-skew = <7>; + cs0_dq18_tx_de-skew = <8>; + cs0_dq19_rx_de-skew = <7>; + cs0_dq19_tx_de-skew = <8>; + cs0_dq20_rx_de-skew = <7>; + cs0_dq20_tx_de-skew = <8>; + cs0_dq21_rx_de-skew = <7>; + cs0_dq21_tx_de-skew = <8>; + cs0_dq22_rx_de-skew = <7>; + cs0_dq22_tx_de-skew = <8>; + cs0_dq23_rx_de-skew = <7>; + cs0_dq23_tx_de-skew = <8>; + cs0_dqs2_rx_de-skew = <6>; + cs0_dqs2p_tx_de-skew = <9>; + cs0_dqs2n_tx_de-skew = <9>; + + cs0_dm3_rx_de-skew = <7>; + cs0_dm3_tx_de-skew = <7>; + cs0_dq24_rx_de-skew = <7>; + cs0_dq24_tx_de-skew = <8>; + cs0_dq25_rx_de-skew = <7>; + cs0_dq25_tx_de-skew = <7>; + cs0_dq26_rx_de-skew = <7>; + cs0_dq26_tx_de-skew = <7>; + cs0_dq27_rx_de-skew = <7>; + cs0_dq27_tx_de-skew = <7>; + cs0_dq28_rx_de-skew = <7>; + cs0_dq28_tx_de-skew = <7>; + cs0_dq29_rx_de-skew = <7>; + cs0_dq29_tx_de-skew = <7>; + cs0_dq30_rx_de-skew = <7>; + cs0_dq30_tx_de-skew = <7>; + cs0_dq31_rx_de-skew = <7>; + cs0_dq31_tx_de-skew = <7>; + cs0_dqs3_rx_de-skew = <7>; + cs0_dqs3p_tx_de-skew = <9>; + cs0_dqs3n_tx_de-skew = <9>; + + cs1_dm0_rx_de-skew = <7>; + cs1_dm0_tx_de-skew = <8>; + cs1_dq0_rx_de-skew = <7>; + cs1_dq0_tx_de-skew = <8>; + cs1_dq1_rx_de-skew = <7>; + cs1_dq1_tx_de-skew = <8>; + cs1_dq2_rx_de-skew = <7>; + cs1_dq2_tx_de-skew = <8>; + cs1_dq3_rx_de-skew = <7>; + cs1_dq3_tx_de-skew = <8>; + cs1_dq4_rx_de-skew = <7>; + cs1_dq4_tx_de-skew = <8>; + cs1_dq5_rx_de-skew = <7>; + cs1_dq5_tx_de-skew = <8>; + cs1_dq6_rx_de-skew = <7>; + cs1_dq6_tx_de-skew = <8>; + cs1_dq7_rx_de-skew = <7>; + cs1_dq7_tx_de-skew = <8>; + cs1_dqs0_rx_de-skew = <6>; + cs1_dqs0p_tx_de-skew = <9>; + cs1_dqs0n_tx_de-skew = <9>; + + cs1_dm1_rx_de-skew = <7>; + cs1_dm1_tx_de-skew = <7>; + cs1_dq8_rx_de-skew = <7>; + cs1_dq8_tx_de-skew = <8>; + cs1_dq9_rx_de-skew = <7>; + cs1_dq9_tx_de-skew = <7>; + cs1_dq10_rx_de-skew = <7>; + cs1_dq10_tx_de-skew = <8>; + cs1_dq11_rx_de-skew = <7>; + cs1_dq11_tx_de-skew = <7>; + cs1_dq12_rx_de-skew = <7>; + cs1_dq12_tx_de-skew = <8>; + cs1_dq13_rx_de-skew = <7>; + cs1_dq13_tx_de-skew = <7>; + cs1_dq14_rx_de-skew = <7>; + cs1_dq14_tx_de-skew = <8>; + cs1_dq15_rx_de-skew = <7>; + cs1_dq15_tx_de-skew = <7>; + cs1_dqs1_rx_de-skew = <7>; + cs1_dqs1p_tx_de-skew = <9>; + cs1_dqs1n_tx_de-skew = <9>; + + cs1_dm2_rx_de-skew = <7>; + cs1_dm2_tx_de-skew = <8>; + cs1_dq16_rx_de-skew = <7>; + cs1_dq16_tx_de-skew = <8>; + cs1_dq17_rx_de-skew = <7>; + cs1_dq17_tx_de-skew = <8>; + cs1_dq18_rx_de-skew = <7>; + cs1_dq18_tx_de-skew = <8>; + cs1_dq19_rx_de-skew = <7>; + cs1_dq19_tx_de-skew = <8>; + cs1_dq20_rx_de-skew = <7>; + cs1_dq20_tx_de-skew = <8>; + cs1_dq21_rx_de-skew = <7>; + cs1_dq21_tx_de-skew = <8>; + cs1_dq22_rx_de-skew = <7>; + cs1_dq22_tx_de-skew = <8>; + cs1_dq23_rx_de-skew = <7>; + cs1_dq23_tx_de-skew = <8>; + cs1_dqs2_rx_de-skew = <6>; + cs1_dqs2p_tx_de-skew = <9>; + cs1_dqs2n_tx_de-skew = <9>; + + cs1_dm3_rx_de-skew = <7>; + cs1_dm3_tx_de-skew = <7>; + cs1_dq24_rx_de-skew = <7>; + cs1_dq24_tx_de-skew = <8>; + cs1_dq25_rx_de-skew = <7>; + cs1_dq25_tx_de-skew = <7>; + cs1_dq26_rx_de-skew = <7>; + cs1_dq26_tx_de-skew = <7>; + cs1_dq27_rx_de-skew = <7>; + cs1_dq27_tx_de-skew = <7>; + cs1_dq28_rx_de-skew = <7>; + cs1_dq28_tx_de-skew = <7>; + cs1_dq29_rx_de-skew = <7>; + cs1_dq29_tx_de-skew = <7>; + cs1_dq30_rx_de-skew = <7>; + cs1_dq30_tx_de-skew = <7>; + cs1_dq31_rx_de-skew = <7>; + cs1_dq31_tx_de-skew = <7>; + cs1_dqs3_rx_de-skew = <7>; + cs1_dqs3p_tx_de-skew = <9>; + cs1_dqs3n_tx_de-skew = <9>; + }; +}; diff --git a/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3328-dram-nanopi2-timing.dtsi b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3328-dram-nanopi2-timing.dtsi new file mode 100644 index 00000000..a3f5ff4b --- /dev/null +++ b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3328-dram-nanopi2-timing.dtsi @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include +#include + +/ { + ddr_timing: ddr_timing { + compatible = "rockchip,ddr-timing"; + ddr3_speed_bin = ; + ddr4_speed_bin = ; + pd_idle = <0>; + sr_idle = <0>; + sr_mc_gate_idle = <0>; + srpd_lite_idle = <0>; + standby_idle = <0>; + + auto_pd_dis_freq = <1066>; + auto_sr_dis_freq = <800>; + ddr3_dll_dis_freq = <300>; + ddr4_dll_dis_freq = <625>; + phy_dll_dis_freq = <400>; + + ddr3_odt_dis_freq = <100>; + phy_ddr3_odt_dis_freq = <100>; + ddr3_drv = ; + ddr3_odt = ; + phy_ddr3_ca_drv = ; + phy_ddr3_ck_drv = ; + phy_ddr3_dq_drv = ; + phy_ddr3_odt = ; + + lpddr3_odt_dis_freq = <666>; + phy_lpddr3_odt_dis_freq = <666>; + lpddr3_drv = ; + lpddr3_odt = ; + phy_lpddr3_ca_drv = ; + phy_lpddr3_ck_drv = ; + phy_lpddr3_dq_drv = ; + phy_lpddr3_odt = ; + + lpddr4_odt_dis_freq = <800>; + phy_lpddr4_odt_dis_freq = <800>; + lpddr4_drv = ; + lpddr4_dq_odt = ; + lpddr4_ca_odt = ; + phy_lpddr4_ca_drv = ; + phy_lpddr4_ck_cs_drv = ; + phy_lpddr4_dq_drv = ; + phy_lpddr4_odt = ; + + ddr4_odt_dis_freq = <666>; + phy_ddr4_odt_dis_freq = <666>; + ddr4_drv = ; + ddr4_odt = ; + phy_ddr4_ca_drv = ; + phy_ddr4_ck_drv = ; + phy_ddr4_dq_drv = ; + phy_ddr4_odt = ; + + /* CA de-skew, one step is 47.8ps, range 0-15 */ + ddr3a1_ddr4a9_de-skew = <7>; + ddr3a0_ddr4a10_de-skew = <7>; + ddr3a3_ddr4a6_de-skew = <8>; + ddr3a2_ddr4a4_de-skew = <8>; + ddr3a5_ddr4a8_de-skew = <7>; + ddr3a4_ddr4a5_de-skew = <9>; + ddr3a7_ddr4a11_de-skew = <7>; + ddr3a6_ddr4a7_de-skew = <9>; + ddr3a9_ddr4a0_de-skew = <8>; + ddr3a8_ddr4a13_de-skew = <7>; + ddr3a11_ddr4a3_de-skew = <9>; + ddr3a10_ddr4cs0_de-skew = <7>; + ddr3a13_ddr4a2_de-skew = <8>; + ddr3a12_ddr4ba1_de-skew = <7>; + ddr3a15_ddr4odt0_de-skew = <7>; + ddr3a14_ddr4a1_de-skew = <8>; + ddr3ba1_ddr4a15_de-skew = <7>; + ddr3ba0_ddr4bg0_de-skew = <7>; + ddr3ras_ddr4cke_de-skew = <7>; + ddr3ba2_ddr4ba0_de-skew = <8>; + ddr3we_ddr4bg1_de-skew = <8>; + ddr3cas_ddr4a12_de-skew = <7>; + ddr3ckn_ddr4ckn_de-skew = <8>; + ddr3ckp_ddr4ckp_de-skew = <8>; + ddr3cke_ddr4a16_de-skew = <8>; + ddr3odt0_ddr4a14_de-skew = <7>; + ddr3cs0_ddr4act_de-skew = <8>; + ddr3reset_ddr4reset_de-skew = <7>; + ddr3cs1_ddr4cs1_de-skew = <7>; + ddr3odt1_ddr4odt1_de-skew = <7>; + + /* DATA de-skew + * RX one step is 25.1ps, range 0-15 + * TX one step is 47.8ps, range 0-15 + */ + cs0_dm0_rx_de-skew = <7>; + cs0_dm0_tx_de-skew = <8>; + cs0_dq0_rx_de-skew = <7>; + cs0_dq0_tx_de-skew = <8>; + cs0_dq1_rx_de-skew = <7>; + cs0_dq1_tx_de-skew = <8>; + cs0_dq2_rx_de-skew = <7>; + cs0_dq2_tx_de-skew = <8>; + cs0_dq3_rx_de-skew = <7>; + cs0_dq3_tx_de-skew = <8>; + cs0_dq4_rx_de-skew = <7>; + cs0_dq4_tx_de-skew = <8>; + cs0_dq5_rx_de-skew = <7>; + cs0_dq5_tx_de-skew = <8>; + cs0_dq6_rx_de-skew = <7>; + cs0_dq6_tx_de-skew = <8>; + cs0_dq7_rx_de-skew = <7>; + cs0_dq7_tx_de-skew = <8>; + cs0_dqs0_rx_de-skew = <6>; + cs0_dqs0p_tx_de-skew = <9>; + cs0_dqs0n_tx_de-skew = <9>; + + cs0_dm1_rx_de-skew = <7>; + cs0_dm1_tx_de-skew = <7>; + cs0_dq8_rx_de-skew = <7>; + cs0_dq8_tx_de-skew = <8>; + cs0_dq9_rx_de-skew = <7>; + cs0_dq9_tx_de-skew = <7>; + cs0_dq10_rx_de-skew = <7>; + cs0_dq10_tx_de-skew = <8>; + cs0_dq11_rx_de-skew = <7>; + cs0_dq11_tx_de-skew = <7>; + cs0_dq12_rx_de-skew = <7>; + cs0_dq12_tx_de-skew = <8>; + cs0_dq13_rx_de-skew = <7>; + cs0_dq13_tx_de-skew = <7>; + cs0_dq14_rx_de-skew = <7>; + cs0_dq14_tx_de-skew = <8>; + cs0_dq15_rx_de-skew = <7>; + cs0_dq15_tx_de-skew = <7>; + cs0_dqs1_rx_de-skew = <7>; + cs0_dqs1p_tx_de-skew = <9>; + cs0_dqs1n_tx_de-skew = <9>; + + cs0_dm2_rx_de-skew = <7>; + cs0_dm2_tx_de-skew = <8>; + cs0_dq16_rx_de-skew = <7>; + cs0_dq16_tx_de-skew = <8>; + cs0_dq17_rx_de-skew = <7>; + cs0_dq17_tx_de-skew = <8>; + cs0_dq18_rx_de-skew = <7>; + cs0_dq18_tx_de-skew = <8>; + cs0_dq19_rx_de-skew = <7>; + cs0_dq19_tx_de-skew = <8>; + cs0_dq20_rx_de-skew = <7>; + cs0_dq20_tx_de-skew = <8>; + cs0_dq21_rx_de-skew = <7>; + cs0_dq21_tx_de-skew = <8>; + cs0_dq22_rx_de-skew = <7>; + cs0_dq22_tx_de-skew = <8>; + cs0_dq23_rx_de-skew = <7>; + cs0_dq23_tx_de-skew = <8>; + cs0_dqs2_rx_de-skew = <6>; + cs0_dqs2p_tx_de-skew = <9>; + cs0_dqs2n_tx_de-skew = <9>; + + cs0_dm3_rx_de-skew = <7>; + cs0_dm3_tx_de-skew = <7>; + cs0_dq24_rx_de-skew = <7>; + cs0_dq24_tx_de-skew = <8>; + cs0_dq25_rx_de-skew = <7>; + cs0_dq25_tx_de-skew = <7>; + cs0_dq26_rx_de-skew = <7>; + cs0_dq26_tx_de-skew = <7>; + cs0_dq27_rx_de-skew = <7>; + cs0_dq27_tx_de-skew = <7>; + cs0_dq28_rx_de-skew = <7>; + cs0_dq28_tx_de-skew = <7>; + cs0_dq29_rx_de-skew = <7>; + cs0_dq29_tx_de-skew = <7>; + cs0_dq30_rx_de-skew = <7>; + cs0_dq30_tx_de-skew = <7>; + cs0_dq31_rx_de-skew = <7>; + cs0_dq31_tx_de-skew = <7>; + cs0_dqs3_rx_de-skew = <7>; + cs0_dqs3p_tx_de-skew = <9>; + cs0_dqs3n_tx_de-skew = <9>; + + cs1_dm0_rx_de-skew = <7>; + cs1_dm0_tx_de-skew = <8>; + cs1_dq0_rx_de-skew = <7>; + cs1_dq0_tx_de-skew = <8>; + cs1_dq1_rx_de-skew = <7>; + cs1_dq1_tx_de-skew = <8>; + cs1_dq2_rx_de-skew = <7>; + cs1_dq2_tx_de-skew = <8>; + cs1_dq3_rx_de-skew = <7>; + cs1_dq3_tx_de-skew = <8>; + cs1_dq4_rx_de-skew = <7>; + cs1_dq4_tx_de-skew = <8>; + cs1_dq5_rx_de-skew = <7>; + cs1_dq5_tx_de-skew = <8>; + cs1_dq6_rx_de-skew = <7>; + cs1_dq6_tx_de-skew = <8>; + cs1_dq7_rx_de-skew = <7>; + cs1_dq7_tx_de-skew = <8>; + cs1_dqs0_rx_de-skew = <6>; + cs1_dqs0p_tx_de-skew = <9>; + cs1_dqs0n_tx_de-skew = <9>; + + cs1_dm1_rx_de-skew = <7>; + cs1_dm1_tx_de-skew = <7>; + cs1_dq8_rx_de-skew = <7>; + cs1_dq8_tx_de-skew = <8>; + cs1_dq9_rx_de-skew = <7>; + cs1_dq9_tx_de-skew = <7>; + cs1_dq10_rx_de-skew = <7>; + cs1_dq10_tx_de-skew = <8>; + cs1_dq11_rx_de-skew = <7>; + cs1_dq11_tx_de-skew = <7>; + cs1_dq12_rx_de-skew = <7>; + cs1_dq12_tx_de-skew = <8>; + cs1_dq13_rx_de-skew = <7>; + cs1_dq13_tx_de-skew = <7>; + cs1_dq14_rx_de-skew = <7>; + cs1_dq14_tx_de-skew = <8>; + cs1_dq15_rx_de-skew = <7>; + cs1_dq15_tx_de-skew = <7>; + cs1_dqs1_rx_de-skew = <7>; + cs1_dqs1p_tx_de-skew = <9>; + cs1_dqs1n_tx_de-skew = <9>; + + cs1_dm2_rx_de-skew = <7>; + cs1_dm2_tx_de-skew = <8>; + cs1_dq16_rx_de-skew = <7>; + cs1_dq16_tx_de-skew = <8>; + cs1_dq17_rx_de-skew = <7>; + cs1_dq17_tx_de-skew = <8>; + cs1_dq18_rx_de-skew = <7>; + cs1_dq18_tx_de-skew = <8>; + cs1_dq19_rx_de-skew = <7>; + cs1_dq19_tx_de-skew = <8>; + cs1_dq20_rx_de-skew = <7>; + cs1_dq20_tx_de-skew = <8>; + cs1_dq21_rx_de-skew = <7>; + cs1_dq21_tx_de-skew = <8>; + cs1_dq22_rx_de-skew = <7>; + cs1_dq22_tx_de-skew = <8>; + cs1_dq23_rx_de-skew = <7>; + cs1_dq23_tx_de-skew = <8>; + cs1_dqs2_rx_de-skew = <6>; + cs1_dqs2p_tx_de-skew = <9>; + cs1_dqs2n_tx_de-skew = <9>; + + cs1_dm3_rx_de-skew = <7>; + cs1_dm3_tx_de-skew = <7>; + cs1_dq24_rx_de-skew = <7>; + cs1_dq24_tx_de-skew = <8>; + cs1_dq25_rx_de-skew = <7>; + cs1_dq25_tx_de-skew = <7>; + cs1_dq26_rx_de-skew = <7>; + cs1_dq26_tx_de-skew = <7>; + cs1_dq27_rx_de-skew = <7>; + cs1_dq27_tx_de-skew = <7>; + cs1_dq28_rx_de-skew = <7>; + cs1_dq28_tx_de-skew = <7>; + cs1_dq29_rx_de-skew = <7>; + cs1_dq29_tx_de-skew = <7>; + cs1_dq30_rx_de-skew = <7>; + cs1_dq30_tx_de-skew = <7>; + cs1_dq31_rx_de-skew = <7>; + cs1_dq31_tx_de-skew = <7>; + cs1_dqs3_rx_de-skew = <7>; + cs1_dqs3p_tx_de-skew = <9>; + cs1_dqs3n_tx_de-skew = <9>; + }; +}; diff --git a/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3368.dtsi b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3368.dtsi new file mode 100644 index 00000000..a4c5aaf1 --- /dev/null +++ b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3368.dtsi @@ -0,0 +1,1393 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2015 Heiko Stuebner + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/ { + compatible = "rockchip,rk3368"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + ethernet0 = &gmac; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c4; + i2c5 = &i2c5; + serial0 = &uart0; + serial1 = &uart1; + serial2 = &uart2; + serial3 = &uart3; + serial4 = &uart4; + spi0 = &spi0; + spi1 = &spi1; + spi2 = &spi2; + }; + + cpus { + #address-cells = <0x2>; + #size-cells = <0x0>; + + cpu-map { + cluster0 { + core0 { + cpu = <&cpu_b0>; + }; + core1 { + cpu = <&cpu_b1>; + }; + core2 { + cpu = <&cpu_b2>; + }; + core3 { + cpu = <&cpu_b3>; + }; + }; + + cluster1 { + core0 { + cpu = <&cpu_l0>; + }; + core1 { + cpu = <&cpu_l1>; + }; + core2 { + cpu = <&cpu_l2>; + }; + core3 { + cpu = <&cpu_l3>; + }; + }; + }; + + cpu_l0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x0 0x0>; + enable-method = "psci"; + #cooling-cells = <2>; /* min followed by max */ + }; + + cpu_l1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x0 0x1>; + enable-method = "psci"; + #cooling-cells = <2>; /* min followed by max */ + }; + + cpu_l2: cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x0 0x2>; + enable-method = "psci"; + #cooling-cells = <2>; /* min followed by max */ + }; + + cpu_l3: cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x0 0x3>; + enable-method = "psci"; + #cooling-cells = <2>; /* min followed by max */ + }; + + cpu_b0: cpu@100 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x0 0x100>; + enable-method = "psci"; + #cooling-cells = <2>; /* min followed by max */ + }; + + cpu_b1: cpu@101 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x0 0x101>; + enable-method = "psci"; + #cooling-cells = <2>; /* min followed by max */ + }; + + cpu_b2: cpu@102 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x0 0x102>; + enable-method = "psci"; + #cooling-cells = <2>; /* min followed by max */ + }; + + cpu_b3: cpu@103 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x0 0x103>; + enable-method = "psci"; + #cooling-cells = <2>; /* min followed by max */ + }; + }; + + arm-pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = , + , + , + , + , + , + , + ; + interrupt-affinity = <&cpu_l0>, <&cpu_l1>, <&cpu_l2>, + <&cpu_l3>, <&cpu_b0>, <&cpu_b1>, + <&cpu_b2>, <&cpu_b3>; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; + + xin24m: oscillator { + compatible = "fixed-clock"; + clock-frequency = <24000000>; + clock-output-names = "xin24m"; + #clock-cells = <0>; + }; + + sdmmc: mmc@ff0c0000 { + compatible = "rockchip,rk3368-dw-mshc", "rockchip,rk3288-dw-mshc"; + reg = <0x0 0xff0c0000 0x0 0x4000>; + max-frequency = <150000000>; + clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>, + <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>; + clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; + fifo-depth = <0x100>; + interrupts = ; + resets = <&cru SRST_MMC0>; + reset-names = "reset"; + status = "disabled"; + }; + + sdio0: mmc@ff0d0000 { + compatible = "rockchip,rk3368-dw-mshc", "rockchip,rk3288-dw-mshc"; + reg = <0x0 0xff0d0000 0x0 0x4000>; + max-frequency = <150000000>; + clocks = <&cru HCLK_SDIO0>, <&cru SCLK_SDIO0>, + <&cru SCLK_SDIO0_DRV>, <&cru SCLK_SDIO0_SAMPLE>; + clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; + fifo-depth = <0x100>; + interrupts = ; + resets = <&cru SRST_SDIO0>; + reset-names = "reset"; + status = "disabled"; + }; + + emmc: mmc@ff0f0000 { + compatible = "rockchip,rk3368-dw-mshc", "rockchip,rk3288-dw-mshc"; + reg = <0x0 0xff0f0000 0x0 0x4000>; + max-frequency = <150000000>; + clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>, + <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>; + clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; + fifo-depth = <0x100>; + interrupts = ; + resets = <&cru SRST_EMMC>; + reset-names = "reset"; + status = "disabled"; + }; + + saradc: saradc@ff100000 { + compatible = "rockchip,saradc"; + reg = <0x0 0xff100000 0x0 0x100>; + interrupts = ; + #io-channel-cells = <1>; + clocks = <&cru SCLK_SARADC>, <&cru PCLK_SARADC>; + clock-names = "saradc", "apb_pclk"; + resets = <&cru SRST_SARADC>; + reset-names = "saradc-apb"; + status = "disabled"; + }; + + spi0: spi@ff110000 { + compatible = "rockchip,rk3368-spi", "rockchip,rk3066-spi"; + reg = <0x0 0xff110000 0x0 0x1000>; + clocks = <&cru SCLK_SPI0>, <&cru PCLK_SPI0>; + clock-names = "spiclk", "apb_pclk"; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&spi0_clk &spi0_tx &spi0_rx &spi0_cs0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi1: spi@ff120000 { + compatible = "rockchip,rk3368-spi", "rockchip,rk3066-spi"; + reg = <0x0 0xff120000 0x0 0x1000>; + clocks = <&cru SCLK_SPI1>, <&cru PCLK_SPI1>; + clock-names = "spiclk", "apb_pclk"; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&spi1_clk &spi1_tx &spi1_rx &spi1_cs0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi2: spi@ff130000 { + compatible = "rockchip,rk3368-spi", "rockchip,rk3066-spi"; + reg = <0x0 0xff130000 0x0 0x1000>; + clocks = <&cru SCLK_SPI2>, <&cru PCLK_SPI2>; + clock-names = "spiclk", "apb_pclk"; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&spi2_clk &spi2_tx &spi2_rx &spi2_cs0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c2: i2c@ff140000 { + compatible = "rockchip,rk3368-i2c", "rockchip,rk3288-i2c"; + reg = <0x0 0xff140000 0x0 0x1000>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clock-names = "i2c"; + clocks = <&cru PCLK_I2C2>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_xfer>; + status = "disabled"; + }; + + i2c3: i2c@ff150000 { + compatible = "rockchip,rk3368-i2c", "rockchip,rk3288-i2c"; + reg = <0x0 0xff150000 0x0 0x1000>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clock-names = "i2c"; + clocks = <&cru PCLK_I2C3>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c3_xfer>; + status = "disabled"; + }; + + i2c4: i2c@ff160000 { + compatible = "rockchip,rk3368-i2c", "rockchip,rk3288-i2c"; + reg = <0x0 0xff160000 0x0 0x1000>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clock-names = "i2c"; + clocks = <&cru PCLK_I2C4>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c4_xfer>; + status = "disabled"; + }; + + i2c5: i2c@ff170000 { + compatible = "rockchip,rk3368-i2c", "rockchip,rk3288-i2c"; + reg = <0x0 0xff170000 0x0 0x1000>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clock-names = "i2c"; + clocks = <&cru PCLK_I2C5>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c5_xfer>; + status = "disabled"; + }; + + uart0: serial@ff180000 { + compatible = "rockchip,rk3368-uart", "snps,dw-apb-uart"; + reg = <0x0 0xff180000 0x0 0x100>; + clock-frequency = <24000000>; + clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>; + clock-names = "baudclk", "apb_pclk"; + interrupts = ; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + uart1: serial@ff190000 { + compatible = "rockchip,rk3368-uart", "snps,dw-apb-uart"; + reg = <0x0 0xff190000 0x0 0x100>; + clock-frequency = <24000000>; + clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>; + clock-names = "baudclk", "apb_pclk"; + interrupts = ; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + uart3: serial@ff1b0000 { + compatible = "rockchip,rk3368-uart", "snps,dw-apb-uart"; + reg = <0x0 0xff1b0000 0x0 0x100>; + clock-frequency = <24000000>; + clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>; + clock-names = "baudclk", "apb_pclk"; + interrupts = ; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + uart4: serial@ff1c0000 { + compatible = "rockchip,rk3368-uart", "snps,dw-apb-uart"; + reg = <0x0 0xff1c0000 0x0 0x100>; + clock-frequency = <24000000>; + clocks = <&cru SCLK_UART4>, <&cru PCLK_UART4>; + clock-names = "baudclk", "apb_pclk"; + interrupts = ; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + dmac_peri: dma-controller@ff250000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0x0 0xff250000 0x0 0x4000>; + interrupts = , + ; + #dma-cells = <1>; + arm,pl330-broken-no-flushp; + arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC_PERI>; + clock-names = "apb_pclk"; + }; + + thermal-zones { + cpu_thermal: cpu-thermal { + polling-delay-passive = <100>; /* milliseconds */ + polling-delay = <5000>; /* milliseconds */ + + thermal-sensors = <&tsadc 0>; + + trips { + cpu_alert0: cpu_alert0 { + temperature = <75000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "passive"; + }; + cpu_alert1: cpu_alert1 { + temperature = <80000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "passive"; + }; + cpu_crit: cpu_crit { + temperature = <95000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu_alert0>; + cooling-device = + <&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu_b1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu_b2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu_b3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + map1 { + trip = <&cpu_alert1>; + cooling-device = + <&cpu_l0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu_l1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu_l2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu_l3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + gpu_thermal: gpu-thermal { + polling-delay-passive = <100>; /* milliseconds */ + polling-delay = <5000>; /* milliseconds */ + + thermal-sensors = <&tsadc 1>; + + trips { + gpu_alert0: gpu_alert0 { + temperature = <80000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "passive"; + }; + gpu_crit: gpu_crit { + temperature = <115000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&gpu_alert0>; + cooling-device = + <&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu_b1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu_b2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu_b3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + }; + + tsadc: tsadc@ff280000 { + compatible = "rockchip,rk3368-tsadc"; + reg = <0x0 0xff280000 0x0 0x100>; + interrupts = ; + clocks = <&cru SCLK_TSADC>, <&cru PCLK_TSADC>; + clock-names = "tsadc", "apb_pclk"; + resets = <&cru SRST_TSADC>; + reset-names = "tsadc-apb"; + pinctrl-names = "init", "default", "sleep"; + pinctrl-0 = <&otp_pin>; + pinctrl-1 = <&otp_out>; + pinctrl-2 = <&otp_pin>; + #thermal-sensor-cells = <1>; + rockchip,hw-tshut-temp = <95000>; + status = "disabled"; + }; + + gmac: ethernet@ff290000 { + compatible = "rockchip,rk3368-gmac"; + reg = <0x0 0xff290000 0x0 0x10000>; + interrupts = ; + interrupt-names = "macirq"; + rockchip,grf = <&grf>; + clocks = <&cru SCLK_MAC>, + <&cru SCLK_MAC_RX>, <&cru SCLK_MAC_TX>, + <&cru SCLK_MACREF>, <&cru SCLK_MACREF_OUT>, + <&cru ACLK_GMAC>, <&cru PCLK_GMAC>; + clock-names = "stmmaceth", + "mac_clk_rx", "mac_clk_tx", + "clk_mac_ref", "clk_mac_refout", + "aclk_mac", "pclk_mac"; + status = "disabled"; + }; + + usb_host0_ehci: usb@ff500000 { + compatible = "generic-ehci"; + reg = <0x0 0xff500000 0x0 0x100>; + interrupts = ; + clocks = <&cru HCLK_HOST0>; + status = "disabled"; + }; + + usb_otg: usb@ff580000 { + compatible = "rockchip,rk3368-usb", "rockchip,rk3066-usb", + "snps,dwc2"; + reg = <0x0 0xff580000 0x0 0x40000>; + interrupts = ; + clocks = <&cru HCLK_OTG0>; + clock-names = "otg"; + dr_mode = "otg"; + g-np-tx-fifo-size = <16>; + g-rx-fifo-size = <275>; + g-tx-fifo-size = <256 128 128 64 64 32>; + status = "disabled"; + }; + + dmac_bus: dma-controller@ff600000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0x0 0xff600000 0x0 0x4000>; + interrupts = , + ; + #dma-cells = <1>; + arm,pl330-broken-no-flushp; + arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC_BUS>; + clock-names = "apb_pclk"; + }; + + i2c0: i2c@ff650000 { + compatible = "rockchip,rk3368-i2c", "rockchip,rk3288-i2c"; + reg = <0x0 0xff650000 0x0 0x1000>; + clocks = <&cru PCLK_I2C0>; + clock-names = "i2c"; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_xfer>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c1: i2c@ff660000 { + compatible = "rockchip,rk3368-i2c", "rockchip,rk3288-i2c"; + reg = <0x0 0xff660000 0x0 0x1000>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clock-names = "i2c"; + clocks = <&cru PCLK_I2C1>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_xfer>; + status = "disabled"; + }; + + pwm0: pwm@ff680000 { + compatible = "rockchip,rk3368-pwm", "rockchip,rk3288-pwm"; + reg = <0x0 0xff680000 0x0 0x10>; + #pwm-cells = <3>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm0_pin>; + clocks = <&cru PCLK_PWM1>; + status = "disabled"; + }; + + pwm1: pwm@ff680010 { + compatible = "rockchip,rk3368-pwm", "rockchip,rk3288-pwm"; + reg = <0x0 0xff680010 0x0 0x10>; + #pwm-cells = <3>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm1_pin>; + clocks = <&cru PCLK_PWM1>; + status = "disabled"; + }; + + pwm2: pwm@ff680020 { + compatible = "rockchip,rk3368-pwm", "rockchip,rk3288-pwm"; + reg = <0x0 0xff680020 0x0 0x10>; + #pwm-cells = <3>; + clocks = <&cru PCLK_PWM1>; + status = "disabled"; + }; + + pwm3: pwm@ff680030 { + compatible = "rockchip,rk3368-pwm", "rockchip,rk3288-pwm"; + reg = <0x0 0xff680030 0x0 0x10>; + #pwm-cells = <3>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm3_pin>; + clocks = <&cru PCLK_PWM1>; + status = "disabled"; + }; + + uart2: serial@ff690000 { + compatible = "rockchip,rk3368-uart", "snps,dw-apb-uart"; + reg = <0x0 0xff690000 0x0 0x100>; + clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>; + clock-names = "baudclk", "apb_pclk"; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&uart2_xfer>; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + mbox: mbox@ff6b0000 { + compatible = "rockchip,rk3368-mailbox"; + reg = <0x0 0xff6b0000 0x0 0x1000>; + interrupts = , + , + , + ; + clocks = <&cru PCLK_MAILBOX>; + clock-names = "pclk_mailbox"; + #mbox-cells = <1>; + status = "disabled"; + }; + + pmu: power-management@ff730000 { + compatible = "rockchip,rk3368-pmu", "syscon", "simple-mfd"; + reg = <0x0 0xff730000 0x0 0x1000>; + + power: power-controller { + compatible = "rockchip,rk3368-power-controller"; + #power-domain-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + + /* + * Note: Although SCLK_* are the working clocks + * of device without including on the NOC, needed for + * synchronous reset. + * + * The clocks on the which NOC: + * ACLK_IEP/ACLK_VIP/ACLK_VOP0 are on ACLK_VIO0_NIU. + * ACLK_ISP/ACLK_VOP1 are on ACLK_VIO1_NIU. + * ACLK_RGA is on ACLK_RGA_NIU. + * The others (HCLK_*,PLCK_*) are on HCLK_VIO_NIU. + * + * Which clock are device clocks: + * clocks devices + * *_IEP IEP:Image Enhancement Processor + * *_ISP ISP:Image Signal Processing + * *_VIP VIP:Video Input Processor + * *_VOP* VOP:Visual Output Processor + * *_RGA RGA + * *_EDP* EDP + * *_DPHY* LVDS + * *_HDMI HDMI + * *_MIPI_* MIPI + */ + power-domain@RK3368_PD_VIO { + reg = ; + clocks = <&cru ACLK_IEP>, + <&cru ACLK_ISP>, + <&cru ACLK_VIP>, + <&cru ACLK_RGA>, + <&cru ACLK_VOP>, + <&cru ACLK_VOP_IEP>, + <&cru DCLK_VOP>, + <&cru HCLK_IEP>, + <&cru HCLK_ISP>, + <&cru HCLK_RGA>, + <&cru HCLK_VIP>, + <&cru HCLK_VOP>, + <&cru HCLK_VIO_HDCPMMU>, + <&cru PCLK_EDP_CTRL>, + <&cru PCLK_HDMI_CTRL>, + <&cru PCLK_HDCP>, + <&cru PCLK_ISP>, + <&cru PCLK_VIP>, + <&cru PCLK_DPHYRX>, + <&cru PCLK_DPHYTX0>, + <&cru PCLK_MIPI_CSI>, + <&cru PCLK_MIPI_DSI0>, + <&cru SCLK_VOP0_PWM>, + <&cru SCLK_EDP_24M>, + <&cru SCLK_EDP>, + <&cru SCLK_HDCP>, + <&cru SCLK_ISP>, + <&cru SCLK_RGA>, + <&cru SCLK_HDMI_CEC>, + <&cru SCLK_HDMI_HDCP>; + pm_qos = <&qos_iep>, + <&qos_isp_r0>, + <&qos_isp_r1>, + <&qos_isp_w0>, + <&qos_isp_w1>, + <&qos_vip>, + <&qos_vop>, + <&qos_rga_r>, + <&qos_rga_w>; + #power-domain-cells = <0>; + }; + + /* + * Note: ACLK_VCODEC/HCLK_VCODEC are VCODEC + * (video endecoder & decoder) clocks that on the + * ACLK_VCODEC_NIU and HCLK_VCODEC_NIU (NOC). + */ + power-domain@RK3368_PD_VIDEO { + reg = ; + clocks = <&cru ACLK_VIDEO>, + <&cru HCLK_VIDEO>, + <&cru SCLK_HEVC_CABAC>, + <&cru SCLK_HEVC_CORE>; + pm_qos = <&qos_hevc_r>, + <&qos_vpu_r>, + <&qos_vpu_w>; + #power-domain-cells = <0>; + }; + + /* + * Note: ACLK_GPU is the GPU clock, + * and on the ACLK_GPU_NIU (NOC). + */ + power-domain@RK3368_PD_GPU_1 { + reg = ; + clocks = <&cru ACLK_GPU_CFG>, + <&cru ACLK_GPU_MEM>, + <&cru SCLK_GPU_CORE>; + pm_qos = <&qos_gpu>; + #power-domain-cells = <0>; + }; + }; + }; + + pmugrf: syscon@ff738000 { + compatible = "rockchip,rk3368-pmugrf", "syscon", "simple-mfd"; + reg = <0x0 0xff738000 0x0 0x1000>; + + pmu_io_domains: io-domains { + compatible = "rockchip,rk3368-pmu-io-voltage-domain"; + status = "disabled"; + }; + + reboot-mode { + compatible = "syscon-reboot-mode"; + offset = <0x200>; + mode-normal = ; + mode-recovery = ; + mode-bootloader = ; + mode-loader = ; + }; + }; + + cru: clock-controller@ff760000 { + compatible = "rockchip,rk3368-cru"; + reg = <0x0 0xff760000 0x0 0x1000>; + clocks = <&xin24m>; + clock-names = "xin24m"; + rockchip,grf = <&grf>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + grf: syscon@ff770000 { + compatible = "rockchip,rk3368-grf", "syscon", "simple-mfd"; + reg = <0x0 0xff770000 0x0 0x1000>; + + io_domains: io-domains { + compatible = "rockchip,rk3368-io-voltage-domain"; + status = "disabled"; + }; + }; + + wdt: watchdog@ff800000 { + compatible = "rockchip,rk3368-wdt", "snps,dw-wdt"; + reg = <0x0 0xff800000 0x0 0x100>; + clocks = <&cru PCLK_WDT>; + interrupts = ; + status = "disabled"; + }; + + timer0: timer@ff810000 { + compatible = "rockchip,rk3368-timer", "rockchip,rk3288-timer"; + reg = <0x0 0xff810000 0x0 0x20>; + interrupts = ; + clocks = <&cru PCLK_TIMER0>, <&cru SCLK_TIMER00>; + clock-names = "pclk", "timer"; + }; + + spdif: spdif@ff880000 { + compatible = "rockchip,rk3368-spdif"; + reg = <0x0 0xff880000 0x0 0x1000>; + interrupts = ; + clocks = <&cru SCLK_SPDIF_8CH>, <&cru HCLK_SPDIF>; + clock-names = "mclk", "hclk"; + dmas = <&dmac_bus 3>; + dma-names = "tx"; + pinctrl-names = "default"; + pinctrl-0 = <&spdif_tx>; + status = "disabled"; + }; + + i2s_2ch: i2s-2ch@ff890000 { + compatible = "rockchip,rk3368-i2s", "rockchip,rk3066-i2s"; + reg = <0x0 0xff890000 0x0 0x1000>; + interrupts = ; + clock-names = "i2s_clk", "i2s_hclk"; + clocks = <&cru SCLK_I2S_2CH>, <&cru HCLK_I2S_2CH>; + dmas = <&dmac_bus 6>, <&dmac_bus 7>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + + i2s_8ch: i2s-8ch@ff898000 { + compatible = "rockchip,rk3368-i2s", "rockchip,rk3066-i2s"; + reg = <0x0 0xff898000 0x0 0x1000>; + interrupts = ; + clock-names = "i2s_clk", "i2s_hclk"; + clocks = <&cru SCLK_I2S_8CH>, <&cru HCLK_I2S_8CH>; + dmas = <&dmac_bus 0>, <&dmac_bus 1>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&i2s_8ch_bus>; + status = "disabled"; + }; + + iep_mmu: iommu@ff900800 { + compatible = "rockchip,iommu"; + reg = <0x0 0xff900800 0x0 0x100>; + interrupts = ; + clocks = <&cru ACLK_IEP>, <&cru HCLK_IEP>; + clock-names = "aclk", "iface"; + power-domains = <&power RK3368_PD_VIO>; + #iommu-cells = <0>; + status = "disabled"; + }; + + isp_mmu: iommu@ff914000 { + compatible = "rockchip,iommu"; + reg = <0x0 0xff914000 0x0 0x100>, + <0x0 0xff915000 0x0 0x100>; + interrupts = ; + clocks = <&cru ACLK_ISP>, <&cru HCLK_ISP>; + clock-names = "aclk", "iface"; + #iommu-cells = <0>; + power-domains = <&power RK3368_PD_VIO>; + rockchip,disable-mmu-reset; + status = "disabled"; + }; + + vop_mmu: iommu@ff930300 { + compatible = "rockchip,iommu"; + reg = <0x0 0xff930300 0x0 0x100>; + interrupts = ; + clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>; + clock-names = "aclk", "iface"; + power-domains = <&power RK3368_PD_VIO>; + #iommu-cells = <0>; + status = "disabled"; + }; + + hevc_mmu: iommu@ff9a0440 { + compatible = "rockchip,iommu"; + reg = <0x0 0xff9a0440 0x0 0x40>, + <0x0 0xff9a0480 0x0 0x40>; + interrupts = ; + clocks = <&cru ACLK_VIDEO>, <&cru HCLK_VIDEO>; + clock-names = "aclk", "iface"; + #iommu-cells = <0>; + status = "disabled"; + }; + + vpu_mmu: iommu@ff9a0800 { + compatible = "rockchip,iommu"; + reg = <0x0 0xff9a0800 0x0 0x100>; + interrupts = , + ; + clocks = <&cru ACLK_VIDEO>, <&cru HCLK_VIDEO>; + clock-names = "aclk", "iface"; + #iommu-cells = <0>; + status = "disabled"; + }; + + qos_iep: qos@ffad0000 { + compatible = "rockchip,rk3368-qos", "syscon"; + reg = <0x0 0xffad0000 0x0 0x20>; + }; + + qos_isp_r0: qos@ffad0080 { + compatible = "rockchip,rk3368-qos", "syscon"; + reg = <0x0 0xffad0080 0x0 0x20>; + }; + + qos_isp_r1: qos@ffad0100 { + compatible = "rockchip,rk3368-qos", "syscon"; + reg = <0x0 0xffad0100 0x0 0x20>; + }; + + qos_isp_w0: qos@ffad0180 { + compatible = "rockchip,rk3368-qos", "syscon"; + reg = <0x0 0xffad0180 0x0 0x20>; + }; + + qos_isp_w1: qos@ffad0200 { + compatible = "rockchip,rk3368-qos", "syscon"; + reg = <0x0 0xffad0200 0x0 0x20>; + }; + + qos_vip: qos@ffad0280 { + compatible = "rockchip,rk3368-qos", "syscon"; + reg = <0x0 0xffad0280 0x0 0x20>; + }; + + qos_vop: qos@ffad0300 { + compatible = "rockchip,rk3368-qos", "syscon"; + reg = <0x0 0xffad0300 0x0 0x20>; + }; + + qos_rga_r: qos@ffad0380 { + compatible = "rockchip,rk3368-qos", "syscon"; + reg = <0x0 0xffad0380 0x0 0x20>; + }; + + qos_rga_w: qos@ffad0400 { + compatible = "rockchip,rk3368-qos", "syscon"; + reg = <0x0 0xffad0400 0x0 0x20>; + }; + + qos_hevc_r: qos@ffae0000 { + compatible = "rockchip,rk3368-qos", "syscon"; + reg = <0x0 0xffae0000 0x0 0x20>; + }; + + qos_vpu_r: qos@ffae0100 { + compatible = "rockchip,rk3368-qos", "syscon"; + reg = <0x0 0xffae0100 0x0 0x20>; + }; + + qos_vpu_w: qos@ffae0180 { + compatible = "rockchip,rk3368-qos", "syscon"; + reg = <0x0 0xffae0180 0x0 0x20>; + }; + + qos_gpu: qos@ffaf0000 { + compatible = "rockchip,rk3368-qos", "syscon"; + reg = <0x0 0xffaf0000 0x0 0x20>; + }; + + efuse256: efuse@ffb00000 { + compatible = "rockchip,rk3368-efuse"; + reg = <0x0 0xffb00000 0x0 0x20>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&cru PCLK_EFUSE256>; + clock-names = "pclk_efuse"; + + cpu_leakage: cpu-leakage@17 { + reg = <0x17 0x1>; + }; + temp_adjust: temp-adjust@1f { + reg = <0x1f 0x1>; + }; + }; + + gic: interrupt-controller@ffb71000 { + compatible = "arm,gic-400"; + interrupt-controller; + #interrupt-cells = <3>; + #address-cells = <0>; + + reg = <0x0 0xffb71000 0x0 0x1000>, + <0x0 0xffb72000 0x0 0x2000>, + <0x0 0xffb74000 0x0 0x2000>, + <0x0 0xffb76000 0x0 0x2000>; + interrupts = ; + }; + + pinctrl: pinctrl { + compatible = "rockchip,rk3368-pinctrl"; + rockchip,grf = <&grf>; + rockchip,pmu = <&pmugrf>; + #address-cells = <0x2>; + #size-cells = <0x2>; + ranges; + + gpio0: gpio@ff750000 { + compatible = "rockchip,gpio-bank"; + reg = <0x0 0xff750000 0x0 0x100>; + clocks = <&cru PCLK_GPIO0>; + interrupts = ; + + gpio-controller; + #gpio-cells = <0x2>; + + interrupt-controller; + #interrupt-cells = <0x2>; + }; + + gpio1: gpio@ff780000 { + compatible = "rockchip,gpio-bank"; + reg = <0x0 0xff780000 0x0 0x100>; + clocks = <&cru PCLK_GPIO1>; + interrupts = ; + + gpio-controller; + #gpio-cells = <0x2>; + + interrupt-controller; + #interrupt-cells = <0x2>; + }; + + gpio2: gpio@ff790000 { + compatible = "rockchip,gpio-bank"; + reg = <0x0 0xff790000 0x0 0x100>; + clocks = <&cru PCLK_GPIO2>; + interrupts = ; + + gpio-controller; + #gpio-cells = <0x2>; + + interrupt-controller; + #interrupt-cells = <0x2>; + }; + + gpio3: gpio@ff7a0000 { + compatible = "rockchip,gpio-bank"; + reg = <0x0 0xff7a0000 0x0 0x100>; + clocks = <&cru PCLK_GPIO3>; + interrupts = ; + + gpio-controller; + #gpio-cells = <0x2>; + + interrupt-controller; + #interrupt-cells = <0x2>; + }; + + pcfg_pull_up: pcfg-pull-up { + bias-pull-up; + }; + + pcfg_pull_down: pcfg-pull-down { + bias-pull-down; + }; + + pcfg_pull_none: pcfg-pull-none { + bias-disable; + }; + + pcfg_pull_none_12ma: pcfg-pull-none-12ma { + bias-disable; + drive-strength = <12>; + }; + + emmc { + emmc_clk: emmc-clk { + rockchip,pins = <2 RK_PA4 2 &pcfg_pull_none>; + }; + + emmc_cmd: emmc-cmd { + rockchip,pins = <1 RK_PD2 2 &pcfg_pull_up>; + }; + + emmc_pwr: emmc-pwr { + rockchip,pins = <1 RK_PD3 2 &pcfg_pull_up>; + }; + + emmc_bus1: emmc-bus1 { + rockchip,pins = <1 RK_PC2 2 &pcfg_pull_up>; + }; + + emmc_bus4: emmc-bus4 { + rockchip,pins = <1 RK_PC2 2 &pcfg_pull_up>, + <1 RK_PC3 2 &pcfg_pull_up>, + <1 RK_PC4 2 &pcfg_pull_up>, + <1 RK_PC5 2 &pcfg_pull_up>; + }; + + emmc_bus8: emmc-bus8 { + rockchip,pins = <1 RK_PC2 2 &pcfg_pull_up>, + <1 RK_PC3 2 &pcfg_pull_up>, + <1 RK_PC4 2 &pcfg_pull_up>, + <1 RK_PC5 2 &pcfg_pull_up>, + <1 RK_PC6 2 &pcfg_pull_up>, + <1 RK_PC7 2 &pcfg_pull_up>, + <1 RK_PD0 2 &pcfg_pull_up>, + <1 RK_PD1 2 &pcfg_pull_up>; + }; + }; + + gmac { + rgmii_pins: rgmii-pins { + rockchip,pins = <3 RK_PC6 1 &pcfg_pull_none>, + <3 RK_PD0 1 &pcfg_pull_none>, + <3 RK_PC3 1 &pcfg_pull_none>, + <3 RK_PB0 1 &pcfg_pull_none_12ma>, + <3 RK_PB1 1 &pcfg_pull_none_12ma>, + <3 RK_PB2 1 &pcfg_pull_none_12ma>, + <3 RK_PB6 1 &pcfg_pull_none_12ma>, + <3 RK_PD4 1 &pcfg_pull_none_12ma>, + <3 RK_PB5 1 &pcfg_pull_none_12ma>, + <3 RK_PB7 1 &pcfg_pull_none>, + <3 RK_PC0 1 &pcfg_pull_none>, + <3 RK_PC1 1 &pcfg_pull_none>, + <3 RK_PC2 1 &pcfg_pull_none>, + <3 RK_PD1 1 &pcfg_pull_none>, + <3 RK_PC4 1 &pcfg_pull_none>; + }; + + rmii_pins: rmii-pins { + rockchip,pins = <3 RK_PC6 1 &pcfg_pull_none>, + <3 RK_PD0 1 &pcfg_pull_none>, + <3 RK_PC3 1 &pcfg_pull_none>, + <3 RK_PB0 1 &pcfg_pull_none_12ma>, + <3 RK_PB1 1 &pcfg_pull_none_12ma>, + <3 RK_PB5 1 &pcfg_pull_none_12ma>, + <3 RK_PB7 1 &pcfg_pull_none>, + <3 RK_PC0 1 &pcfg_pull_none>, + <3 RK_PC4 1 &pcfg_pull_none>, + <3 RK_PC5 1 &pcfg_pull_none>; + }; + }; + + i2c0 { + i2c0_xfer: i2c0-xfer { + rockchip,pins = <0 RK_PA6 1 &pcfg_pull_none>, + <0 RK_PA7 1 &pcfg_pull_none>; + }; + }; + + i2c1 { + i2c1_xfer: i2c1-xfer { + rockchip,pins = <2 RK_PC5 1 &pcfg_pull_none>, + <2 RK_PC6 1 &pcfg_pull_none>; + }; + }; + + i2c2 { + i2c2_xfer: i2c2-xfer { + rockchip,pins = <0 RK_PB1 2 &pcfg_pull_none>, + <3 RK_PD7 2 &pcfg_pull_none>; + }; + }; + + i2c3 { + i2c3_xfer: i2c3-xfer { + rockchip,pins = <1 RK_PC0 1 &pcfg_pull_none>, + <1 RK_PC1 1 &pcfg_pull_none>; + }; + }; + + i2c4 { + i2c4_xfer: i2c4-xfer { + rockchip,pins = <3 RK_PD0 2 &pcfg_pull_none>, + <3 RK_PD1 2 &pcfg_pull_none>; + }; + }; + + i2c5 { + i2c5_xfer: i2c5-xfer { + rockchip,pins = <3 RK_PD2 2 &pcfg_pull_none>, + <3 RK_PD3 2 &pcfg_pull_none>; + }; + }; + + i2s { + i2s_8ch_bus: i2s-8ch-bus { + rockchip,pins = <2 RK_PB4 1 &pcfg_pull_none>, + <2 RK_PB5 1 &pcfg_pull_none>, + <2 RK_PB6 1 &pcfg_pull_none>, + <2 RK_PB7 1 &pcfg_pull_none>, + <2 RK_PC0 1 &pcfg_pull_none>, + <2 RK_PC1 1 &pcfg_pull_none>, + <2 RK_PC2 1 &pcfg_pull_none>, + <2 RK_PC3 1 &pcfg_pull_none>, + <2 RK_PC4 1 &pcfg_pull_none>; + }; + }; + + pwm0 { + pwm0_pin: pwm0-pin { + rockchip,pins = <3 RK_PB0 2 &pcfg_pull_none>; + }; + }; + + pwm1 { + pwm1_pin: pwm1-pin { + rockchip,pins = <0 RK_PB0 2 &pcfg_pull_none>; + }; + }; + + pwm3 { + pwm3_pin: pwm3-pin { + rockchip,pins = <3 RK_PD5 3 &pcfg_pull_none>; + }; + }; + + sdio0 { + sdio0_bus1: sdio0-bus1 { + rockchip,pins = <2 RK_PD4 1 &pcfg_pull_up>; + }; + + sdio0_bus4: sdio0-bus4 { + rockchip,pins = <2 RK_PD4 1 &pcfg_pull_up>, + <2 RK_PD5 1 &pcfg_pull_up>, + <2 RK_PD6 1 &pcfg_pull_up>, + <2 RK_PD7 1 &pcfg_pull_up>; + }; + + sdio0_cmd: sdio0-cmd { + rockchip,pins = <3 RK_PA0 1 &pcfg_pull_up>; + }; + + sdio0_clk: sdio0-clk { + rockchip,pins = <3 RK_PA1 1 &pcfg_pull_none>; + }; + + sdio0_cd: sdio0-cd { + rockchip,pins = <3 RK_PA2 1 &pcfg_pull_up>; + }; + + sdio0_wp: sdio0-wp { + rockchip,pins = <3 RK_PA3 1 &pcfg_pull_up>; + }; + + sdio0_pwr: sdio0-pwr { + rockchip,pins = <3 RK_PA4 1 &pcfg_pull_up>; + }; + + sdio0_bkpwr: sdio0-bkpwr { + rockchip,pins = <3 RK_PA5 1 &pcfg_pull_up>; + }; + + sdio0_int: sdio0-int { + rockchip,pins = <3 RK_PA6 1 &pcfg_pull_up>; + }; + }; + + sdmmc { + sdmmc_clk: sdmmc-clk { + rockchip,pins = <2 RK_PB1 1 &pcfg_pull_none>; + }; + + sdmmc_cmd: sdmmc-cmd { + rockchip,pins = <2 RK_PB2 1 &pcfg_pull_up>; + }; + + sdmmc_cd: sdmmc-cd { + rockchip,pins = <2 RK_PB3 1 &pcfg_pull_up>; + }; + + sdmmc_bus1: sdmmc-bus1 { + rockchip,pins = <2 RK_PA5 1 &pcfg_pull_up>; + }; + + sdmmc_bus4: sdmmc-bus4 { + rockchip,pins = <2 RK_PA5 1 &pcfg_pull_up>, + <2 RK_PA6 1 &pcfg_pull_up>, + <2 RK_PA7 1 &pcfg_pull_up>, + <2 RK_PB0 1 &pcfg_pull_up>; + }; + }; + + spdif { + spdif_tx: spdif-tx { + rockchip,pins = <2 RK_PC7 1 &pcfg_pull_none>; + }; + }; + + spi0 { + spi0_clk: spi0-clk { + rockchip,pins = <1 RK_PD5 2 &pcfg_pull_up>; + }; + spi0_cs0: spi0-cs0 { + rockchip,pins = <1 RK_PD0 3 &pcfg_pull_up>; + }; + spi0_cs1: spi0-cs1 { + rockchip,pins = <1 RK_PD1 3 &pcfg_pull_up>; + }; + spi0_tx: spi0-tx { + rockchip,pins = <1 RK_PC7 3 &pcfg_pull_up>; + }; + spi0_rx: spi0-rx { + rockchip,pins = <1 RK_PC6 3 &pcfg_pull_up>; + }; + }; + + spi1 { + spi1_clk: spi1-clk { + rockchip,pins = <1 RK_PB6 2 &pcfg_pull_up>; + }; + spi1_cs0: spi1-cs0 { + rockchip,pins = <1 RK_PB7 2 &pcfg_pull_up>; + }; + spi1_cs1: spi1-cs1 { + rockchip,pins = <3 RK_PD4 2 &pcfg_pull_up>; + }; + spi1_rx: spi1-rx { + rockchip,pins = <1 RK_PC0 2 &pcfg_pull_up>; + }; + spi1_tx: spi1-tx { + rockchip,pins = <1 RK_PC1 2 &pcfg_pull_up>; + }; + }; + + spi2 { + spi2_clk: spi2-clk { + rockchip,pins = <0 RK_PB4 2 &pcfg_pull_up>; + }; + spi2_cs0: spi2-cs0 { + rockchip,pins = <0 RK_PB5 2 &pcfg_pull_up>; + }; + spi2_rx: spi2-rx { + rockchip,pins = <0 RK_PB2 2 &pcfg_pull_up>; + }; + spi2_tx: spi2-tx { + rockchip,pins = <0 RK_PB3 2 &pcfg_pull_up>; + }; + }; + + tsadc { + otp_pin: otp-pin { + rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + otp_out: otp-out { + rockchip,pins = <0 RK_PA3 1 &pcfg_pull_none>; + }; + }; + + uart0 { + uart0_xfer: uart0-xfer { + rockchip,pins = <2 RK_PD0 1 &pcfg_pull_up>, + <2 RK_PD1 1 &pcfg_pull_none>; + }; + + uart0_cts: uart0-cts { + rockchip,pins = <2 RK_PD2 1 &pcfg_pull_none>; + }; + + uart0_rts: uart0-rts { + rockchip,pins = <2 RK_PD3 1 &pcfg_pull_none>; + }; + }; + + uart1 { + uart1_xfer: uart1-xfer { + rockchip,pins = <0 RK_PC4 3 &pcfg_pull_up>, + <0 RK_PC5 3 &pcfg_pull_none>; + }; + + uart1_cts: uart1-cts { + rockchip,pins = <0 RK_PC6 3 &pcfg_pull_none>; + }; + + uart1_rts: uart1-rts { + rockchip,pins = <0 RK_PC7 3 &pcfg_pull_none>; + }; + }; + + uart2 { + uart2_xfer: uart2-xfer { + rockchip,pins = <2 RK_PA6 2 &pcfg_pull_up>, + <2 RK_PA5 2 &pcfg_pull_none>; + }; + /* no rts / cts for uart2 */ + }; + + uart3 { + uart3_xfer: uart3-xfer { + rockchip,pins = <3 RK_PD5 2 &pcfg_pull_up>, + <3 RK_PD6 3 &pcfg_pull_none>; + }; + + uart3_cts: uart3-cts { + rockchip,pins = <3 RK_PC0 2 &pcfg_pull_none>; + }; + + uart3_rts: uart3-rts { + rockchip,pins = <3 RK_PC1 2 &pcfg_pull_none>; + }; + }; + + uart4 { + uart4_xfer: uart4-xfer { + rockchip,pins = <0 RK_PD3 3 &pcfg_pull_up>, + <0 RK_PD2 3 &pcfg_pull_none>; + }; + + uart4_cts: uart4-cts { + rockchip,pins = <0 RK_PD0 3 &pcfg_pull_none>; + }; + + uart4_rts: uart4-rts { + rockchip,pins = <0 RK_PD1 3 &pcfg_pull_none>; + }; + }; + }; +}; diff --git a/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3399-guangmiao-g4c.dts b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3399-guangmiao-g4c.dts new file mode 100644 index 00000000..c33a2cf1 --- /dev/null +++ b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3399-guangmiao-g4c.dts @@ -0,0 +1,664 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +/dts-v1/; +#include +#include "rk3399.dtsi" +#include "rk3399-opp.dtsi" + +/ { + model = "SHAREVDI GuangMiao G4C"; + compatible = "sharevdi,guangmiao-g4c", "rockchip,rk3399"; + + /delete-node/ display-subsystem; + + aliases { + led-boot = &status_led; + led-failsafe = &status_led; + led-running = &status_led; + led-upgrade = &status_led; + }; + + chosen { + stdout-path = "serial2:1500000n8"; + }; + + clkin_gmac: external-gmac-clock { + compatible = "fixed-clock"; + clock-frequency = <125000000>; + clock-output-names = "clkin_gmac"; + #clock-cells = <0>; + }; + + vcc_sys: vcc-sys { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-name = "vcc_sys"; + }; + + vcc3v3_sys: vcc3v3-sys { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc3v3_sys"; + vin-supply = <&vcc_sys>; + }; + + vcc_0v9: vcc-0v9 { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-name = "vcc_0v9"; + vin-supply = <&vcc3v3_sys>; + }; + + vcc5v0_host0: vcc5v0-host0 { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc5v0_host0"; + vin-supply = <&vcc_sys>; + }; + + vdd_log: vdd-log { + compatible = "pwm-regulator"; + pwms = <&pwm2 0 25000 1>; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1400000>; + regulator-name = "vdd_log"; + vin-supply = <&vcc_sys>; + }; + + gpio-keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&reset_button_pin>; + + reset { + label = "reset"; + debounce-interval = <100>; + gpios = <&gpio0 RK_PA5 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&lan_led_pin>, <&status_led_pin>, <&wan_led_pin>; + + lan_led: led-lan { + gpios = <&gpio0 RK_PA3 GPIO_ACTIVE_HIGH>; + label = "green:lan"; + }; + + status_led: led-status { + gpios = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>; + label = "green:status"; + }; + + wan_led: led-wan { + gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_HIGH>; + label = "green:wan"; + }; + }; +}; + +&cpu_b0 { + cpu-supply = <&vdd_cpu_b>; +}; + +&cpu_b1 { + cpu-supply = <&vdd_cpu_b>; +}; + +&cpu_l0 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l1 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l2 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l3 { + cpu-supply = <&vdd_cpu_l>; +}; + +&emmc_phy { + status = "okay"; +}; + +&gmac { + assigned-clock-parents = <&clkin_gmac>; + assigned-clocks = <&cru SCLK_RMII_SRC>; + clock_in_out = "input"; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>, <&phy_intb>, <&phy_pmeb>, <&phy_rstb>; + phy-handle = <&rtl8211e>; + phy-mode = "rgmii"; + phy-supply = <&vcc3v3_s3>; + tx_delay = <0x28>; + rx_delay = <0x11>; + status = "okay"; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + rtl8211e: ethernet-phy@1 { + reg = <1>; + interrupt-parent = <&gpio3>; + interrupts = ; + reset-assert-us = <10000>; + reset-deassert-us = <30000>; + reset-gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&gpu { + mali-supply = <&vdd_gpu>; + status = "okay"; +}; + +&i2c0 { + clock-frequency = <400000>; + i2c-scl-rising-time-ns = <160>; + i2c-scl-falling-time-ns = <30>; + status = "okay"; + + vdd_cpu_b: regulator@40 { + compatible = "silergy,syr827"; + reg = <0x40>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&cpu_b_sleep>; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; + regulator-name = "vdd_cpu_b"; + regulator-ramp-delay = <1000>; + vin-supply = <&vcc_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_gpu: regulator@41 { + compatible = "silergy,syr828"; + reg = <0x41>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&gpu_sleep>; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; + regulator-name = "vdd_gpu"; + regulator-ramp-delay = <1000>; + vin-supply = <&vcc_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + rk808: pmic@1b { + compatible = "rockchip,rk808"; + reg = <0x1b>; + clock-output-names = "rtc_clko_soc", "rtc_clko_wifi"; + #clock-cells = <1>; + interrupt-parent = <&gpio1>; + interrupts = <21 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int_l>; + rockchip,system-power-controller; + wakeup-source; + + vcc1-supply = <&vcc_sys>; + vcc2-supply = <&vcc_sys>; + vcc3-supply = <&vcc_sys>; + vcc4-supply = <&vcc_sys>; + vcc6-supply = <&vcc_sys>; + vcc7-supply = <&vcc_sys>; + vcc8-supply = <&vcc_3v0>; + vcc9-supply = <&vcc_sys>; + vcc10-supply = <&vcc_sys>; + vcc11-supply = <&vcc_sys>; + vcc12-supply = <&vcc_sys>; + vddio-supply = <&vcc_3v0>; + + regulators { + vdd_center: DCDC_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1350000>; + regulator-name = "vdd_center"; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_l: DCDC_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1350000>; + regulator-name = "vdd_cpu_l"; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc_ddr"; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_1v8: DCDC_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc_1v8"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc_vldo1: LDO_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc_vldo1"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_vldo2: LDO_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc_vldo2"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcca_1v8: LDO_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcca_1v8"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc_sdio: LDO_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc_sdio"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc3v0_sd: LDO_REG5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-name = "vcc3v0_sd"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc_1v5: LDO_REG6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-name = "vcc_1v5"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1500000>; + }; + }; + + vcca1v8_codec: LDO_REG7 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcca1v8_codec"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v0: LDO_REG8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-name = "vcc_3v0"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc3v3_s3: SWITCH_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc3v3_s3"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_s0: SWITCH_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc3v3_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; +}; + +&i2c3 { + i2c-scl-rising-time-ns = <450>; + i2c-scl-falling-time-ns = <15>; + status = "okay"; +}; + +&io_domains { + bt656-supply = <&vcc_1v8>; + audio-supply = <&vcca1v8_codec>; + sdmmc-supply = <&vcc_sdio>; + gpio1830-supply = <&vcc_3v0>; + status = "okay"; +}; + +&pcie_phy { + assigned-clock-parents = <&cru SCLK_PCIEPHY_REF100M>; + assigned-clock-rates = <100000000>; + assigned-clocks = <&cru SCLK_PCIEPHY_REF>; + status = "okay"; +}; + +&pcie0 { + ep-gpios = <&gpio4 RK_PD2 GPIO_ACTIVE_HIGH>; + max-link-speed = <1>; + num-lanes = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie_clkreqnb_cpm>; + vpcie0v9-supply = <&vcc_0v9>; + vpcie1v8-supply = <&vcca_1v8>; + vpcie3v3-supply = <&vcc3v3_sys>; + status = "okay"; + + pcie@0 { + reg = <0x00000000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + + pcie-eth@0,0 { + compatible = "realtek,r8168"; + reg = <0x000000 0 0 0 0>; + + realtek,led-data = <0x87>; + }; + }; +}; + +&pinctrl { + gpio-leds { + lan_led_pin: lan-led-pin { + rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + status_led_pin: status-led-pin { + rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + wan_led_pin: wan-led-pin { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + gmac { + phy_intb: phy-intb { + rockchip,pins = <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + phy_pmeb: phy-pmeb { + rockchip,pins = <0 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + phy_rstb: phy-rstb { + rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + cpu_b_sleep: cpu-b-sleep { + rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + gpu_sleep: gpu-sleep { + rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + pmic_int_l: pmic-int-l { + rockchip,pins = <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + rockchip-key { + reset_button_pin: reset-button-pin { + rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + sdio { + bt_reg_on_h: bt-reg-on-h { + /* external pullup to VCC1V8_PMUPLL */ + rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + sdmmc { + sdmmc0_det_l: sdmmc0-det-l { + rockchip,pins = <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; + +&pmu_io_domains { + pmu1830-supply = <&vcc_3v0>; + status = "okay"; +}; + +&pwm0 { + status = "okay"; +}; + +&pwm1 { + status = "okay"; +}; + +&pwm2 { + pinctrl-names = "active"; + pinctrl-0 = <&pwm2_pin_pull_down>; + status = "okay"; +}; + +&saradc { + vref-supply = <&vcc_1v8>; + status = "okay"; +}; + +&sdhci { + bus-width = <8>; + mmc-hs200-1_8v; + non-removable; + status = "okay"; +}; + +&sdmmc { + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + cd-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>; + disable-wp; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc_bus4 &sdmmc_clk &sdmmc_cmd &sdmmc0_det_l>; + vqmmc-supply = <&vcc_sdio>; + status = "okay"; +}; + +&tcphy0 { + status = "okay"; +}; + +&tcphy1 { + status = "okay"; +}; + +&tsadc { + rockchip,hw-tshut-mode = <1>; + rockchip,hw-tshut-polarity = <1>; + status = "okay"; +}; + +&u2phy0 { + status = "okay"; +}; + +&u2phy0_host { + phy-supply = <&vcc5v0_host0>; + status = "okay"; +}; + +&u2phy0_otg { + status = "okay"; +}; + +&u2phy1 { + status = "okay"; +}; + +&u2phy1_host { + phy-supply = <&vcc5v0_host0>; + status = "okay"; +}; + +&u2phy1_otg { + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&usbdrd3_0 { + status = "okay"; +}; + +&usbdrd3_1 { + status = "okay"; +}; + +&usbdrd_dwc3_0 { + dr_mode = "host"; + status = "okay"; +}; + +&usbdrd_dwc3_1 { + dr_mode = "host"; + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; + +&vopl { + status = "okay"; +}; + +&vopl_mmu { + status = "okay"; +}; diff --git a/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3399-king3399.dts b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3399-king3399.dts new file mode 100755 index 00000000..568ba176 --- /dev/null +++ b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3399-king3399.dts @@ -0,0 +1,1127 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd. + */ + +/dts-v1/; + +#include +#include +#include +#include "rk3399.dtsi" +#include "rk3399-opp.dtsi" + +/ { + model = "Rongpin King3399"; + compatible = "rongpin,king3399", "rockchip,rk3399"; + + aliases { + led-boot = &breathe_led; + led-failsafe = &breathe_led; + led-running = &breathe_led; + led-upgrade = &breathe_led; + mmc0 = &sdio0; + mmc1 = &sdmmc; + mmc2 = &sdhci; + }; + + chosen { + stdout-path = "serial2:1500000n8"; + }; + + clkin_gmac: external-gmac-clock { + compatible = "fixed-clock"; + clock-frequency = <125000000>; + clock-output-names = "clkin_gmac"; + #clock-cells = <0>; + }; + + adc-keys { + compatible = "adc-keys"; + io-channels = <&saradc 1>; + io-channel-names = "buttons"; + keyup-threshold-microvolt = <1800000>; + poll-interval = <100>; + + button-up { + label = "Volume Up"; + linux,code = ; + press-threshold-microvolt = <100000>; + }; + + button-down { + label = "Volume Down"; + linux,code = ; + press-threshold-microvolt = <300000>; + }; + + back { + label = "Back"; + linux,code = ; + press-threshold-microvolt = <985000>; + }; + }; + + keys: gpio-keys { + compatible = "gpio-keys"; // poweroff not sure + autorepeat; + + power { + debounce-interval = <100>; + gpios = <&gpio0 RK_PA5 GPIO_ACTIVE_LOW>; + label = "GPIO Power"; + linux,code = ; + linux,input-type = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&pwr_btn>; + wakeup-source; + }; + }; + + ir-receiver { + compatible = "gpio-ir-receiver"; + gpios = <&gpio0 RK_PA6 GPIO_ACTIVE_LOW>; // bsp + pinctrl-names = "default"; + pinctrl-0 = <&ir_int>; + }; + + backlight: backlight { + status = "disabled"; + compatible = "pwm-backlight"; + brightness-levels = < + 0 1 2 3 4 5 6 7 + 8 9 10 11 12 13 14 15 + 16 17 18 19 20 21 22 23 + 24 25 26 27 28 29 30 31 + 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255>; + default-brightness-level = <200>; + enable-gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_HIGH>; + pwms = <&pwm0 0 25000 0>; + }; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + clocks = <&rk808 1>; + clock-names = "ext_clock"; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_reg_on_h>; + + /* + * On the module itself this is one of these (depending + * on the actual card populated): + * - SDIO_RESET_L_WL_REG_ON + * - PDN (power down when low) + */ + reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>; + }; + + /* switched by pmic_sleep */ + vcc1v8_s3: vcca1v8_s3: vcc1v8-s3 { + compatible = "regulator-fixed"; + regulator-name = "vcc1v8_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&vcc_1v8>; + }; + + vcc3v0_sd: vcc3v0-sd { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>; // bsp + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc0_pwr_h>; + regulator-boot-on; + regulator-max-microvolt = <3000000>; + regulator-min-microvolt = <3000000>; + regulator-name = "vcc3v0_sd"; + vin-supply = <&vcc5v0_sys>; + }; + + vcc3v3_sys: vcc3v3-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc5v0_sys>; + }; + + // 4G Module + vcc3v3_gsm: vcc3v3-gsm { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio4 RK_PC6 GPIO_ACTIVE_HIGH>; // bsp + pinctrl-names = "default"; + pinctrl-0 = <&vcc3v3_gsm_en>; + regulator-name = "vcc3v3_gsm"; + // regulator-always-on; + vin-supply = <&dc_12v>; + }; + + // vdd 5v: USB 2&3, USB Hub, Type-C, HDMI, MIPI, IR + vcc5v0_host: vcc5v0-host-regulator { + compatible = "regulator-fixed"; + enable-active-high; + regulator-boot-on; + gpio = <&gpio4 RK_PD6 GPIO_ACTIVE_HIGH>; // bsp + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_host_en>; + regulator-name = "vcc5v0_host"; + // regulator-always-on; + vin-supply = <&vcc5v0_sys>; + }; + + vcc5v0_typec0: vbus-typec-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio4 RK_PD2 GPIO_ACTIVE_HIGH>; // bsp + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_typec_en>; + regulator-name = "vcc5v0_typec0"; + vin-supply = <&vcc5v0_sys>; + }; + + vcc_sys: vcc5v0_sys: vcc5v0-sys { // bsp + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&dc_12v>; + }; + + + dc_12v: vdd_12v: dc-12v { // dc_12v vdd_12V + compatible = "regulator-fixed"; + regulator-name = "dc_12v"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + }; + + rt5651-sound { // verify + status = "okay"; + compatible = "simple-audio-card"; + pinctrl-names = "default"; + pinctrl-0 = <&hp_det>; + + simple-audio-card,name = "realtek,rt5651-codec"; + simple-audio-card,format = "i2s"; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,hp-det-gpio = <&gpio4 RK_PD4 GPIO_ACTIVE_HIGH>; + simple-audio-card,aux-devs = <&speaker_amp>; + simple-audio-card,pin-switches = "Speaker"; + simple-audio-card,widgets = + "Microphone", "Mic Jack", + "Headphone", "Headphones", + "Speaker", "Speaker"; + simple-audio-card,routing = + "Mic Jack", "micbias1", + "Headphones", "HPOL", + "Headphones", "HPOR", + "Speaker Amplifier INL", "HPOL", + "Speaker Amplifier INR", "HPOR", + "Speaker", "Speaker Amplifier OUTL", + "Speaker", "Speaker Amplifier OUTR"; + simple-audio-card,cpu { + sound-dai = <&i2s0>; + }; + simple-audio-card,codec { + sound-dai = <&rt5651>; + }; + }; + + speaker_amp: speaker-amplifier { // verify + compatible = "simple-audio-amplifier"; + pinctrl-names = "default"; + pinctrl-0 = <&spk_ctl>; + enable-gpios = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>; + sound-name-prefix = "Speaker Amplifier"; + VCC-supply = <&vcc5v0_sys>; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&breathe_led_pin>; + + breathe_led: led-breathe-led { // bsp // vdd_12V + label = "breathe_led"; + linux,default-trigger = "heartbeat"; + default-state = "off"; + gpios = <&gpio4 RK_PD0 GPIO_ACTIVE_LOW>; + }; + }; + + fan0: gpio-fan { // verify // vcc5v0_sys + #cooling-cells = <2>; + compatible = "gpio-fan"; + gpio-fan,speed-map = <0 0 3000 1>; + gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; + + gpio-restart { + compatible = "gpio-restart"; + gpios = <&gpio1 RK_PD0 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&hub_rst>; + priority = <200>; + active-delay = <100>; + inactive-delay = <10>; + wait-delay = <100>; + }; + +}; + +&cpu_l0 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l1 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l2 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l3 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_b0 { + cpu-supply = <&vdd_cpu_b>; +}; + +&cpu_b1 { + cpu-supply = <&vdd_cpu_b>; +}; + +&cpu_thermal { // verify + trips { + cpu_hot: cpu_hot { + hysteresis = <10000>; + temperature = <55000>; + type = "active"; + }; + }; + + cooling-maps { + map2 { + cooling-device = + <&fan0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + trip = <&cpu_hot>; + }; + }; +}; + +&emmc_phy { + status = "okay"; +}; + +&gmac { + assigned-clocks = <&cru SCLK_RMII_SRC>; + assigned-clock-parents = <&clkin_gmac>; + clock_in_out = "input"; + phy-supply = <&vcc3v3_s3>; + phy-mode = "rgmii"; + phy-handle = <&rtl8211e>; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>, <&phy_intb>, <&phy_rstb>; + tx_delay = <0x28>; + rx_delay = <0x11>; + status = "okay"; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + rtl8211e: ethernet-phy@1 { + reg = <1>; + interrupt-parent = <&gpio3>; + interrupts = ; + reset-assert-us = <10000>; + reset-deassert-us = <30000>; + reset-gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + }; + }; +}; + +/* +&gmac { + assigned-clocks = <&cru SCLK_RMII_SRC>; + assigned-clock-parents = <&clkin_gmac>; + clock_in_out = "input"; + phy-supply = <&vcc_lan>; + phy-mode = "rgmii"; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>; + snps,reset-gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + snps,reset-delays-us = <0 10000 50000>; + tx_delay = <0x28>; + rx_delay = <0x11>; + status = "okay"; +}; +*/ + +&gpu { + mali-supply = <&vdd_gpu>; + status = "okay"; +}; + +&hdmi { + ddc-i2c-bus = <&i2c3>; + status = "okay"; +}; + +&hdmi_sound { + status = "okay"; +}; + +&i2s0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2s_8ch_mclk_pin>, <&i2s0_2ch_bus>; + #sound-dai-cells = <0>; + rockchip,capture-channels = <8>; + rockchip,playback-channels = <8>; + status = "okay"; +}; + +&i2s2 { + #sound-dai-cells = <0>; + status = "okay"; +}; + +&i2c0 { + clock-frequency = <400000>; + i2c-scl-rising-time-ns = <168>; + i2c-scl-falling-time-ns = <4>; + status = "okay"; + + rk808: pmic@1b { // bsp checked + compatible = "rockchip,rk808"; + reg = <0x1b>; + interrupt-parent = <&gpio1>; + interrupts = ; + #clock-cells = <1>; + clock-output-names = "rk808-clkout1", "rk808-clkout2"; // bsp + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int_l &pmic_dvs2>; + rockchip,system-power-controller; + wakeup-source; + + vcc1-supply = <&vcc5v0_sys>; + vcc2-supply = <&vcc5v0_sys>; + vcc3-supply = <&vcc5v0_sys>; + vcc4-supply = <&vcc5v0_sys>; + vcc6-supply = <&vcc5v0_sys>; + vcc7-supply = <&vcc5v0_sys>; + vcc8-supply = <&vcc3v3_sys>; + vcc9-supply = <&vcc5v0_sys>; + vcc10-supply = <&vcc5v0_sys>; + vcc11-supply = <&vcc5v0_sys>; + vcc12-supply = <&vcc3v3_sys>; + vddio-supply = <&vcc1v8_pmu>; + + regulators { + vdd_center: DCDC_REG1 { + regulator-name = "vdd_center"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_l: DCDC_REG2 { + regulator-name = "vdd_cpu_l"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_1v8: DCDC_REG4 { + regulator-name = "vcc_1v8"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc1v8_dvp: LDO_REG1 { + regulator-name = "vcc1v8_dvp"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v0_tp: LDO_REG2 { + regulator-name = "vcc3v0_tp"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc1v8_pmu: LDO_REG3 { + regulator-name = "vcc1v8_pmu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc_sdio: LDO_REG4 { + regulator-name = "vcc_sdio"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcca3v0_codec: LDO_REG5 { + regulator-name = "vcca3v0_codec"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v5: LDO_REG6 { + regulator-name = "vcc_1v5"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1500000>; + }; + }; + + vcca1v8_codec: LDO_REG7 { + regulator-name = "vcca1v8_codec"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v0: LDO_REG8 { + regulator-name = "vcc_3v0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc3v3_s3: vcc_lan: SWITCH_REG1 { + regulator-name = "vcc3v3_s3"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_s0: SWITCH_REG2 { + regulator-name = "vcc3v3_s0"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; + + vdd_cpu_b: regulator@40 { // bsp checked + compatible = "silergy,syr827"; + reg = <0x40>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&cpu_b_sleep>; + regulator-name = "vdd_cpu_b"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; + regulator-ramp-delay = <1000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_gpu: regulator@41 { // bsp checked + compatible = "silergy,syr828"; + reg = <0x41>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&gpu_sleep>; + regulator-name = "vdd_gpu"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; + regulator-ramp-delay = <1000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c1 { + i2c-scl-rising-time-ns = <300>; + i2c-scl-falling-time-ns = <15>; + status = "okay"; + + rt5651: rt5651@1a { + #sound-dai-cells = <0>; + compatible = "realtek,rt5651"; + reg = <0x1a>; + clocks = <&cru SCLK_I2S_8CH_OUT>; + clock-names = "mclk"; + status = "okay"; + }; +}; + +&i2c2 { + status = "okay"; +}; + +// Used for HDMI +&i2c3 { + i2c-scl-rising-time-ns = <450>; + i2c-scl-falling-time-ns = <15>; + status = "okay"; +}; + +// Type-C +// Accelerometer +// Touch Screen +&i2c4 { + clock-frequency = <400000>; + i2c-scl-rising-time-ns = <450>; + i2c-scl-falling-time-ns = <15>; + status = "okay"; + + fusb302@22 { // bsp checked + compatible = "fcs,fusb302"; + reg = <0x22>; + interrupt-parent = <&gpio1>; + interrupts = ; // bsp + pinctrl-names = "default"; + pinctrl-0 = <&chg_cc_int_l>; + vbus-supply = <&vcc5v0_typec0>; + + typec_con: connector { + compatible = "usb-c-connector"; + data-role = "host"; + label = "USB-C"; + op-sink-microwatt = <1000000>; + power-role = "dual"; + sink-pdos = + ; + source-pdos = + ; + try-power-role = "sink"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + typec_hs: endpoint { + remote-endpoint = <&u2phy0_typec_hs>; + }; + }; + port@1 { + reg = <1>; + typec_ss: endpoint { + remote-endpoint = <&tcphy0_typec_ss>; + }; + }; + port@2 { + reg = <2>; + typec_dp: endpoint { + remote-endpoint = <&tcphy0_typec_dp>; + }; + }; + }; + }; + }; + + mma8452: mma8452@1d { + compatible = "fsl,mma8452"; + reg = <0x1d>; + interrupt-parent = <&gpio1>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&gsensor_int>; + }; +}; + +&io_domains { // bsp checked + status = "okay"; + bt656-supply = <&vcc_1v8>; + audio-supply = <&vcca1v8_codec>; + sdmmc-supply = <&vcc_sdio>; + gpio1830-supply = <&vcc_3v0>; +}; + +&pmu_io_domains { // bsp checked + status = "okay"; + pmu1830-supply = <&vcc_1v8>; +}; + +&hdmi { // bsp + ddc-i2c-bus = <&i2c3>; + status = "okay"; +}; + +// &cpu_thermal { +// trips { +// cpu_hot: cpu_hot { +// hysteresis = <10000>; +// temperature = <65000>; +// type = "active"; +// }; +// }; + +// cooling-maps { +// map2 { +// cooling-device = <&fan0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; +// trip = <&cpu_hot>; +// }; +// }; +// }; + +&pinctrl { + buttons { + pwr_btn: pwr-btn { + rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + fan { + motor_pwr: motor-pwr { + rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + ir { + ir_int: ir-int { + rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; // bsp + }; + }; + + gmac { + phy_intb: phy-intb { + rockchip,pins = <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; // verify + }; + + phy_rstb: phy-rstb { + rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; // verify + }; + }; + + pmic { + cpu_b_sleep: cpu-b-sleep { + rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; // verify + }; + + gpu_sleep: gpu-sleep { + rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; // verify + }; + + pmic_int_l: pmic-int-l { + rockchip,pins = <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; // verify + }; + + pmic_dvs2: pmic-dvs2 { + rockchip,pins = <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + sd { + sdmmc0_pwr_h: sdmmc0-pwr-h { + rockchip,pins = <0 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>; // bsp + }; + }; + + usb2 { + vcc5v0_host_en: vcc5v0-host-en { + rockchip,pins = <4 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>; // bsp + }; + + vcc5v0_typec_en: vcc5v0-typec-en { + rockchip,pins = <4 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; // bsp + }; + + hub_rst: hub-rst { + rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + sdio-pwrseq { + wifi_reg_on_h: wifi-reg-on-h { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; // checked + }; + }; + + wifi { + wifi_host_wake_l: wifi-host-wake-l { + rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>; // checked + }; + }; + + bluetooth { + bt_reg_on_h: bt-enable-h { + rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>; // checked + }; + + bt_host_wake_l: bt-host-wake-l { + rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>; // checked + }; + + bt_wake_l: bt-wake-l { + rockchip,pins = <2 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; // checked + }; + }; + + fusb302 { + chg_cc_int_l: chg-cc-int-l { + rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>; // bsp + }; + }; + + leds { + breathe_led_pin: breathe-led-pin { + rockchip,pins = <4 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>; // bsp + }; + }; + + gsm { + vcc3v3_gsm_en: vcc3v3-gsm-en { + rockchip,pins = <4 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; // bsp + }; + }; + + headphone { + hp_det: hp-det { + rockchip,pins = <4 RK_PD4 RK_FUNC_GPIO &pcfg_pull_up>; // verify + }; + spk_ctl: spk-ctl { + rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_up>; // verify + }; + }; + + mma8452 { + gsensor_int: gsensor-int { + rockchip,pins = <1 RK_PC7 RK_FUNC_GPIO &pcfg_pull_up>; // bsp + }; + }; + + i2s0 { + i2s_8ch_mclk_pin: i2s-8ch-mclk-pin { + rockchip,pins = <4 RK_PA0 1 &pcfg_pull_none>; // verify + }; + }; +}; + +&pwm0 { + status = "okay"; +}; + +&pwm2 { + status = "okay"; +}; + +&saradc { + vref-supply = <&vcca1v8_s3>; + status = "okay"; +}; + +&sdhci { + bus-width = <8>; + mmc-hs400-1_8v; + mmc-hs400-enhanced-strobe; + // keep-power-in-suspend; + non-removable; + status = "okay"; +}; + +&sdio0 { + bus-width = <4>; + cap-sd-highspeed; + cap-sdio-irq; + clock-frequency = <50000000>; + disable-wp; + keep-power-in-suspend; + max-frequency = <50000000>; + mmc-pwrseq = <&sdio_pwrseq>; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&sdio0_bus4 &sdio0_cmd &sdio0_clk>; + sd-uhs-sdr104; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + brcmf: wifi@1 { + reg = <1>; + compatible = "brcm,bcm43455-fmac"; + interrupt-parent = <&gpio0>; + interrupts = ; // bsp verify + interrupt-names = "host-wake"; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_host_wake_l>; + }; +}; + +&sdmmc { + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + cd-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>; // checked + clock-frequency = <150000000>; + disable-wp; + max-frequency = <150000000>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>; + vmmc-supply = <&vcc3v0_sd>; + vqmmc-supply = <&vcc_sdio>; + status = "okay"; +}; + +&tcphy0 { // verify + status = "okay"; +}; + +&tcphy0_dp { // verify + port { + tcphy0_typec_dp: endpoint { + remote-endpoint = <&typec_dp>; + }; + }; +}; + +&tcphy0_usb3 { // verify + port { + tcphy0_typec_ss: endpoint { + remote-endpoint = <&typec_ss>; + }; + }; +}; + +&tcphy1 { // verify + status = "okay"; +}; + +&tsadc { + /* tshut mode 0:CRU 1:GPIO */ + rockchip,hw-tshut-mode = <1>; + /* tshut polarity 0:LOW 1:HIGH */ + rockchip,hw-tshut-polarity = <1>; + status = "okay"; +}; + +&u2phy0 { + status = "okay"; + + u2phy0_otg: otg-port { + phy-supply = <&vcc5v0_typec0>; + status = "okay"; + }; + + u2phy0_host: host-port { + phy-supply = <&vcc5v0_host>; + status = "okay"; + }; + + port { + u2phy0_typec_hs: endpoint { + remote-endpoint = <&typec_hs>; + }; + }; +}; + +&u2phy1 { + status = "okay"; + + u2phy1_otg: otg-port { + status = "okay"; + }; + + u2phy1_host: host-port { + phy-supply = <&vcc5v0_host>; + status = "okay"; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>; + status = "okay"; + + bluetooth { + compatible = "brcm,bcm43438-bt"; + clocks = <&rk808 1>; + clock-names = "lpo"; + device-wakeup-gpios = <&gpio2 RK_PD2 GPIO_ACTIVE_HIGH>; + host-wakeup-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_HIGH>; + shutdown-gpios = <&gpio0 RK_PB1 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&bt_host_wake_l &bt_wake_l &bt_reg_on_h>; + vbat-supply = <&vcc5v0_sys>; + vddio-supply = <&vcc_1v8>; + }; +}; + +&uart2 { + status = "okay"; +}; + +&uart4 { + status = "okay"; +}; + +&spi1 { + status = "disabled"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +&usbdrd3_0 { + status = "okay"; +}; + +&usbdrd_dwc3_0 { + status = "okay"; + dr_mode = "host"; +}; + +&usbdrd3_1 { + status = "okay"; +}; + +&usbdrd_dwc3_1 { + status = "okay"; + dr_mode = "host"; +}; + +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; + +&vopl { + status = "okay"; +}; + +&vopl_mmu { + status = "okay"; +}; diff --git a/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4se.dts b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4se.dts new file mode 100644 index 00000000..6b503165 --- /dev/null +++ b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4se.dts @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +/dts-v1/; +#include "rk3399-nanopi-r4s.dts" + +/ { + model = "FriendlyElec NanoPi R4SE"; + compatible = "friendlyarm,nanopi-r4se", "rockchip,rk3399"; +}; + + +&emmc_phy { + status = "okay"; +}; + +&sdhci { + status = "okay"; +}; diff --git a/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-fastrhino.dtsi b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-fastrhino.dtsi new file mode 100644 index 00000000..1322c909 --- /dev/null +++ b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-fastrhino.dtsi @@ -0,0 +1,530 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +#include +#include +#include +#include "rk3568.dtsi" + +/ { + aliases { + led-boot = &led_work; + led-failsafe = &led_work; + led-running = &led_work; + led-upgrade = &led_work; + }; + + chosen { + stdout-path = "serial2:1500000n8"; + }; + + vcc12v_dcin: vcc12v-dcin { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + regulator-name = "vcc12v_dcin"; + }; + + vcc3v3_sys: vcc3v3-sys { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc3v3_sys"; + vin-supply = <&vcc12v_dcin>; + }; + + vcc5v0_sys: vcc5v0-sys { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-name = "vcc5v0_sys"; + vin-supply = <&vcc12v_dcin>; + }; + + vcc5v0_usb: vcc5v0-usb { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-name = "vcc5v0_usb"; + vin-supply = <&vcc12v_dcin>; + }; + + vcc5v0_usb_otg: vcc5v0-usb-otg { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_usb_otg_en>; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-name = "vcc5v0_usb_otg"; + vin-supply = <&vcc5v0_usb>; + }; + + vcc3v3_pcie: vcc3v3-pcie { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc3v3_pcie"; + vin-supply = <&vcc12v_dcin>; + }; + + gpio-keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&reset_button_pin>; + + reset { + label = "reset"; + gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_LOW>; + linux,code = ; + debounce-interval = <50>; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_work_en>; + + led_work: led-0 { + label = "blue:work-led"; + gpios = <&gpio0 RK_PC0 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + }; + }; +}; + +&combphy0 { + status = "okay"; +}; + +&combphy1 { + status = "okay"; +}; + +&combphy2 { + status = "okay"; +}; + +&cpu0 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu1 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu2 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu3 { + cpu-supply = <&vdd_cpu>; +}; + +#ifdef DTS_NO_LEGACY +&display_subsystem { + status = "disabled"; +}; + +&gpu { + mali-supply = <&vdd_gpu>; + status = "okay"; +}; +#endif + +&i2c0 { + status = "okay"; + + vdd_cpu: regulator@1c { + compatible = "tcs,tcs4525"; + reg = <0x1c>; + fcs,suspend-voltage-selector = <1>; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1390000>; + regulator-name = "vdd_cpu"; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + rk809: pmic@20 { + compatible = "rockchip,rk809"; + reg = <0x20>; + interrupt-parent = <&gpio0>; + interrupts = ; + #clock-cells = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>; + rockchip,system-power-controller; + wakeup-source; + + vcc1-supply = <&vcc3v3_sys>; + vcc2-supply = <&vcc3v3_sys>; + vcc3-supply = <&vcc3v3_sys>; + vcc4-supply = <&vcc3v3_sys>; + vcc5-supply = <&vcc3v3_sys>; + vcc6-supply = <&vcc3v3_sys>; + vcc7-supply = <&vcc3v3_sys>; + vcc8-supply = <&vcc3v3_sys>; + vcc9-supply = <&vcc3v3_sys>; + + regulators { + vdd_logic: DCDC_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-init-microvolt = <900000>; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-name = "vdd_logic"; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_gpu: DCDC_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-init-microvolt = <900000>; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-name = "vdd_gpu"; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-initial-mode = <0x2>; + regulator-name = "vcc_ddr"; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vdd_npu: DCDC_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-init-microvolt = <900000>; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-name = "vdd_npu"; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8: DCDC_REG5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc_1v8"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda0v9_image: LDO_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <950000>; + regulator-name = "vdda0v9_image"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda_0v9: LDO_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-name = "vdda_0v9"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda0v9_pmu: LDO_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-name = "vdda0v9_pmu"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <900000>; + }; + }; + + vccio_acodec: LDO_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vccio_acodec"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vccio_sd: LDO_REG5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vccio_sd"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_pmu: LDO_REG6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc3v3_pmu"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcca_1v8: LDO_REG7 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcca_1v8"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcca1v8_pmu: LDO_REG8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcca1v8_pmu"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcca1v8_image: LDO_REG9 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1800000>; + regulator-init-microvolt = <950000>; + regulator-name = "vcca1v8_image"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vcc_3v3: SWITCH_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc_3v3"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_sd: SWITCH_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc3v3_sd"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; +}; + +&gic { + mbi-ranges = <94 31>, <229 31>, <289 31>; +}; + +&pcie30phy { + data-lanes = <1 2>; + status = "okay"; +}; + +&pcie3x1 { + num-lanes = <1>; + reset-gpios = <&gpio0 RK_PC3 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie>; + status = "okay"; + + pcie@10 { + reg = <0x00100000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + + rtl8125_1: pcie-eth@10,0 { + compatible = "pci10ec,8125"; + reg = <0x000000 0 0 0 0>; + + realtek,led-data = <0x4078>; + }; + }; +}; + +&pcie3x2 { + num-lanes = <1>; + reset-gpios = <&gpio0 RK_PC6 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie>; + status = "okay"; + + pcie@20 { + reg = <0x00200000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + + rtl8125_2: pcie-eth@20,0 { + compatible = "pci10ec,8125"; + reg = <0x000000 0 0 0 0>; + + realtek,led-data = <0x4078>; + }; + }; +}; + +&pinctrl { + leds { + led_work_en: led_work_en { + rockchip,pins = <0 RK_PC0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + pmic_int: pmic_int { + rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + rockchip-key { + reset_button_pin: reset-button-pin { + rockchip,pins = <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + usb { + vcc5v0_usb_otg_en: vcc5v0_usb_otg_en { + rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pmu_io_domains { + pmuio1-supply = <&vcc3v3_pmu>; + pmuio2-supply = <&vcc3v3_pmu>; + vccio1-supply = <&vccio_acodec>; + vccio3-supply = <&vccio_sd>; + vccio4-supply = <&vcc_1v8>; + vccio5-supply = <&vcc_3v3>; + vccio6-supply = <&vcc_1v8>; + vccio7-supply = <&vcc_3v3>; + status = "okay"; +}; + +&rng { + status = "okay"; +}; + +&saradc { + vref-supply = <&vcca_1v8>; + status = "okay"; +}; + +&tsadc { + rockchip,hw-tshut-mode = <1>; + rockchip,hw-tshut-polarity = <0>; + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&usb_host0_xhci { + dr_mode = "host"; + status = "okay"; +}; + +&usb_host1_xhci { + status = "okay"; +}; + +&usb2phy0 { + status = "okay"; +}; + +&usb2phy0_host { + status = "okay"; +}; + +&usb2phy0_otg { + phy-supply = <&vcc5v0_usb_otg>; + status = "okay"; +}; + +#ifdef DTS_NO_LEGACY +&vop { + assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>; + assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>; + status = "okay"; +}; + +&vop_mmu { + status = "okay"; +}; +#endif diff --git a/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-mrkaio-m68s.dts b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-mrkaio-m68s.dts new file mode 100644 index 00000000..3d983e9b --- /dev/null +++ b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-mrkaio-m68s.dts @@ -0,0 +1,654 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +// Copyright (c) 2022 AmadeusGhost + +/dts-v1/; + +#include +#include +#include +#include +#include "rk3568.dtsi" + +/ { + model = "EZPRO Mrkaio M68S"; + compatible = "ezpro,mrkaio-m68s", "rockchip,rk3568"; + + aliases { + ethernet0 = &gmac0; + ethernet1 = &gmac1; + mmc0 = &sdmmc0; + mmc1 = &sdhci; + + led-boot = &led_sys; + led-failsafe = &led_sys; + led-running = &led_sys; + led-upgrade = &led_sys; + }; + + chosen { + stdout-path = "serial2:1500000n8"; + }; + +#ifdef DTS_NO_LEGACY + hdmi-con { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con_in: endpoint { + remote-endpoint = <&hdmi_out_con>; + }; + }; + }; +#endif + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_sata_en>, <&led_sys_en>; + + sata { + label = "blue:sata"; + gpios = <&gpio0 RK_PC2 GPIO_ACTIVE_HIGH>; + }; + + led_sys: sys { + label = "red:sys"; + gpios = <&gpio4 RK_PC4 GPIO_ACTIVE_HIGH>; + }; + }; + + dc_12v: dc-12v { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + regulator-name = "dc_12v"; + }; + + vcc3v3_sys: vcc3v3-sys { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc3v3_sys"; + vin-supply = <&dc_12v>; + }; + + vcc5v0_sys: vcc5v0-sys { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-name = "vcc5v0_sys"; + vin-supply = <&dc_12v>; + }; + + vcc5v0_usb_host: vcc5v0-usb-host { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_usb_host_en>; + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc5v0_usb_host"; + }; + + vcc5v0_usb_otg: vcc5v0-usb-otg { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_usb_otg_en>; + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc5v0_usb_otg"; + }; + + vcc5v0_ahci: vcc5v0-ahci { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&sata_pwr_en>; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-name = "vcc5v0_ahci"; + }; +}; + +&combphy0 { + status = "okay"; +}; + +&combphy1 { + status = "okay"; +}; + +&combphy2 { + status = "okay"; +}; + +&cpu0 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu1 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu2 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu3 { + cpu-supply = <&vdd_cpu>; +}; + +&gmac0 { + assigned-clocks = <&cru SCLK_GMAC0_RX_TX>, <&cru SCLK_GMAC0>; + assigned-clock-parents = <&cru SCLK_GMAC0_RGMII_SPEED>; + assigned-clock-rates = <0>, <125000000>; + clock_in_out = "output"; + phy-mode = "rgmii-id"; + pinctrl-names = "default"; + pinctrl-0 = <&gmac0_miim + &gmac0_tx_bus2 + &gmac0_rx_bus2 + &gmac0_rgmii_clk + &gmac0_rgmii_bus>; + snps,reset-gpio = <&gpio3 RK_PA6 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + /* Reset time is 20ms, 100ms for rtl8211f */ + snps,reset-delays-us = <0 20000 100000>; + tx_delay = <0x3c>; + rx_delay = <0x2f>; + phy-handle = <&rgmii_phy0>; + status = "okay"; +}; + +&gmac1 { + assigned-clocks = <&cru SCLK_GMAC1_RX_TX>, <&cru SCLK_GMAC1>; + assigned-clock-parents = <&cru SCLK_GMAC1_RGMII_SPEED>; + assigned-clock-rates = <0>, <125000000>; + clock_in_out = "output"; + phy-mode = "rgmii-id"; + pinctrl-names = "default"; + pinctrl-0 = <&gmac1m1_miim + &gmac1m1_tx_bus2 + &gmac1m1_rx_bus2 + &gmac1m1_rgmii_clk + &gmac1m1_rgmii_bus>; + snps,reset-gpio = <&gpio3 RK_PA7 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + /* Reset time is 20ms, 100ms for rtl8211f */ + snps,reset-delays-us = <0 20000 100000>; + tx_delay = <0x42>; + rx_delay = <0x28>; + phy-handle = <&rgmii_phy1>; + status = "okay"; +}; + +#ifdef DTS_NO_LEGACY +&gpu { + mali-supply = <&vdd_gpu>; + status = "okay"; +}; + +&hdmi { + avdd-0v9-supply = <&vdda0v9_image>; + avdd-1v8-supply = <&vcca1v8_image>; + status = "okay"; +}; + +&hdmi_in { + hdmi_in_vp0: endpoint { + remote-endpoint = <&vp0_out_hdmi>; + }; +}; + +&hdmi_out { + hdmi_out_con: endpoint { + remote-endpoint = <&hdmi_con_in>; + }; +}; + +&hdmi_sound { + status = "okay"; +}; +#endif + +&i2c0 { + status = "okay"; + + vdd_cpu: regulator@1c { + compatible = "tcs,tcs4525"; + reg = <0x1c>; + fcs,suspend-voltage-selector = <1>; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1390000>; + regulator-name = "vdd_cpu"; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + rk809: pmic@20 { + compatible = "rockchip,rk809"; + reg = <0x20>; + interrupt-parent = <&gpio0>; + interrupts = ; + #clock-cells = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>; + rockchip,system-power-controller; + wakeup-source; + + vcc1-supply = <&vcc3v3_sys>; + vcc2-supply = <&vcc3v3_sys>; + vcc3-supply = <&vcc3v3_sys>; + vcc4-supply = <&vcc3v3_sys>; + vcc5-supply = <&vcc3v3_sys>; + vcc6-supply = <&vcc3v3_sys>; + vcc7-supply = <&vcc3v3_sys>; + vcc8-supply = <&vcc3v3_sys>; + vcc9-supply = <&vcc3v3_sys>; + + regulators { + vdd_logic: DCDC_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-init-microvolt = <900000>; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-name = "vdd_logic"; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_gpu: DCDC_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-init-microvolt = <900000>; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-name = "vdd_gpu"; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-initial-mode = <0x2>; + regulator-name = "vcc_ddr"; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vdd_npu: DCDC_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-init-microvolt = <900000>; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-name = "vdd_npu"; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8: DCDC_REG5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc_1v8"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda0v9_image: LDO_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-name = "vdda0v9_image"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda_0v9: LDO_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-name = "vdda_0v9"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda0v9_pmu: LDO_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-name = "vdda0v9_pmu"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <900000>; + }; + }; + + vccio_acodec: LDO_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vccio_acodec"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vccio_sd: LDO_REG5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vccio_sd"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_pmu: LDO_REG6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc3v3_pmu"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcca_1v8: LDO_REG7 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcca_1v8"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcca1v8_pmu: LDO_REG8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcca1v8_pmu"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcca1v8_image: LDO_REG9 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcca1v8_image"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v3: SWITCH_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc_3v3"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_sd: SWITCH_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc3v3_sd"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; +}; + +#ifdef DTS_NO_LEGACY +&i2s0_8ch { + status = "okay"; +}; +#endif + +&mdio0 { + rgmii_phy0: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0x0>; + }; +}; + +&mdio1 { + rgmii_phy1: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0x0>; + }; +}; + +&pinctrl { + leds { + led_sata_en: led_sata_en { + rockchip,pins = <0 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + led_sys_en: led_sys_en { + rockchip,pins = <4 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + pmic_int: pmic_int { + rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + sata { + sata_pwr_en: sata-pwr-en { + rockchip,pins = <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + usb { + vcc5v0_usb_host_en: vcc5v0_usb_host_en { + rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + vcc5v0_usb_otg_en: vcc5v0_usb_otg_en { + rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pmu_io_domains { + pmuio1-supply = <&vcc3v3_pmu>; + pmuio2-supply = <&vcc3v3_pmu>; + vccio1-supply = <&vccio_acodec>; + vccio2-supply = <&vcc_1v8>; + vccio3-supply = <&vccio_sd>; + vccio4-supply = <&vcc_1v8>; + vccio5-supply = <&vcc_3v3>; + vccio6-supply = <&vcc_1v8>; + vccio7-supply = <&vcc_3v3>; + status = "okay"; +}; + +&rng { + status = "okay"; +}; + +&saradc { + vref-supply = <&vcca_1v8>; + status = "okay"; +}; + +&sata2 { + target-supply = <&vcc5v0_ahci>; + status = "okay"; +}; + +&sdhci { + bus-width = <8>; + max-frequency = <200000000>; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_datastrobe>; + status = "okay"; +}; + +&sdmmc0 { + bus-width = <4>; + cap-sd-highspeed; + cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>; + disable-wp; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc0_bus4 &sdmmc0_clk &sdmmc0_cmd &sdmmc0_det>; + sd-uhs-sdr104; + vmmc-supply = <&vcc3v3_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&tsadc { + rockchip,hw-tshut-mode = <1>; + rockchip,hw-tshut-polarity = <0>; + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb_host0_xhci { + dr_mode = "host"; + status = "okay"; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +&usb_host1_xhci { + status = "okay"; +}; + +&usb2phy0 { + status = "okay"; +}; + +&usb2phy0_host { + phy-supply = <&vcc5v0_usb_host>; + status = "okay"; +}; + +&usb2phy0_otg { + phy-supply = <&vcc5v0_usb_otg>; + status = "okay"; +}; + +&usb2phy1 { + status = "okay"; +}; + +&usb2phy1_host { + phy-supply = <&vcc5v0_usb_host>; + status = "okay"; +}; + +&usb2phy1_otg { + phy-supply = <&vcc5v0_usb_host>; + status = "okay"; +}; + +#ifdef DTS_NO_LEGACY +&vop { + assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>; + assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>; + status = "okay"; +}; + +&vop_mmu { + status = "okay"; +}; + +&vp0 { + vp0_out_hdmi: endpoint@ROCKCHIP_VOP2_EP_HDMI0 { + reg = ; + remote-endpoint = <&hdmi_in_vp0>; + }; +}; +#endif diff --git a/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dts b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dts new file mode 100644 index 00000000..1283d4cb --- /dev/null +++ b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dts @@ -0,0 +1,710 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2021 FriendlyElec Computer Tech. Co., Ltd. + * (http://www.friendlyarm.com) + * + * Copyright (c) 2022 Marty Jones + * Copyright (c) 2022 Tianling Shen + */ + +/dts-v1/; + +#include +#include +#include +#include +#include "rk3568.dtsi" + +/ { + model = "FriendlyElec NanoPi R5S"; + compatible = "friendlyarm,nanopi-r5s","rockchip,rk3568"; + + aliases { + ethernet0 = &gmac0; + mmc0 = &sdmmc0; + mmc1 = &sdhci; + + led-boot = &sys_led; + led-failsafe = &sys_led; + led-running = &sys_led; + led-upgrade = &sys_led; + }; + + chosen: chosen { + stdout-path = "serial2:1500000n8"; + }; + +#ifdef DTS_NO_LEGACY + hdmi-con { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con_in: endpoint { + remote-endpoint = <&hdmi_out_con>; + }; + }; + }; +#endif + + leds { + compatible = "gpio-leds"; + pinctrl-0 = <&lan1_led_pin>, <&lan2_led_pin>, + <&sys_led_pin>, <&wan_led_pin>; + pinctrl-names = "default"; + + lan1_led: led-0 { + gpios = <&gpio3 RK_PD6 GPIO_ACTIVE_HIGH>; + label = "green:lan1"; + }; + + lan2_led: led-1 { + gpios = <&gpio3 RK_PD7 GPIO_ACTIVE_HIGH>; + label = "green:lan2"; + }; + + sys_led: led-2 { + gpios = <&gpio4 RK_PD2 GPIO_ACTIVE_HIGH>; + label = "red:power"; + }; + + wan_led: led-3 { + gpios = <&gpio2 RK_PC1 GPIO_ACTIVE_HIGH>; + label = "green:wan"; + }; + }; + + vdd_5v: vdd-5v { + compatible = "regulator-fixed"; + regulator-name = "vdd_5v"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + vcc3v3_sys: vcc3v3-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vdd_5v>; + }; + + vcc3v3_sysp: vcc3v3-sysp { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_sysp"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vdd_5v>; + }; + + vcc5v0_sysp: vcc5v0-sysp { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sysp"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc3v3_sysp>; + }; + + vcc5v0_usb_host: vcc5v0-usb-host { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_usb_host_en>; + regulator-name = "vcc5v0_usb_host"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_sysp>; + }; + + vcc3v3_pcie: vcc3v3-pcie { + compatible = "regulator-fixed"; + enable-active-high; + gpios = <&gpio0 RK_PD4 GPIO_ACTIVE_HIGH>; + regulator-name = "vcc3v3_pcie"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + startup-delay-us = <5000>; + vin-supply = <&vcc3v3_sysp>; + }; +}; + +&combphy0 { + status = "okay"; +}; + +&combphy1 { + status = "okay"; +}; + +&combphy2 { + status = "okay"; +}; + +&cpu0 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu1 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu2 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu3 { + cpu-supply = <&vdd_cpu>; +}; + +&gmac0 { + clock_in_out = "output"; + assigned-clocks = <&cru SCLK_GMAC0_RX_TX>, <&cru SCLK_GMAC0>; + assigned-clock-parents = <&cru SCLK_GMAC0_RGMII_SPEED>, <&cru CLK_MAC0_2TOP>; + assigned-clock-rates = <0>, <125000000>; + phy-mode = "rgmii-id"; + pinctrl-names = "default"; + pinctrl-0 = <&gmac0_miim + &gmac0_tx_bus2 + &gmac0_rx_bus2 + &gmac0_rgmii_clk + &gmac0_rgmii_bus>; + snps,reset-gpio = <&gpio0 RK_PC5 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + /* Reset time is 15ms, 50ms for rtl8211f */ + snps,reset-delays-us = <0 15000 50000>; + tx_delay = <0x3c>; + rx_delay = <0x2f>; + phy-handle = <&rgmii_phy0>; + status = "okay"; +}; + +#ifdef DTS_NO_LEGACY +&gpu { + mali-supply = <&vdd_gpu>; + status = "okay"; +}; + +&hdmi { + avdd-0v9-supply = <&vdda0v9_image>; + avdd-1v8-supply = <&vcca1v8_image>; + status = "okay"; +}; + +&hdmi_in { + hdmi_in_vp0: endpoint { + remote-endpoint = <&vp0_out_hdmi>; + }; +}; + +&hdmi_out { + hdmi_out_con: endpoint { + remote-endpoint = <&hdmi_con_in>; + }; +}; + +&hdmi_sound { + status = "okay"; +}; +#endif + +&i2c0 { + i2c-scl-rising-time-ns = <160>; + i2c-scl-falling-time-ns = <30>; + clock-frequency = <400000>; + status = "okay"; + + vdd_cpu: regulator@1c { + compatible = "tcs,tcs4525"; + reg = <0x1c>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1390000>; + regulator-init-microvolt = <900000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc3v3_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + rk809: pmic@20 { + compatible = "rockchip,rk809"; + reg = <0x20>; + interrupt-parent = <&gpio0>; + interrupts = ; + #clock-cells = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>; + rockchip,system-power-controller; + wakeup-source; + + vcc1-supply = <&vcc3v3_sys>; + vcc2-supply = <&vcc3v3_sys>; + vcc3-supply = <&vcc3v3_sys>; + vcc4-supply = <&vcc3v3_sys>; + vcc5-supply = <&vcc3v3_sys>; + vcc6-supply = <&vcc3v3_sys>; + vcc7-supply = <&vcc3v3_sys>; + vcc8-supply = <&vcc3v3_sys>; + vcc9-supply = <&vcc3v3_sys>; + + regulators { + vdd_logic: DCDC_REG1 { + regulator-name = "vdd_logic"; + regulator-always-on; + regulator-boot-on; + regulator-init-microvolt = <900000>; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_gpu: DCDC_REG2 { + regulator-name = "vdd_gpu"; + regulator-always-on; + regulator-init-microvolt = <900000>; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + regulator-initial-mode = <0x2>; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vdd_npu: DCDC_REG4 { + regulator-name = "vdd_npu"; + regulator-init-microvolt = <900000>; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8: DCDC_REG5 { + regulator-name = "vcc_1v8"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda0v9_image: LDO_REG1 { + regulator-name = "vdda0v9_image"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda_0v9: LDO_REG2 { + regulator-name = "vdda_0v9"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda0v9_pmu: LDO_REG3 { + regulator-name = "vdda0v9_pmu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <900000>; + }; + }; + + vccio_acodec: LDO_REG4 { + regulator-name = "vccio_acodec"; + regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vccio_sd: LDO_REG5 { + regulator-name = "vccio_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_pmu: LDO_REG6 { + regulator-name = "vcc3v3_pmu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcca_1v8: LDO_REG7 { + regulator-name = "vcca_1v8"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcca1v8_pmu: LDO_REG8 { + regulator-name = "vcca1v8_pmu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcca1v8_image: LDO_REG9 { + regulator-name = "vcca1v8_image"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v3: SWITCH_REG1 { + regulator-name = "vcc_3v3"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_sd: SWITCH_REG2 { + regulator-name = "vcc3v3_sd"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; +}; + +&i2c5 { + i2c-scl-rising-time-ns = <160>; + i2c-scl-falling-time-ns = <30>; + clock-frequency = <400000>; + status = "okay"; + + hym8563: hym8563@51 { + compatible = "haoyu,hym8563"; + reg = <0x51>; + interrupt-parent = <&gpio0>; + interrupts = ; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "xin32k"; + pinctrl-names = "default"; + pinctrl-0 = <&hym8563_int>; + }; +}; + +#ifdef DTS_NO_LEGACY +&i2s0_8ch { + status = "okay"; +}; +#endif + +&mdio0 { + rgmii_phy0: phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0x1>; + interrupt-parent = <&gpio0>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&gmac_int>; + }; +}; + +&pcie2x1 { + num-lanes = <1>; + num-viewport = <4>; + reset-gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>; + status = "okay"; + + pcie@00 { + reg = <0x00000000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + + r8125_1: pcie@01,0 { + reg = <0x000000 0 0 0 0>; + }; + }; +}; + +&pcie30phy { + data-lanes = <1 2>; + status = "okay"; +}; + +&pcie3x1 { + num-lanes = <1>; + num-viewport = <4>; + reset-gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; + status = "okay"; + + pcie@10 { + reg = <0x00100000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + + r8125_2: pcie@10,0 { + reg = <0x000000 0 0 0 0>; + }; + }; +}; + +&pcie3x2 { + num-lanes = <1>; + max-link-speed = <2>; + num-ib-windows = <8>; + num-ob-windows = <8>; + num-viewport = <4>; + reset-gpios = <&gpio2 RK_PD6 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie>; + status = "okay"; +}; + +&pinctrl { + leds { + lan1_led_pin: lan1-led-pin { + rockchip,pins = <3 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + lan2_led_pin: lan2-led-pin { + rockchip,pins = <3 RK_PD7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + sys_led_pin: sys-led-pin { + rockchip,pins = <4 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + wan_led_pin: wan-led-pin { + rockchip,pins = <2 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + eth_phy { + gmac_int: gmac-int { + rockchip,pins = <0 RK_PC4 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + hym8563 { + hym8563_int: hym8563-int { + rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + pmic { + pmic_int: pmic_int { + rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + usb { + vcc5v0_usb_host_en: vcc5v0_usb_host_en { + rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pmu_io_domains { + pmuio2-supply = <&vcc3v3_pmu>; + vccio1-supply = <&vccio_acodec>; + vccio3-supply = <&vccio_sd>; + vccio4-supply = <&vcc_1v8>; + vccio5-supply = <&vcc_3v3>; + vccio6-supply = <&vcc_1v8>; + vccio7-supply = <&vcc_3v3>; + status = "okay"; +}; + +&pwm0 { + status = "okay"; +}; + +&rng { + status = "okay"; +}; + +&saradc { + vref-supply = <&vcca_1v8>; + status = "okay"; +}; + +&sdhci { + bus-width = <8>; + max-frequency = <200000000>; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd>; + status = "okay"; +}; + +&sdmmc0 { + bus-width = <4>; + cap-sd-highspeed; + cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>; + disable-wp; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc0_bus4 &sdmmc0_clk &sdmmc0_cmd &sdmmc0_det>; + sd-uhs-sdr104; + vmmc-supply = <&vcc3v3_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&tsadc { + rockchip,hw-tshut-mode = <1>; + rockchip,hw-tshut-polarity = <0>; + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb_host0_xhci { + dr_mode = "host"; + status = "okay"; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +&usb_host1_xhci { + status = "okay"; +}; + +&usb2phy0 { + status = "okay"; +}; + +&usb2phy0_host { + phy-supply = <&vcc5v0_usb_host>; + status = "okay"; +}; + +&usb2phy0_otg { + status = "okay"; +}; + +&usb2phy1 { + status = "okay"; +}; + +&usb2phy1_host { + status = "okay"; +}; + +&usb2phy1_otg { + status = "okay"; +}; + +#ifdef DTS_NO_LEGACY +&vop { + assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>; + assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>; + status = "okay"; +}; + +&vop_mmu { + status = "okay"; +}; + +&vp0 { + vp0_out_hdmi: endpoint@ROCKCHIP_VOP2_EP_HDMI0 { + reg = ; + remote-endpoint = <&hdmi_in_vp0>; + }; +}; +#endif diff --git a/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-opc-h68k.dts b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-opc-h68k.dts new file mode 100644 index 00000000..9fea2d58 --- /dev/null +++ b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-opc-h68k.dts @@ -0,0 +1,725 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +// Copyright (c) 2022 AmadeusGhost + +/dts-v1/; + +#include +#include +#include +#include +#include "rk3568.dtsi" + +/ { + model = "HINLINK OPC-H68K Board"; + compatible = "hinlink,opc-h68k", "rockchip,rk3568"; + + aliases { + ethernet0 = &gmac0; + ethernet1 = &gmac1; + mmc0 = &sdmmc0; + mmc1 = &sdhci; + + led-boot = &led_work; + led-failsafe = &led_work; + led-running = &led_work; + led-upgrade = &led_work; + }; + + chosen { + stdout-path = "serial2:1500000n8"; + }; + +#ifdef DTS_NO_LEGACY + hdmi-con { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con_in: endpoint { + remote-endpoint = <&hdmi_out_con>; + }; + }; + }; +#endif + + keys { + compatible = "gpio-keys"; + pinctrl-0 = <&reset_button_pin>; + pinctrl-names = "default"; + + reset { + label = "reset"; + gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_LOW>; + linux,code = ; + debounce-interval = <50>; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_net_en>, <&led_sata_en>, <&led_work_en>; + + net { + label = "blue:net"; + gpios = <&gpio3 RK_PA5 GPIO_ACTIVE_HIGH>; + }; + + sata { + label = "amber:sata"; + gpios = <&gpio3 RK_PA7 GPIO_ACTIVE_HIGH>; + }; + + led_work: work { + label = "green:work"; + gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_HIGH>; + }; + }; + + dc_12v: dc-12v { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + regulator-name = "dc_12v"; + }; + + vcc3v3_sys: vcc3v3-sys { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc3v3_sys"; + vin-supply = <&dc_12v>; + }; + + vcc5v0_sys: vcc5v0-sys { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-name = "vcc5v0_sys"; + vin-supply = <&dc_12v>; + }; + + vcc5v0_usb: vcc5v0-usb { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-name = "vcc5v0_usb"; + vin-supply = <&dc_12v>; + }; + + vcc5v0_usb_host: vcc5v0-usb-host { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_usb_host_en>; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-name = "vcc5v0_usb_host"; + vin-supply = <&vcc5v0_usb>; + }; + + vcc3v3_pcie: gpio-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio2 RK_PD2 GPIO_ACTIVE_HIGH>; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc3v3_pcie"; + startup-delay-us = <5000>; + vin-supply = <&vcc5v0_sys>; + }; + + rk809-sound { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; + simple-audio-card,name = "Analog RK809"; + simple-audio-card,mclk-fs = <256>; + + simple-audio-card,cpu { + sound-dai = <&i2s1_8ch>; + }; + simple-audio-card,codec { + sound-dai = <&rk809>; + }; + }; +}; + +&combphy0 { + status = "okay"; +}; + +&combphy1 { + status = "okay"; +}; + +&combphy2 { + status = "okay"; +}; + +&cpu0 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu1 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu2 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu3 { + cpu-supply = <&vdd_cpu>; +}; + +&gmac0 { + assigned-clocks = <&cru SCLK_GMAC0_RX_TX>, <&cru SCLK_GMAC0>; + assigned-clock-parents = <&cru SCLK_GMAC0_RGMII_SPEED>; + assigned-clock-rates = <0>, <125000000>; + clock_in_out = "output"; + phy-mode = "rgmii-id"; + pinctrl-names = "default"; + pinctrl-0 = <&gmac0_miim + &gmac0_tx_bus2 + &gmac0_rx_bus2 + &gmac0_rgmii_clk + &gmac0_rgmii_bus>; + snps,reset-gpio = <&gpio2 RK_PD3 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + snps,reset-delays-us = <0 20000 100000>; + tx_delay = <0x3c>; + rx_delay = <0x2f>; + phy-handle = <&rgmii_phy0>; + status = "okay"; +}; + +&gmac1 { + assigned-clocks = <&cru SCLK_GMAC1_RX_TX>, <&cru SCLK_GMAC1>; + assigned-clock-parents = <&cru SCLK_GMAC1_RGMII_SPEED>; + assigned-clock-rates = <0>, <125000000>; + clock_in_out = "output"; + phy-mode = "rgmii-id"; + pinctrl-names = "default"; + pinctrl-0 = <&gmac1m1_miim + &gmac1m1_tx_bus2 + &gmac1m1_rx_bus2 + &gmac1m1_rgmii_clk + &gmac1m1_rgmii_bus>; + snps,reset-gpio = <&gpio1 RK_PB0 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + snps,reset-delays-us = <0 20000 100000>; + tx_delay = <0x4f>; + rx_delay = <0x26>; + phy-handle = <&rgmii_phy1>; + status = "okay"; +}; + +#ifdef DTS_NO_LEGACY +&gpu { + mali-supply = <&vdd_gpu>; + status = "okay"; +}; + +&hdmi { + avdd-0v9-supply = <&vdda0v9_image>; + avdd-1v8-supply = <&vcca1v8_image>; + status = "okay"; +}; + +&hdmi_in { + hdmi_in_vp0: endpoint { + remote-endpoint = <&vp0_out_hdmi>; + }; +}; + +&hdmi_out { + hdmi_out_con: endpoint { + remote-endpoint = <&hdmi_con_in>; + }; +}; + +&hdmi_sound { + status = "okay"; +}; +#endif + +&i2c0 { + status = "okay"; + + vdd_cpu: regulator@1c { + compatible = "tcs,tcs4525"; + reg = <0x1c>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1150000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + rk809: pmic@20 { + compatible = "rockchip,rk809"; + reg = <0x20>; + interrupt-parent = <&gpio0>; + interrupts = ; + assigned-clocks = <&cru I2S1_MCLKOUT_TX>; + assigned-clock-parents = <&cru CLK_I2S1_8CH_TX>; + #clock-cells = <1>; + clock-names = "mclk"; + clocks = <&cru I2S1_MCLKOUT_TX>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>, <&i2s1m0_mclk>; + rockchip,system-power-controller; + #sound-dai-cells = <0>; + wakeup-source; + + vcc1-supply = <&vcc3v3_sys>; + vcc2-supply = <&vcc3v3_sys>; + vcc3-supply = <&vcc3v3_sys>; + vcc4-supply = <&vcc3v3_sys>; + vcc5-supply = <&vcc3v3_sys>; + vcc6-supply = <&vcc3v3_sys>; + vcc7-supply = <&vcc3v3_sys>; + vcc8-supply = <&vcc3v3_sys>; + vcc9-supply = <&vcc3v3_sys>; + + regulators { + vdd_logic: DCDC_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-init-microvolt = <900000>; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-name = "vdd_logic"; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_gpu: DCDC_REG2 { + regulator-always-on; + regulator-init-microvolt = <900000>; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-name = "vdd_gpu"; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-initial-mode = <0x2>; + regulator-name = "vcc_ddr"; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vdd_npu: DCDC_REG4 { + regulator-init-microvolt = <900000>; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-name = "vdd_npu"; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8: DCDC_REG5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc_1v8"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda0v9_image: LDO_REG1 { + regulator-name = "vdda0v9_image"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda_0v9: LDO_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-name = "vdda_0v9"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda0v9_pmu: LDO_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-name = "vdda0v9_pmu"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <900000>; + }; + }; + + vccio_acodec: LDO_REG4 { + regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vccio_acodec"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vccio_sd: LDO_REG5 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vccio_sd"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_pmu: LDO_REG6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc3v3_pmu"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcca_1v8: LDO_REG7 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcca_1v8"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcca1v8_pmu: LDO_REG8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcca1v8_pmu"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcca1v8_image: LDO_REG9 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcca1v8_image"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v3: SWITCH_REG1 { + regulator-name = "vcc_3v3"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_sd: SWITCH_REG2 { + regulator-name = "vcc3v3_sd"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + + codec { + mic-in-differential; + }; + }; +}; + +#ifdef DTS_NO_LEGACY +&i2s0_8ch { + status = "okay"; +}; +#endif + +&i2s1_8ch { + rockchip,trcm-sync-tx-only; + status = "okay"; +}; + +&mdio0 { + rgmii_phy0: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0x0>; + }; +}; + +&mdio1 { + rgmii_phy1: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0x0>; + }; +}; + +&pcie2x1 { + reset-gpios = <&gpio2 RK_PD6 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie>; + status = "okay"; +}; + +&pcie30phy { + data-lanes = <1 2>; + status = "okay"; +}; + +&pcie3x1 { + num-lanes = <1>; + reset-gpios = <&gpio3 RK_PA4 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie>; + status = "okay"; + + pcie@10 { + reg = <0x00100000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + + rtl8125_1: pcie-eth@10,0 { + compatible = "pci10ec,8125"; + reg = <0x000000 0 0 0 0>; + }; + }; +}; + +&pcie3x2 { + num-lanes = <1>; + reset-gpios = <&gpio2 RK_PD0 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie>; + status = "okay"; + + pcie@20 { + reg = <0x00200000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + + rtl8125_2: pcie-eth@20,0 { + compatible = "pci10ec,8125"; + reg = <0x000000 0 0 0 0>; + }; + }; +}; + +&pinctrl { + button { + reset_button_pin: reset-button-pin { + rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + leds { + led_net_en: led_net_en { + rockchip,pins = <3 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + led_sata_en: led_sata_en { + rockchip,pins = <3 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + led_work_en: led_work_en { + rockchip,pins = <3 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + pmic_int: pmic_int { + rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + usb { + vcc5v0_usb_host_en: vcc5v0_usb_host_en { + rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pmu_io_domains { + pmuio1-supply = <&vcc3v3_pmu>; + pmuio2-supply = <&vcc3v3_pmu>; + vccio1-supply = <&vccio_acodec>; + vccio2-supply = <&vcc_1v8>; + vccio3-supply = <&vccio_sd>; + vccio4-supply = <&vcc_1v8>; + vccio5-supply = <&vcc_3v3>; + vccio6-supply = <&vcc_1v8>; + vccio7-supply = <&vcc_3v3>; + status = "okay"; +}; + +&rng { + status = "okay"; +}; + +&saradc { + vref-supply = <&vcca_1v8>; + status = "okay"; +}; + +&sdhci { + bus-width = <8>; + max-frequency = <200000000>; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_datastrobe>; + status = "okay"; +}; + +&sdmmc0 { + bus-width = <4>; + cap-sd-highspeed; + cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>; + disable-wp; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc0_bus4 &sdmmc0_clk &sdmmc0_cmd &sdmmc0_det>; + sd-uhs-sdr104; + vmmc-supply = <&vcc3v3_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&tsadc { + rockchip,hw-tshut-mode = <1>; + rockchip,hw-tshut-polarity = <0>; + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb_host0_xhci { + dr_mode = "host"; + status = "okay"; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +&usb_host1_xhci { + status = "okay"; +}; + +&usb2phy0 { + status = "okay"; +}; + +&usb2phy0_host { + phy-supply = <&vcc5v0_usb_host>; + status = "okay"; +}; + +&usb2phy0_otg { + status = "okay"; +}; + +&usb2phy1 { + status = "okay"; +}; + +&usb2phy1_host { + phy-supply = <&vcc5v0_usb_host>; + status = "okay"; +}; + +&usb2phy1_otg { + phy-supply = <&vcc5v0_usb_host>; + status = "okay"; +}; + +#ifdef DTS_NO_LEGACY +&vop { + assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>; + assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>; + status = "okay"; +}; + +&vop_mmu { + status = "okay"; +}; + +&vp0 { + vp0_out_hdmi: endpoint@ROCKCHIP_VOP2_EP_HDMI0 { + reg = ; + remote-endpoint = <&hdmi_in_vp0>; + }; +}; +#endif diff --git a/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-pinctrl.dtsi b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-pinctrl.dtsi new file mode 100644 index 00000000..8f90c66d --- /dev/null +++ b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-pinctrl.dtsi @@ -0,0 +1,3120 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + */ + +#include +#include "rockchip-pinconf.dtsi" + +/* + * This file is auto generated by pin2dts tool, please keep these code + * by adding changes at end of this file. + */ +&pinctrl { + acodec { + /omit-if-no-ref/ + acodec_pins: acodec-pins { + rockchip,pins = + /* acodec_adc_sync */ + <1 RK_PB1 5 &pcfg_pull_none>, + /* acodec_adcclk */ + <1 RK_PA1 5 &pcfg_pull_none>, + /* acodec_adcdata */ + <1 RK_PA0 5 &pcfg_pull_none>, + /* acodec_dac_datal */ + <1 RK_PA7 5 &pcfg_pull_none>, + /* acodec_dac_datar */ + <1 RK_PB0 5 &pcfg_pull_none>, + /* acodec_dacclk */ + <1 RK_PA3 5 &pcfg_pull_none>, + /* acodec_dacsync */ + <1 RK_PA5 5 &pcfg_pull_none>; + }; + }; + + audiopwm { + /omit-if-no-ref/ + audiopwm_lout: audiopwm-lout { + rockchip,pins = + /* audiopwm_lout */ + <1 RK_PA0 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + audiopwm_loutn: audiopwm-loutn { + rockchip,pins = + /* audiopwm_loutn */ + <1 RK_PA1 6 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + audiopwm_loutp: audiopwm-loutp { + rockchip,pins = + /* audiopwm_loutp */ + <1 RK_PA0 6 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + audiopwm_rout: audiopwm-rout { + rockchip,pins = + /* audiopwm_rout */ + <1 RK_PA1 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + audiopwm_routn: audiopwm-routn { + rockchip,pins = + /* audiopwm_routn */ + <1 RK_PA7 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + audiopwm_routp: audiopwm-routp { + rockchip,pins = + /* audiopwm_routp */ + <1 RK_PA6 4 &pcfg_pull_none>; + }; + }; + + bt656 { + /omit-if-no-ref/ + bt656m0_pins: bt656m0-pins { + rockchip,pins = + /* bt656_clkm0 */ + <3 RK_PA0 2 &pcfg_pull_none>, + /* bt656_d0m0 */ + <2 RK_PD0 2 &pcfg_pull_none>, + /* bt656_d1m0 */ + <2 RK_PD1 2 &pcfg_pull_none>, + /* bt656_d2m0 */ + <2 RK_PD2 2 &pcfg_pull_none>, + /* bt656_d3m0 */ + <2 RK_PD3 2 &pcfg_pull_none>, + /* bt656_d4m0 */ + <2 RK_PD4 2 &pcfg_pull_none>, + /* bt656_d5m0 */ + <2 RK_PD5 2 &pcfg_pull_none>, + /* bt656_d6m0 */ + <2 RK_PD6 2 &pcfg_pull_none>, + /* bt656_d7m0 */ + <2 RK_PD7 2 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + bt656m1_pins: bt656m1-pins { + rockchip,pins = + /* bt656_clkm1 */ + <4 RK_PB4 5 &pcfg_pull_none>, + /* bt656_d0m1 */ + <3 RK_PC6 5 &pcfg_pull_none>, + /* bt656_d1m1 */ + <3 RK_PC7 5 &pcfg_pull_none>, + /* bt656_d2m1 */ + <3 RK_PD0 5 &pcfg_pull_none>, + /* bt656_d3m1 */ + <3 RK_PD1 5 &pcfg_pull_none>, + /* bt656_d4m1 */ + <3 RK_PD2 5 &pcfg_pull_none>, + /* bt656_d5m1 */ + <3 RK_PD3 5 &pcfg_pull_none>, + /* bt656_d6m1 */ + <3 RK_PD4 5 &pcfg_pull_none>, + /* bt656_d7m1 */ + <3 RK_PD5 5 &pcfg_pull_none>; + }; + }; + + bt1120 { + /omit-if-no-ref/ + bt1120_pins: bt1120-pins { + rockchip,pins = + /* bt1120_clk */ + <3 RK_PA6 2 &pcfg_pull_none>, + /* bt1120_d0 */ + <3 RK_PA1 2 &pcfg_pull_none>, + /* bt1120_d1 */ + <3 RK_PA2 2 &pcfg_pull_none>, + /* bt1120_d2 */ + <3 RK_PA3 2 &pcfg_pull_none>, + /* bt1120_d3 */ + <3 RK_PA4 2 &pcfg_pull_none>, + /* bt1120_d4 */ + <3 RK_PA5 2 &pcfg_pull_none>, + /* bt1120_d5 */ + <3 RK_PA7 2 &pcfg_pull_none>, + /* bt1120_d6 */ + <3 RK_PB0 2 &pcfg_pull_none>, + /* bt1120_d7 */ + <3 RK_PB1 2 &pcfg_pull_none>, + /* bt1120_d8 */ + <3 RK_PB2 2 &pcfg_pull_none>, + /* bt1120_d9 */ + <3 RK_PB3 2 &pcfg_pull_none>, + /* bt1120_d10 */ + <3 RK_PB4 2 &pcfg_pull_none>, + /* bt1120_d11 */ + <3 RK_PB5 2 &pcfg_pull_none>, + /* bt1120_d12 */ + <3 RK_PB6 2 &pcfg_pull_none>, + /* bt1120_d13 */ + <3 RK_PC1 2 &pcfg_pull_none>, + /* bt1120_d14 */ + <3 RK_PC2 2 &pcfg_pull_none>, + /* bt1120_d15 */ + <3 RK_PC3 2 &pcfg_pull_none>; + }; + }; + + cam { + /omit-if-no-ref/ + cam_clkout0: cam-clkout0 { + rockchip,pins = + /* cam_clkout0 */ + <4 RK_PA7 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + cam_clkout1: cam-clkout1 { + rockchip,pins = + /* cam_clkout1 */ + <4 RK_PB0 1 &pcfg_pull_none>; + }; + }; + + can0 { + /omit-if-no-ref/ + can0m0_pins: can0m0-pins { + rockchip,pins = + /* can0_rxm0 */ + <0 RK_PB4 2 &pcfg_pull_none>, + /* can0_txm0 */ + <0 RK_PB3 2 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + can0m1_pins: can0m1-pins { + rockchip,pins = + /* can0_rxm1 */ + <2 RK_PA2 4 &pcfg_pull_none>, + /* can0_txm1 */ + <2 RK_PA1 4 &pcfg_pull_none>; + }; + }; + + can1 { + /omit-if-no-ref/ + can1m0_pins: can1m0-pins { + rockchip,pins = + /* can1_rxm0 */ + <1 RK_PA0 3 &pcfg_pull_none>, + /* can1_txm0 */ + <1 RK_PA1 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + can1m1_pins: can1m1-pins { + rockchip,pins = + /* can1_rxm1 */ + <4 RK_PC2 3 &pcfg_pull_none>, + /* can1_txm1 */ + <4 RK_PC3 3 &pcfg_pull_none>; + }; + }; + + can2 { + /omit-if-no-ref/ + can2m0_pins: can2m0-pins { + rockchip,pins = + /* can2_rxm0 */ + <4 RK_PB4 3 &pcfg_pull_none>, + /* can2_txm0 */ + <4 RK_PB5 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + can2m1_pins: can2m1-pins { + rockchip,pins = + /* can2_rxm1 */ + <2 RK_PB1 4 &pcfg_pull_none>, + /* can2_txm1 */ + <2 RK_PB2 4 &pcfg_pull_none>; + }; + }; + + cif { + /omit-if-no-ref/ + cif_clk: cif-clk { + rockchip,pins = + /* cif_clkout */ + <4 RK_PC0 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + cif_dvp_clk: cif-dvp-clk { + rockchip,pins = + /* cif_clkin */ + <4 RK_PC1 1 &pcfg_pull_none>, + /* cif_href */ + <4 RK_PB6 1 &pcfg_pull_none>, + /* cif_vsync */ + <4 RK_PB7 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + cif_dvp_bus16: cif-dvp-bus16 { + rockchip,pins = + /* cif_d8 */ + <3 RK_PD6 1 &pcfg_pull_none>, + /* cif_d9 */ + <3 RK_PD7 1 &pcfg_pull_none>, + /* cif_d10 */ + <4 RK_PA0 1 &pcfg_pull_none>, + /* cif_d11 */ + <4 RK_PA1 1 &pcfg_pull_none>, + /* cif_d12 */ + <4 RK_PA2 1 &pcfg_pull_none>, + /* cif_d13 */ + <4 RK_PA3 1 &pcfg_pull_none>, + /* cif_d14 */ + <4 RK_PA4 1 &pcfg_pull_none>, + /* cif_d15 */ + <4 RK_PA5 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + cif_dvp_bus8: cif-dvp-bus8 { + rockchip,pins = + /* cif_d0 */ + <3 RK_PC6 1 &pcfg_pull_none>, + /* cif_d1 */ + <3 RK_PC7 1 &pcfg_pull_none>, + /* cif_d2 */ + <3 RK_PD0 1 &pcfg_pull_none>, + /* cif_d3 */ + <3 RK_PD1 1 &pcfg_pull_none>, + /* cif_d4 */ + <3 RK_PD2 1 &pcfg_pull_none>, + /* cif_d5 */ + <3 RK_PD3 1 &pcfg_pull_none>, + /* cif_d6 */ + <3 RK_PD4 1 &pcfg_pull_none>, + /* cif_d7 */ + <3 RK_PD5 1 &pcfg_pull_none>; + }; + }; + + clk32k { + /omit-if-no-ref/ + clk32k_in: clk32k-in { + rockchip,pins = + /* clk32k_in */ + <0 RK_PB0 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + clk32k_out0: clk32k-out0 { + rockchip,pins = + /* clk32k_out0 */ + <0 RK_PB0 2 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + clk32k_out1: clk32k-out1 { + rockchip,pins = + /* clk32k_out1 */ + <2 RK_PC6 1 &pcfg_pull_none>; + }; + }; + + cpu { + /omit-if-no-ref/ + cpu_pins: cpu-pins { + rockchip,pins = + /* cpu_avs */ + <0 RK_PB7 2 &pcfg_pull_none>; + }; + }; + + ebc { + /omit-if-no-ref/ + ebc_extern: ebc-extern { + rockchip,pins = + /* ebc_sdce1 */ + <4 RK_PA7 2 &pcfg_pull_none>, + /* ebc_sdce2 */ + <4 RK_PB0 2 &pcfg_pull_none>, + /* ebc_sdce3 */ + <4 RK_PB1 2 &pcfg_pull_none>, + /* ebc_sdshr */ + <4 RK_PB5 2 &pcfg_pull_none>, + /* ebc_vcom */ + <4 RK_PB2 2 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + ebc_pins: ebc-pins { + rockchip,pins = + /* ebc_gdclk */ + <4 RK_PC0 2 &pcfg_pull_none>, + /* ebc_gdoe */ + <4 RK_PB3 2 &pcfg_pull_none>, + /* ebc_gdsp */ + <4 RK_PB4 2 &pcfg_pull_none>, + /* ebc_sdce0 */ + <4 RK_PA6 2 &pcfg_pull_none>, + /* ebc_sdclk */ + <4 RK_PC1 2 &pcfg_pull_none>, + /* ebc_sddo0 */ + <3 RK_PC6 2 &pcfg_pull_none>, + /* ebc_sddo1 */ + <3 RK_PC7 2 &pcfg_pull_none>, + /* ebc_sddo2 */ + <3 RK_PD0 2 &pcfg_pull_none>, + /* ebc_sddo3 */ + <3 RK_PD1 2 &pcfg_pull_none>, + /* ebc_sddo4 */ + <3 RK_PD2 2 &pcfg_pull_none>, + /* ebc_sddo5 */ + <3 RK_PD3 2 &pcfg_pull_none>, + /* ebc_sddo6 */ + <3 RK_PD4 2 &pcfg_pull_none>, + /* ebc_sddo7 */ + <3 RK_PD5 2 &pcfg_pull_none>, + /* ebc_sddo8 */ + <3 RK_PD6 2 &pcfg_pull_none>, + /* ebc_sddo9 */ + <3 RK_PD7 2 &pcfg_pull_none>, + /* ebc_sddo10 */ + <4 RK_PA0 2 &pcfg_pull_none>, + /* ebc_sddo11 */ + <4 RK_PA1 2 &pcfg_pull_none>, + /* ebc_sddo12 */ + <4 RK_PA2 2 &pcfg_pull_none>, + /* ebc_sddo13 */ + <4 RK_PA3 2 &pcfg_pull_none>, + /* ebc_sddo14 */ + <4 RK_PA4 2 &pcfg_pull_none>, + /* ebc_sddo15 */ + <4 RK_PA5 2 &pcfg_pull_none>, + /* ebc_sdle */ + <4 RK_PB6 2 &pcfg_pull_none>, + /* ebc_sdoe */ + <4 RK_PB7 2 &pcfg_pull_none>; + }; + }; + + edpdp { + /omit-if-no-ref/ + edpdpm0_pins: edpdpm0-pins { + rockchip,pins = + /* edpdp_hpdinm0 */ + <4 RK_PC4 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + edpdpm1_pins: edpdpm1-pins { + rockchip,pins = + /* edpdp_hpdinm1 */ + <0 RK_PC2 2 &pcfg_pull_none>; + }; + }; + + emmc { + /omit-if-no-ref/ + emmc_rstnout: emmc-rstnout { + rockchip,pins = + /* emmc_rstn */ + <1 RK_PC7 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + emmc_bus8: emmc-bus8 { + rockchip,pins = + /* emmc_d0 */ + <1 RK_PB4 1 &pcfg_pull_up_drv_level_2>, + /* emmc_d1 */ + <1 RK_PB5 1 &pcfg_pull_up_drv_level_2>, + /* emmc_d2 */ + <1 RK_PB6 1 &pcfg_pull_up_drv_level_2>, + /* emmc_d3 */ + <1 RK_PB7 1 &pcfg_pull_up_drv_level_2>, + /* emmc_d4 */ + <1 RK_PC0 1 &pcfg_pull_up_drv_level_2>, + /* emmc_d5 */ + <1 RK_PC1 1 &pcfg_pull_up_drv_level_2>, + /* emmc_d6 */ + <1 RK_PC2 1 &pcfg_pull_up_drv_level_2>, + /* emmc_d7 */ + <1 RK_PC3 1 &pcfg_pull_up_drv_level_2>; + }; + + /omit-if-no-ref/ + emmc_clk: emmc-clk { + rockchip,pins = + /* emmc_clkout */ + <1 RK_PC5 1 &pcfg_pull_up_drv_level_2>; + }; + + /omit-if-no-ref/ + emmc_cmd: emmc-cmd { + rockchip,pins = + /* emmc_cmd */ + <1 RK_PC4 1 &pcfg_pull_up_drv_level_2>; + }; + + /omit-if-no-ref/ + emmc_datastrobe: emmc-datastrobe { + rockchip,pins = + /* emmc_datastrobe */ + <1 RK_PC6 1 &pcfg_pull_none>; + }; + }; + + eth0 { + /omit-if-no-ref/ + eth0_pins: eth0-pins { + rockchip,pins = + /* eth0_refclko25m */ + <2 RK_PC1 2 &pcfg_pull_none>; + }; + }; + + eth1 { + /omit-if-no-ref/ + eth1m0_pins: eth1m0-pins { + rockchip,pins = + /* eth1_refclko25mm0 */ + <3 RK_PB0 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + eth1m1_pins: eth1m1-pins { + rockchip,pins = + /* eth1_refclko25mm1 */ + <4 RK_PB3 3 &pcfg_pull_none>; + }; + }; + + flash { + /omit-if-no-ref/ + flash_pins: flash-pins { + rockchip,pins = + /* flash_ale */ + <1 RK_PD0 2 &pcfg_pull_none>, + /* flash_cle */ + <1 RK_PC6 3 &pcfg_pull_none>, + /* flash_cs0n */ + <1 RK_PD3 2 &pcfg_pull_none>, + /* flash_cs1n */ + <1 RK_PD4 2 &pcfg_pull_none>, + /* flash_d0 */ + <1 RK_PB4 2 &pcfg_pull_none>, + /* flash_d1 */ + <1 RK_PB5 2 &pcfg_pull_none>, + /* flash_d2 */ + <1 RK_PB6 2 &pcfg_pull_none>, + /* flash_d3 */ + <1 RK_PB7 2 &pcfg_pull_none>, + /* flash_d4 */ + <1 RK_PC0 2 &pcfg_pull_none>, + /* flash_d5 */ + <1 RK_PC1 2 &pcfg_pull_none>, + /* flash_d6 */ + <1 RK_PC2 2 &pcfg_pull_none>, + /* flash_d7 */ + <1 RK_PC3 2 &pcfg_pull_none>, + /* flash_dqs */ + <1 RK_PC5 2 &pcfg_pull_none>, + /* flash_rdn */ + <1 RK_PD2 2 &pcfg_pull_none>, + /* flash_rdy */ + <1 RK_PD1 2 &pcfg_pull_none>, + /* flash_volsel */ + <0 RK_PA7 1 &pcfg_pull_none>, + /* flash_wpn */ + <1 RK_PC7 3 &pcfg_pull_none>, + /* flash_wrn */ + <1 RK_PC4 2 &pcfg_pull_none>; + }; + }; + + fspi { + /omit-if-no-ref/ + fspi_pins: fspi-pins { + rockchip,pins = + /* fspi_clk */ + <1 RK_PD0 1 &pcfg_pull_none>, + /* fspi_cs0n */ + <1 RK_PD3 1 &pcfg_pull_none>, + /* fspi_d0 */ + <1 RK_PD1 1 &pcfg_pull_none>, + /* fspi_d1 */ + <1 RK_PD2 1 &pcfg_pull_none>, + /* fspi_d2 */ + <1 RK_PC7 2 &pcfg_pull_none>, + /* fspi_d3 */ + <1 RK_PD4 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + fspi_cs1: fspi-cs1 { + rockchip,pins = + /* fspi_cs1n */ + <1 RK_PC6 2 &pcfg_pull_up>; + }; + }; + + gmac0 { + /omit-if-no-ref/ + gmac0_miim: gmac0-miim { + rockchip,pins = + /* gmac0_mdc */ + <2 RK_PC3 2 &pcfg_pull_none>, + /* gmac0_mdio */ + <2 RK_PC4 2 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + gmac0_clkinout: gmac0-clkinout { + rockchip,pins = + /* gmac0_mclkinout */ + <2 RK_PC2 2 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + gmac0_rx_er: gmac0-rx-er { + rockchip,pins = + /* gmac0_rxer */ + <2 RK_PC5 2 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + gmac0_rx_bus2: gmac0-rx-bus2 { + rockchip,pins = + /* gmac0_rxd0 */ + <2 RK_PB6 1 &pcfg_pull_none>, + /* gmac0_rxd1 */ + <2 RK_PB7 2 &pcfg_pull_none>, + /* gmac0_rxdvcrs */ + <2 RK_PC0 2 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + gmac0_tx_bus2: gmac0-tx-bus2 { + rockchip,pins = + /* gmac0_txd0 */ + <2 RK_PB3 1 &pcfg_pull_none_drv_level_2>, + /* gmac0_txd1 */ + <2 RK_PB4 1 &pcfg_pull_none_drv_level_2>, + /* gmac0_txen */ + <2 RK_PB5 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + gmac0_rgmii_clk: gmac0-rgmii-clk { + rockchip,pins = + /* gmac0_rxclk */ + <2 RK_PA5 2 &pcfg_pull_none>, + /* gmac0_txclk */ + <2 RK_PB0 2 &pcfg_pull_none_drv_level_1>; + }; + + /omit-if-no-ref/ + gmac0_rgmii_bus: gmac0-rgmii-bus { + rockchip,pins = + /* gmac0_rxd2 */ + <2 RK_PA3 2 &pcfg_pull_none>, + /* gmac0_rxd3 */ + <2 RK_PA4 2 &pcfg_pull_none>, + /* gmac0_txd2 */ + <2 RK_PA6 2 &pcfg_pull_none_drv_level_2>, + /* gmac0_txd3 */ + <2 RK_PA7 2 &pcfg_pull_none_drv_level_2>; + }; + }; + + gmac1 { + /omit-if-no-ref/ + gmac1m0_miim: gmac1m0-miim { + rockchip,pins = + /* gmac1_mdcm0 */ + <3 RK_PC4 3 &pcfg_pull_none>, + /* gmac1_mdiom0 */ + <3 RK_PC5 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + gmac1m0_clkinout: gmac1m0-clkinout { + rockchip,pins = + /* gmac1_mclkinoutm0 */ + <3 RK_PC0 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + gmac1m0_rx_er: gmac1m0-rx-er { + rockchip,pins = + /* gmac1_rxerm0 */ + <3 RK_PB4 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + gmac1m0_rx_bus2: gmac1m0-rx-bus2 { + rockchip,pins = + /* gmac1_rxd0m0 */ + <3 RK_PB1 3 &pcfg_pull_none>, + /* gmac1_rxd1m0 */ + <3 RK_PB2 3 &pcfg_pull_none>, + /* gmac1_rxdvcrsm0 */ + <3 RK_PB3 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + gmac1m0_tx_bus2: gmac1m0-tx-bus2 { + rockchip,pins = + /* gmac1_txd0m0 */ + <3 RK_PB5 3 &pcfg_pull_none_drv_level_2>, + /* gmac1_txd1m0 */ + <3 RK_PB6 3 &pcfg_pull_none_drv_level_2>, + /* gmac1_txenm0 */ + <3 RK_PB7 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + gmac1m0_rgmii_clk: gmac1m0-rgmii-clk { + rockchip,pins = + /* gmac1_rxclkm0 */ + <3 RK_PA7 3 &pcfg_pull_none>, + /* gmac1_txclkm0 */ + <3 RK_PA6 3 &pcfg_pull_none_drv_level_1>; + }; + + /omit-if-no-ref/ + gmac1m0_rgmii_bus: gmac1m0-rgmii-bus { + rockchip,pins = + /* gmac1_rxd2m0 */ + <3 RK_PA4 3 &pcfg_pull_none>, + /* gmac1_rxd3m0 */ + <3 RK_PA5 3 &pcfg_pull_none>, + /* gmac1_txd2m0 */ + <3 RK_PA2 3 &pcfg_pull_none_drv_level_2>, + /* gmac1_txd3m0 */ + <3 RK_PA3 3 &pcfg_pull_none_drv_level_2>; + }; + + /omit-if-no-ref/ + gmac1m1_miim: gmac1m1-miim { + rockchip,pins = + /* gmac1_mdcm1 */ + <4 RK_PB6 3 &pcfg_pull_none>, + /* gmac1_mdiom1 */ + <4 RK_PB7 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + gmac1m1_clkinout: gmac1m1-clkinout { + rockchip,pins = + /* gmac1_mclkinoutm1 */ + <4 RK_PC1 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + gmac1m1_rx_er: gmac1m1-rx-er { + rockchip,pins = + /* gmac1_rxerm1 */ + <4 RK_PB2 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + gmac1m1_rx_bus2: gmac1m1-rx-bus2 { + rockchip,pins = + /* gmac1_rxd0m1 */ + <4 RK_PA7 3 &pcfg_pull_none>, + /* gmac1_rxd1m1 */ + <4 RK_PB0 3 &pcfg_pull_none>, + /* gmac1_rxdvcrsm1 */ + <4 RK_PB1 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + gmac1m1_tx_bus2: gmac1m1-tx-bus2 { + rockchip,pins = + /* gmac1_txd0m1 */ + <4 RK_PA4 3 &pcfg_pull_none_drv_level_2>, + /* gmac1_txd1m1 */ + <4 RK_PA5 3 &pcfg_pull_none_drv_level_2>, + /* gmac1_txenm1 */ + <4 RK_PA6 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + gmac1m1_rgmii_clk: gmac1m1-rgmii-clk { + rockchip,pins = + /* gmac1_rxclkm1 */ + <4 RK_PA3 3 &pcfg_pull_none>, + /* gmac1_txclkm1 */ + <4 RK_PA0 3 &pcfg_pull_none_drv_level_1>; + }; + + /omit-if-no-ref/ + gmac1m1_rgmii_bus: gmac1m1-rgmii-bus { + rockchip,pins = + /* gmac1_rxd2m1 */ + <4 RK_PA1 3 &pcfg_pull_none>, + /* gmac1_rxd3m1 */ + <4 RK_PA2 3 &pcfg_pull_none>, + /* gmac1_txd2m1 */ + <3 RK_PD6 3 &pcfg_pull_none_drv_level_2>, + /* gmac1_txd3m1 */ + <3 RK_PD7 3 &pcfg_pull_none_drv_level_2>; + }; + }; + + gpu { + /omit-if-no-ref/ + gpu_pins: gpu-pins { + rockchip,pins = + /* gpu_avs */ + <0 RK_PC0 2 &pcfg_pull_none>, + /* gpu_pwren */ + <0 RK_PA6 4 &pcfg_pull_none>; + }; + }; + + hdmitx { + /omit-if-no-ref/ + hdmitxm0_cec: hdmitxm0-cec { + rockchip,pins = + /* hdmitxm0_cec */ + <4 RK_PD1 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + hdmitxm1_cec: hdmitxm1-cec { + rockchip,pins = + /* hdmitxm1_cec */ + <0 RK_PC7 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + hdmitx_scl: hdmitx-scl { + rockchip,pins = + /* hdmitx_scl */ + <4 RK_PC7 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + hdmitx_sda: hdmitx-sda { + rockchip,pins = + /* hdmitx_sda */ + <4 RK_PD0 1 &pcfg_pull_none>; + }; + }; + + i2c0 { + /omit-if-no-ref/ + i2c0_xfer: i2c0-xfer { + rockchip,pins = + /* i2c0_scl */ + <0 RK_PB1 1 &pcfg_pull_none_smt>, + /* i2c0_sda */ + <0 RK_PB2 1 &pcfg_pull_none_smt>; + }; + }; + + i2c1 { + /omit-if-no-ref/ + i2c1_xfer: i2c1-xfer { + rockchip,pins = + /* i2c1_scl */ + <0 RK_PB3 1 &pcfg_pull_none_smt>, + /* i2c1_sda */ + <0 RK_PB4 1 &pcfg_pull_none_smt>; + }; + }; + + i2c2 { + /omit-if-no-ref/ + i2c2m0_xfer: i2c2m0-xfer { + rockchip,pins = + /* i2c2_sclm0 */ + <0 RK_PB5 1 &pcfg_pull_none_smt>, + /* i2c2_sdam0 */ + <0 RK_PB6 1 &pcfg_pull_none_smt>; + }; + + /omit-if-no-ref/ + i2c2m1_xfer: i2c2m1-xfer { + rockchip,pins = + /* i2c2_sclm1 */ + <4 RK_PB5 1 &pcfg_pull_none_smt>, + /* i2c2_sdam1 */ + <4 RK_PB4 1 &pcfg_pull_none_smt>; + }; + }; + + i2c3 { + /omit-if-no-ref/ + i2c3m0_xfer: i2c3m0-xfer { + rockchip,pins = + /* i2c3_sclm0 */ + <1 RK_PA1 1 &pcfg_pull_none_smt>, + /* i2c3_sdam0 */ + <1 RK_PA0 1 &pcfg_pull_none_smt>; + }; + + /omit-if-no-ref/ + i2c3m1_xfer: i2c3m1-xfer { + rockchip,pins = + /* i2c3_sclm1 */ + <3 RK_PB5 4 &pcfg_pull_none_smt>, + /* i2c3_sdam1 */ + <3 RK_PB6 4 &pcfg_pull_none_smt>; + }; + }; + + i2c4 { + /omit-if-no-ref/ + i2c4m0_xfer: i2c4m0-xfer { + rockchip,pins = + /* i2c4_sclm0 */ + <4 RK_PB3 1 &pcfg_pull_none_smt>, + /* i2c4_sdam0 */ + <4 RK_PB2 1 &pcfg_pull_none_smt>; + }; + + /omit-if-no-ref/ + i2c4m1_xfer: i2c4m1-xfer { + rockchip,pins = + /* i2c4_sclm1 */ + <2 RK_PB2 2 &pcfg_pull_none_smt>, + /* i2c4_sdam1 */ + <2 RK_PB1 2 &pcfg_pull_none_smt>; + }; + }; + + i2c5 { + /omit-if-no-ref/ + i2c5m0_xfer: i2c5m0-xfer { + rockchip,pins = + /* i2c5_sclm0 */ + <3 RK_PB3 4 &pcfg_pull_none_smt>, + /* i2c5_sdam0 */ + <3 RK_PB4 4 &pcfg_pull_none_smt>; + }; + + /omit-if-no-ref/ + i2c5m1_xfer: i2c5m1-xfer { + rockchip,pins = + /* i2c5_sclm1 */ + <4 RK_PC7 2 &pcfg_pull_none_smt>, + /* i2c5_sdam1 */ + <4 RK_PD0 2 &pcfg_pull_none_smt>; + }; + }; + + i2s1 { + /omit-if-no-ref/ + i2s1m0_lrckrx: i2s1m0-lrckrx { + rockchip,pins = + /* i2s1m0_lrckrx */ + <1 RK_PA6 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m0_lrcktx: i2s1m0-lrcktx { + rockchip,pins = + /* i2s1m0_lrcktx */ + <1 RK_PA5 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m0_mclk: i2s1m0-mclk { + rockchip,pins = + /* i2s1m0_mclk */ + <1 RK_PA2 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m0_sclkrx: i2s1m0-sclkrx { + rockchip,pins = + /* i2s1m0_sclkrx */ + <1 RK_PA4 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m0_sclktx: i2s1m0-sclktx { + rockchip,pins = + /* i2s1m0_sclktx */ + <1 RK_PA3 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m0_sdi0: i2s1m0-sdi0 { + rockchip,pins = + /* i2s1m0_sdi0 */ + <1 RK_PB3 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m0_sdi1: i2s1m0-sdi1 { + rockchip,pins = + /* i2s1m0_sdi1 */ + <1 RK_PB2 2 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m0_sdi2: i2s1m0-sdi2 { + rockchip,pins = + /* i2s1m0_sdi2 */ + <1 RK_PB1 2 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m0_sdi3: i2s1m0-sdi3 { + rockchip,pins = + /* i2s1m0_sdi3 */ + <1 RK_PB0 2 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m0_sdo0: i2s1m0-sdo0 { + rockchip,pins = + /* i2s1m0_sdo0 */ + <1 RK_PA7 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m0_sdo1: i2s1m0-sdo1 { + rockchip,pins = + /* i2s1m0_sdo1 */ + <1 RK_PB0 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m0_sdo2: i2s1m0-sdo2 { + rockchip,pins = + /* i2s1m0_sdo2 */ + <1 RK_PB1 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m0_sdo3: i2s1m0-sdo3 { + rockchip,pins = + /* i2s1m0_sdo3 */ + <1 RK_PB2 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m1_lrckrx: i2s1m1-lrckrx { + rockchip,pins = + /* i2s1m1_lrckrx */ + <4 RK_PA7 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m1_lrcktx: i2s1m1-lrcktx { + rockchip,pins = + /* i2s1m1_lrcktx */ + <3 RK_PD0 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m1_mclk: i2s1m1-mclk { + rockchip,pins = + /* i2s1m1_mclk */ + <3 RK_PC6 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m1_sclkrx: i2s1m1-sclkrx { + rockchip,pins = + /* i2s1m1_sclkrx */ + <4 RK_PA6 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m1_sclktx: i2s1m1-sclktx { + rockchip,pins = + /* i2s1m1_sclktx */ + <3 RK_PC7 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m1_sdi0: i2s1m1-sdi0 { + rockchip,pins = + /* i2s1m1_sdi0 */ + <3 RK_PD2 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m1_sdi1: i2s1m1-sdi1 { + rockchip,pins = + /* i2s1m1_sdi1 */ + <3 RK_PD3 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m1_sdi2: i2s1m1-sdi2 { + rockchip,pins = + /* i2s1m1_sdi2 */ + <3 RK_PD4 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m1_sdi3: i2s1m1-sdi3 { + rockchip,pins = + /* i2s1m1_sdi3 */ + <3 RK_PD5 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m1_sdo0: i2s1m1-sdo0 { + rockchip,pins = + /* i2s1m1_sdo0 */ + <3 RK_PD1 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m1_sdo1: i2s1m1-sdo1 { + rockchip,pins = + /* i2s1m1_sdo1 */ + <4 RK_PB0 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m1_sdo2: i2s1m1-sdo2 { + rockchip,pins = + /* i2s1m1_sdo2 */ + <4 RK_PB1 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m1_sdo3: i2s1m1-sdo3 { + rockchip,pins = + /* i2s1m1_sdo3 */ + <4 RK_PB5 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m2_lrckrx: i2s1m2-lrckrx { + rockchip,pins = + /* i2s1m2_lrckrx */ + <3 RK_PC5 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m2_lrcktx: i2s1m2-lrcktx { + rockchip,pins = + /* i2s1m2_lrcktx */ + <2 RK_PD2 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m2_mclk: i2s1m2-mclk { + rockchip,pins = + /* i2s1m2_mclk */ + <2 RK_PD0 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m2_sclkrx: i2s1m2-sclkrx { + rockchip,pins = + /* i2s1m2_sclkrx */ + <3 RK_PC3 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m2_sclktx: i2s1m2-sclktx { + rockchip,pins = + /* i2s1m2_sclktx */ + <2 RK_PD1 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m2_sdi0: i2s1m2-sdi0 { + rockchip,pins = + /* i2s1m2_sdi0 */ + <2 RK_PD3 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m2_sdi1: i2s1m2-sdi1 { + rockchip,pins = + /* i2s1m2_sdi1 */ + <2 RK_PD4 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m2_sdi2: i2s1m2-sdi2 { + rockchip,pins = + /* i2s1m2_sdi2 */ + <2 RK_PD5 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m2_sdi3: i2s1m2-sdi3 { + rockchip,pins = + /* i2s1m2_sdi3 */ + <2 RK_PD6 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m2_sdo0: i2s1m2-sdo0 { + rockchip,pins = + /* i2s1m2_sdo0 */ + <2 RK_PD7 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m2_sdo1: i2s1m2-sdo1 { + rockchip,pins = + /* i2s1m2_sdo1 */ + <3 RK_PA0 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m2_sdo2: i2s1m2-sdo2 { + rockchip,pins = + /* i2s1m2_sdo2 */ + <3 RK_PC1 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s1m2_sdo3: i2s1m2-sdo3 { + rockchip,pins = + /* i2s1m2_sdo3 */ + <3 RK_PC2 5 &pcfg_pull_none>; + }; + }; + + i2s2 { + /omit-if-no-ref/ + i2s2m0_lrckrx: i2s2m0-lrckrx { + rockchip,pins = + /* i2s2m0_lrckrx */ + <2 RK_PC0 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s2m0_lrcktx: i2s2m0-lrcktx { + rockchip,pins = + /* i2s2m0_lrcktx */ + <2 RK_PC3 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s2m0_mclk: i2s2m0-mclk { + rockchip,pins = + /* i2s2m0_mclk */ + <2 RK_PC1 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s2m0_sclkrx: i2s2m0-sclkrx { + rockchip,pins = + /* i2s2m0_sclkrx */ + <2 RK_PB7 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s2m0_sclktx: i2s2m0-sclktx { + rockchip,pins = + /* i2s2m0_sclktx */ + <2 RK_PC2 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s2m0_sdi: i2s2m0-sdi { + rockchip,pins = + /* i2s2m0_sdi */ + <2 RK_PC5 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s2m0_sdo: i2s2m0-sdo { + rockchip,pins = + /* i2s2m0_sdo */ + <2 RK_PC4 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s2m1_lrckrx: i2s2m1-lrckrx { + rockchip,pins = + /* i2s2m1_lrckrx */ + <4 RK_PA5 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s2m1_lrcktx: i2s2m1-lrcktx { + rockchip,pins = + /* i2s2m1_lrcktx */ + <4 RK_PA4 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s2m1_mclk: i2s2m1-mclk { + rockchip,pins = + /* i2s2m1_mclk */ + <4 RK_PB6 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s2m1_sclkrx: i2s2m1-sclkrx { + rockchip,pins = + /* i2s2m1_sclkrx */ + <4 RK_PC1 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s2m1_sclktx: i2s2m1-sclktx { + rockchip,pins = + /* i2s2m1_sclktx */ + <4 RK_PB7 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s2m1_sdi: i2s2m1-sdi { + rockchip,pins = + /* i2s2m1_sdi */ + <4 RK_PB2 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s2m1_sdo: i2s2m1-sdo { + rockchip,pins = + /* i2s2m1_sdo */ + <4 RK_PB3 5 &pcfg_pull_none>; + }; + }; + + i2s3 { + /omit-if-no-ref/ + i2s3m0_lrck: i2s3m0-lrck { + rockchip,pins = + /* i2s3m0_lrck */ + <3 RK_PA4 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s3m0_mclk: i2s3m0-mclk { + rockchip,pins = + /* i2s3m0_mclk */ + <3 RK_PA2 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s3m0_sclk: i2s3m0-sclk { + rockchip,pins = + /* i2s3m0_sclk */ + <3 RK_PA3 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s3m0_sdi: i2s3m0-sdi { + rockchip,pins = + /* i2s3m0_sdi */ + <3 RK_PA6 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s3m0_sdo: i2s3m0-sdo { + rockchip,pins = + /* i2s3m0_sdo */ + <3 RK_PA5 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s3m1_lrck: i2s3m1-lrck { + rockchip,pins = + /* i2s3m1_lrck */ + <4 RK_PC4 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s3m1_mclk: i2s3m1-mclk { + rockchip,pins = + /* i2s3m1_mclk */ + <4 RK_PC2 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s3m1_sclk: i2s3m1-sclk { + rockchip,pins = + /* i2s3m1_sclk */ + <4 RK_PC3 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s3m1_sdi: i2s3m1-sdi { + rockchip,pins = + /* i2s3m1_sdi */ + <4 RK_PC6 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + i2s3m1_sdo: i2s3m1-sdo { + rockchip,pins = + /* i2s3m1_sdo */ + <4 RK_PC5 5 &pcfg_pull_none>; + }; + }; + + isp { + /omit-if-no-ref/ + isp_pins: isp-pins { + rockchip,pins = + /* isp_flashtrigin */ + <4 RK_PB4 4 &pcfg_pull_none>, + /* isp_flashtrigout */ + <4 RK_PA6 1 &pcfg_pull_none>, + /* isp_prelighttrig */ + <4 RK_PB1 1 &pcfg_pull_none>; + }; + }; + + jtag { + /omit-if-no-ref/ + jtag_pins: jtag-pins { + rockchip,pins = + /* jtag_tck */ + <1 RK_PD7 2 &pcfg_pull_none>, + /* jtag_tms */ + <2 RK_PA0 2 &pcfg_pull_none>; + }; + }; + + lcdc { + /omit-if-no-ref/ + lcdc_ctl: lcdc-ctl { + rockchip,pins = + /* lcdc_clk */ + <3 RK_PA0 1 &pcfg_pull_none>, + /* lcdc_d0 */ + <2 RK_PD0 1 &pcfg_pull_none>, + /* lcdc_d1 */ + <2 RK_PD1 1 &pcfg_pull_none>, + /* lcdc_d2 */ + <2 RK_PD2 1 &pcfg_pull_none>, + /* lcdc_d3 */ + <2 RK_PD3 1 &pcfg_pull_none>, + /* lcdc_d4 */ + <2 RK_PD4 1 &pcfg_pull_none>, + /* lcdc_d5 */ + <2 RK_PD5 1 &pcfg_pull_none>, + /* lcdc_d6 */ + <2 RK_PD6 1 &pcfg_pull_none>, + /* lcdc_d7 */ + <2 RK_PD7 1 &pcfg_pull_none>, + /* lcdc_d8 */ + <3 RK_PA1 1 &pcfg_pull_none>, + /* lcdc_d9 */ + <3 RK_PA2 1 &pcfg_pull_none>, + /* lcdc_d10 */ + <3 RK_PA3 1 &pcfg_pull_none>, + /* lcdc_d11 */ + <3 RK_PA4 1 &pcfg_pull_none>, + /* lcdc_d12 */ + <3 RK_PA5 1 &pcfg_pull_none>, + /* lcdc_d13 */ + <3 RK_PA6 1 &pcfg_pull_none>, + /* lcdc_d14 */ + <3 RK_PA7 1 &pcfg_pull_none>, + /* lcdc_d15 */ + <3 RK_PB0 1 &pcfg_pull_none>, + /* lcdc_d16 */ + <3 RK_PB1 1 &pcfg_pull_none>, + /* lcdc_d17 */ + <3 RK_PB2 1 &pcfg_pull_none>, + /* lcdc_d18 */ + <3 RK_PB3 1 &pcfg_pull_none>, + /* lcdc_d19 */ + <3 RK_PB4 1 &pcfg_pull_none>, + /* lcdc_d20 */ + <3 RK_PB5 1 &pcfg_pull_none>, + /* lcdc_d21 */ + <3 RK_PB6 1 &pcfg_pull_none>, + /* lcdc_d22 */ + <3 RK_PB7 1 &pcfg_pull_none>, + /* lcdc_d23 */ + <3 RK_PC0 1 &pcfg_pull_none>, + /* lcdc_den */ + <3 RK_PC3 1 &pcfg_pull_none>, + /* lcdc_hsync */ + <3 RK_PC1 1 &pcfg_pull_none>, + /* lcdc_vsync */ + <3 RK_PC2 1 &pcfg_pull_none>; + }; + }; + + mcu { + /omit-if-no-ref/ + mcu_pins: mcu-pins { + rockchip,pins = + /* mcu_jtagtck */ + <0 RK_PB4 4 &pcfg_pull_none>, + /* mcu_jtagtdi */ + <0 RK_PC1 4 &pcfg_pull_none>, + /* mcu_jtagtdo */ + <0 RK_PB3 4 &pcfg_pull_none>, + /* mcu_jtagtms */ + <0 RK_PC2 4 &pcfg_pull_none>, + /* mcu_jtagtrstn */ + <0 RK_PC3 4 &pcfg_pull_none>; + }; + }; + + npu { + /omit-if-no-ref/ + npu_pins: npu-pins { + rockchip,pins = + /* npu_avs */ + <0 RK_PC1 2 &pcfg_pull_none>; + }; + }; + + pcie20 { + /omit-if-no-ref/ + pcie20m0_pins: pcie20m0-pins { + rockchip,pins = + /* pcie20_clkreqnm0 */ + <0 RK_PA5 3 &pcfg_pull_none>, + /* pcie20_perstnm0 */ + <0 RK_PB6 3 &pcfg_pull_none>, + /* pcie20_wakenm0 */ + <0 RK_PB5 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pcie20m1_pins: pcie20m1-pins { + rockchip,pins = + /* pcie20_clkreqnm1 */ + <2 RK_PD0 4 &pcfg_pull_none>, + /* pcie20_perstnm1 */ + <3 RK_PC1 4 &pcfg_pull_none>, + /* pcie20_wakenm1 */ + <2 RK_PD1 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pcie20m2_pins: pcie20m2-pins { + rockchip,pins = + /* pcie20_clkreqnm2 */ + <1 RK_PB0 4 &pcfg_pull_none>, + /* pcie20_perstnm2 */ + <1 RK_PB2 4 &pcfg_pull_none>, + /* pcie20_wakenm2 */ + <1 RK_PB1 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pcie20_buttonrstn: pcie20-buttonrstn { + rockchip,pins = + /* pcie20_buttonrstn */ + <0 RK_PB4 3 &pcfg_pull_none>; + }; + }; + + pcie30x1 { + /omit-if-no-ref/ + pcie30x1m0_pins: pcie30x1m0-pins { + rockchip,pins = + /* pcie30x1_clkreqnm0 */ + <0 RK_PA4 3 &pcfg_pull_none>, + /* pcie30x1_perstnm0 */ + <0 RK_PC3 3 &pcfg_pull_none>, + /* pcie30x1_wakenm0 */ + <0 RK_PC2 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pcie30x1m1_pins: pcie30x1m1-pins { + rockchip,pins = + /* pcie30x1_clkreqnm1 */ + <2 RK_PD2 4 &pcfg_pull_none>, + /* pcie30x1_perstnm1 */ + <3 RK_PA1 4 &pcfg_pull_none>, + /* pcie30x1_wakenm1 */ + <2 RK_PD3 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pcie30x1m2_pins: pcie30x1m2-pins { + rockchip,pins = + /* pcie30x1_clkreqnm2 */ + <1 RK_PA5 4 &pcfg_pull_none>, + /* pcie30x1_perstnm2 */ + <1 RK_PA2 4 &pcfg_pull_none>, + /* pcie30x1_wakenm2 */ + <1 RK_PA3 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pcie30x1_buttonrstn: pcie30x1-buttonrstn { + rockchip,pins = + /* pcie30x1_buttonrstn */ + <0 RK_PB3 3 &pcfg_pull_none>; + }; + }; + + pcie30x2 { + /omit-if-no-ref/ + pcie30x2m0_pins: pcie30x2m0-pins { + rockchip,pins = + /* pcie30x2_clkreqnm0 */ + <0 RK_PA6 2 &pcfg_pull_none>, + /* pcie30x2_perstnm0 */ + <0 RK_PC6 3 &pcfg_pull_none>, + /* pcie30x2_wakenm0 */ + <0 RK_PC5 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pcie30x2m1_pins: pcie30x2m1-pins { + rockchip,pins = + /* pcie30x2_clkreqnm1 */ + <2 RK_PD4 4 &pcfg_pull_none>, + /* pcie30x2_perstnm1 */ + <2 RK_PD6 4 &pcfg_pull_none>, + /* pcie30x2_wakenm1 */ + <2 RK_PD5 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pcie30x2m2_pins: pcie30x2m2-pins { + rockchip,pins = + /* pcie30x2_clkreqnm2 */ + <4 RK_PC2 4 &pcfg_pull_none>, + /* pcie30x2_perstnm2 */ + <4 RK_PC4 4 &pcfg_pull_none>, + /* pcie30x2_wakenm2 */ + <4 RK_PC3 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pcie30x2_buttonrstn: pcie30x2-buttonrstn { + rockchip,pins = + /* pcie30x2_buttonrstn */ + <0 RK_PB0 3 &pcfg_pull_none>; + }; + }; + + pdm { + /omit-if-no-ref/ + pdmm0_clk: pdmm0-clk { + rockchip,pins = + /* pdm_clk0m0 */ + <1 RK_PA6 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pdmm0_clk1: pdmm0-clk1 { + rockchip,pins = + /* pdmm0_clk1 */ + <1 RK_PA4 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pdmm0_sdi0: pdmm0-sdi0 { + rockchip,pins = + /* pdmm0_sdi0 */ + <1 RK_PB3 2 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pdmm0_sdi1: pdmm0-sdi1 { + rockchip,pins = + /* pdmm0_sdi1 */ + <1 RK_PB2 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pdmm0_sdi2: pdmm0-sdi2 { + rockchip,pins = + /* pdmm0_sdi2 */ + <1 RK_PB1 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pdmm0_sdi3: pdmm0-sdi3 { + rockchip,pins = + /* pdmm0_sdi3 */ + <1 RK_PB0 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pdmm1_clk: pdmm1-clk { + rockchip,pins = + /* pdm_clk0m1 */ + <3 RK_PD6 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pdmm1_clk1: pdmm1-clk1 { + rockchip,pins = + /* pdmm1_clk1 */ + <4 RK_PA0 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pdmm1_sdi0: pdmm1-sdi0 { + rockchip,pins = + /* pdmm1_sdi0 */ + <3 RK_PD7 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pdmm1_sdi1: pdmm1-sdi1 { + rockchip,pins = + /* pdmm1_sdi1 */ + <4 RK_PA1 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pdmm1_sdi2: pdmm1-sdi2 { + rockchip,pins = + /* pdmm1_sdi2 */ + <4 RK_PA2 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pdmm1_sdi3: pdmm1-sdi3 { + rockchip,pins = + /* pdmm1_sdi3 */ + <4 RK_PA3 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pdmm2_clk1: pdmm2-clk1 { + rockchip,pins = + /* pdmm2_clk1 */ + <3 RK_PC4 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pdmm2_sdi0: pdmm2-sdi0 { + rockchip,pins = + /* pdmm2_sdi0 */ + <3 RK_PB3 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pdmm2_sdi1: pdmm2-sdi1 { + rockchip,pins = + /* pdmm2_sdi1 */ + <3 RK_PB4 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pdmm2_sdi2: pdmm2-sdi2 { + rockchip,pins = + /* pdmm2_sdi2 */ + <3 RK_PB7 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pdmm2_sdi3: pdmm2-sdi3 { + rockchip,pins = + /* pdmm2_sdi3 */ + <3 RK_PC0 5 &pcfg_pull_none>; + }; + }; + + pmic { + /omit-if-no-ref/ + pmic_pins: pmic-pins { + rockchip,pins = + /* pmic_sleep */ + <0 RK_PA2 1 &pcfg_pull_none>; + }; + }; + + pmu { + /omit-if-no-ref/ + pmu_pins: pmu-pins { + rockchip,pins = + /* pmu_debug0 */ + <0 RK_PA5 4 &pcfg_pull_none>, + /* pmu_debug1 */ + <0 RK_PA6 3 &pcfg_pull_none>, + /* pmu_debug2 */ + <0 RK_PC4 4 &pcfg_pull_none>, + /* pmu_debug3 */ + <0 RK_PC5 4 &pcfg_pull_none>, + /* pmu_debug4 */ + <0 RK_PC6 4 &pcfg_pull_none>, + /* pmu_debug5 */ + <0 RK_PC7 4 &pcfg_pull_none>; + }; + }; + + pwm0 { + /omit-if-no-ref/ + pwm0m0_pins: pwm0m0-pins { + rockchip,pins = + /* pwm0_m0 */ + <0 RK_PB7 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pwm0m1_pins: pwm0m1-pins { + rockchip,pins = + /* pwm0_m1 */ + <0 RK_PC7 2 &pcfg_pull_none>; + }; + }; + + pwm1 { + /omit-if-no-ref/ + pwm1m0_pins: pwm1m0-pins { + rockchip,pins = + /* pwm1_m0 */ + <0 RK_PC0 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pwm1m1_pins: pwm1m1-pins { + rockchip,pins = + /* pwm1_m1 */ + <0 RK_PB5 4 &pcfg_pull_none>; + }; + }; + + pwm2 { + /omit-if-no-ref/ + pwm2m0_pins: pwm2m0-pins { + rockchip,pins = + /* pwm2_m0 */ + <0 RK_PC1 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pwm2m1_pins: pwm2m1-pins { + rockchip,pins = + /* pwm2_m1 */ + <0 RK_PB6 4 &pcfg_pull_none>; + }; + }; + + pwm3 { + /omit-if-no-ref/ + pwm3_pins: pwm3-pins { + rockchip,pins = + /* pwm3_ir */ + <0 RK_PC2 1 &pcfg_pull_none>; + }; + }; + + pwm4 { + /omit-if-no-ref/ + pwm4_pins: pwm4-pins { + rockchip,pins = + /* pwm4 */ + <0 RK_PC3 1 &pcfg_pull_none>; + }; + }; + + pwm5 { + /omit-if-no-ref/ + pwm5_pins: pwm5-pins { + rockchip,pins = + /* pwm5 */ + <0 RK_PC4 1 &pcfg_pull_none>; + }; + }; + + pwm6 { + /omit-if-no-ref/ + pwm6_pins: pwm6-pins { + rockchip,pins = + /* pwm6 */ + <0 RK_PC5 1 &pcfg_pull_none>; + }; + }; + + pwm7 { + /omit-if-no-ref/ + pwm7_pins: pwm7-pins { + rockchip,pins = + /* pwm7_ir */ + <0 RK_PC6 1 &pcfg_pull_none>; + }; + }; + + pwm8 { + /omit-if-no-ref/ + pwm8m0_pins: pwm8m0-pins { + rockchip,pins = + /* pwm8_m0 */ + <3 RK_PB1 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pwm8m1_pins: pwm8m1-pins { + rockchip,pins = + /* pwm8_m1 */ + <1 RK_PD5 4 &pcfg_pull_none>; + }; + }; + + pwm9 { + /omit-if-no-ref/ + pwm9m0_pins: pwm9m0-pins { + rockchip,pins = + /* pwm9_m0 */ + <3 RK_PB2 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pwm9m1_pins: pwm9m1-pins { + rockchip,pins = + /* pwm9_m1 */ + <1 RK_PD6 4 &pcfg_pull_none>; + }; + }; + + pwm10 { + /omit-if-no-ref/ + pwm10m0_pins: pwm10m0-pins { + rockchip,pins = + /* pwm10_m0 */ + <3 RK_PB5 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pwm10m1_pins: pwm10m1-pins { + rockchip,pins = + /* pwm10_m1 */ + <2 RK_PA1 2 &pcfg_pull_none>; + }; + }; + + pwm11 { + /omit-if-no-ref/ + pwm11m0_pins: pwm11m0-pins { + rockchip,pins = + /* pwm11_irm0 */ + <3 RK_PB6 5 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pwm11m1_pins: pwm11m1-pins { + rockchip,pins = + /* pwm11_irm1 */ + <4 RK_PC0 3 &pcfg_pull_none>; + }; + }; + + pwm12 { + /omit-if-no-ref/ + pwm12m0_pins: pwm12m0-pins { + rockchip,pins = + /* pwm12_m0 */ + <3 RK_PB7 2 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pwm12m1_pins: pwm12m1-pins { + rockchip,pins = + /* pwm12_m1 */ + <4 RK_PC5 1 &pcfg_pull_none>; + }; + }; + + pwm13 { + /omit-if-no-ref/ + pwm13m0_pins: pwm13m0-pins { + rockchip,pins = + /* pwm13_m0 */ + <3 RK_PC0 2 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pwm13m1_pins: pwm13m1-pins { + rockchip,pins = + /* pwm13_m1 */ + <4 RK_PC6 1 &pcfg_pull_none>; + }; + }; + + pwm14 { + /omit-if-no-ref/ + pwm14m0_pins: pwm14m0-pins { + rockchip,pins = + /* pwm14_m0 */ + <3 RK_PC4 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pwm14m1_pins: pwm14m1-pins { + rockchip,pins = + /* pwm14_m1 */ + <4 RK_PC2 1 &pcfg_pull_none>; + }; + }; + + pwm15 { + /omit-if-no-ref/ + pwm15m0_pins: pwm15m0-pins { + rockchip,pins = + /* pwm15_irm0 */ + <3 RK_PC5 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + pwm15m1_pins: pwm15m1-pins { + rockchip,pins = + /* pwm15_irm1 */ + <4 RK_PC3 1 &pcfg_pull_none>; + }; + }; + + refclk { + /omit-if-no-ref/ + refclk_pins: refclk-pins { + rockchip,pins = + /* refclk_ou */ + <0 RK_PA0 1 &pcfg_pull_none>; + }; + }; + + sata { + /omit-if-no-ref/ + sata_pins: sata-pins { + rockchip,pins = + /* sata_cpdet */ + <0 RK_PA4 2 &pcfg_pull_none>, + /* sata_cppod */ + <0 RK_PA6 1 &pcfg_pull_none>, + /* sata_mpswitch */ + <0 RK_PA5 2 &pcfg_pull_none>; + }; + }; + + sata0 { + /omit-if-no-ref/ + sata0_pins: sata0-pins { + rockchip,pins = + /* sata0_actled */ + <4 RK_PC6 3 &pcfg_pull_none>; + }; + }; + + sata1 { + /omit-if-no-ref/ + sata1_pins: sata1-pins { + rockchip,pins = + /* sata1_actled */ + <4 RK_PC5 3 &pcfg_pull_none>; + }; + }; + + sata2 { + /omit-if-no-ref/ + sata2_pins: sata2-pins { + rockchip,pins = + /* sata2_actled */ + <4 RK_PC4 3 &pcfg_pull_none>; + }; + }; + + scr { + /omit-if-no-ref/ + scr_pins: scr-pins { + rockchip,pins = + /* scr_clk */ + <1 RK_PA2 3 &pcfg_pull_none>, + /* scr_det */ + <1 RK_PA7 3 &pcfg_pull_up>, + /* scr_io */ + <1 RK_PA3 3 &pcfg_pull_up>, + /* scr_rst */ + <1 RK_PA5 3 &pcfg_pull_none>; + }; + }; + + sdmmc0 { + /omit-if-no-ref/ + sdmmc0_bus4: sdmmc0-bus4 { + rockchip,pins = + /* sdmmc0_d0 */ + <1 RK_PD5 1 &pcfg_pull_up_drv_level_2>, + /* sdmmc0_d1 */ + <1 RK_PD6 1 &pcfg_pull_up_drv_level_2>, + /* sdmmc0_d2 */ + <1 RK_PD7 1 &pcfg_pull_up_drv_level_2>, + /* sdmmc0_d3 */ + <2 RK_PA0 1 &pcfg_pull_up_drv_level_2>; + }; + + /omit-if-no-ref/ + sdmmc0_clk: sdmmc0-clk { + rockchip,pins = + /* sdmmc0_clk */ + <2 RK_PA2 1 &pcfg_pull_up_drv_level_2>; + }; + + /omit-if-no-ref/ + sdmmc0_cmd: sdmmc0-cmd { + rockchip,pins = + /* sdmmc0_cmd */ + <2 RK_PA1 1 &pcfg_pull_up_drv_level_2>; + }; + + /omit-if-no-ref/ + sdmmc0_det: sdmmc0-det { + rockchip,pins = + /* sdmmc0_det */ + <0 RK_PA4 1 &pcfg_pull_up>; + }; + + /omit-if-no-ref/ + sdmmc0_pwren: sdmmc0-pwren { + rockchip,pins = + /* sdmmc0_pwren */ + <0 RK_PA5 1 &pcfg_pull_none>; + }; + }; + + sdmmc1 { + /omit-if-no-ref/ + sdmmc1_bus4: sdmmc1-bus4 { + rockchip,pins = + /* sdmmc1_d0 */ + <2 RK_PA3 1 &pcfg_pull_up_drv_level_2>, + /* sdmmc1_d1 */ + <2 RK_PA4 1 &pcfg_pull_up_drv_level_2>, + /* sdmmc1_d2 */ + <2 RK_PA5 1 &pcfg_pull_up_drv_level_2>, + /* sdmmc1_d3 */ + <2 RK_PA6 1 &pcfg_pull_up_drv_level_2>; + }; + + /omit-if-no-ref/ + sdmmc1_clk: sdmmc1-clk { + rockchip,pins = + /* sdmmc1_clk */ + <2 RK_PB0 1 &pcfg_pull_up_drv_level_2>; + }; + + /omit-if-no-ref/ + sdmmc1_cmd: sdmmc1-cmd { + rockchip,pins = + /* sdmmc1_cmd */ + <2 RK_PA7 1 &pcfg_pull_up_drv_level_2>; + }; + + /omit-if-no-ref/ + sdmmc1_det: sdmmc1-det { + rockchip,pins = + /* sdmmc1_det */ + <2 RK_PB2 1 &pcfg_pull_up>; + }; + + /omit-if-no-ref/ + sdmmc1_pwren: sdmmc1-pwren { + rockchip,pins = + /* sdmmc1_pwren */ + <2 RK_PB1 1 &pcfg_pull_none>; + }; + }; + + sdmmc2 { + /omit-if-no-ref/ + sdmmc2m0_bus4: sdmmc2m0-bus4 { + rockchip,pins = + /* sdmmc2_d0m0 */ + <3 RK_PC6 3 &pcfg_pull_up_drv_level_2>, + /* sdmmc2_d1m0 */ + <3 RK_PC7 3 &pcfg_pull_up_drv_level_2>, + /* sdmmc2_d2m0 */ + <3 RK_PD0 3 &pcfg_pull_up_drv_level_2>, + /* sdmmc2_d3m0 */ + <3 RK_PD1 3 &pcfg_pull_up_drv_level_2>; + }; + + /omit-if-no-ref/ + sdmmc2m0_clk: sdmmc2m0-clk { + rockchip,pins = + /* sdmmc2_clkm0 */ + <3 RK_PD3 3 &pcfg_pull_up_drv_level_2>; + }; + + /omit-if-no-ref/ + sdmmc2m0_cmd: sdmmc2m0-cmd { + rockchip,pins = + /* sdmmc2_cmdm0 */ + <3 RK_PD2 3 &pcfg_pull_up_drv_level_2>; + }; + + /omit-if-no-ref/ + sdmmc2m0_det: sdmmc2m0-det { + rockchip,pins = + /* sdmmc2_detm0 */ + <3 RK_PD4 3 &pcfg_pull_up>; + }; + + /omit-if-no-ref/ + sdmmc2m0_pwren: sdmmc2m0-pwren { + rockchip,pins = + /* sdmmc2m0_pwren */ + <3 RK_PD5 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + sdmmc2m1_bus4: sdmmc2m1-bus4 { + rockchip,pins = + /* sdmmc2_d0m1 */ + <3 RK_PA1 5 &pcfg_pull_up_drv_level_2>, + /* sdmmc2_d1m1 */ + <3 RK_PA2 5 &pcfg_pull_up_drv_level_2>, + /* sdmmc2_d2m1 */ + <3 RK_PA3 5 &pcfg_pull_up_drv_level_2>, + /* sdmmc2_d3m1 */ + <3 RK_PA4 5 &pcfg_pull_up_drv_level_2>; + }; + + /omit-if-no-ref/ + sdmmc2m1_clk: sdmmc2m1-clk { + rockchip,pins = + /* sdmmc2_clkm1 */ + <3 RK_PA6 5 &pcfg_pull_up_drv_level_2>; + }; + + /omit-if-no-ref/ + sdmmc2m1_cmd: sdmmc2m1-cmd { + rockchip,pins = + /* sdmmc2_cmdm1 */ + <3 RK_PA5 5 &pcfg_pull_up_drv_level_2>; + }; + + /omit-if-no-ref/ + sdmmc2m1_det: sdmmc2m1-det { + rockchip,pins = + /* sdmmc2_detm1 */ + <3 RK_PA7 4 &pcfg_pull_up>; + }; + + /omit-if-no-ref/ + sdmmc2m1_pwren: sdmmc2m1-pwren { + rockchip,pins = + /* sdmmc2m1_pwren */ + <3 RK_PB0 4 &pcfg_pull_none>; + }; + }; + + spdif { + /omit-if-no-ref/ + spdifm0_tx: spdifm0-tx { + rockchip,pins = + /* spdifm0_tx */ + <1 RK_PA4 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + spdifm1_tx: spdifm1-tx { + rockchip,pins = + /* spdifm1_tx */ + <3 RK_PC5 2 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + spdifm2_tx: spdifm2-tx { + rockchip,pins = + /* spdifm2_tx */ + <4 RK_PC4 2 &pcfg_pull_none>; + }; + }; + + spi0 { + /omit-if-no-ref/ + spi0m0_pins: spi0m0-pins { + rockchip,pins = + /* spi0_clkm0 */ + <0 RK_PB5 2 &pcfg_pull_none>, + /* spi0_misom0 */ + <0 RK_PC5 2 &pcfg_pull_none>, + /* spi0_mosim0 */ + <0 RK_PB6 2 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + spi0m0_cs0: spi0m0-cs0 { + rockchip,pins = + /* spi0_cs0m0 */ + <0 RK_PC6 2 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + spi0m0_cs1: spi0m0-cs1 { + rockchip,pins = + /* spi0_cs1m0 */ + <0 RK_PC4 2 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + spi0m1_pins: spi0m1-pins { + rockchip,pins = + /* spi0_clkm1 */ + <2 RK_PD3 3 &pcfg_pull_none>, + /* spi0_misom1 */ + <2 RK_PD0 3 &pcfg_pull_none>, + /* spi0_mosim1 */ + <2 RK_PD1 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + spi0m1_cs0: spi0m1-cs0 { + rockchip,pins = + /* spi0_cs0m1 */ + <2 RK_PD2 3 &pcfg_pull_none>; + }; + }; + + spi1 { + /omit-if-no-ref/ + spi1m0_pins: spi1m0-pins { + rockchip,pins = + /* spi1_clkm0 */ + <2 RK_PB5 3 &pcfg_pull_none>, + /* spi1_misom0 */ + <2 RK_PB6 3 &pcfg_pull_none>, + /* spi1_mosim0 */ + <2 RK_PB7 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + spi1m0_cs0: spi1m0-cs0 { + rockchip,pins = + /* spi1_cs0m0 */ + <2 RK_PC0 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + spi1m0_cs1: spi1m0-cs1 { + rockchip,pins = + /* spi1_cs1m0 */ + <2 RK_PC6 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + spi1m1_pins: spi1m1-pins { + rockchip,pins = + /* spi1_clkm1 */ + <3 RK_PC3 3 &pcfg_pull_none>, + /* spi1_misom1 */ + <3 RK_PC2 3 &pcfg_pull_none>, + /* spi1_mosim1 */ + <3 RK_PC1 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + spi1m1_cs0: spi1m1-cs0 { + rockchip,pins = + /* spi1_cs0m1 */ + <3 RK_PA1 3 &pcfg_pull_none>; + }; + }; + + spi2 { + /omit-if-no-ref/ + spi2m0_pins: spi2m0-pins { + rockchip,pins = + /* spi2_clkm0 */ + <2 RK_PC1 4 &pcfg_pull_none>, + /* spi2_misom0 */ + <2 RK_PC2 4 &pcfg_pull_none>, + /* spi2_mosim0 */ + <2 RK_PC3 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + spi2m0_cs0: spi2m0-cs0 { + rockchip,pins = + /* spi2_cs0m0 */ + <2 RK_PC4 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + spi2m0_cs1: spi2m0-cs1 { + rockchip,pins = + /* spi2_cs1m0 */ + <2 RK_PC5 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + spi2m1_pins: spi2m1-pins { + rockchip,pins = + /* spi2_clkm1 */ + <3 RK_PA0 3 &pcfg_pull_none>, + /* spi2_misom1 */ + <2 RK_PD7 3 &pcfg_pull_none>, + /* spi2_mosim1 */ + <2 RK_PD6 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + spi2m1_cs0: spi2m1-cs0 { + rockchip,pins = + /* spi2_cs0m1 */ + <2 RK_PD5 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + spi2m1_cs1: spi2m1-cs1 { + rockchip,pins = + /* spi2_cs1m1 */ + <2 RK_PD4 3 &pcfg_pull_none>; + }; + }; + + spi3 { + /omit-if-no-ref/ + spi3m0_pins: spi3m0-pins { + rockchip,pins = + /* spi3_clkm0 */ + <4 RK_PB3 4 &pcfg_pull_none>, + /* spi3_misom0 */ + <4 RK_PB0 4 &pcfg_pull_none>, + /* spi3_mosim0 */ + <4 RK_PB2 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + spi3m0_cs0: spi3m0-cs0 { + rockchip,pins = + /* spi3_cs0m0 */ + <4 RK_PA6 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + spi3m0_cs1: spi3m0-cs1 { + rockchip,pins = + /* spi3_cs1m0 */ + <4 RK_PA7 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + spi3m1_pins: spi3m1-pins { + rockchip,pins = + /* spi3_clkm1 */ + <4 RK_PC2 2 &pcfg_pull_none>, + /* spi3_misom1 */ + <4 RK_PC5 2 &pcfg_pull_none>, + /* spi3_mosim1 */ + <4 RK_PC3 2 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + spi3m1_cs0: spi3m1-cs0 { + rockchip,pins = + /* spi3_cs0m1 */ + <4 RK_PC6 2 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + spi3m1_cs1: spi3m1-cs1 { + rockchip,pins = + /* spi3_cs1m1 */ + <4 RK_PD1 2 &pcfg_pull_none>; + }; + }; + + tsadc { + /omit-if-no-ref/ + tsadcm0_shut: tsadcm0-shut { + rockchip,pins = + /* tsadcm0_shut */ + <0 RK_PA1 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + tsadcm1_shut: tsadcm1-shut { + rockchip,pins = + /* tsadcm1_shut */ + <0 RK_PA2 2 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + tsadc_shutorg: tsadc-shutorg { + rockchip,pins = + /* tsadc_shutorg */ + <0 RK_PA1 2 &pcfg_pull_none>; + }; + }; + + uart0 { + /omit-if-no-ref/ + uart0_xfer: uart0-xfer { + rockchip,pins = + /* uart0_rx */ + <0 RK_PC0 3 &pcfg_pull_up>, + /* uart0_tx */ + <0 RK_PC1 3 &pcfg_pull_up>; + }; + + /omit-if-no-ref/ + uart0_ctsn: uart0-ctsn { + rockchip,pins = + /* uart0_ctsn */ + <0 RK_PC7 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + uart0_rtsn: uart0-rtsn { + rockchip,pins = + /* uart0_rtsn */ + <0 RK_PC4 3 &pcfg_pull_none>; + }; + }; + + uart1 { + /omit-if-no-ref/ + uart1m0_xfer: uart1m0-xfer { + rockchip,pins = + /* uart1_rxm0 */ + <2 RK_PB3 2 &pcfg_pull_up>, + /* uart1_txm0 */ + <2 RK_PB4 2 &pcfg_pull_up>; + }; + + /omit-if-no-ref/ + uart1m0_ctsn: uart1m0-ctsn { + rockchip,pins = + /* uart1m0_ctsn */ + <2 RK_PB6 2 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + uart1m0_rtsn: uart1m0-rtsn { + rockchip,pins = + /* uart1m0_rtsn */ + <2 RK_PB5 2 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + uart1m1_xfer: uart1m1-xfer { + rockchip,pins = + /* uart1_rxm1 */ + <3 RK_PD7 4 &pcfg_pull_up>, + /* uart1_txm1 */ + <3 RK_PD6 4 &pcfg_pull_up>; + }; + + /omit-if-no-ref/ + uart1m1_ctsn: uart1m1-ctsn { + rockchip,pins = + /* uart1m1_ctsn */ + <4 RK_PC1 4 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + uart1m1_rtsn: uart1m1-rtsn { + rockchip,pins = + /* uart1m1_rtsn */ + <4 RK_PB6 4 &pcfg_pull_none>; + }; + }; + + uart2 { + /omit-if-no-ref/ + uart2m0_xfer: uart2m0-xfer { + rockchip,pins = + /* uart2_rxm0 */ + <0 RK_PD0 1 &pcfg_pull_up>, + /* uart2_txm0 */ + <0 RK_PD1 1 &pcfg_pull_up>; + }; + + /omit-if-no-ref/ + uart2m1_xfer: uart2m1-xfer { + rockchip,pins = + /* uart2_rxm1 */ + <1 RK_PD6 2 &pcfg_pull_up>, + /* uart2_txm1 */ + <1 RK_PD5 2 &pcfg_pull_up>; + }; + }; + + uart3 { + /omit-if-no-ref/ + uart3m0_xfer: uart3m0-xfer { + rockchip,pins = + /* uart3_rxm0 */ + <1 RK_PA0 2 &pcfg_pull_up>, + /* uart3_txm0 */ + <1 RK_PA1 2 &pcfg_pull_up>; + }; + + /omit-if-no-ref/ + uart3m0_ctsn: uart3m0-ctsn { + rockchip,pins = + /* uart3m0_ctsn */ + <1 RK_PA3 2 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + uart3m0_rtsn: uart3m0-rtsn { + rockchip,pins = + /* uart3m0_rtsn */ + <1 RK_PA2 2 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + uart3m1_xfer: uart3m1-xfer { + rockchip,pins = + /* uart3_rxm1 */ + <3 RK_PC0 4 &pcfg_pull_up>, + /* uart3_txm1 */ + <3 RK_PB7 4 &pcfg_pull_up>; + }; + }; + + uart4 { + /omit-if-no-ref/ + uart4m0_xfer: uart4m0-xfer { + rockchip,pins = + /* uart4_rxm0 */ + <1 RK_PA4 2 &pcfg_pull_up>, + /* uart4_txm0 */ + <1 RK_PA6 2 &pcfg_pull_up>; + }; + + /omit-if-no-ref/ + uart4m0_ctsn: uart4m0-ctsn { + rockchip,pins = + /* uart4m0_ctsn */ + <1 RK_PA7 2 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + uart4m0_rtsn: uart4m0-rtsn { + rockchip,pins = + /* uart4m0_rtsn */ + <1 RK_PA5 2 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + uart4m1_xfer: uart4m1-xfer { + rockchip,pins = + /* uart4_rxm1 */ + <3 RK_PB1 4 &pcfg_pull_up>, + /* uart4_txm1 */ + <3 RK_PB2 4 &pcfg_pull_up>; + }; + }; + + uart5 { + /omit-if-no-ref/ + uart5m0_xfer: uart5m0-xfer { + rockchip,pins = + /* uart5_rxm0 */ + <2 RK_PA1 3 &pcfg_pull_up>, + /* uart5_txm0 */ + <2 RK_PA2 3 &pcfg_pull_up>; + }; + + /omit-if-no-ref/ + uart5m0_ctsn: uart5m0-ctsn { + rockchip,pins = + /* uart5m0_ctsn */ + <1 RK_PD7 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + uart5m0_rtsn: uart5m0-rtsn { + rockchip,pins = + /* uart5m0_rtsn */ + <2 RK_PA0 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + uart5m1_xfer: uart5m1-xfer { + rockchip,pins = + /* uart5_rxm1 */ + <3 RK_PC3 4 &pcfg_pull_up>, + /* uart5_txm1 */ + <3 RK_PC2 4 &pcfg_pull_up>; + }; + }; + + uart6 { + /omit-if-no-ref/ + uart6m0_xfer: uart6m0-xfer { + rockchip,pins = + /* uart6_rxm0 */ + <2 RK_PA3 3 &pcfg_pull_up>, + /* uart6_txm0 */ + <2 RK_PA4 3 &pcfg_pull_up>; + }; + + /omit-if-no-ref/ + uart6m0_ctsn: uart6m0-ctsn { + rockchip,pins = + /* uart6m0_ctsn */ + <2 RK_PC0 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + uart6m0_rtsn: uart6m0-rtsn { + rockchip,pins = + /* uart6m0_rtsn */ + <2 RK_PB7 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + uart6m1_xfer: uart6m1-xfer { + rockchip,pins = + /* uart6_rxm1 */ + <1 RK_PD6 3 &pcfg_pull_up>, + /* uart6_txm1 */ + <1 RK_PD5 3 &pcfg_pull_up>; + }; + }; + + uart7 { + /omit-if-no-ref/ + uart7m0_xfer: uart7m0-xfer { + rockchip,pins = + /* uart7_rxm0 */ + <2 RK_PA5 3 &pcfg_pull_up>, + /* uart7_txm0 */ + <2 RK_PA6 3 &pcfg_pull_up>; + }; + + /omit-if-no-ref/ + uart7m0_ctsn: uart7m0-ctsn { + rockchip,pins = + /* uart7m0_ctsn */ + <2 RK_PC2 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + uart7m0_rtsn: uart7m0-rtsn { + rockchip,pins = + /* uart7m0_rtsn */ + <2 RK_PC1 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + uart7m1_xfer: uart7m1-xfer { + rockchip,pins = + /* uart7_rxm1 */ + <3 RK_PC5 4 &pcfg_pull_up>, + /* uart7_txm1 */ + <3 RK_PC4 4 &pcfg_pull_up>; + }; + + /omit-if-no-ref/ + uart7m2_xfer: uart7m2-xfer { + rockchip,pins = + /* uart7_rxm2 */ + <4 RK_PA3 4 &pcfg_pull_up>, + /* uart7_txm2 */ + <4 RK_PA2 4 &pcfg_pull_up>; + }; + }; + + uart8 { + /omit-if-no-ref/ + uart8m0_xfer: uart8m0-xfer { + rockchip,pins = + /* uart8_rxm0 */ + <2 RK_PC6 2 &pcfg_pull_up>, + /* uart8_txm0 */ + <2 RK_PC5 3 &pcfg_pull_up>; + }; + + /omit-if-no-ref/ + uart8m0_ctsn: uart8m0-ctsn { + rockchip,pins = + /* uart8m0_ctsn */ + <2 RK_PB2 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + uart8m0_rtsn: uart8m0-rtsn { + rockchip,pins = + /* uart8m0_rtsn */ + <2 RK_PB1 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + uart8m1_xfer: uart8m1-xfer { + rockchip,pins = + /* uart8_rxm1 */ + <3 RK_PA0 4 &pcfg_pull_up>, + /* uart8_txm1 */ + <2 RK_PD7 4 &pcfg_pull_up>; + }; + }; + + uart9 { + /omit-if-no-ref/ + uart9m0_xfer: uart9m0-xfer { + rockchip,pins = + /* uart9_rxm0 */ + <2 RK_PA7 3 &pcfg_pull_up>, + /* uart9_txm0 */ + <2 RK_PB0 3 &pcfg_pull_up>; + }; + + /omit-if-no-ref/ + uart9m0_ctsn: uart9m0-ctsn { + rockchip,pins = + /* uart9m0_ctsn */ + <2 RK_PC4 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + uart9m0_rtsn: uart9m0-rtsn { + rockchip,pins = + /* uart9m0_rtsn */ + <2 RK_PC3 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + uart9m1_xfer: uart9m1-xfer { + rockchip,pins = + /* uart9_rxm1 */ + <4 RK_PC6 4 &pcfg_pull_up>, + /* uart9_txm1 */ + <4 RK_PC5 4 &pcfg_pull_up>; + }; + + /omit-if-no-ref/ + uart9m2_xfer: uart9m2-xfer { + rockchip,pins = + /* uart9_rxm2 */ + <4 RK_PA5 4 &pcfg_pull_up>, + /* uart9_txm2 */ + <4 RK_PA4 4 &pcfg_pull_up>; + }; + }; + + vop { + /omit-if-no-ref/ + vopm0_pins: vopm0-pins { + rockchip,pins = + /* vop_pwmm0 */ + <0 RK_PC3 2 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + vopm1_pins: vopm1-pins { + rockchip,pins = + /* vop_pwmm1 */ + <3 RK_PC4 2 &pcfg_pull_none>; + }; + }; +}; + +/* + * This part is edited handly. + */ +&pinctrl { + spi0-hs { + /omit-if-no-ref/ + spi0m0_pins_hs: spi0m0-pins { + rockchip,pins = + /* spi0_clkm0 */ + <0 RK_PB5 2 &pcfg_pull_up_drv_level_1>, + /* spi0_misom0 */ + <0 RK_PC5 2 &pcfg_pull_up_drv_level_1>, + /* spi0_mosim0 */ + <0 RK_PB6 2 &pcfg_pull_up_drv_level_1>; + }; + + /omit-if-no-ref/ + spi0m0_cs0_hs: spi0m0-cs0 { + rockchip,pins = + /* spi0_cs0m0 */ + <0 RK_PC6 2 &pcfg_pull_up_drv_level_1>; + }; + + /omit-if-no-ref/ + spi0m0_cs1_hs: spi0m0-cs1 { + rockchip,pins = + /* spi0_cs1m0 */ + <0 RK_PC4 2 &pcfg_pull_up_drv_level_1>; + }; + + /omit-if-no-ref/ + spi0m1_pins_hs: spi0m1-pins { + rockchip,pins = + /* spi0_clkm1 */ + <2 RK_PD3 3 &pcfg_pull_up_drv_level_1>, + /* spi0_misom1 */ + <2 RK_PD0 3 &pcfg_pull_up_drv_level_1>, + /* spi0_mosim1 */ + <2 RK_PD1 3 &pcfg_pull_up_drv_level_1>; + }; + + /omit-if-no-ref/ + spi0m1_cs0_hs: spi0m1-cs0 { + rockchip,pins = + /* spi0_cs0m1 */ + <2 RK_PD2 3 &pcfg_pull_up_drv_level_1>; + }; + }; + + spi1-hs { + /omit-if-no-ref/ + spi1m0_pins_hs: spi1m0-pins { + rockchip,pins = + /* spi1_clkm0 */ + <2 RK_PB5 3 &pcfg_pull_up_drv_level_1>, + /* spi1_misom0 */ + <2 RK_PB6 3 &pcfg_pull_up_drv_level_1>, + /* spi1_mosim0 */ + <2 RK_PB7 4 &pcfg_pull_up_drv_level_1>; + }; + + /omit-if-no-ref/ + spi1m0_cs0_hs: spi1m0-cs0 { + rockchip,pins = + /* spi1_cs0m0 */ + <2 RK_PC0 4 &pcfg_pull_up_drv_level_1>; + }; + + /omit-if-no-ref/ + spi1m0_cs1_hs: spi1m0-cs1 { + rockchip,pins = + /* spi1_cs1m0 */ + <2 RK_PC6 3 &pcfg_pull_up_drv_level_1>; + }; + + /omit-if-no-ref/ + spi1m1_pins_hs: spi1m1-pins { + rockchip,pins = + /* spi1_clkm1 */ + <3 RK_PC3 3 &pcfg_pull_up_drv_level_1>, + /* spi1_misom1 */ + <3 RK_PC2 3 &pcfg_pull_up_drv_level_1>, + /* spi1_mosim1 */ + <3 RK_PC1 3 &pcfg_pull_up_drv_level_1>; + }; + + /omit-if-no-ref/ + spi1m1_cs0_hs: spi1m1-cs0 { + rockchip,pins = + /* spi1_cs0m1 */ + <3 RK_PA1 3 &pcfg_pull_up_drv_level_1>; + }; + }; + + spi2-hs { + /omit-if-no-ref/ + spi2m0_pins_hs: spi2m0-pins { + rockchip,pins = + /* spi2_clkm0 */ + <2 RK_PC1 4 &pcfg_pull_up_drv_level_1>, + /* spi2_misom0 */ + <2 RK_PC2 4 &pcfg_pull_up_drv_level_1>, + /* spi2_mosim0 */ + <2 RK_PC3 4 &pcfg_pull_up_drv_level_1>; + }; + + /omit-if-no-ref/ + spi2m0_cs0_hs: spi2m0-cs0 { + rockchip,pins = + /* spi2_cs0m0 */ + <2 RK_PC4 4 &pcfg_pull_up_drv_level_1>; + }; + + /omit-if-no-ref/ + spi2m0_cs1_hs: spi2m0-cs1 { + rockchip,pins = + /* spi2_cs1m0 */ + <2 RK_PC5 4 &pcfg_pull_up_drv_level_1>; + }; + + /omit-if-no-ref/ + spi2m1_pins_hs: spi2m1-pins { + rockchip,pins = + /* spi2_clkm1 */ + <3 RK_PA0 3 &pcfg_pull_up_drv_level_1>, + /* spi2_misom1 */ + <2 RK_PD7 3 &pcfg_pull_up_drv_level_1>, + /* spi2_mosim1 */ + <2 RK_PD6 3 &pcfg_pull_up_drv_level_1>; + }; + + /omit-if-no-ref/ + spi2m1_cs0_hs: spi2m1-cs0 { + rockchip,pins = + /* spi2_cs0m1 */ + <2 RK_PD5 3 &pcfg_pull_up_drv_level_1>; + }; + + /omit-if-no-ref/ + spi2m1_cs1_hs: spi2m1-cs1 { + rockchip,pins = + /* spi2_cs1m1 */ + <2 RK_PD4 3 &pcfg_pull_up_drv_level_1>; + }; + }; + + spi3-hs { + /omit-if-no-ref/ + spi3m0_pins_hs: spi3m0-pins { + rockchip,pins = + /* spi3_clkm0 */ + <4 RK_PB3 4 &pcfg_pull_up_drv_level_1>, + /* spi3_misom0 */ + <4 RK_PB0 4 &pcfg_pull_up_drv_level_1>, + /* spi3_mosim0 */ + <4 RK_PB2 4 &pcfg_pull_up_drv_level_1>; + }; + + /omit-if-no-ref/ + spi3m0_cs0_hs: spi3m0-cs0 { + rockchip,pins = + /* spi3_cs0m0 */ + <4 RK_PA6 4 &pcfg_pull_up_drv_level_1>; + }; + + /omit-if-no-ref/ + spi3m0_cs1_hs: spi3m0-cs1 { + rockchip,pins = + /* spi3_cs1m0 */ + <4 RK_PA7 4 &pcfg_pull_up_drv_level_1>; + }; + + /omit-if-no-ref/ + spi3m1_pins_hs: spi3m1-pins { + rockchip,pins = + /* spi3_clkm1 */ + <4 RK_PC2 2 &pcfg_pull_up_drv_level_1>, + /* spi3_misom1 */ + <4 RK_PC5 2 &pcfg_pull_up_drv_level_1>, + /* spi3_mosim1 */ + <4 RK_PC3 2 &pcfg_pull_up_drv_level_1>; + }; + + /omit-if-no-ref/ + spi3m1_cs0_hs: spi3m1-cs0 { + rockchip,pins = + /* spi3_cs0m1 */ + <4 RK_PC6 2 &pcfg_pull_up_drv_level_1>; + }; + + /omit-if-no-ref/ + spi3m1_cs1_hs: spi3m1-cs1 { + rockchip,pins = + /* spi3_cs1m1 */ + <4 RK_PD1 2 &pcfg_pull_up_drv_level_1>; + }; + }; + + gmac-txd-level3 { + /omit-if-no-ref/ + gmac0_tx_bus2_level3: gmac0-tx-bus2-level3 { + rockchip,pins = + /* gmac0_txd0 */ + <2 RK_PB3 1 &pcfg_pull_none_drv_level_3>, + /* gmac0_txd1 */ + <2 RK_PB4 1 &pcfg_pull_none_drv_level_3>, + /* gmac0_txen */ + <2 RK_PB5 1 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + gmac0_rgmii_bus_level3: gmac0-rgmii-bus-level3 { + rockchip,pins = + /* gmac0_rxd2 */ + <2 RK_PA3 2 &pcfg_pull_none>, + /* gmac0_rxd3 */ + <2 RK_PA4 2 &pcfg_pull_none>, + /* gmac0_txd2 */ + <2 RK_PA6 2 &pcfg_pull_none_drv_level_3>, + /* gmac0_txd3 */ + <2 RK_PA7 2 &pcfg_pull_none_drv_level_3>; + }; + + /omit-if-no-ref/ + gmac1m0_tx_bus2_level3: gmac1m0-tx-bus2-level3 { + rockchip,pins = + /* gmac1_txd0m0 */ + <3 RK_PB5 3 &pcfg_pull_none_drv_level_3>, + /* gmac1_txd1m0 */ + <3 RK_PB6 3 &pcfg_pull_none_drv_level_3>, + /* gmac1_txenm0 */ + <3 RK_PB7 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + gmac1m0_rgmii_bus_level3: gmac1m0-rgmii-bus-level3 { + rockchip,pins = + /* gmac1_rxd2m0 */ + <3 RK_PA4 3 &pcfg_pull_none>, + /* gmac1_rxd3m0 */ + <3 RK_PA5 3 &pcfg_pull_none>, + /* gmac1_txd2m0 */ + <3 RK_PA2 3 &pcfg_pull_none_drv_level_3>, + /* gmac1_txd3m0 */ + <3 RK_PA3 3 &pcfg_pull_none_drv_level_3>; + }; + + /omit-if-no-ref/ + gmac1m1_tx_bus2_level3: gmac1m1-tx-bus2-level3 { + rockchip,pins = + /* gmac1_txd0m1 */ + <4 RK_PA4 3 &pcfg_pull_none_drv_level_3>, + /* gmac1_txd1m1 */ + <4 RK_PA5 3 &pcfg_pull_none_drv_level_3>, + /* gmac1_txenm1 */ + <4 RK_PA6 3 &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + gmac1m1_rgmii_bus_level3: gmac1m1-rgmii-bus-level3 { + rockchip,pins = + /* gmac1_rxd2m1 */ + <4 RK_PA1 3 &pcfg_pull_none>, + /* gmac1_rxd3m1 */ + <4 RK_PA2 3 &pcfg_pull_none>, + /* gmac1_txd2m1 */ + <3 RK_PD6 3 &pcfg_pull_none_drv_level_3>, + /* gmac1_txd3m1 */ + <3 RK_PD7 3 &pcfg_pull_none_drv_level_3>; + }; + }; + + gmac-txc-level2 { + /omit-if-no-ref/ + gmac0_rgmii_clk_level2: gmac0-rgmii-clk-level2 { + rockchip,pins = + /* gmac0_rxclk */ + <2 RK_PA5 2 &pcfg_pull_none>, + /* gmac0_txclk */ + <2 RK_PB0 2 &pcfg_pull_none_drv_level_2>; + }; + + /omit-if-no-ref/ + gmac1m0_rgmii_clk_level2: gmac1m0-rgmii-clk-level2 { + rockchip,pins = + /* gmac1_rxclkm0 */ + <3 RK_PA7 3 &pcfg_pull_none>, + /* gmac1_txclkm0 */ + <3 RK_PA6 3 &pcfg_pull_none_drv_level_2>; + }; + + /omit-if-no-ref/ + gmac1m1_rgmii_clk_level2: gmac1m1-rgmii-clk-level2 { + rockchip,pins = + /* gmac1_rxclkm1 */ + <4 RK_PA3 3 &pcfg_pull_none>, + /* gmac1_txclkm1 */ + <4 RK_PA0 3 &pcfg_pull_none_drv_level_2>; + }; + }; + + tsadc { + /omit-if-no-ref/ + tsadc_pin: tsadc-pin { + rockchip,pins = + /* tsadc_pin */ + <0 RK_PA1 0 &pcfg_pull_none>; + }; + }; +}; diff --git a/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-r66s.dts b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-r66s.dts new file mode 100644 index 00000000..60733c12 --- /dev/null +++ b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-r66s.dts @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +/dts-v1/; + +#include "rk3568-fastrhino.dtsi" + +/ { + model = "FastRhino R66S"; + compatible = "fastrhino,r66s", "rockchip,rk3568"; + + aliases { + mmc0 = &sdmmc0; + }; +}; + +&sdmmc0 { + bus-width = <4>; + cap-sd-highspeed; + cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>; + disable-wp; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc0_bus4 &sdmmc0_clk &sdmmc0_cmd &sdmmc0_det>; + vmmc-supply = <&vcc3v3_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; diff --git a/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-r68s.dts b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-r68s.dts new file mode 100644 index 00000000..020b7f01 --- /dev/null +++ b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-r68s.dts @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +/dts-v1/; + +#include "rk3568-fastrhino.dtsi" + +/ { + model = "FastRhino R68S"; + compatible = "fastrhino,r68s", "rockchip,rk3568"; + + aliases { + ethernet0 = &gmac0; + ethernet1 = &gmac1; + mmc0 = &sdhci; + }; +}; + +&gmac0 { + assigned-clocks = <&cru SCLK_GMAC0_RX_TX>, <&cru SCLK_GMAC0>; + assigned-clock-parents = <&cru SCLK_GMAC0_RGMII_SPEED>; + assigned-clock-rates = <0>, <125000000>; + clock_in_out = "output"; + phy-mode = "rgmii-id"; + pinctrl-names = "default"; + pinctrl-0 = <&gmac0_miim + &gmac0_tx_bus2 + &gmac0_rx_bus2 + &gmac0_rgmii_clk + &gmac0_rgmii_bus>; + snps,reset-gpio = <&gpio1 RK_PB0 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + /* Reset time is 20ms, 100ms for rtl8211f */ + snps,reset-delays-us = <0 20000 100000>; + tx_delay = <0x3c>; + rx_delay = <0x2f>; + phy-handle = <&rgmii_phy0>; + status = "okay"; +}; + +&gmac1 { + assigned-clocks = <&cru SCLK_GMAC1_RX_TX>, <&cru SCLK_GMAC1>; + assigned-clock-parents = <&cru SCLK_GMAC1_RGMII_SPEED>; + assigned-clock-rates = <0>, <125000000>; + clock_in_out = "output"; + phy-mode = "rgmii-id"; + pinctrl-names = "default"; + pinctrl-0 = <&gmac1m1_miim + &gmac1m1_tx_bus2 + &gmac1m1_rx_bus2 + &gmac1m1_rgmii_clk + &gmac1m1_rgmii_bus>; + snps,reset-gpio = <&gpio1 RK_PB1 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + /* Reset time is 20ms, 100ms for rtl8211f */ + snps,reset-delays-us = <0 20000 100000>; + tx_delay = <0x4f>; + rx_delay = <0x26>; + phy-handle = <&rgmii_phy1>; + status = "okay"; +}; + +&mdio0 { + rgmii_phy0: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0x0>; + }; +}; + +&mdio1 { + rgmii_phy1: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0x0>; + }; +}; + +&sdhci { + bus-width = <8>; + max-frequency = <200000000>; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_datastrobe>; + status = "okay"; +}; diff --git a/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-roc-pc.dts b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-roc-pc.dts new file mode 100644 index 00000000..8e1fc8ac --- /dev/null +++ b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-roc-pc.dts @@ -0,0 +1,797 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +/dts-v1/; +#include +#include +#include +#include +#include "rk3568.dtsi" + +/ { + model = "Firefly Station P2"; + compatible = "firefly,rk3568-roc-pc", "rockchip,rk3568"; + + aliases { + ethernet0 = &gmac0; + ethernet1 = &gmac1; + mmc0 = &sdmmc0; + mmc1 = &sdhci; + }; + + chosen: chosen { + stdout-path = "serial2:1500000n8"; + }; + +#ifdef DTS_NO_LEGACY + hdmi-con { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con_in: endpoint { + remote-endpoint = <&hdmi_out_con>; + }; + }; + }; +#endif + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_work_en>, <&led_user_en>; + + led-work { + label = "blue:work"; + gpios = <&gpio1 RK_PB2 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + + }; + + led-user { + label = "yellow:user"; + gpios = <&gpio1 RK_PB1 GPIO_ACTIVE_HIGH>; + }; + }; + + rk809-sound { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; + simple-audio-card,name = "Analog RK809"; + simple-audio-card,mclk-fs = <256>; + + simple-audio-card,cpu { + sound-dai = <&i2s1_8ch>; + }; + simple-audio-card,codec { + sound-dai = <&rk809>; + }; + }; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + clocks = <&rk809 1>; + clock-names = "ext_clock"; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_enable_h>; + reset-gpios = <&gpio3 RK_PD5 GPIO_ACTIVE_LOW>; + post-power-on-delay-ms = <100>; + }; + + dc_12v: dc-12v { + compatible = "regulator-fixed"; + regulator-name = "dc_12v"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + }; + + vcc3v3_sys: vcc3v3-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&dc_12v>; + }; + + vcc5v0_sys: vcc5v0-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&dc_12v>; + }; + + vcc5v0_usb: vcc5v0-usb { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_usb"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&dc_12v>; + }; + + pcie30_avdd0v9: pcie30-avdd0v9 { + compatible = "regulator-fixed"; + regulator-name = "pcie30_avdd0v9"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + vin-supply = <&vcc3v3_sys>; + }; + + pcie30_avdd1v8: pcie30-avdd1v8 { + compatible = "regulator-fixed"; + regulator-name = "pcie30_avdd1v8"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&vcc3v3_sys>; + }; + + pcie_pi6c_oe: pcie-pi6c-oe { + compatible = "regulator-fixed"; + regulator-name = "pcie_pi6c_oe_en"; + regulator-always-on; + gpio = <&gpio3 RK_PA7 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie_pi6c_oe_en>; + }; + + vcc3v3_pcie: vcc3v3_pi6c: vcc3v3-pcie { + compatible = "regulator-fixed"; + regulator-always-on; + enable-active-high; + gpio = <&gpio0 RK_PD4 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie_enable_h>; + regulator-name = "vcc3v3_pcie"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc5v0_host: vcc5v0-host { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_host"; + enable-active-high; + gpio = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_host_en>; + regulator-always-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_usb>; + }; + + vcc5v0_otg: vcc5v0-otg { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_otg"; + enable-active-high; + gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_otg_en>; + vin-supply = <&vcc5v0_usb>; + }; + + vcc_hub_reset: vcc-hub-reset { + compatible = "regulator-fixed"; + regulator-name = "vcc_hub_reset"; + regulator-always-on; + enable-active-high; + gpio = <&gpio1 RK_PA4 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc_hub_reset_en>; + }; + + vcc3v3_lcd0_n: vcc3v3-lcd0-n { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_lcd0_n"; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_lcd1_n: vcc3v3-lcd1-n { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_lcd1_n"; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&combphy0 { + status = "okay"; +}; + +&combphy1 { + status = "okay"; +}; + +&combphy2 { + status = "okay"; +}; + +&cpu0 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu1 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu2 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu3 { + cpu-supply = <&vdd_cpu>; +}; + +&gmac0 { + phy-mode = "rgmii"; + clock_in_out = "output"; + + snps,reset-gpio = <&gpio2 RK_PD3 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + /* Reset time is 20ms, 100ms for rtl8211f */ + snps,reset-delays-us = <0 20000 100000>; + + assigned-clocks = <&cru SCLK_GMAC0_RX_TX>, <&cru SCLK_GMAC0>; + assigned-clock-parents = <&cru SCLK_GMAC0_RGMII_SPEED>; + assigned-clock-rates = <0>, <125000000>; + + pinctrl-names = "default"; + pinctrl-0 = <&gmac0_miim + &gmac0_tx_bus2 + &gmac0_rx_bus2 + &gmac0_rgmii_clk + &gmac0_rgmii_bus + &gmac0_clkinout>; + + tx_delay = <0x3c>; + rx_delay = <0x2f>; + + phy-handle = <&rgmii_phy0>; + status = "okay"; +}; + +&gmac1 { + phy-mode = "rgmii"; + clock_in_out = "output"; + + snps,reset-gpio = <&gpio2 RK_PD1 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + /* Reset time is 20ms, 100ms for rtl8211f */ + snps,reset-delays-us = <0 20000 100000>; + + assigned-clocks = <&cru SCLK_GMAC1_RX_TX>, <&cru SCLK_GMAC1>; + assigned-clock-parents = <&cru SCLK_GMAC1_RGMII_SPEED>; + assigned-clock-rates = <0>, <125000000>; + + pinctrl-names = "default"; + pinctrl-0 = <&gmac1m1_miim + &gmac1m1_tx_bus2 + &gmac1m1_rx_bus2 + &gmac1m1_rgmii_clk + &gmac1m1_rgmii_bus + &gmac1m1_clkinout>; + + tx_delay = <0x4f>; + rx_delay = <0x26>; + + phy-handle = <&rgmii_phy1>; + status = "okay"; +}; + +#ifdef DTS_NO_LEGACY +&gpu { + mali-supply = <&vdd_gpu>; + status = "okay"; +}; + +&hdmi { + avdd-0v9-supply = <&vdda0v9_image>; + avdd-1v8-supply = <&vcca1v8_image>; + status = "okay"; +}; + +&hdmi_in { + hdmi_in_vp0: endpoint { + remote-endpoint = <&vp0_out_hdmi>; + }; +}; + +&hdmi_out { + hdmi_out_con: endpoint { + remote-endpoint = <&hdmi_con_in>; + }; +}; + +&hdmi_sound { + status = "okay"; +}; +#endif + +&i2c0 { + status = "okay"; + + vdd_cpu: regulator@1c { + compatible = "tcs,tcs4525"; + reg = <0x1c>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1150000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + rk809: pmic@20 { + compatible = "rockchip,rk809"; + reg = <0x20>; + interrupt-parent = <&gpio0>; + interrupts = ; + assigned-clocks = <&cru I2S1_MCLKOUT_TX>; + assigned-clock-parents = <&cru CLK_I2S1_8CH_TX>; + #clock-cells = <1>; + clock-names = "mclk"; + clocks = <&cru I2S1_MCLKOUT_TX>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>; + rockchip,system-power-controller; + #sound-dai-cells = <0>; + vcc1-supply = <&vcc3v3_sys>; + vcc2-supply = <&vcc3v3_sys>; + vcc3-supply = <&vcc3v3_sys>; + vcc4-supply = <&vcc3v3_sys>; + vcc5-supply = <&vcc3v3_sys>; + vcc6-supply = <&vcc3v3_sys>; + vcc7-supply = <&vcc3v3_sys>; + vcc8-supply = <&vcc3v3_sys>; + vcc9-supply = <&vcc3v3_sys>; + wakeup-source; + + regulators { + vdd_logic: DCDC_REG1 { + regulator-name = "vdd_logic"; + regulator-always-on; + regulator-boot-on; + regulator-init-microvolt = <900000>; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_gpu: DCDC_REG2 { + regulator-name = "vdd_gpu"; + regulator-always-on; + regulator-init-microvolt = <900000>; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + regulator-initial-mode = <0x2>; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vdd_npu: DCDC_REG4 { + regulator-name = "vdd_npu"; + regulator-init-microvolt = <900000>; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8: DCDC_REG5 { + regulator-name = "vcc_1v8"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda0v9_image: LDO_REG1 { + regulator-name = "vdda0v9_image"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda_0v9: LDO_REG2 { + regulator-name = "vdda_0v9"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda0v9_pmu: LDO_REG3 { + regulator-name = "vdda0v9_pmu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <900000>; + }; + }; + + vccio_acodec: LDO_REG4 { + regulator-name = "vccio_acodec"; + regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vccio_sd: LDO_REG5 { + regulator-name = "vccio_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_pmu: LDO_REG6 { + regulator-name = "vcc3v3_pmu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcca_1v8: LDO_REG7 { + regulator-name = "vcca_1v8"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcca1v8_pmu: LDO_REG8 { + regulator-name = "vcca1v8_pmu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcca1v8_image: LDO_REG9 { + regulator-name = "vcca1v8_image"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v3: SWITCH_REG1 { + regulator-name = "vcc_3v3"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_sd: SWITCH_REG2 { + regulator-name = "vcc3v3_sd"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; +}; + +#ifdef DTS_NO_LEGACY +&i2s0_8ch { + status = "okay"; +}; +#endif + +&i2s1_8ch { + rockchip,trcm-sync-tx-only; + status = "okay"; +}; + +&mdio0 { + rgmii_phy0: phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0x0>; + }; +}; + +&mdio1 { + rgmii_phy1: phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0x0>; + }; +}; + +&pinctrl { + leds { + led_work_en: led_work_en { + rockchip,pins = <1 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + led_user_en: led_user_en { + rockchip,pins = <1 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + sdio-pwrseq { + wifi_enable_h: wifi-enable-h { + rockchip,pins = <3 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + usb { + vcc5v0_host_en: vcc5v0-host-en { + rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + vcc5v0_otg_en: vcc5v0-otg-en { + rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + vcc_hub_reset_en: vcc-hub-reset-en { + rockchip,pins = <1 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + fusb0_int { + fusb0_int: fusb0-int { + rockchip,pins = <0 RK_PC1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + pcie { + pcie_enable_h: pcie-enable-h { + rockchip,pins = <0 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pcie_reset_h: pcie-reset-h { + rockchip,pins = <2 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pcie_pi6c_oe_en: pcie-pi6c-oe-en { + rockchip,pins = <3 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + pmic_int: pmic_int { + rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; + +&pcie30phy { + phy-supply = <&pcie_pi6c_oe>; + status = "okay"; +}; + +&pcie3x2 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie_reset_h>; + reset-gpios = <&gpio2 RK_PD6 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie>; + status = "okay"; +}; + +&pmu_io_domains { + pmuio1-supply = <&vcc3v3_pmu>; + pmuio2-supply = <&vcc3v3_pmu>; + vccio1-supply = <&vccio_acodec>; + vccio2-supply = <&vcc_1v8>; + vccio3-supply = <&vccio_sd>; + vccio4-supply = <&vcc_1v8>; + vccio5-supply = <&vcc_3v3>; + vccio6-supply = <&vcc_1v8>; + vccio7-supply = <&vcc_3v3>; + status = "okay"; +}; + +&rng { + status = "okay"; +}; + +&saradc { + vref-supply = <&vcca_1v8>; + status = "okay"; +}; + +&sata2 { + status = "okay"; +}; + +&sdhci { + bus-width = <8>; + max-frequency = <200000000>; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_datastrobe>; + status = "okay"; +}; + +&sdmmc0 { + bus-width = <4>; + cap-sd-highspeed; + cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>; + disable-wp; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc0_bus4 &sdmmc0_clk &sdmmc0_cmd &sdmmc0_det>; + sd-uhs-sdr104; + vmmc-supply = <&vcc3v3_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&sdmmc2 { + max-frequency = <150000000>; + supports-sdio; + bus-width = <4>; + disable-wp; + cap-sd-highspeed; + cap-sdio-irq; + keep-power-in-suspend; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc2m0_bus4 &sdmmc2m0_cmd &sdmmc2m0_clk>; + sd-uhs-sdr104; + mmc-pwrseq = <&sdio_pwrseq>; + non-removable; + status = "okay"; +}; + +&tsadc { + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&usb2phy0_host { + phy-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&usb2phy1_host { + phy-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&usb2phy1_otg { + phy-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&usb2phy0 { + status = "okay"; +}; + +&usb2phy1 { + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb_host0_xhci { + extcon = <&usb2phy0>; + status = "okay"; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +&usb_host1_xhci { + status = "okay"; +}; + +#ifdef DTS_NO_LEGACY +&vop { + assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>; + assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>; + status = "okay"; +}; + +&vop_mmu { + status = "okay"; +}; + +&vp0 { + vp0_out_hdmi: endpoint@ROCKCHIP_VOP2_EP_HDMI0 { + reg = ; + remote-endpoint = <&hdmi_in_vp0>; + }; +}; +#endif diff --git a/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts new file mode 100644 index 00000000..af2f3a5b --- /dev/null +++ b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts @@ -0,0 +1,766 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +/dts-v1/; +#include +#include +#include +#include +#include "rk3568.dtsi" + +/ { + model = "Radxa ROCK3 Model A"; + compatible = "radxa,rock3a", "rockchip,rk3568"; + + aliases { + ethernet0 = &gmac1; + mmc0 = &sdmmc0; + mmc1 = &sdhci; + }; + + chosen: chosen { + stdout-path = "serial2:1500000n8"; + }; + +#ifdef DTS_NO_LEGACY + hdmi-con { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con_in: endpoint { + remote-endpoint = <&hdmi_out_con>; + }; + }; + }; +#endif + + leds { + compatible = "gpio-leds"; + + led_user: led-0 { + gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>; + function = LED_FUNCTION_HEARTBEAT; + color = ; + linux,default-trigger = "heartbeat"; + pinctrl-names = "default"; + pinctrl-0 = <&led_user_en>; + }; + }; + + rk809-sound { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; + simple-audio-card,name = "Analog RK809"; + simple-audio-card,mclk-fs = <256>; + + simple-audio-card,cpu { + sound-dai = <&i2s1_8ch>; + }; + + simple-audio-card,codec { + sound-dai = <&rk809>; + }; + }; + + vcc12v_dcin: vcc12v-dcin { + compatible = "regulator-fixed"; + regulator-name = "vcc12v_dcin"; + regulator-always-on; + regulator-boot-on; + }; + + vcc3v3_sys: vcc3v3-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc12v_dcin>; + }; + + vcc5v0_sys: vcc5v0-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc12v_dcin>; + }; + + vcc5v0_usb: vcc5v0-usb { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_usb"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc12v_dcin>; + }; + + vcc5v0_usb_host: vcc5v0-usb-host { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_usb_host_en>; + regulator-name = "vcc5v0_usb_host"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_usb>; + }; + + vcc5v0_usb_hub: vcc5v0-usb-hub { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio0 RK_PD5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_usb_hub_en>; + regulator-name = "vcc5v0_usb_hub"; + regulator-always-on; + vin-supply = <&vcc5v0_usb>; + }; + + vcc5v0_usb_otg: vcc5v0-usb-otg { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_usb_otg_en>; + regulator-name = "vcc5v0_usb_otg"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_usb>; + }; + + pcie30_avdd0v9: pcie30-avdd0v9 { + compatible = "regulator-fixed"; + regulator-name = "pcie30_avdd0v9"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + vin-supply = <&vcc3v3_sys>; + }; + + pcie30_avdd1v8: pcie30-avdd1v8 { + compatible = "regulator-fixed"; + regulator-name = "pcie30_avdd1v8"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&vcc3v3_sys>; + }; + + /* pi6c pcie clock generator */ + vcc3v3_pi6c_03: vcc3v3-pi6c-03 { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_pi6c_03"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc3v3_pcie: vcc3v3-pcie { + compatible = "regulator-fixed"; + enable-active-high; + gpios = <&gpio0 RK_PD4 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie_enable_h>; + regulator-name = "vcc3v3_pcie"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc_cam: vcc-cam { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio1 RK_PB1 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc_cam_en>; + regulator-name = "vcc_cam"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc3v3_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_mipi: vcc-mipi { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio3 RK_PC0 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc_mipi_en>; + regulator-name = "vcc_mipi"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc3v3_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&combphy0 { + status = "okay"; +}; + +&combphy1 { + status = "okay"; +}; + +&combphy2 { + status = "okay"; +}; + +&cpu0 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu1 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu2 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu3 { + cpu-supply = <&vdd_cpu>; +}; + +&gmac1 { + assigned-clocks = <&cru SCLK_GMAC1_RX_TX>, <&cru SCLK_GMAC1>; + assigned-clock-parents = <&cru SCLK_GMAC1_RGMII_SPEED>; + assigned-clock-rates = <0>, <125000000>; + clock_in_out = "output"; + phy-handle = <&rgmii_phy1>; + phy-mode = "rgmii-id"; + pinctrl-names = "default"; + pinctrl-0 = <&gmac1m1_miim + &gmac1m1_tx_bus2 + &gmac1m1_rx_bus2 + &gmac1m1_rgmii_clk + &gmac1m1_rgmii_bus>; + snps,reset-gpio = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + /* Reset time is 20ms, 100ms for rtl8211f */ + snps,reset-delays-us = <0 20000 100000>; + tx_delay = <0x42>; + rx_delay = <0x28>; + status = "okay"; +}; + +#ifdef DTS_NO_LEGACY +&gpu { + mali-supply = <&vdd_gpu>; + status = "okay"; +}; + +&hdmi { + avdd-0v9-supply = <&vdda0v9_image>; + avdd-1v8-supply = <&vcca1v8_image>; + status = "okay"; +}; + +&hdmi_in { + hdmi_in_vp0: endpoint { + remote-endpoint = <&vp0_out_hdmi>; + }; +}; + +&hdmi_out { + hdmi_out_con: endpoint { + remote-endpoint = <&hdmi_con_in>; + }; +}; + +&hdmi_sound { + status = "okay"; +}; +#endif + +&i2c0 { + status = "okay"; + + vdd_cpu: regulator@1c { + compatible = "tcs,tcs4525"; + reg = <0x1c>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1150000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + rk809: pmic@20 { + compatible = "rockchip,rk809"; + reg = <0x20>; + interrupt-parent = <&gpio0>; + interrupts = ; + assigned-clocks = <&cru I2S1_MCLKOUT_TX>; + assigned-clock-parents = <&cru CLK_I2S1_8CH_TX>; + #clock-cells = <1>; + clock-names = "mclk"; + clocks = <&cru I2S1_MCLKOUT_TX>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>, <&i2s1m0_mclk>; + rockchip,system-power-controller; + #sound-dai-cells = <0>; + wakeup-source; + + vcc1-supply = <&vcc3v3_sys>; + vcc2-supply = <&vcc3v3_sys>; + vcc3-supply = <&vcc3v3_sys>; + vcc4-supply = <&vcc3v3_sys>; + vcc5-supply = <&vcc3v3_sys>; + vcc6-supply = <&vcc3v3_sys>; + vcc7-supply = <&vcc3v3_sys>; + vcc8-supply = <&vcc3v3_sys>; + vcc9-supply = <&vcc3v3_sys>; + + regulators { + vdd_logic: DCDC_REG1 { + regulator-name = "vdd_logic"; + regulator-always-on; + regulator-boot-on; + regulator-init-microvolt = <900000>; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_gpu: DCDC_REG2 { + regulator-name = "vdd_gpu"; + regulator-always-on; + regulator-init-microvolt = <900000>; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + regulator-initial-mode = <0x2>; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vdd_npu: DCDC_REG4 { + regulator-name = "vdd_npu"; + regulator-init-microvolt = <900000>; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8: DCDC_REG5 { + regulator-name = "vcc_1v8"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda0v9_image: LDO_REG1 { + regulator-name = "vdda0v9_image"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda_0v9: LDO_REG2 { + regulator-name = "vdda_0v9"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda0v9_pmu: LDO_REG3 { + regulator-name = "vdda0v9_pmu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <900000>; + }; + }; + + vccio_acodec: LDO_REG4 { + regulator-name = "vccio_acodec"; + regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vccio_sd: LDO_REG5 { + regulator-name = "vccio_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_pmu: LDO_REG6 { + regulator-name = "vcc3v3_pmu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcca_1v8: LDO_REG7 { + regulator-name = "vcca_1v8"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcca1v8_pmu: LDO_REG8 { + regulator-name = "vcca1v8_pmu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcca1v8_image: LDO_REG9 { + regulator-name = "vcca1v8_image"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v3: SWITCH_REG1 { + regulator-name = "vcc_3v3"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_sd: SWITCH_REG2 { + regulator-name = "vcc3v3_sd"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + + codec { + mic-in-differential; + }; + }; +}; + +&i2c5 { + status = "okay"; + + hym8563: hym8563@51 { + compatible = "haoyu,hym8563"; + reg = <0x51>; + interrupt-parent = <&gpio0>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&hym8563_int>; + }; +}; + +#ifdef DTS_NO_LEGACY +&i2s0_8ch { + status = "okay"; +}; +#endif + +&i2s1_8ch { + rockchip,trcm-sync-tx-only; + status = "okay"; +}; + +&mdio1 { + rgmii_phy1: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0x0>; + }; +}; + +&pcie2x1 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie_reset_h>; + reset-gpios = <&gpio3 RK_PC1 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie>; + status = "okay"; +}; + +&pcie30phy { + phy-supply = <&vcc3v3_pi6c_03>; + status = "okay"; +}; + +&pcie3x2 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie30x2m1_pins>; + reset-gpios = <&gpio2 RK_PD6 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie>; + status = "okay"; +}; + +&pinctrl { + cam { + vcc_cam_en: vcc_cam_en { + rockchip,pins = <1 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + display { + vcc_mipi_en: vcc_mipi_en { + rockchip,pins = <3 RK_PC0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + hym8563 { + hym8563_int: hym8563-int { + rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + leds { + led_user_en: led_user_en { + rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pcie { + pcie_enable_h: pcie-enable-h { + rockchip,pins = <0 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pcie_reset_h: pcie-reset-h { + rockchip,pins = <3 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + pmic_int: pmic_int { + rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + usb { + vcc5v0_usb_host_en: vcc5v0_usb_host_en { + rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + vcc5v0_usb_hub_en: vcc5v0_usb_hub_en { + rockchip,pins = <0 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + vcc5v0_usb_otg_en: vcc5v0_usb_otg_en { + rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pmu_io_domains { + pmuio1-supply = <&vcc3v3_pmu>; + pmuio2-supply = <&vcc3v3_pmu>; + vccio1-supply = <&vccio_acodec>; + vccio2-supply = <&vcc_1v8>; + vccio3-supply = <&vccio_sd>; + vccio4-supply = <&vcc_1v8>; + vccio5-supply = <&vcc_3v3>; + vccio6-supply = <&vcc_1v8>; + vccio7-supply = <&vcc_3v3>; + status = "okay"; +}; + +&rng { + status = "okay"; +}; + +&saradc { + vref-supply = <&vcca_1v8>; + status = "okay"; +}; + +&sdhci { + bus-width = <8>; + max-frequency = <200000000>; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_datastrobe>; + vmmc-supply = <&vcc_3v3>; + vqmmc-supply = <&vcc_1v8>; + status = "okay"; +}; + +&sdmmc0 { + bus-width = <4>; + cap-sd-highspeed; + cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>; + disable-wp; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc0_bus4 &sdmmc0_clk &sdmmc0_cmd &sdmmc0_det>; + sd-uhs-sdr104; + vmmc-supply = <&vcc3v3_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&tsadc { + rockchip,hw-tshut-mode = <1>; + rockchip,hw-tshut-polarity = <0>; + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb_host0_xhci { + status = "okay"; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +&usb_host1_xhci { + status = "okay"; +}; + +&usb2phy0 { + status = "okay"; +}; + +&usb2phy0_host { + phy-supply = <&vcc5v0_usb_host>; + status = "okay"; +}; + +&usb2phy0_otg { + phy-supply = <&vcc5v0_usb_otg>; + status = "okay"; +}; + +&usb2phy1 { + status = "okay"; +}; + +&usb2phy1_host { + phy-supply = <&vcc5v0_usb_host>; + status = "okay"; +}; + +&usb2phy1_otg { + phy-supply = <&vcc5v0_usb_host>; + status = "okay"; +}; + +#ifdef DTS_NO_LEGACY +&vop { + assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>; + assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>; + status = "okay"; +}; + +&vop_mmu { + status = "okay"; +}; + +&vp0 { + vp0_out_hdmi: endpoint@ROCKCHIP_VOP2_EP_HDMI0 { + reg = ; + remote-endpoint = <&hdmi_in_vp0>; + }; +}; +#endif diff --git a/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-rock-pi-e25.dts b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-rock-pi-e25.dts new file mode 100644 index 00000000..1e24f5b3 --- /dev/null +++ b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-rock-pi-e25.dts @@ -0,0 +1,630 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +// Copyright (c) 2022 AmadeusGhost + +/dts-v1/; +#include +#include +#include +#include "rk3568.dtsi" + +/ { + model = "Radxa ROCK Pi E25"; + compatible = "radxa,rockpi-e25", "rockchip,rk3568"; + + aliases { + mmc0 = &sdmmc0; + mmc1 = &sdhci; + }; + + chosen: chosen { + stdout-path = "serial2:1500000n8"; + }; + + gpio-leds { + compatible = "gpio-leds"; + + led_user: led-0 { + gpios = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>; + function = LED_FUNCTION_HEARTBEAT; + color = ; + linux,default-trigger = "heartbeat"; + pinctrl-names = "default"; + pinctrl-0 = <&led_user_en>; + }; + }; + + pwm-leds { + compatible = "pwm-leds-multicolor"; + + multi-led { + color = ; + max-brightness = <255>; + + led-red { + color = ; + pwms = <&pwm1 0 1000000 0>; + }; + + led-green { + color = ; + pwms = <&pwm2 0 1000000 0>; + }; + + led-blue { + color = ; + pwms = <&pwm12 0 1000000 0>; + }; + }; + }; + + typec_5v: typec-5v { + compatible = "regulator-fixed"; + regulator-name = "typec_5v"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + pcie30_avdd0v9: pcie30-avdd0v9 { + compatible = "regulator-fixed"; + regulator-name = "pcie30_avdd0v9"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + vin-supply = <&vcc3v3_sys>; + }; + + pcie30_avdd1v8: pcie30-avdd1v8 { + compatible = "regulator-fixed"; + regulator-name = "pcie30_avdd1v8"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&vcc3v3_sys>; + }; + + /* actually fed by vcc5v0_sys, dependent + * on pi6c clock generator + */ + vcc3v3_pcie30x1: vcc3v3-pcie30x1 { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie30x1_enable_h>; + regulator-name = "vcc3v3_pcie30x1"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc3v3_pi6c_05>; + }; + + vcc3v3_pi6c_05: vcc3v3-pi6c-05 { + compatible = "regulator-fixed"; + enable-active-high; + gpios = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie_enable_h>; + regulator-name = "vcc3v3_pcie"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc3v3_minipcie: vcc3v3-minipcie { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio3 RK_PA7 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&minipcie_enable_h>; + regulator-name = "vcc3v3_minipcie"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc3v3_ngff: vcc3v3-ngff { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&ngffpcie_enable_h>; + regulator-name = "vcc3v3_ngff"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc3v3_sys: vcc3v3-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&typec_5v>; + }; + + vcc5v0_sys: vcc5v0-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&typec_5v>; + }; + + vcc5v0_usb_otg: vcc5v0-usb-otg { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_usb_otg_en>; + regulator-name = "vcc5v0_usb_otg"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_sys>; + }; +}; + +&combphy0 { + status = "okay"; +}; + +&combphy2 { + status = "okay"; +}; + +&cpu0 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu1 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu2 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu3 { + cpu-supply = <&vdd_cpu>; +}; + +#ifdef DTS_NO_LEGACY +&display_subsystem { + status = "disabled"; +}; + +&gpu { + mali-supply = <&vdd_gpu>; + status = "okay"; +}; +#endif + +&i2c0 { + status = "okay"; + + vdd_cpu: regulator@1c { + compatible = "tcs,tcs4525"; + reg = <0x1c>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1150000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + rk809: pmic@20 { + compatible = "rockchip,rk809"; + reg = <0x20>; + interrupt-parent = <&gpio0>; + interrupts = ; + #clock-cells = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>; + rockchip,system-power-controller; + wakeup-source; + + vcc1-supply = <&vcc3v3_sys>; + vcc2-supply = <&vcc3v3_sys>; + vcc3-supply = <&vcc3v3_sys>; + vcc4-supply = <&vcc3v3_sys>; + vcc5-supply = <&vcc3v3_sys>; + vcc6-supply = <&vcc3v3_sys>; + vcc7-supply = <&vcc3v3_sys>; + vcc8-supply = <&vcc3v3_sys>; + vcc9-supply = <&vcc3v3_sys>; + + regulators { + vdd_logic: DCDC_REG1 { + regulator-name = "vdd_logic"; + regulator-always-on; + regulator-boot-on; + regulator-init-microvolt = <900000>; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_gpu: DCDC_REG2 { + regulator-name = "vdd_gpu"; + regulator-always-on; + regulator-init-microvolt = <900000>; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + regulator-initial-mode = <0x2>; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vdd_npu: DCDC_REG4 { + regulator-name = "vdd_npu"; + regulator-init-microvolt = <900000>; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8: DCDC_REG5 { + regulator-name = "vcc_1v8"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda0v9_image: LDO_REG1 { + regulator-name = "vdda0v9_image"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda_0v9: LDO_REG2 { + regulator-name = "vdda_0v9"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda0v9_pmu: LDO_REG3 { + regulator-name = "vdda0v9_pmu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <900000>; + }; + }; + + vccio_acodec: LDO_REG4 { + regulator-name = "vccio_acodec"; + regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vccio_sd: LDO_REG5 { + regulator-name = "vccio_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_pmu: LDO_REG6 { + regulator-name = "vcc3v3_pmu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcca_1v8: LDO_REG7 { + regulator-name = "vcca_1v8"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcca1v8_pmu: LDO_REG8 { + regulator-name = "vcca1v8_pmu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcca1v8_image: LDO_REG9 { + regulator-name = "vcca1v8_image"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v3: SWITCH_REG1 { + regulator-name = "vcc_3v3"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_sd: SWITCH_REG2 { + regulator-name = "vcc3v3_sd"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; +}; + +&pcie2x1 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie20_reset_h>; + reset-gpios = <&gpio1 RK_PB2 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pi6c_05>; + status = "okay"; +}; + +&pcie30phy { + data-lanes = <1 2>; + status = "okay"; +}; + +&pcie3x1 { + num-lanes = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie30x1m0_pins>; + reset-gpios = <&gpio0 RK_PC3 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie30x1>; + status = "okay"; +}; + +&pcie3x2 { + num-lanes = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie30x2_reset_h>; + reset-gpios = <&gpio2 RK_PD6 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pi6c_05>; + status = "okay"; +}; + +&pinctrl { + leds { + led_user_en: led_user_en { + rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pcie { + pcie20_reset_h: pcie20-reset-h { + rockchip,pins = <1 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pcie30x1_enable_h: pcie30x1-enable-h { + rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pcie30x2_reset_h: pcie30x2-reset-h { + rockchip,pins = <2 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pcie_enable_h: pcie-enable-h { + rockchip,pins = <0 RK_PC7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + pmic_int: pmic_int { + rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + usb { + minipcie_enable_h: minipcie-enable-h { + rockchip,pins = <3 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + ngffpcie_enable_h: ngffpcie-enable-h { + rockchip,pins = <0 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + vcc5v0_usb_otg_en: vcc5v0_usb_otg_en { + rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pmu_io_domains { + pmuio1-supply = <&vcc3v3_pmu>; + pmuio2-supply = <&vcc3v3_pmu>; + vccio1-supply = <&vccio_acodec>; + vccio2-supply = <&vcc_1v8>; + vccio3-supply = <&vccio_sd>; + vccio4-supply = <&vcc_1v8>; + vccio5-supply = <&vcc_3v3>; + vccio6-supply = <&vcc_1v8>; + vccio7-supply = <&vcc_3v3>; + status = "okay"; +}; + +&pwm1 { + status = "okay"; +}; + +&pwm2 { + status = "okay"; +}; + +&pwm12 { + pinctrl-names = "default"; + pinctrl-0 = <&pwm12m1_pins>; + status = "okay"; +}; + +&rng { + status = "okay"; +}; + +&saradc { + vref-supply = <&vcca_1v8>; + status = "okay"; +}; + +&sdhci { + bus-width = <8>; + max-frequency = <200000000>; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_datastrobe>; + vmmc-supply = <&vcc_3v3>; + vqmmc-supply = <&vcc_1v8>; + status = "okay"; +}; + +&sdmmc0 { + bus-width = <4>; + cap-sd-highspeed; + cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>; + /* Also used in pcie30x1_clkreqnm0 */ + disable-wp; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc0_bus4 &sdmmc0_clk &sdmmc0_cmd>; + sd-uhs-sdr104; + vmmc-supply = <&vcc3v3_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&tsadc { + rockchip,hw-tshut-mode = <1>; + rockchip,hw-tshut-polarity = <0>; + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb_host0_xhci { + extcon = <&usb2phy0>; + status = "okay"; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +&usb2phy0 { + status = "okay"; +}; + +&usb2phy0_otg { + phy-supply = <&vcc5v0_usb_otg>; + status = "okay"; +}; + +&usb2phy1 { + status = "okay"; +}; + +&usb2phy1_host { + phy-supply = <&vcc3v3_minipcie>; + status = "okay"; +}; + +&usb2phy1_otg { + phy-supply = <&vcc3v3_ngff>; + status = "okay"; +}; diff --git a/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568.dtsi b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568.dtsi new file mode 100644 index 00000000..ba67b58f --- /dev/null +++ b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568.dtsi @@ -0,0 +1,265 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + */ + +#include "rk356x.dtsi" + +/ { + compatible = "rockchip,rk3568"; + + sata0: sata@fc000000 { + compatible = "rockchip,rk3568-dwc-ahci", "snps,dwc-ahci"; + reg = <0 0xfc000000 0 0x1000>; + clocks = <&cru ACLK_SATA0>, <&cru CLK_SATA0_PMALIVE>, + <&cru CLK_SATA0_RXOOB>; + clock-names = "sata", "pmalive", "rxoob"; + interrupts = ; + phys = <&combphy0 PHY_TYPE_SATA>; + phy-names = "sata-phy"; + ports-implemented = <0x1>; + power-domains = <&power RK3568_PD_PIPE>; + status = "disabled"; + }; + + pipe_phy_grf0: syscon@fdc70000 { + compatible = "rockchip,rk3568-pipe-phy-grf", "syscon"; + reg = <0x0 0xfdc70000 0x0 0x1000>; + }; + + qos_pcie3x1: qos@fe190080 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe190080 0x0 0x20>; + }; + + qos_pcie3x2: qos@fe190100 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe190100 0x0 0x20>; + }; + + qos_sata0: qos@fe190200 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe190200 0x0 0x20>; + }; + + pcie30_phy_grf: syscon@fdcb8000 { + compatible = "rockchip,rk3568-pcie3-phy-grf", "syscon"; + reg = <0x0 0xfdcb8000 0x0 0x10000>; + }; + + pcie30phy: phy@fe8c0000 { + compatible = "rockchip,rk3568-pcie3-phy"; + reg = <0x0 0xfe8c0000 0x0 0x20000>; + #phy-cells = <0>; + clocks = <&pmucru CLK_PCIE30PHY_REF_M>, <&pmucru CLK_PCIE30PHY_REF_N>, + <&cru PCLK_PCIE30PHY>; + clock-names = "refclk_m", "refclk_n", "pclk"; + resets = <&cru SRST_PCIE30PHY>; + reset-names = "phy"; + rockchip,phy-grf = <&pcie30_phy_grf>; + status = "disabled"; + }; + + pcie3x1: pcie@fe270000 { + compatible = "rockchip,rk3568-pcie"; + #address-cells = <3>; + #size-cells = <2>; + bus-range = <0x0 0xf>; + clocks = <&cru ACLK_PCIE30X1_MST>, <&cru ACLK_PCIE30X1_SLV>, + <&cru ACLK_PCIE30X1_DBI>, <&cru PCLK_PCIE30X1>, + <&cru CLK_PCIE30X1_AUX_NDFT>; + clock-names = "aclk_mst", "aclk_slv", + "aclk_dbi", "pclk", "aux"; + device_type = "pci"; + interrupts = , + , + , + , + ; + interrupt-names = "sys", "pmc", "msg", "legacy", "err"; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &pcie3x1_intc 0>, + <0 0 0 2 &pcie3x1_intc 1>, + <0 0 0 3 &pcie3x1_intc 2>, + <0 0 0 4 &pcie3x1_intc 3>; + linux,pci-domain = <1>; + num-ib-windows = <6>; + num-ob-windows = <2>; + max-link-speed = <3>; + msi-map = <0x0 &gic 0x1000 0x1000>; + num-lanes = <1>; + phys = <&pcie30phy>; + phy-names = "pcie-phy"; + power-domains = <&power RK3568_PD_PIPE>; + reg = <0x3 0xc0400000 0x0 0x00400000>, + <0x0 0xfe270000 0x0 0x00010000>, + <0x3 0x7f000000 0x0 0x01000000>; + ranges = <0x01000000 0x0 0x3ef00000 0x3 0x7ef00000 0x0 0x00100000>, + <0x02000000 0x0 0x00000000 0x3 0x40000000 0x0 0x3ef00000>; + reg-names = "dbi", "apb", "config"; + resets = <&cru SRST_PCIE30X1_POWERUP>; + reset-names = "pipe"; + /* bifurcation; lane1 when using 1+1 */ + status = "disabled"; + + pcie3x1_intc: legacy-interrupt-controller { + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-parent = <&gic>; + interrupts = ; + }; + }; + + pcie3x2: pcie@fe280000 { + compatible = "rockchip,rk3568-pcie"; + #address-cells = <3>; + #size-cells = <2>; + bus-range = <0x0 0xf>; + clocks = <&cru ACLK_PCIE30X2_MST>, <&cru ACLK_PCIE30X2_SLV>, + <&cru ACLK_PCIE30X2_DBI>, <&cru PCLK_PCIE30X2>, + <&cru CLK_PCIE30X2_AUX_NDFT>; + clock-names = "aclk_mst", "aclk_slv", + "aclk_dbi", "pclk", "aux"; + device_type = "pci"; + interrupts = , + , + , + , + ; + interrupt-names = "sys", "pmc", "msg", "legacy", "err"; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &pcie3x2_intc 0>, + <0 0 0 2 &pcie3x2_intc 1>, + <0 0 0 3 &pcie3x2_intc 2>, + <0 0 0 4 &pcie3x2_intc 3>; + linux,pci-domain = <2>; + num-ib-windows = <6>; + num-ob-windows = <2>; + max-link-speed = <3>; + msi-map = <0x0 &gic 0x2000 0x1000>; + num-lanes = <2>; + phys = <&pcie30phy>; + phy-names = "pcie-phy"; + power-domains = <&power RK3568_PD_PIPE>; + reg = <0x3 0xc0800000 0x0 0x00400000>, + <0x0 0xfe280000 0x0 0x00010000>, + <0x3 0xbf000000 0x0 0x01000000>; + ranges = <0x01000000 0x0 0x3ef00000 0x3 0xbef00000 0x0 0x00100000>, + <0x02000000 0x0 0x00000000 0x3 0x80000000 0x0 0x3ef00000>; + reg-names = "dbi", "apb", "config"; + resets = <&cru SRST_PCIE30X2_POWERUP>; + reset-names = "pipe"; + /* bifurcation; lane0 when using 1+1 */ + status = "disabled"; + + pcie3x2_intc: legacy-interrupt-controller { + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-parent = <&gic>; + interrupts = ; + }; + }; + + gmac0: ethernet@fe2a0000 { + compatible = "rockchip,rk3568-gmac", "snps,dwmac-4.20a"; + reg = <0x0 0xfe2a0000 0x0 0x10000>; + interrupts = , + ; + interrupt-names = "macirq", "eth_wake_irq"; + clocks = <&cru SCLK_GMAC0>, <&cru SCLK_GMAC0_RX_TX>, + <&cru SCLK_GMAC0_RX_TX>, <&cru CLK_MAC0_REFOUT>, + <&cru ACLK_GMAC0>, <&cru PCLK_GMAC0>, + <&cru SCLK_GMAC0_RX_TX>, <&cru CLK_GMAC0_PTP_REF>; + clock-names = "stmmaceth", "mac_clk_rx", + "mac_clk_tx", "clk_mac_refout", + "aclk_mac", "pclk_mac", + "clk_mac_speed", "ptp_ref"; + resets = <&cru SRST_A_GMAC0>; + reset-names = "stmmaceth"; + rockchip,grf = <&grf>; + snps,axi-config = <&gmac0_stmmac_axi_setup>; + snps,mixed-burst; + snps,mtl-rx-config = <&gmac0_mtl_rx_setup>; + snps,mtl-tx-config = <&gmac0_mtl_tx_setup>; + snps,tso; + status = "disabled"; + + mdio0: mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <0x1>; + #size-cells = <0x0>; + }; + + gmac0_stmmac_axi_setup: stmmac-axi-config { + snps,blen = <0 0 0 0 16 8 4>; + snps,rd_osr_lmt = <8>; + snps,wr_osr_lmt = <4>; + }; + + gmac0_mtl_rx_setup: rx-queues-config { + snps,rx-queues-to-use = <1>; + queue0 {}; + }; + + gmac0_mtl_tx_setup: tx-queues-config { + snps,tx-queues-to-use = <1>; + queue0 {}; + }; + }; + + combphy0: phy@fe820000 { + compatible = "rockchip,rk3568-naneng-combphy"; + reg = <0x0 0xfe820000 0x0 0x100>; + clocks = <&pmucru CLK_PCIEPHY0_REF>, + <&cru PCLK_PIPEPHY0>, + <&cru PCLK_PIPE>; + clock-names = "ref", "apb", "pipe"; + assigned-clocks = <&pmucru CLK_PCIEPHY0_REF>; + assigned-clock-rates = <100000000>; + resets = <&cru SRST_PIPEPHY0>; + rockchip,pipe-grf = <&pipegrf>; + rockchip,pipe-phy-grf = <&pipe_phy_grf0>; + #phy-cells = <1>; + status = "disabled"; + }; +}; + +&cpu0_opp_table { + opp-1992000000 { + opp-hz = /bits/ 64 <1992000000>; + opp-microvolt = <1150000 1150000 1150000>; + }; +}; + +&pipegrf { + compatible = "rockchip,rk3568-pipe-grf", "syscon"; +}; + +&power { + power-domain@RK3568_PD_PIPE { + reg = ; + clocks = <&cru PCLK_PIPE>; + pm_qos = <&qos_pcie2x1>, + <&qos_pcie3x1>, + <&qos_pcie3x2>, + <&qos_sata0>, + <&qos_sata1>, + <&qos_sata2>, + <&qos_usb3_0>, + <&qos_usb3_1>; + #power-domain-cells = <0>; + }; +}; + +&usb_host0_xhci { + phys = <&usb2phy0_otg>, <&combphy0 PHY_TYPE_USB3>; + phy-names = "usb2-phy", "usb3-phy"; +}; + +&vop { + compatible = "rockchip,rk3568-vop"; +}; diff --git a/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk356x.dtsi new file mode 100644 index 00000000..164708f1 --- /dev/null +++ b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk356x.dtsi @@ -0,0 +1,1838 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/ { + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + gpio0 = &gpio0; + gpio1 = &gpio1; + gpio2 = &gpio2; + gpio3 = &gpio3; + gpio4 = &gpio4; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c4; + i2c5 = &i2c5; + serial0 = &uart0; + serial1 = &uart1; + serial2 = &uart2; + serial3 = &uart3; + serial4 = &uart4; + serial5 = &uart5; + serial6 = &uart6; + serial7 = &uart7; + serial8 = &uart8; + serial9 = &uart9; + spi0 = &spi0; + spi1 = &spi1; + spi2 = &spi2; + spi3 = &spi3; + }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a55"; + reg = <0x0 0x0>; + clocks = <&scmi_clk 0>; + #cooling-cells = <2>; + enable-method = "psci"; + operating-points-v2 = <&cpu0_opp_table>; + }; + + cpu1: cpu@100 { + device_type = "cpu"; + compatible = "arm,cortex-a55"; + reg = <0x0 0x100>; + #cooling-cells = <2>; + enable-method = "psci"; + operating-points-v2 = <&cpu0_opp_table>; + }; + + cpu2: cpu@200 { + device_type = "cpu"; + compatible = "arm,cortex-a55"; + reg = <0x0 0x200>; + #cooling-cells = <2>; + enable-method = "psci"; + operating-points-v2 = <&cpu0_opp_table>; + }; + + cpu3: cpu@300 { + device_type = "cpu"; + compatible = "arm,cortex-a55"; + reg = <0x0 0x300>; + #cooling-cells = <2>; + enable-method = "psci"; + operating-points-v2 = <&cpu0_opp_table>; + }; + }; + + cpu0_opp_table: opp-table-0 { + compatible = "operating-points-v2"; + opp-shared; + + opp-408000000 { + opp-hz = /bits/ 64 <408000000>; + opp-microvolt = <900000 900000 1150000>; + clock-latency-ns = <40000>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + opp-microvolt = <900000 900000 1150000>; + }; + + opp-816000000 { + opp-hz = /bits/ 64 <816000000>; + opp-microvolt = <900000 900000 1150000>; + opp-suspend; + }; + + opp-1104000000 { + opp-hz = /bits/ 64 <1104000000>; + opp-microvolt = <900000 900000 1150000>; + }; + + opp-1416000000 { + opp-hz = /bits/ 64 <1416000000>; + opp-microvolt = <900000 900000 1150000>; + }; + + opp-1608000000 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <975000 975000 1150000>; + }; + + opp-1800000000 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <1050000 1050000 1150000>; + }; + }; + + display_subsystem: display-subsystem { + compatible = "rockchip,display-subsystem"; + ports = <&vop_out>; + }; + + firmware { + scmi: scmi { + compatible = "arm,scmi-smc"; + arm,smc-id = <0x82000010>; + shmem = <&scmi_shmem>; + #address-cells = <1>; + #size-cells = <0>; + + scmi_clk: protocol@14 { + reg = <0x14>; + #clock-cells = <1>; + }; + }; + }; + + gpu_opp_table: opp-table-1 { + compatible = "operating-points-v2"; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + opp-microvolt = <825000>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + opp-microvolt = <825000>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + opp-microvolt = <825000>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + opp-microvolt = <825000>; + }; + + opp-700000000 { + opp-hz = /bits/ 64 <700000000>; + opp-microvolt = <900000>; + }; + + opp-800000000 { + opp-hz = /bits/ 64 <800000000>; + opp-microvolt = <1000000>; + }; + }; + + hdmi_sound: hdmi-sound { + compatible = "simple-audio-card"; + simple-audio-card,name = "HDMI"; + simple-audio-card,format = "i2s"; + simple-audio-card,mclk-fs = <256>; + status = "disabled"; + + simple-audio-card,codec { + sound-dai = <&hdmi>; + }; + + simple-audio-card,cpu { + sound-dai = <&i2s0_8ch>; + }; + }; + + pmu { + compatible = "arm,cortex-a55-pmu"; + interrupts = , + , + , + ; + interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + arm,no-tick-in-suspend; + }; + + xin24m: xin24m { + compatible = "fixed-clock"; + clock-frequency = <24000000>; + clock-output-names = "xin24m"; + #clock-cells = <0>; + }; + + xin32k: xin32k { + compatible = "fixed-clock"; + clock-frequency = <32768>; + clock-output-names = "xin32k"; + pinctrl-0 = <&clk32k_out0>; + pinctrl-names = "default"; + #clock-cells = <0>; + }; + + sram@10f000 { + compatible = "mmio-sram"; + reg = <0x0 0x0010f000 0x0 0x100>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x0 0x0010f000 0x100>; + + scmi_shmem: sram@0 { + compatible = "arm,scmi-shmem"; + reg = <0x0 0x100>; + }; + }; + + sata1: sata@fc400000 { + compatible = "rockchip,rk3568-dwc-ahci", "snps,dwc-ahci"; + reg = <0 0xfc400000 0 0x1000>; + clocks = <&cru ACLK_SATA1>, <&cru CLK_SATA1_PMALIVE>, + <&cru CLK_SATA1_RXOOB>; + clock-names = "sata", "pmalive", "rxoob"; + interrupts = ; + phys = <&combphy1 PHY_TYPE_SATA>; + phy-names = "sata-phy"; + ports-implemented = <0x1>; + power-domains = <&power RK3568_PD_PIPE>; + status = "disabled"; + }; + + sata2: sata@fc800000 { + compatible = "rockchip,rk3568-dwc-ahci", "snps,dwc-ahci"; + reg = <0 0xfc800000 0 0x1000>; + clocks = <&cru ACLK_SATA2>, <&cru CLK_SATA2_PMALIVE>, + <&cru CLK_SATA2_RXOOB>; + clock-names = "sata", "pmalive", "rxoob"; + interrupts = ; + phys = <&combphy2 PHY_TYPE_SATA>; + phy-names = "sata-phy"; + ports-implemented = <0x1>; + power-domains = <&power RK3568_PD_PIPE>; + status = "disabled"; + }; + + usb_host0_xhci: usb@fcc00000 { + compatible = "rockchip,rk3568-dwc3", "snps,dwc3"; + reg = <0x0 0xfcc00000 0x0 0x400000>; + interrupts = ; + clocks = <&cru CLK_USB3OTG0_REF>, <&cru CLK_USB3OTG0_SUSPEND>, + <&cru ACLK_USB3OTG0>; + clock-names = "ref_clk", "suspend_clk", + "bus_clk"; + dr_mode = "otg"; + phy_type = "utmi_wide"; + power-domains = <&power RK3568_PD_PIPE>; + resets = <&cru SRST_USB3OTG0>; + snps,dis_u2_susphy_quirk; + status = "disabled"; + }; + + usb_host1_xhci: usb@fd000000 { + compatible = "rockchip,rk3568-dwc3", "snps,dwc3"; + reg = <0x0 0xfd000000 0x0 0x400000>; + interrupts = ; + clocks = <&cru CLK_USB3OTG1_REF>, <&cru CLK_USB3OTG1_SUSPEND>, + <&cru ACLK_USB3OTG1>; + clock-names = "ref_clk", "suspend_clk", + "bus_clk"; + dr_mode = "host"; + phys = <&usb2phy0_host>, <&combphy1 PHY_TYPE_USB3>; + phy-names = "usb2-phy", "usb3-phy"; + phy_type = "utmi_wide"; + power-domains = <&power RK3568_PD_PIPE>; + resets = <&cru SRST_USB3OTG1>; + snps,dis_u2_susphy_quirk; + status = "disabled"; + }; + + gic: interrupt-controller@fd400000 { + compatible = "arm,gic-v3"; + reg = <0x0 0xfd400000 0 0x10000>, /* GICD */ + <0x0 0xfd460000 0 0x80000>; /* GICR */ + interrupts = ; + interrupt-controller; + #interrupt-cells = <3>; + mbi-alias = <0x0 0xfd410000>; + mbi-ranges = <296 24>; + msi-controller; + }; + + usb_host0_ehci: usb@fd800000 { + compatible = "generic-ehci"; + reg = <0x0 0xfd800000 0x0 0x40000>; + interrupts = ; + clocks = <&cru HCLK_USB2HOST0>, <&cru HCLK_USB2HOST0_ARB>, + <&cru PCLK_USB>; + phys = <&usb2phy1_otg>; + phy-names = "usb"; + status = "disabled"; + }; + + usb_host0_ohci: usb@fd840000 { + compatible = "generic-ohci"; + reg = <0x0 0xfd840000 0x0 0x40000>; + interrupts = ; + clocks = <&cru HCLK_USB2HOST0>, <&cru HCLK_USB2HOST0_ARB>, + <&cru PCLK_USB>; + phys = <&usb2phy1_otg>; + phy-names = "usb"; + status = "disabled"; + }; + + usb_host1_ehci: usb@fd880000 { + compatible = "generic-ehci"; + reg = <0x0 0xfd880000 0x0 0x40000>; + interrupts = ; + clocks = <&cru HCLK_USB2HOST1>, <&cru HCLK_USB2HOST1_ARB>, + <&cru PCLK_USB>; + phys = <&usb2phy1_host>; + phy-names = "usb"; + status = "disabled"; + }; + + usb_host1_ohci: usb@fd8c0000 { + compatible = "generic-ohci"; + reg = <0x0 0xfd8c0000 0x0 0x40000>; + interrupts = ; + clocks = <&cru HCLK_USB2HOST1>, <&cru HCLK_USB2HOST1_ARB>, + <&cru PCLK_USB>; + phys = <&usb2phy1_host>; + phy-names = "usb"; + status = "disabled"; + }; + + pmugrf: syscon@fdc20000 { + compatible = "rockchip,rk3568-pmugrf", "syscon", "simple-mfd"; + reg = <0x0 0xfdc20000 0x0 0x10000>; + + pmu_io_domains: io-domains { + compatible = "rockchip,rk3568-pmu-io-voltage-domain"; + status = "disabled"; + }; + }; + + pipegrf: syscon@fdc50000 { + reg = <0x0 0xfdc50000 0x0 0x1000>; + }; + + grf: syscon@fdc60000 { + compatible = "rockchip,rk3568-grf", "syscon", "simple-mfd"; + reg = <0x0 0xfdc60000 0x0 0x10000>; + }; + + pipe_phy_grf1: syscon@fdc80000 { + compatible = "rockchip,rk3568-pipe-phy-grf", "syscon"; + reg = <0x0 0xfdc80000 0x0 0x1000>; + }; + + pipe_phy_grf2: syscon@fdc90000 { + compatible = "rockchip,rk3568-pipe-phy-grf", "syscon"; + reg = <0x0 0xfdc90000 0x0 0x1000>; + }; + + usb2phy0_grf: syscon@fdca0000 { + compatible = "rockchip,rk3568-usb2phy-grf", "syscon"; + reg = <0x0 0xfdca0000 0x0 0x8000>; + }; + + usb2phy1_grf: syscon@fdca8000 { + compatible = "rockchip,rk3568-usb2phy-grf", "syscon"; + reg = <0x0 0xfdca8000 0x0 0x8000>; + }; + + pmucru: clock-controller@fdd00000 { + compatible = "rockchip,rk3568-pmucru"; + reg = <0x0 0xfdd00000 0x0 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + cru: clock-controller@fdd20000 { + compatible = "rockchip,rk3568-cru"; + reg = <0x0 0xfdd20000 0x0 0x1000>; + clocks = <&xin24m>; + clock-names = "xin24m"; + #clock-cells = <1>; + #reset-cells = <1>; + assigned-clocks = <&cru PLL_GPLL>, <&pmucru PLL_PPLL>; + assigned-clock-rates = <1200000000>, <200000000>; + rockchip,grf = <&grf>; + }; + + i2c0: i2c@fdd40000 { + compatible = "rockchip,rk3568-i2c", "rockchip,rk3399-i2c"; + reg = <0x0 0xfdd40000 0x0 0x1000>; + interrupts = ; + clocks = <&pmucru CLK_I2C0>, <&pmucru PCLK_I2C0>; + clock-names = "i2c", "pclk"; + pinctrl-0 = <&i2c0_xfer>; + pinctrl-names = "default"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + uart0: serial@fdd50000 { + compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; + reg = <0x0 0xfdd50000 0x0 0x100>; + interrupts = ; + clocks = <&pmucru SCLK_UART0>, <&pmucru PCLK_UART0>; + clock-names = "baudclk", "apb_pclk"; + dmas = <&dmac0 0>, <&dmac0 1>; + pinctrl-0 = <&uart0_xfer>; + pinctrl-names = "default"; + reg-io-width = <4>; + reg-shift = <2>; + status = "disabled"; + }; + + pwm0: pwm@fdd70000 { + compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; + reg = <0x0 0xfdd70000 0x0 0x10>; + clocks = <&pmucru CLK_PWM0>, <&pmucru PCLK_PWM0>; + clock-names = "pwm", "pclk"; + pinctrl-0 = <&pwm0m0_pins>; + pinctrl-names = "default"; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm1: pwm@fdd70010 { + compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; + reg = <0x0 0xfdd70010 0x0 0x10>; + clocks = <&pmucru CLK_PWM0>, <&pmucru PCLK_PWM0>; + clock-names = "pwm", "pclk"; + pinctrl-0 = <&pwm1m0_pins>; + pinctrl-names = "default"; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm2: pwm@fdd70020 { + compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; + reg = <0x0 0xfdd70020 0x0 0x10>; + clocks = <&pmucru CLK_PWM0>, <&pmucru PCLK_PWM0>; + clock-names = "pwm", "pclk"; + pinctrl-0 = <&pwm2m0_pins>; + pinctrl-names = "default"; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm3: pwm@fdd70030 { + compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; + reg = <0x0 0xfdd70030 0x0 0x10>; + clocks = <&pmucru CLK_PWM0>, <&pmucru PCLK_PWM0>; + clock-names = "pwm", "pclk"; + pinctrl-0 = <&pwm3_pins>; + pinctrl-names = "default"; + #pwm-cells = <3>; + status = "disabled"; + }; + + pmu: power-management@fdd90000 { + compatible = "rockchip,rk3568-pmu", "syscon", "simple-mfd"; + reg = <0x0 0xfdd90000 0x0 0x1000>; + + power: power-controller { + compatible = "rockchip,rk3568-power-controller"; + #power-domain-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + + /* These power domains are grouped by VD_GPU */ + power-domain@RK3568_PD_GPU { + reg = ; + clocks = <&cru ACLK_GPU_PRE>, + <&cru PCLK_GPU_PRE>; + pm_qos = <&qos_gpu>; + #power-domain-cells = <0>; + }; + + /* These power domains are grouped by VD_LOGIC */ + power-domain@RK3568_PD_VI { + reg = ; + clocks = <&cru HCLK_VI>, + <&cru PCLK_VI>; + pm_qos = <&qos_isp>, + <&qos_vicap0>, + <&qos_vicap1>; + #power-domain-cells = <0>; + }; + + power-domain@RK3568_PD_VO { + reg = ; + clocks = <&cru HCLK_VO>, + <&cru PCLK_VO>, + <&cru ACLK_VOP_PRE>; + pm_qos = <&qos_hdcp>, + <&qos_vop_m0>, + <&qos_vop_m1>; + #power-domain-cells = <0>; + }; + + power-domain@RK3568_PD_RGA { + reg = ; + clocks = <&cru HCLK_RGA_PRE>, + <&cru PCLK_RGA_PRE>; + pm_qos = <&qos_ebc>, + <&qos_iep>, + <&qos_jpeg_dec>, + <&qos_jpeg_enc>, + <&qos_rga_rd>, + <&qos_rga_wr>; + #power-domain-cells = <0>; + }; + + power-domain@RK3568_PD_VPU { + reg = ; + clocks = <&cru HCLK_VPU_PRE>; + pm_qos = <&qos_vpu>; + #power-domain-cells = <0>; + }; + + power-domain@RK3568_PD_RKVDEC { + clocks = <&cru HCLK_RKVDEC_PRE>; + reg = ; + pm_qos = <&qos_rkvdec>; + #power-domain-cells = <0>; + }; + + power-domain@RK3568_PD_RKVENC { + reg = ; + clocks = <&cru HCLK_RKVENC_PRE>; + pm_qos = <&qos_rkvenc_rd_m0>, + <&qos_rkvenc_rd_m1>, + <&qos_rkvenc_wr_m0>; + #power-domain-cells = <0>; + }; + }; + }; + + gpu: gpu@fde60000 { + compatible = "rockchip,rk3568-mali", "arm,mali-bifrost"; + reg = <0x0 0xfde60000 0x0 0x4000>; + interrupts = , + , + ; + interrupt-names = "job", "mmu", "gpu"; + clocks = <&scmi_clk 1>, <&cru CLK_GPU>; + clock-names = "gpu", "bus"; + #cooling-cells = <2>; + operating-points-v2 = <&gpu_opp_table>; + power-domains = <&power RK3568_PD_GPU>; + status = "disabled"; + }; + + vpu: video-codec@fdea0400 { + compatible = "rockchip,rk3568-vpu"; + reg = <0x0 0xfdea0000 0x0 0x800>; + interrupts = ; + clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; + clock-names = "aclk", "hclk"; + iommus = <&vdpu_mmu>; + power-domains = <&power RK3568_PD_VPU>; + }; + + vdpu_mmu: iommu@fdea0800 { + compatible = "rockchip,rk3568-iommu"; + reg = <0x0 0xfdea0800 0x0 0x40>; + interrupts = ; + clock-names = "aclk", "iface"; + clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; + power-domains = <&power RK3568_PD_VPU>; + #iommu-cells = <0>; + }; + + vepu: video-codec@fdee0000 { + compatible = "rockchip,rk3568-vepu"; + reg = <0x0 0xfdee0000 0x0 0x800>; + interrupts = ; + clocks = <&cru ACLK_JENC>, <&cru HCLK_JENC>; + clock-names = "aclk", "hclk"; + iommus = <&vepu_mmu>; + power-domains = <&power RK3568_PD_RGA>; + }; + + vepu_mmu: iommu@fdee0800 { + compatible = "rockchip,rk3568-iommu"; + reg = <0x0 0xfdee0800 0x0 0x40>; + interrupts = ; + clocks = <&cru ACLK_JENC>, <&cru HCLK_JENC>; + clock-names = "aclk", "iface"; + power-domains = <&power RK3568_PD_RGA>; + #iommu-cells = <0>; + }; + + sdmmc2: mmc@fe000000 { + compatible = "rockchip,rk3568-dw-mshc", "rockchip,rk3288-dw-mshc"; + reg = <0x0 0xfe000000 0x0 0x4000>; + interrupts = ; + clocks = <&cru HCLK_SDMMC2>, <&cru CLK_SDMMC2>, + <&cru SCLK_SDMMC2_DRV>, <&cru SCLK_SDMMC2_SAMPLE>; + clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; + fifo-depth = <0x100>; + max-frequency = <150000000>; + resets = <&cru SRST_SDMMC2>; + reset-names = "reset"; + status = "disabled"; + }; + + gmac1: ethernet@fe010000 { + compatible = "rockchip,rk3568-gmac", "snps,dwmac-4.20a"; + reg = <0x0 0xfe010000 0x0 0x10000>; + interrupts = , + ; + interrupt-names = "macirq", "eth_wake_irq"; + clocks = <&cru SCLK_GMAC1>, <&cru SCLK_GMAC1_RX_TX>, + <&cru SCLK_GMAC1_RX_TX>, <&cru CLK_MAC1_REFOUT>, + <&cru ACLK_GMAC1>, <&cru PCLK_GMAC1>, + <&cru SCLK_GMAC1_RX_TX>, <&cru CLK_GMAC1_PTP_REF>; + clock-names = "stmmaceth", "mac_clk_rx", + "mac_clk_tx", "clk_mac_refout", + "aclk_mac", "pclk_mac", + "clk_mac_speed", "ptp_ref"; + resets = <&cru SRST_A_GMAC1>; + reset-names = "stmmaceth"; + rockchip,grf = <&grf>; + snps,axi-config = <&gmac1_stmmac_axi_setup>; + snps,mixed-burst; + snps,mtl-rx-config = <&gmac1_mtl_rx_setup>; + snps,mtl-tx-config = <&gmac1_mtl_tx_setup>; + snps,tso; + status = "disabled"; + + mdio1: mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <0x1>; + #size-cells = <0x0>; + }; + + gmac1_stmmac_axi_setup: stmmac-axi-config { + snps,blen = <0 0 0 0 16 8 4>; + snps,rd_osr_lmt = <8>; + snps,wr_osr_lmt = <4>; + }; + + gmac1_mtl_rx_setup: rx-queues-config { + snps,rx-queues-to-use = <1>; + queue0 {}; + }; + + gmac1_mtl_tx_setup: tx-queues-config { + snps,tx-queues-to-use = <1>; + queue0 {}; + }; + }; + + vop: vop@fe040000 { + reg = <0x0 0xfe040000 0x0 0x3000>, <0x0 0xfe044000 0x0 0x1000>; + reg-names = "vop", "gamma-lut"; + interrupts = ; + clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>, <&cru DCLK_VOP0>, + <&cru DCLK_VOP1>, <&cru DCLK_VOP2>; + clock-names = "aclk", "hclk", "dclk_vp0", "dclk_vp1", "dclk_vp2"; + iommus = <&vop_mmu>; + power-domains = <&power RK3568_PD_VO>; + rockchip,grf = <&grf>; + status = "disabled"; + + vop_out: ports { + #address-cells = <1>; + #size-cells = <0>; + + vp0: port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + }; + + vp1: port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + }; + + vp2: port@2 { + reg = <2>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + }; + + vop_mmu: iommu@fe043e00 { + compatible = "rockchip,rk3568-iommu"; + reg = <0x0 0xfe043e00 0x0 0x100>, <0x0 0xfe043f00 0x0 0x100>; + interrupts = ; + clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>; + clock-names = "aclk", "iface"; + #iommu-cells = <0>; + status = "disabled"; + }; + + dsi0: dsi@fe060000 { + compatible = "rockchip,rk3568-mipi-dsi", "snps,dw-mipi-dsi"; + reg = <0x00 0xfe060000 0x00 0x10000>; + interrupts = ; + clock-names = "pclk", "hclk"; + clocks = <&cru PCLK_DSITX_0>, <&cru HCLK_VO>; + phy-names = "dphy"; + phys = <&dsi_dphy0>; + power-domains = <&power RK3568_PD_VO>; + reset-names = "apb"; + resets = <&cru SRST_P_DSITX_0>; + rockchip,grf = <&grf>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + dsi0_in: port@0 { + reg = <0>; + }; + + dsi0_out: port@1 { + reg = <1>; + }; + }; + }; + + dsi1: dsi@fe070000 { + compatible = "rockchip,rk3568-mipi-dsi", "snps,dw-mipi-dsi"; + reg = <0x0 0xfe070000 0x0 0x10000>; + interrupts = ; + clock-names = "pclk", "hclk"; + clocks = <&cru PCLK_DSITX_1>, <&cru HCLK_VO>; + phy-names = "dphy"; + phys = <&dsi_dphy1>; + power-domains = <&power RK3568_PD_VO>; + reset-names = "apb"; + resets = <&cru SRST_P_DSITX_1>; + rockchip,grf = <&grf>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + dsi1_in: port@0 { + reg = <0>; + }; + + dsi1_out: port@1 { + reg = <1>; + }; + }; + }; + + hdmi: hdmi@fe0a0000 { + compatible = "rockchip,rk3568-dw-hdmi"; + reg = <0x0 0xfe0a0000 0x0 0x20000>; + interrupts = ; + clocks = <&cru PCLK_HDMI_HOST>, + <&cru CLK_HDMI_SFR>, + <&cru CLK_HDMI_CEC>, + <&pmucru CLK_HDMI_REF>, + <&cru HCLK_VO>; + clock-names = "iahb", "isfr", "cec", "ref"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmitx_scl &hdmitx_sda &hdmitxm0_cec>; + power-domains = <&power RK3568_PD_VO>; + reg-io-width = <4>; + rockchip,grf = <&grf>; + #sound-dai-cells = <0>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + hdmi_in: port@0 { + reg = <0>; + }; + + hdmi_out: port@1 { + reg = <1>; + }; + }; + }; + + qos_gpu: qos@fe128000 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe128000 0x0 0x20>; + }; + + qos_rkvenc_rd_m0: qos@fe138080 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe138080 0x0 0x20>; + }; + + qos_rkvenc_rd_m1: qos@fe138100 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe138100 0x0 0x20>; + }; + + qos_rkvenc_wr_m0: qos@fe138180 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe138180 0x0 0x20>; + }; + + qos_isp: qos@fe148000 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe148000 0x0 0x20>; + }; + + qos_vicap0: qos@fe148080 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe148080 0x0 0x20>; + }; + + qos_vicap1: qos@fe148100 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe148100 0x0 0x20>; + }; + + qos_vpu: qos@fe150000 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe150000 0x0 0x20>; + }; + + qos_ebc: qos@fe158000 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe158000 0x0 0x20>; + }; + + qos_iep: qos@fe158100 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe158100 0x0 0x20>; + }; + + qos_jpeg_dec: qos@fe158180 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe158180 0x0 0x20>; + }; + + qos_jpeg_enc: qos@fe158200 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe158200 0x0 0x20>; + }; + + qos_rga_rd: qos@fe158280 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe158280 0x0 0x20>; + }; + + qos_rga_wr: qos@fe158300 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe158300 0x0 0x20>; + }; + + qos_npu: qos@fe180000 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe180000 0x0 0x20>; + }; + + qos_pcie2x1: qos@fe190000 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe190000 0x0 0x20>; + }; + + qos_sata1: qos@fe190280 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe190280 0x0 0x20>; + }; + + qos_sata2: qos@fe190300 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe190300 0x0 0x20>; + }; + + qos_usb3_0: qos@fe190380 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe190380 0x0 0x20>; + }; + + qos_usb3_1: qos@fe190400 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe190400 0x0 0x20>; + }; + + qos_rkvdec: qos@fe198000 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe198000 0x0 0x20>; + }; + + qos_hdcp: qos@fe1a8000 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe1a8000 0x0 0x20>; + }; + + qos_vop_m0: qos@fe1a8080 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe1a8080 0x0 0x20>; + }; + + qos_vop_m1: qos@fe1a8100 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe1a8100 0x0 0x20>; + }; + + pcie2x1: pcie@fe260000 { + compatible = "rockchip,rk3568-pcie"; + reg = <0x3 0xc0000000 0x0 0x00400000>, + <0x0 0xfe260000 0x0 0x00010000>, + <0x3 0x3f000000 0x0 0x01000000>; + reg-names = "dbi", "apb", "config"; + interrupts = , + , + , + , + ; + interrupt-names = "sys", "pmc", "msi", "legacy", "err"; + bus-range = <0x0 0xf>; + clocks = <&cru ACLK_PCIE20_MST>, <&cru ACLK_PCIE20_SLV>, + <&cru ACLK_PCIE20_DBI>, <&cru PCLK_PCIE20>, + <&cru CLK_PCIE20_AUX_NDFT>; + clock-names = "aclk_mst", "aclk_slv", + "aclk_dbi", "pclk", "aux"; + device_type = "pci"; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &pcie_intc 0>, + <0 0 0 2 &pcie_intc 1>, + <0 0 0 3 &pcie_intc 2>, + <0 0 0 4 &pcie_intc 3>; + linux,pci-domain = <0>; + num-ib-windows = <6>; + num-ob-windows = <2>; + max-link-speed = <2>; + msi-map = <0x0 &gic 0x0 0x1000>; + num-lanes = <1>; + phys = <&combphy2 PHY_TYPE_PCIE>; + phy-names = "pcie-phy"; + power-domains = <&power RK3568_PD_PIPE>; + ranges = <0x01000000 0x0 0x3ef00000 0x3 0x3ef00000 0x0 0x00100000 + 0x02000000 0x0 0x00000000 0x3 0x00000000 0x0 0x3ef00000>; + resets = <&cru SRST_PCIE20_POWERUP>; + reset-names = "pipe"; + #address-cells = <3>; + #size-cells = <2>; + status = "disabled"; + + pcie_intc: legacy-interrupt-controller { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + interrupt-parent = <&gic>; + interrupts = ; + }; + }; + + sdmmc0: mmc@fe2b0000 { + compatible = "rockchip,rk3568-dw-mshc", "rockchip,rk3288-dw-mshc"; + reg = <0x0 0xfe2b0000 0x0 0x4000>; + interrupts = ; + clocks = <&cru HCLK_SDMMC0>, <&cru CLK_SDMMC0>, + <&cru SCLK_SDMMC0_DRV>, <&cru SCLK_SDMMC0_SAMPLE>; + clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; + fifo-depth = <0x100>; + max-frequency = <150000000>; + resets = <&cru SRST_SDMMC0>; + reset-names = "reset"; + status = "disabled"; + }; + + sdmmc1: mmc@fe2c0000 { + compatible = "rockchip,rk3568-dw-mshc", "rockchip,rk3288-dw-mshc"; + reg = <0x0 0xfe2c0000 0x0 0x4000>; + interrupts = ; + clocks = <&cru HCLK_SDMMC1>, <&cru CLK_SDMMC1>, + <&cru SCLK_SDMMC1_DRV>, <&cru SCLK_SDMMC1_SAMPLE>; + clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; + fifo-depth = <0x100>; + max-frequency = <150000000>; + resets = <&cru SRST_SDMMC1>; + reset-names = "reset"; + status = "disabled"; + }; + + sfc: spi@fe300000 { + compatible = "rockchip,sfc"; + reg = <0x0 0xfe300000 0x0 0x4000>; + interrupts = ; + clocks = <&cru SCLK_SFC>, <&cru HCLK_SFC>; + clock-names = "clk_sfc", "hclk_sfc"; + pinctrl-0 = <&fspi_pins>; + pinctrl-names = "default"; + status = "disabled"; + }; + + sdhci: mmc@fe310000 { + compatible = "rockchip,rk3568-dwcmshc"; + reg = <0x0 0xfe310000 0x0 0x10000>; + interrupts = ; + assigned-clocks = <&cru BCLK_EMMC>, <&cru TCLK_EMMC>; + assigned-clock-rates = <200000000>, <24000000>; + clocks = <&cru CCLK_EMMC>, <&cru HCLK_EMMC>, + <&cru ACLK_EMMC>, <&cru BCLK_EMMC>, + <&cru TCLK_EMMC>; + clock-names = "core", "bus", "axi", "block", "timer"; + status = "disabled"; + }; + + spdif: spdif@fe460000 { + compatible = "rockchip,rk3568-spdif"; + reg = <0x0 0xfe460000 0x0 0x1000>; + interrupts = ; + clock-names = "mclk", "hclk"; + clocks = <&cru MCLK_SPDIF_8CH>, <&cru HCLK_SPDIF_8CH>; + dmas = <&dmac1 1>; + dma-names = "tx"; + pinctrl-names = "default"; + pinctrl-0 = <&spdifm0_tx>; + #sound-dai-cells = <0>; + status = "disabled"; + }; + + i2s0_8ch: i2s@fe400000 { + compatible = "rockchip,rk3568-i2s-tdm"; + reg = <0x0 0xfe400000 0x0 0x1000>; + interrupts = ; + assigned-clocks = <&cru CLK_I2S0_8CH_TX_SRC>, <&cru CLK_I2S0_8CH_RX_SRC>; + assigned-clock-rates = <1188000000>, <1188000000>; + clocks = <&cru MCLK_I2S0_8CH_TX>, <&cru MCLK_I2S0_8CH_RX>, <&cru HCLK_I2S0_8CH>; + clock-names = "mclk_tx", "mclk_rx", "hclk"; + dmas = <&dmac1 0>; + dma-names = "tx"; + resets = <&cru SRST_M_I2S0_8CH_TX>, <&cru SRST_M_I2S0_8CH_RX>; + reset-names = "tx-m", "rx-m"; + rockchip,grf = <&grf>; + #sound-dai-cells = <0>; + status = "disabled"; + }; + + i2s1_8ch: i2s@fe410000 { + compatible = "rockchip,rk3568-i2s-tdm"; + reg = <0x0 0xfe410000 0x0 0x1000>; + interrupts = ; + assigned-clocks = <&cru CLK_I2S1_8CH_TX_SRC>, <&cru CLK_I2S1_8CH_RX_SRC>; + assigned-clock-rates = <1188000000>, <1188000000>; + clocks = <&cru MCLK_I2S1_8CH_TX>, <&cru MCLK_I2S1_8CH_RX>, + <&cru HCLK_I2S1_8CH>; + clock-names = "mclk_tx", "mclk_rx", "hclk"; + dmas = <&dmac1 3>, <&dmac1 2>; + dma-names = "rx", "tx"; + resets = <&cru SRST_M_I2S1_8CH_TX>, <&cru SRST_M_I2S1_8CH_RX>; + reset-names = "tx-m", "rx-m"; + rockchip,grf = <&grf>; + pinctrl-names = "default"; + pinctrl-0 = <&i2s1m0_sclktx &i2s1m0_sclkrx + &i2s1m0_lrcktx &i2s1m0_lrckrx + &i2s1m0_sdi0 &i2s1m0_sdi1 + &i2s1m0_sdi2 &i2s1m0_sdi3 + &i2s1m0_sdo0 &i2s1m0_sdo1 + &i2s1m0_sdo2 &i2s1m0_sdo3>; + #sound-dai-cells = <0>; + status = "disabled"; + }; + + i2s3_2ch: i2s@fe430000 { + compatible = "rockchip,rk3568-i2s-tdm"; + reg = <0x0 0xfe430000 0x0 0x1000>; + interrupts = ; + clocks = <&cru MCLK_I2S3_2CH_TX>, <&cru MCLK_I2S3_2CH_RX>, + <&cru HCLK_I2S3_2CH>; + clock-names = "mclk_tx", "mclk_rx", "hclk"; + dmas = <&dmac1 6>, <&dmac1 7>; + dma-names = "tx", "rx"; + resets = <&cru SRST_M_I2S3_2CH_TX>, <&cru SRST_M_I2S3_2CH_RX>; + reset-names = "tx-m", "rx-m"; + rockchip,grf = <&grf>; + #sound-dai-cells = <0>; + status = "disabled"; + }; + + pdm: pdm@fe440000 { + compatible = "rockchip,rk3568-pdm"; + reg = <0x0 0xfe440000 0x0 0x1000>; + interrupts = ; + clocks = <&cru MCLK_PDM>, <&cru HCLK_PDM>; + clock-names = "pdm_clk", "pdm_hclk"; + dmas = <&dmac1 9>; + dma-names = "rx"; + pinctrl-0 = <&pdmm0_clk + &pdmm0_clk1 + &pdmm0_sdi0 + &pdmm0_sdi1 + &pdmm0_sdi2 + &pdmm0_sdi3>; + pinctrl-names = "default"; + resets = <&cru SRST_M_PDM>; + reset-names = "pdm-m"; + #sound-dai-cells = <0>; + status = "disabled"; + }; + + dmac0: dma-controller@fe530000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0x0 0xfe530000 0x0 0x4000>; + interrupts = , + ; + arm,pl330-periph-burst; + clocks = <&cru ACLK_BUS>; + clock-names = "apb_pclk"; + #dma-cells = <1>; + }; + + dmac1: dma-controller@fe550000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0x0 0xfe550000 0x0 0x4000>; + interrupts = , + ; + arm,pl330-periph-burst; + clocks = <&cru ACLK_BUS>; + clock-names = "apb_pclk"; + #dma-cells = <1>; + }; + + i2c1: i2c@fe5a0000 { + compatible = "rockchip,rk3568-i2c", "rockchip,rk3399-i2c"; + reg = <0x0 0xfe5a0000 0x0 0x1000>; + interrupts = ; + clocks = <&cru CLK_I2C1>, <&cru PCLK_I2C1>; + clock-names = "i2c", "pclk"; + pinctrl-0 = <&i2c1_xfer>; + pinctrl-names = "default"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c2: i2c@fe5b0000 { + compatible = "rockchip,rk3568-i2c", "rockchip,rk3399-i2c"; + reg = <0x0 0xfe5b0000 0x0 0x1000>; + interrupts = ; + clocks = <&cru CLK_I2C2>, <&cru PCLK_I2C2>; + clock-names = "i2c", "pclk"; + pinctrl-0 = <&i2c2m0_xfer>; + pinctrl-names = "default"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c3: i2c@fe5c0000 { + compatible = "rockchip,rk3568-i2c", "rockchip,rk3399-i2c"; + reg = <0x0 0xfe5c0000 0x0 0x1000>; + interrupts = ; + clocks = <&cru CLK_I2C3>, <&cru PCLK_I2C3>; + clock-names = "i2c", "pclk"; + pinctrl-0 = <&i2c3m0_xfer>; + pinctrl-names = "default"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c4: i2c@fe5d0000 { + compatible = "rockchip,rk3568-i2c", "rockchip,rk3399-i2c"; + reg = <0x0 0xfe5d0000 0x0 0x1000>; + interrupts = ; + clocks = <&cru CLK_I2C4>, <&cru PCLK_I2C4>; + clock-names = "i2c", "pclk"; + pinctrl-0 = <&i2c4m0_xfer>; + pinctrl-names = "default"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c5: i2c@fe5e0000 { + compatible = "rockchip,rk3568-i2c", "rockchip,rk3399-i2c"; + reg = <0x0 0xfe5e0000 0x0 0x1000>; + interrupts = ; + clocks = <&cru CLK_I2C5>, <&cru PCLK_I2C5>; + clock-names = "i2c", "pclk"; + pinctrl-0 = <&i2c5m0_xfer>; + pinctrl-names = "default"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + wdt: watchdog@fe600000 { + compatible = "rockchip,rk3568-wdt", "snps,dw-wdt"; + reg = <0x0 0xfe600000 0x0 0x100>; + interrupts = ; + clocks = <&cru TCLK_WDT_NS>, <&cru PCLK_WDT_NS>; + clock-names = "tclk", "pclk"; + }; + + spi0: spi@fe610000 { + compatible = "rockchip,rk3568-spi", "rockchip,rk3066-spi"; + reg = <0x0 0xfe610000 0x0 0x1000>; + interrupts = ; + clocks = <&cru CLK_SPI0>, <&cru PCLK_SPI0>; + clock-names = "spiclk", "apb_pclk"; + dmas = <&dmac0 20>, <&dmac0 21>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&spi0m0_cs0 &spi0m0_cs1 &spi0m0_pins>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi1: spi@fe620000 { + compatible = "rockchip,rk3568-spi", "rockchip,rk3066-spi"; + reg = <0x0 0xfe620000 0x0 0x1000>; + interrupts = ; + clocks = <&cru CLK_SPI1>, <&cru PCLK_SPI1>; + clock-names = "spiclk", "apb_pclk"; + dmas = <&dmac0 22>, <&dmac0 23>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&spi1m0_cs0 &spi1m0_cs1 &spi1m0_pins>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi2: spi@fe630000 { + compatible = "rockchip,rk3568-spi", "rockchip,rk3066-spi"; + reg = <0x0 0xfe630000 0x0 0x1000>; + interrupts = ; + clocks = <&cru CLK_SPI2>, <&cru PCLK_SPI2>; + clock-names = "spiclk", "apb_pclk"; + dmas = <&dmac0 24>, <&dmac0 25>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&spi2m0_cs0 &spi2m0_cs1 &spi2m0_pins>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi3: spi@fe640000 { + compatible = "rockchip,rk3568-spi", "rockchip,rk3066-spi"; + reg = <0x0 0xfe640000 0x0 0x1000>; + interrupts = ; + clocks = <&cru CLK_SPI3>, <&cru PCLK_SPI3>; + clock-names = "spiclk", "apb_pclk"; + dmas = <&dmac0 26>, <&dmac0 27>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&spi3m0_cs0 &spi3m0_cs1 &spi3m0_pins>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + uart1: serial@fe650000 { + compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; + reg = <0x0 0xfe650000 0x0 0x100>; + interrupts = ; + clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>; + clock-names = "baudclk", "apb_pclk"; + dmas = <&dmac0 2>, <&dmac0 3>; + pinctrl-0 = <&uart1m0_xfer>; + pinctrl-names = "default"; + reg-io-width = <4>; + reg-shift = <2>; + status = "disabled"; + }; + + uart2: serial@fe660000 { + compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; + reg = <0x0 0xfe660000 0x0 0x100>; + interrupts = ; + clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>; + clock-names = "baudclk", "apb_pclk"; + dmas = <&dmac0 4>, <&dmac0 5>; + pinctrl-0 = <&uart2m0_xfer>; + pinctrl-names = "default"; + reg-io-width = <4>; + reg-shift = <2>; + status = "disabled"; + }; + + uart3: serial@fe670000 { + compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; + reg = <0x0 0xfe670000 0x0 0x100>; + interrupts = ; + clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>; + clock-names = "baudclk", "apb_pclk"; + dmas = <&dmac0 6>, <&dmac0 7>; + pinctrl-0 = <&uart3m0_xfer>; + pinctrl-names = "default"; + reg-io-width = <4>; + reg-shift = <2>; + status = "disabled"; + }; + + uart4: serial@fe680000 { + compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; + reg = <0x0 0xfe680000 0x0 0x100>; + interrupts = ; + clocks = <&cru SCLK_UART4>, <&cru PCLK_UART4>; + clock-names = "baudclk", "apb_pclk"; + dmas = <&dmac0 8>, <&dmac0 9>; + pinctrl-0 = <&uart4m0_xfer>; + pinctrl-names = "default"; + reg-io-width = <4>; + reg-shift = <2>; + status = "disabled"; + }; + + uart5: serial@fe690000 { + compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; + reg = <0x0 0xfe690000 0x0 0x100>; + interrupts = ; + clocks = <&cru SCLK_UART5>, <&cru PCLK_UART5>; + clock-names = "baudclk", "apb_pclk"; + dmas = <&dmac0 10>, <&dmac0 11>; + pinctrl-0 = <&uart5m0_xfer>; + pinctrl-names = "default"; + reg-io-width = <4>; + reg-shift = <2>; + status = "disabled"; + }; + + uart6: serial@fe6a0000 { + compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; + reg = <0x0 0xfe6a0000 0x0 0x100>; + interrupts = ; + clocks = <&cru SCLK_UART6>, <&cru PCLK_UART6>; + clock-names = "baudclk", "apb_pclk"; + dmas = <&dmac0 12>, <&dmac0 13>; + pinctrl-0 = <&uart6m0_xfer>; + pinctrl-names = "default"; + reg-io-width = <4>; + reg-shift = <2>; + status = "disabled"; + }; + + uart7: serial@fe6b0000 { + compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; + reg = <0x0 0xfe6b0000 0x0 0x100>; + interrupts = ; + clocks = <&cru SCLK_UART7>, <&cru PCLK_UART7>; + clock-names = "baudclk", "apb_pclk"; + dmas = <&dmac0 14>, <&dmac0 15>; + pinctrl-0 = <&uart7m0_xfer>; + pinctrl-names = "default"; + reg-io-width = <4>; + reg-shift = <2>; + status = "disabled"; + }; + + uart8: serial@fe6c0000 { + compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; + reg = <0x0 0xfe6c0000 0x0 0x100>; + interrupts = ; + clocks = <&cru SCLK_UART8>, <&cru PCLK_UART8>; + clock-names = "baudclk", "apb_pclk"; + dmas = <&dmac0 16>, <&dmac0 17>; + pinctrl-0 = <&uart8m0_xfer>; + pinctrl-names = "default"; + reg-io-width = <4>; + reg-shift = <2>; + status = "disabled"; + }; + + uart9: serial@fe6d0000 { + compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; + reg = <0x0 0xfe6d0000 0x0 0x100>; + interrupts = ; + clocks = <&cru SCLK_UART9>, <&cru PCLK_UART9>; + clock-names = "baudclk", "apb_pclk"; + dmas = <&dmac0 18>, <&dmac0 19>; + pinctrl-0 = <&uart9m0_xfer>; + pinctrl-names = "default"; + reg-io-width = <4>; + reg-shift = <2>; + status = "disabled"; + }; + + thermal_zones: thermal-zones { + cpu_thermal: cpu-thermal { + polling-delay-passive = <100>; + polling-delay = <1000>; + + thermal-sensors = <&tsadc 0>; + + trips { + cpu_alert0: cpu_alert0 { + temperature = <70000>; + hysteresis = <2000>; + type = "passive"; + }; + cpu_alert1: cpu_alert1 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + cpu_crit: cpu_crit { + temperature = <95000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu_alert0>; + cooling-device = + <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + gpu_thermal: gpu-thermal { + polling-delay-passive = <20>; /* milliseconds */ + polling-delay = <1000>; /* milliseconds */ + + thermal-sensors = <&tsadc 1>; + + trips { + gpu_threshold: gpu-threshold { + temperature = <70000>; + hysteresis = <2000>; + type = "passive"; + }; + gpu_target: gpu-target { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + gpu_crit: gpu-crit { + temperature = <95000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&gpu_target>; + cooling-device = + <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + }; + + tsadc: tsadc@fe710000 { + compatible = "rockchip,rk3568-tsadc"; + reg = <0x0 0xfe710000 0x0 0x100>; + interrupts = ; + assigned-clocks = <&cru CLK_TSADC_TSEN>, <&cru CLK_TSADC>; + assigned-clock-rates = <17000000>, <700000>; + clocks = <&cru CLK_TSADC>, <&cru PCLK_TSADC>; + clock-names = "tsadc", "apb_pclk"; + resets = <&cru SRST_P_TSADC>, <&cru SRST_TSADC>, + <&cru SRST_TSADCPHY>; + rockchip,grf = <&grf>; + rockchip,hw-tshut-temp = <95000>; + pinctrl-names = "init", "default", "sleep"; + pinctrl-0 = <&tsadc_pin>; + pinctrl-1 = <&tsadc_shutorg>; + pinctrl-2 = <&tsadc_pin>; + #thermal-sensor-cells = <1>; + status = "disabled"; + }; + + saradc: saradc@fe720000 { + compatible = "rockchip,rk3568-saradc", "rockchip,rk3399-saradc"; + reg = <0x0 0xfe720000 0x0 0x100>; + interrupts = ; + clocks = <&cru CLK_SARADC>, <&cru PCLK_SARADC>; + clock-names = "saradc", "apb_pclk"; + resets = <&cru SRST_P_SARADC>; + reset-names = "saradc-apb"; + #io-channel-cells = <1>; + status = "disabled"; + }; + + pwm4: pwm@fe6e0000 { + compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; + reg = <0x0 0xfe6e0000 0x0 0x10>; + clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>; + clock-names = "pwm", "pclk"; + pinctrl-0 = <&pwm4_pins>; + pinctrl-names = "default"; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm5: pwm@fe6e0010 { + compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; + reg = <0x0 0xfe6e0010 0x0 0x10>; + clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>; + clock-names = "pwm", "pclk"; + pinctrl-0 = <&pwm5_pins>; + pinctrl-names = "default"; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm6: pwm@fe6e0020 { + compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; + reg = <0x0 0xfe6e0020 0x0 0x10>; + clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>; + clock-names = "pwm", "pclk"; + pinctrl-0 = <&pwm6_pins>; + pinctrl-names = "default"; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm7: pwm@fe6e0030 { + compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; + reg = <0x0 0xfe6e0030 0x0 0x10>; + clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>; + clock-names = "pwm", "pclk"; + pinctrl-0 = <&pwm7_pins>; + pinctrl-names = "default"; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm8: pwm@fe6f0000 { + compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; + reg = <0x0 0xfe6f0000 0x0 0x10>; + clocks = <&cru CLK_PWM2>, <&cru PCLK_PWM2>; + clock-names = "pwm", "pclk"; + pinctrl-0 = <&pwm8m0_pins>; + pinctrl-names = "default"; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm9: pwm@fe6f0010 { + compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; + reg = <0x0 0xfe6f0010 0x0 0x10>; + clocks = <&cru CLK_PWM2>, <&cru PCLK_PWM2>; + clock-names = "pwm", "pclk"; + pinctrl-0 = <&pwm9m0_pins>; + pinctrl-names = "default"; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm10: pwm@fe6f0020 { + compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; + reg = <0x0 0xfe6f0020 0x0 0x10>; + clocks = <&cru CLK_PWM2>, <&cru PCLK_PWM2>; + clock-names = "pwm", "pclk"; + pinctrl-0 = <&pwm10m0_pins>; + pinctrl-names = "default"; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm11: pwm@fe6f0030 { + compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; + reg = <0x0 0xfe6f0030 0x0 0x10>; + clocks = <&cru CLK_PWM2>, <&cru PCLK_PWM2>; + clock-names = "pwm", "pclk"; + pinctrl-0 = <&pwm11m0_pins>; + pinctrl-names = "default"; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm12: pwm@fe700000 { + compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; + reg = <0x0 0xfe700000 0x0 0x10>; + clocks = <&cru CLK_PWM3>, <&cru PCLK_PWM3>; + clock-names = "pwm", "pclk"; + pinctrl-0 = <&pwm12m0_pins>; + pinctrl-names = "default"; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm13: pwm@fe700010 { + compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; + reg = <0x0 0xfe700010 0x0 0x10>; + clocks = <&cru CLK_PWM3>, <&cru PCLK_PWM3>; + clock-names = "pwm", "pclk"; + pinctrl-0 = <&pwm13m0_pins>; + pinctrl-names = "default"; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm14: pwm@fe700020 { + compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; + reg = <0x0 0xfe700020 0x0 0x10>; + clocks = <&cru CLK_PWM3>, <&cru PCLK_PWM3>; + clock-names = "pwm", "pclk"; + pinctrl-0 = <&pwm14m0_pins>; + pinctrl-names = "default"; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm15: pwm@fe700030 { + compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm"; + reg = <0x0 0xfe700030 0x0 0x10>; + clocks = <&cru CLK_PWM3>, <&cru PCLK_PWM3>; + clock-names = "pwm", "pclk"; + pinctrl-0 = <&pwm15m0_pins>; + pinctrl-names = "default"; + #pwm-cells = <3>; + status = "disabled"; + }; + + combphy1: phy@fe830000 { + compatible = "rockchip,rk3568-naneng-combphy"; + reg = <0x0 0xfe830000 0x0 0x100>; + clocks = <&pmucru CLK_PCIEPHY1_REF>, + <&cru PCLK_PIPEPHY1>, + <&cru PCLK_PIPE>; + clock-names = "ref", "apb", "pipe"; + assigned-clocks = <&pmucru CLK_PCIEPHY1_REF>; + assigned-clock-rates = <100000000>; + resets = <&cru SRST_PIPEPHY1>; + rockchip,pipe-grf = <&pipegrf>; + rockchip,pipe-phy-grf = <&pipe_phy_grf1>; + #phy-cells = <1>; + status = "disabled"; + }; + + combphy2: phy@fe840000 { + compatible = "rockchip,rk3568-naneng-combphy"; + reg = <0x0 0xfe840000 0x0 0x100>; + clocks = <&pmucru CLK_PCIEPHY2_REF>, + <&cru PCLK_PIPEPHY2>, + <&cru PCLK_PIPE>; + clock-names = "ref", "apb", "pipe"; + assigned-clocks = <&pmucru CLK_PCIEPHY2_REF>; + assigned-clock-rates = <100000000>; + resets = <&cru SRST_PIPEPHY2>; + rockchip,pipe-grf = <&pipegrf>; + rockchip,pipe-phy-grf = <&pipe_phy_grf2>; + #phy-cells = <1>; + status = "disabled"; + }; + + csi_dphy: phy@fe870000 { + compatible = "rockchip,rk3568-csi-dphy"; + reg = <0x0 0xfe870000 0x0 0x10000>; + clocks = <&cru PCLK_MIPICSIPHY>; + clock-names = "pclk"; + #phy-cells = <0>; + resets = <&cru SRST_P_MIPICSIPHY>; + reset-names = "apb"; + rockchip,grf = <&grf>; + status = "disabled"; + }; + + dsi_dphy0: mipi-dphy@fe850000 { + compatible = "rockchip,rk3568-dsi-dphy"; + reg = <0x0 0xfe850000 0x0 0x10000>; + clock-names = "ref", "pclk"; + clocks = <&pmucru CLK_MIPIDSIPHY0_REF>, <&cru PCLK_MIPIDSIPHY0>; + #phy-cells = <0>; + power-domains = <&power RK3568_PD_VO>; + reset-names = "apb"; + resets = <&cru SRST_P_MIPIDSIPHY0>; + status = "disabled"; + }; + + dsi_dphy1: mipi-dphy@fe860000 { + compatible = "rockchip,rk3568-dsi-dphy"; + reg = <0x0 0xfe860000 0x0 0x10000>; + clock-names = "ref", "pclk"; + clocks = <&pmucru CLK_MIPIDSIPHY1_REF>, <&cru PCLK_MIPIDSIPHY1>; + #phy-cells = <0>; + power-domains = <&power RK3568_PD_VO>; + reset-names = "apb"; + resets = <&cru SRST_P_MIPIDSIPHY1>; + status = "disabled"; + }; + + usb2phy0: usb2phy@fe8a0000 { + compatible = "rockchip,rk3568-usb2phy"; + reg = <0x0 0xfe8a0000 0x0 0x10000>; + clocks = <&pmucru CLK_USBPHY0_REF>; + clock-names = "phyclk"; + clock-output-names = "clk_usbphy0_480m"; + interrupts = ; + rockchip,usbgrf = <&usb2phy0_grf>; + #clock-cells = <0>; + status = "disabled"; + + usb2phy0_host: host-port { + #phy-cells = <0>; + status = "disabled"; + }; + + usb2phy0_otg: otg-port { + #phy-cells = <0>; + status = "disabled"; + }; + }; + + usb2phy1: usb2phy@fe8b0000 { + compatible = "rockchip,rk3568-usb2phy"; + reg = <0x0 0xfe8b0000 0x0 0x10000>; + clocks = <&pmucru CLK_USBPHY1_REF>; + clock-names = "phyclk"; + clock-output-names = "clk_usbphy1_480m"; + interrupts = ; + rockchip,usbgrf = <&usb2phy1_grf>; + #clock-cells = <0>; + status = "disabled"; + + usb2phy1_host: host-port { + #phy-cells = <0>; + status = "disabled"; + }; + + usb2phy1_otg: otg-port { + #phy-cells = <0>; + status = "disabled"; + }; + }; + + pinctrl: pinctrl { + compatible = "rockchip,rk3568-pinctrl"; + rockchip,grf = <&grf>; + rockchip,pmu = <&pmugrf>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gpio0: gpio@fdd60000 { + compatible = "rockchip,gpio-bank"; + reg = <0x0 0xfdd60000 0x0 0x100>; + interrupts = ; + clocks = <&pmucru PCLK_GPIO0>, <&pmucru DBCLK_GPIO0>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio1: gpio@fe740000 { + compatible = "rockchip,gpio-bank"; + reg = <0x0 0xfe740000 0x0 0x100>; + interrupts = ; + clocks = <&cru PCLK_GPIO1>, <&cru DBCLK_GPIO1>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio2: gpio@fe750000 { + compatible = "rockchip,gpio-bank"; + reg = <0x0 0xfe750000 0x0 0x100>; + interrupts = ; + clocks = <&cru PCLK_GPIO2>, <&cru DBCLK_GPIO2>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio3: gpio@fe760000 { + compatible = "rockchip,gpio-bank"; + reg = <0x0 0xfe760000 0x0 0x100>; + interrupts = ; + clocks = <&cru PCLK_GPIO3>, <&cru DBCLK_GPIO3>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio4: gpio@fe770000 { + compatible = "rockchip,gpio-bank"; + reg = <0x0 0xfe770000 0x0 0x100>; + interrupts = ; + clocks = <&cru PCLK_GPIO4>, <&cru DBCLK_GPIO4>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; +}; + +#include "rk3568-pinctrl.dtsi" diff --git a/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rockchip-pinconf.dtsi b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rockchip-pinconf.dtsi new file mode 100644 index 00000000..5c645437 --- /dev/null +++ b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rockchip-pinconf.dtsi @@ -0,0 +1,344 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + */ + +&pinctrl { + /omit-if-no-ref/ + pcfg_pull_up: pcfg-pull-up { + bias-pull-up; + }; + + /omit-if-no-ref/ + pcfg_pull_down: pcfg-pull-down { + bias-pull-down; + }; + + /omit-if-no-ref/ + pcfg_pull_none: pcfg-pull-none { + bias-disable; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_0: pcfg-pull-none-drv-level-0 { + bias-disable; + drive-strength = <0>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_1: pcfg-pull-none-drv-level-1 { + bias-disable; + drive-strength = <1>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_2: pcfg-pull-none-drv-level-2 { + bias-disable; + drive-strength = <2>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_3: pcfg-pull-none-drv-level-3 { + bias-disable; + drive-strength = <3>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_4: pcfg-pull-none-drv-level-4 { + bias-disable; + drive-strength = <4>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_5: pcfg-pull-none-drv-level-5 { + bias-disable; + drive-strength = <5>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_6: pcfg-pull-none-drv-level-6 { + bias-disable; + drive-strength = <6>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_7: pcfg-pull-none-drv-level-7 { + bias-disable; + drive-strength = <7>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_8: pcfg-pull-none-drv-level-8 { + bias-disable; + drive-strength = <8>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_9: pcfg-pull-none-drv-level-9 { + bias-disable; + drive-strength = <9>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_10: pcfg-pull-none-drv-level-10 { + bias-disable; + drive-strength = <10>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_11: pcfg-pull-none-drv-level-11 { + bias-disable; + drive-strength = <11>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_12: pcfg-pull-none-drv-level-12 { + bias-disable; + drive-strength = <12>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_13: pcfg-pull-none-drv-level-13 { + bias-disable; + drive-strength = <13>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_14: pcfg-pull-none-drv-level-14 { + bias-disable; + drive-strength = <14>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_15: pcfg-pull-none-drv-level-15 { + bias-disable; + drive-strength = <15>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_0: pcfg-pull-up-drv-level-0 { + bias-pull-up; + drive-strength = <0>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_1: pcfg-pull-up-drv-level-1 { + bias-pull-up; + drive-strength = <1>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_2: pcfg-pull-up-drv-level-2 { + bias-pull-up; + drive-strength = <2>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_3: pcfg-pull-up-drv-level-3 { + bias-pull-up; + drive-strength = <3>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_4: pcfg-pull-up-drv-level-4 { + bias-pull-up; + drive-strength = <4>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_5: pcfg-pull-up-drv-level-5 { + bias-pull-up; + drive-strength = <5>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_6: pcfg-pull-up-drv-level-6 { + bias-pull-up; + drive-strength = <6>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_7: pcfg-pull-up-drv-level-7 { + bias-pull-up; + drive-strength = <7>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_8: pcfg-pull-up-drv-level-8 { + bias-pull-up; + drive-strength = <8>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_9: pcfg-pull-up-drv-level-9 { + bias-pull-up; + drive-strength = <9>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_10: pcfg-pull-up-drv-level-10 { + bias-pull-up; + drive-strength = <10>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_11: pcfg-pull-up-drv-level-11 { + bias-pull-up; + drive-strength = <11>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_12: pcfg-pull-up-drv-level-12 { + bias-pull-up; + drive-strength = <12>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_13: pcfg-pull-up-drv-level-13 { + bias-pull-up; + drive-strength = <13>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_14: pcfg-pull-up-drv-level-14 { + bias-pull-up; + drive-strength = <14>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_15: pcfg-pull-up-drv-level-15 { + bias-pull-up; + drive-strength = <15>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_0: pcfg-pull-down-drv-level-0 { + bias-pull-down; + drive-strength = <0>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_1: pcfg-pull-down-drv-level-1 { + bias-pull-down; + drive-strength = <1>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_2: pcfg-pull-down-drv-level-2 { + bias-pull-down; + drive-strength = <2>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_3: pcfg-pull-down-drv-level-3 { + bias-pull-down; + drive-strength = <3>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_4: pcfg-pull-down-drv-level-4 { + bias-pull-down; + drive-strength = <4>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_5: pcfg-pull-down-drv-level-5 { + bias-pull-down; + drive-strength = <5>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_6: pcfg-pull-down-drv-level-6 { + bias-pull-down; + drive-strength = <6>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_7: pcfg-pull-down-drv-level-7 { + bias-pull-down; + drive-strength = <7>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_8: pcfg-pull-down-drv-level-8 { + bias-pull-down; + drive-strength = <8>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_9: pcfg-pull-down-drv-level-9 { + bias-pull-down; + drive-strength = <9>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_10: pcfg-pull-down-drv-level-10 { + bias-pull-down; + drive-strength = <10>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_11: pcfg-pull-down-drv-level-11 { + bias-pull-down; + drive-strength = <11>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_12: pcfg-pull-down-drv-level-12 { + bias-pull-down; + drive-strength = <12>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_13: pcfg-pull-down-drv-level-13 { + bias-pull-down; + drive-strength = <13>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_14: pcfg-pull-down-drv-level-14 { + bias-pull-down; + drive-strength = <14>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_15: pcfg-pull-down-drv-level-15 { + bias-pull-down; + drive-strength = <15>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_smt: pcfg-pull-up-smt { + bias-pull-up; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_pull_down_smt: pcfg-pull-down-smt { + bias-pull-down; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_pull_none_smt: pcfg-pull-none-smt { + bias-disable; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_0_smt: pcfg-pull-none-drv-level-0-smt { + bias-disable; + drive-strength = <0>; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_output_high: pcfg-output-high { + output-high; + }; + + /omit-if-no-ref/ + pcfg_output_low: pcfg-output-low { + output-low; + }; +}; diff --git a/root/target/linux/rockchip/files/drivers/char/hw_random/rockchip-rng.c b/root/target/linux/rockchip/files/drivers/char/hw_random/rockchip-rng.c new file mode 100644 index 00000000..9a61f808 --- /dev/null +++ b/root/target/linux/rockchip/files/drivers/char/hw_random/rockchip-rng.c @@ -0,0 +1,310 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * rockchip-rng.c Random Number Generator driver for the Rockchip + * + * Copyright (c) 2018, Fuzhou Rockchip Electronics Co., Ltd. + * Author: Lin Jinhan + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define _SBF(s, v) ((v) << (s)) +#define HIWORD_UPDATE(val, mask, shift) \ + ((val) << (shift) | (mask) << ((shift) + 16)) + +#define ROCKCHIP_AUTOSUSPEND_DELAY 100 +#define ROCKCHIP_POLL_PERIOD_US 100 +#define ROCKCHIP_POLL_TIMEOUT_US 10000 +#define RK_MAX_RNG_BYTE (32) + +/* start of CRYPTO V1 register define */ +#define CRYPTO_V1_CTRL 0x0008 +#define CRYPTO_V1_RNG_START BIT(8) +#define CRYPTO_V1_RNG_FLUSH BIT(9) + +#define CRYPTO_V1_TRNG_CTRL 0x0200 +#define CRYPTO_V1_OSC_ENABLE BIT(16) +#define CRYPTO_V1_TRNG_SAMPLE_PERIOD(x) (x) + +#define CRYPTO_V1_TRNG_DOUT_0 0x0204 +/* end of CRYPTO V1 register define */ + +/* start of CRYPTO V2 register define */ +#define CRYPTO_V2_RNG_CTL 0x0400 +#define CRYPTO_V2_RNG_64_BIT_LEN _SBF(4, 0x00) +#define CRYPTO_V2_RNG_128_BIT_LEN _SBF(4, 0x01) +#define CRYPTO_V2_RNG_192_BIT_LEN _SBF(4, 0x02) +#define CRYPTO_V2_RNG_256_BIT_LEN _SBF(4, 0x03) +#define CRYPTO_V2_RNG_FATESY_SOC_RING _SBF(2, 0x00) +#define CRYPTO_V2_RNG_SLOWER_SOC_RING_0 _SBF(2, 0x01) +#define CRYPTO_V2_RNG_SLOWER_SOC_RING_1 _SBF(2, 0x02) +#define CRYPTO_V2_RNG_SLOWEST_SOC_RING _SBF(2, 0x03) +#define CRYPTO_V2_RNG_ENABLE BIT(1) +#define CRYPTO_V2_RNG_START BIT(0) +#define CRYPTO_V2_RNG_SAMPLE_CNT 0x0404 +#define CRYPTO_V2_RNG_DOUT_0 0x0410 +/* end of CRYPTO V2 register define */ + +struct rk_rng_soc_data { + int (*rk_rng_read)(struct hwrng *rng, void *buf, size_t max, bool wait); +}; + +struct rk_rng { + struct device *dev; + struct hwrng rng; + void __iomem *mem; + struct rk_rng_soc_data *soc_data; + int clk_num; + struct clk_bulk_data *clk_bulks; +}; + +static void rk_rng_writel(struct rk_rng *rng, u32 val, u32 offset) +{ + __raw_writel(val, rng->mem + offset); +} + +static u32 rk_rng_readl(struct rk_rng *rng, u32 offset) +{ + return __raw_readl(rng->mem + offset); +} + +static int rk_rng_init(struct hwrng *rng) +{ + int ret; + struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng); + + dev_dbg(rk_rng->dev, "clk_bulk_prepare_enable.\n"); + + ret = clk_bulk_prepare_enable(rk_rng->clk_num, rk_rng->clk_bulks); + if (ret < 0) { + dev_err(rk_rng->dev, "failed to enable clks %d\n", ret); + return ret; + } + + return 0; +} + +static void rk_rng_cleanup(struct hwrng *rng) +{ + struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng); + + dev_dbg(rk_rng->dev, "clk_bulk_disable_unprepare.\n"); + clk_bulk_disable_unprepare(rk_rng->clk_num, rk_rng->clk_bulks); +} + +static void rk_rng_read_regs(struct rk_rng *rng, u32 offset, void *buf, + size_t size) +{ + u32 i; + + for (i = 0; i < size; i += 4) + *(u32 *)(buf + i) = be32_to_cpu(rk_rng_readl(rng, offset + i)); +} + +static int rk_rng_v1_read(struct hwrng *rng, void *buf, size_t max, bool wait) +{ + int ret = 0; + u32 reg_ctrl = 0; + struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng); + + ret = pm_runtime_get_sync(rk_rng->dev); + if (ret < 0) { + pm_runtime_put_noidle(rk_rng->dev); + return ret; + } + + /* enable osc_ring to get entropy, sample period is set as 100 */ + reg_ctrl = CRYPTO_V1_OSC_ENABLE | CRYPTO_V1_TRNG_SAMPLE_PERIOD(100); + rk_rng_writel(rk_rng, reg_ctrl, CRYPTO_V1_TRNG_CTRL); + + reg_ctrl = HIWORD_UPDATE(CRYPTO_V1_RNG_START, CRYPTO_V1_RNG_START, 0); + + rk_rng_writel(rk_rng, reg_ctrl, CRYPTO_V1_CTRL); + + ret = readl_poll_timeout(rk_rng->mem + CRYPTO_V1_CTRL, reg_ctrl, + !(reg_ctrl & CRYPTO_V1_RNG_START), + ROCKCHIP_POLL_PERIOD_US, + ROCKCHIP_POLL_TIMEOUT_US); + if (ret < 0) + goto out; + + ret = min_t(size_t, max, RK_MAX_RNG_BYTE); + + rk_rng_read_regs(rk_rng, CRYPTO_V1_TRNG_DOUT_0, buf, ret); + +out: + /* close TRNG */ + rk_rng_writel(rk_rng, HIWORD_UPDATE(0, CRYPTO_V1_RNG_START, 0), + CRYPTO_V1_CTRL); + + pm_runtime_mark_last_busy(rk_rng->dev); + pm_runtime_put_sync_autosuspend(rk_rng->dev); + + return ret; +} + +static int rk_rng_v2_read(struct hwrng *rng, void *buf, size_t max, bool wait) +{ + int ret = 0; + u32 reg_ctrl = 0; + struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng); + + ret = pm_runtime_get_sync(rk_rng->dev); + if (ret < 0) { + pm_runtime_put_noidle(rk_rng->dev); + return ret; + } + + /* enable osc_ring to get entropy, sample period is set as 100 */ + rk_rng_writel(rk_rng, 100, CRYPTO_V2_RNG_SAMPLE_CNT); + + reg_ctrl |= CRYPTO_V2_RNG_256_BIT_LEN; + reg_ctrl |= CRYPTO_V2_RNG_SLOWER_SOC_RING_0; + reg_ctrl |= CRYPTO_V2_RNG_ENABLE; + reg_ctrl |= CRYPTO_V2_RNG_START; + + rk_rng_writel(rk_rng, HIWORD_UPDATE(reg_ctrl, 0xffff, 0), + CRYPTO_V2_RNG_CTL); + + ret = readl_poll_timeout(rk_rng->mem + CRYPTO_V2_RNG_CTL, reg_ctrl, + !(reg_ctrl & CRYPTO_V2_RNG_START), + ROCKCHIP_POLL_PERIOD_US, + ROCKCHIP_POLL_TIMEOUT_US); + if (ret < 0) + goto out; + + ret = min_t(size_t, max, RK_MAX_RNG_BYTE); + + rk_rng_read_regs(rk_rng, CRYPTO_V2_RNG_DOUT_0, buf, ret); + +out: + /* close TRNG */ + rk_rng_writel(rk_rng, HIWORD_UPDATE(0, 0xffff, 0), CRYPTO_V2_RNG_CTL); + + pm_runtime_mark_last_busy(rk_rng->dev); + pm_runtime_put_sync_autosuspend(rk_rng->dev); + + return ret; +} + +static const struct rk_rng_soc_data rk_rng_v1_soc_data = { + .rk_rng_read = rk_rng_v1_read, +}; + +static const struct rk_rng_soc_data rk_rng_v2_soc_data = { + .rk_rng_read = rk_rng_v2_read, +}; + +static const struct of_device_id rk_rng_dt_match[] = { + { + .compatible = "rockchip,cryptov1-rng", + .data = (void *)&rk_rng_v1_soc_data, + }, + { + .compatible = "rockchip,cryptov2-rng", + .data = (void *)&rk_rng_v2_soc_data, + }, + { }, +}; + +MODULE_DEVICE_TABLE(of, rk_rng_dt_match); + +static int rk_rng_probe(struct platform_device *pdev) +{ + int ret; + struct rk_rng *rk_rng; + struct device_node *np = pdev->dev.of_node; + const struct of_device_id *match; + + dev_dbg(&pdev->dev, "probing...\n"); + rk_rng = devm_kzalloc(&pdev->dev, sizeof(struct rk_rng), GFP_KERNEL); + if (!rk_rng) + return -ENOMEM; + + match = of_match_node(rk_rng_dt_match, np); + rk_rng->soc_data = (struct rk_rng_soc_data *)match->data; + + rk_rng->dev = &pdev->dev; + rk_rng->rng.name = "rockchip"; +#ifndef CONFIG_PM + rk_rng->rng.init = rk_rng_init; + rk_rng->rng.cleanup = rk_rng_cleanup, +#endif + rk_rng->rng.read = rk_rng->soc_data->rk_rng_read; + rk_rng->rng.quality = 999; + + rk_rng->mem = devm_of_iomap(&pdev->dev, pdev->dev.of_node, 0, NULL); + if (IS_ERR(rk_rng->mem)) + return PTR_ERR(rk_rng->mem); + + rk_rng->clk_num = devm_clk_bulk_get_all(&pdev->dev, &rk_rng->clk_bulks); + if (rk_rng->clk_num < 0) { + dev_err(&pdev->dev, "failed to get clks property\n"); + return -ENODEV; + } + + platform_set_drvdata(pdev, rk_rng); + + pm_runtime_set_autosuspend_delay(&pdev->dev, + ROCKCHIP_AUTOSUSPEND_DELAY); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_enable(&pdev->dev); + + ret = devm_hwrng_register(&pdev->dev, &rk_rng->rng); + if (ret) { + pm_runtime_dont_use_autosuspend(&pdev->dev); + pm_runtime_disable(&pdev->dev); + } + + return ret; +} + +#ifdef CONFIG_PM +static int rk_rng_runtime_suspend(struct device *dev) +{ + struct rk_rng *rk_rng = dev_get_drvdata(dev); + + rk_rng_cleanup(&rk_rng->rng); + + return 0; +} + +static int rk_rng_runtime_resume(struct device *dev) +{ + struct rk_rng *rk_rng = dev_get_drvdata(dev); + + return rk_rng_init(&rk_rng->rng); +} + +static const struct dev_pm_ops rk_rng_pm_ops = { + SET_RUNTIME_PM_OPS(rk_rng_runtime_suspend, + rk_rng_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + +#endif + +static struct platform_driver rk_rng_driver = { + .driver = { + .name = "rockchip-rng", +#ifdef CONFIG_PM + .pm = &rk_rng_pm_ops, +#endif + .of_match_table = rk_rng_dt_match, + }, + .probe = rk_rng_probe, +}; + +module_platform_driver(rk_rng_driver); + +MODULE_DESCRIPTION("ROCKCHIP H/W Random Number Generator driver"); +MODULE_AUTHOR("Lin Jinhan "); +MODULE_LICENSE("GPL v2"); diff --git a/root/target/linux/rockchip/files/drivers/devfreq/rk3328_dmc.c b/root/target/linux/rockchip/files/drivers/devfreq/rk3328_dmc.c new file mode 100644 index 00000000..72601a09 --- /dev/null +++ b/root/target/linux/rockchip/files/drivers/devfreq/rk3328_dmc.c @@ -0,0 +1,852 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd. + * Author: Lin Huang + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DTS_PAR_OFFSET (4096) + +struct share_params { + u32 hz; + u32 lcdc_type; + u32 vop; + u32 vop_dclk_mode; + u32 sr_idle_en; + u32 addr_mcu_el3; + /* + * 1: need to wait flag1 + * 0: never wait flag1 + */ + u32 wait_flag1; + /* + * 1: need to wait flag1 + * 0: never wait flag1 + */ + u32 wait_flag0; + u32 complt_hwirq; + /* if need, add parameter after */ +}; + +static struct share_params *ddr_psci_param; + +/* hope this define can adapt all future platform */ +static const char * const rk3328_dts_timing[] = { + "ddr3_speed_bin", + "ddr4_speed_bin", + "pd_idle", + "sr_idle", + "sr_mc_gate_idle", + "srpd_lite_idle", + "standby_idle", + + "auto_pd_dis_freq", + "auto_sr_dis_freq", + "ddr3_dll_dis_freq", + "ddr4_dll_dis_freq", + "phy_dll_dis_freq", + + "ddr3_odt_dis_freq", + "phy_ddr3_odt_dis_freq", + "ddr3_drv", + "ddr3_odt", + "phy_ddr3_ca_drv", + "phy_ddr3_ck_drv", + "phy_ddr3_dq_drv", + "phy_ddr3_odt", + + "lpddr3_odt_dis_freq", + "phy_lpddr3_odt_dis_freq", + "lpddr3_drv", + "lpddr3_odt", + "phy_lpddr3_ca_drv", + "phy_lpddr3_ck_drv", + "phy_lpddr3_dq_drv", + "phy_lpddr3_odt", + + "lpddr4_odt_dis_freq", + "phy_lpddr4_odt_dis_freq", + "lpddr4_drv", + "lpddr4_dq_odt", + "lpddr4_ca_odt", + "phy_lpddr4_ca_drv", + "phy_lpddr4_ck_cs_drv", + "phy_lpddr4_dq_drv", + "phy_lpddr4_odt", + + "ddr4_odt_dis_freq", + "phy_ddr4_odt_dis_freq", + "ddr4_drv", + "ddr4_odt", + "phy_ddr4_ca_drv", + "phy_ddr4_ck_drv", + "phy_ddr4_dq_drv", + "phy_ddr4_odt", +}; + +static const char * const rk3328_dts_ca_timing[] = { + "ddr3a1_ddr4a9_de-skew", + "ddr3a0_ddr4a10_de-skew", + "ddr3a3_ddr4a6_de-skew", + "ddr3a2_ddr4a4_de-skew", + "ddr3a5_ddr4a8_de-skew", + "ddr3a4_ddr4a5_de-skew", + "ddr3a7_ddr4a11_de-skew", + "ddr3a6_ddr4a7_de-skew", + "ddr3a9_ddr4a0_de-skew", + "ddr3a8_ddr4a13_de-skew", + "ddr3a11_ddr4a3_de-skew", + "ddr3a10_ddr4cs0_de-skew", + "ddr3a13_ddr4a2_de-skew", + "ddr3a12_ddr4ba1_de-skew", + "ddr3a15_ddr4odt0_de-skew", + "ddr3a14_ddr4a1_de-skew", + "ddr3ba1_ddr4a15_de-skew", + "ddr3ba0_ddr4bg0_de-skew", + "ddr3ras_ddr4cke_de-skew", + "ddr3ba2_ddr4ba0_de-skew", + "ddr3we_ddr4bg1_de-skew", + "ddr3cas_ddr4a12_de-skew", + "ddr3ckn_ddr4ckn_de-skew", + "ddr3ckp_ddr4ckp_de-skew", + "ddr3cke_ddr4a16_de-skew", + "ddr3odt0_ddr4a14_de-skew", + "ddr3cs0_ddr4act_de-skew", + "ddr3reset_ddr4reset_de-skew", + "ddr3cs1_ddr4cs1_de-skew", + "ddr3odt1_ddr4odt1_de-skew", +}; + +static const char * const rk3328_dts_cs0_timing[] = { + "cs0_dm0_rx_de-skew", + "cs0_dm0_tx_de-skew", + "cs0_dq0_rx_de-skew", + "cs0_dq0_tx_de-skew", + "cs0_dq1_rx_de-skew", + "cs0_dq1_tx_de-skew", + "cs0_dq2_rx_de-skew", + "cs0_dq2_tx_de-skew", + "cs0_dq3_rx_de-skew", + "cs0_dq3_tx_de-skew", + "cs0_dq4_rx_de-skew", + "cs0_dq4_tx_de-skew", + "cs0_dq5_rx_de-skew", + "cs0_dq5_tx_de-skew", + "cs0_dq6_rx_de-skew", + "cs0_dq6_tx_de-skew", + "cs0_dq7_rx_de-skew", + "cs0_dq7_tx_de-skew", + "cs0_dqs0_rx_de-skew", + "cs0_dqs0p_tx_de-skew", + "cs0_dqs0n_tx_de-skew", + + "cs0_dm1_rx_de-skew", + "cs0_dm1_tx_de-skew", + "cs0_dq8_rx_de-skew", + "cs0_dq8_tx_de-skew", + "cs0_dq9_rx_de-skew", + "cs0_dq9_tx_de-skew", + "cs0_dq10_rx_de-skew", + "cs0_dq10_tx_de-skew", + "cs0_dq11_rx_de-skew", + "cs0_dq11_tx_de-skew", + "cs0_dq12_rx_de-skew", + "cs0_dq12_tx_de-skew", + "cs0_dq13_rx_de-skew", + "cs0_dq13_tx_de-skew", + "cs0_dq14_rx_de-skew", + "cs0_dq14_tx_de-skew", + "cs0_dq15_rx_de-skew", + "cs0_dq15_tx_de-skew", + "cs0_dqs1_rx_de-skew", + "cs0_dqs1p_tx_de-skew", + "cs0_dqs1n_tx_de-skew", + + "cs0_dm2_rx_de-skew", + "cs0_dm2_tx_de-skew", + "cs0_dq16_rx_de-skew", + "cs0_dq16_tx_de-skew", + "cs0_dq17_rx_de-skew", + "cs0_dq17_tx_de-skew", + "cs0_dq18_rx_de-skew", + "cs0_dq18_tx_de-skew", + "cs0_dq19_rx_de-skew", + "cs0_dq19_tx_de-skew", + "cs0_dq20_rx_de-skew", + "cs0_dq20_tx_de-skew", + "cs0_dq21_rx_de-skew", + "cs0_dq21_tx_de-skew", + "cs0_dq22_rx_de-skew", + "cs0_dq22_tx_de-skew", + "cs0_dq23_rx_de-skew", + "cs0_dq23_tx_de-skew", + "cs0_dqs2_rx_de-skew", + "cs0_dqs2p_tx_de-skew", + "cs0_dqs2n_tx_de-skew", + + "cs0_dm3_rx_de-skew", + "cs0_dm3_tx_de-skew", + "cs0_dq24_rx_de-skew", + "cs0_dq24_tx_de-skew", + "cs0_dq25_rx_de-skew", + "cs0_dq25_tx_de-skew", + "cs0_dq26_rx_de-skew", + "cs0_dq26_tx_de-skew", + "cs0_dq27_rx_de-skew", + "cs0_dq27_tx_de-skew", + "cs0_dq28_rx_de-skew", + "cs0_dq28_tx_de-skew", + "cs0_dq29_rx_de-skew", + "cs0_dq29_tx_de-skew", + "cs0_dq30_rx_de-skew", + "cs0_dq30_tx_de-skew", + "cs0_dq31_rx_de-skew", + "cs0_dq31_tx_de-skew", + "cs0_dqs3_rx_de-skew", + "cs0_dqs3p_tx_de-skew", + "cs0_dqs3n_tx_de-skew", +}; + +static const char * const rk3328_dts_cs1_timing[] = { + "cs1_dm0_rx_de-skew", + "cs1_dm0_tx_de-skew", + "cs1_dq0_rx_de-skew", + "cs1_dq0_tx_de-skew", + "cs1_dq1_rx_de-skew", + "cs1_dq1_tx_de-skew", + "cs1_dq2_rx_de-skew", + "cs1_dq2_tx_de-skew", + "cs1_dq3_rx_de-skew", + "cs1_dq3_tx_de-skew", + "cs1_dq4_rx_de-skew", + "cs1_dq4_tx_de-skew", + "cs1_dq5_rx_de-skew", + "cs1_dq5_tx_de-skew", + "cs1_dq6_rx_de-skew", + "cs1_dq6_tx_de-skew", + "cs1_dq7_rx_de-skew", + "cs1_dq7_tx_de-skew", + "cs1_dqs0_rx_de-skew", + "cs1_dqs0p_tx_de-skew", + "cs1_dqs0n_tx_de-skew", + + "cs1_dm1_rx_de-skew", + "cs1_dm1_tx_de-skew", + "cs1_dq8_rx_de-skew", + "cs1_dq8_tx_de-skew", + "cs1_dq9_rx_de-skew", + "cs1_dq9_tx_de-skew", + "cs1_dq10_rx_de-skew", + "cs1_dq10_tx_de-skew", + "cs1_dq11_rx_de-skew", + "cs1_dq11_tx_de-skew", + "cs1_dq12_rx_de-skew", + "cs1_dq12_tx_de-skew", + "cs1_dq13_rx_de-skew", + "cs1_dq13_tx_de-skew", + "cs1_dq14_rx_de-skew", + "cs1_dq14_tx_de-skew", + "cs1_dq15_rx_de-skew", + "cs1_dq15_tx_de-skew", + "cs1_dqs1_rx_de-skew", + "cs1_dqs1p_tx_de-skew", + "cs1_dqs1n_tx_de-skew", + + "cs1_dm2_rx_de-skew", + "cs1_dm2_tx_de-skew", + "cs1_dq16_rx_de-skew", + "cs1_dq16_tx_de-skew", + "cs1_dq17_rx_de-skew", + "cs1_dq17_tx_de-skew", + "cs1_dq18_rx_de-skew", + "cs1_dq18_tx_de-skew", + "cs1_dq19_rx_de-skew", + "cs1_dq19_tx_de-skew", + "cs1_dq20_rx_de-skew", + "cs1_dq20_tx_de-skew", + "cs1_dq21_rx_de-skew", + "cs1_dq21_tx_de-skew", + "cs1_dq22_rx_de-skew", + "cs1_dq22_tx_de-skew", + "cs1_dq23_rx_de-skew", + "cs1_dq23_tx_de-skew", + "cs1_dqs2_rx_de-skew", + "cs1_dqs2p_tx_de-skew", + "cs1_dqs2n_tx_de-skew", + + "cs1_dm3_rx_de-skew", + "cs1_dm3_tx_de-skew", + "cs1_dq24_rx_de-skew", + "cs1_dq24_tx_de-skew", + "cs1_dq25_rx_de-skew", + "cs1_dq25_tx_de-skew", + "cs1_dq26_rx_de-skew", + "cs1_dq26_tx_de-skew", + "cs1_dq27_rx_de-skew", + "cs1_dq27_tx_de-skew", + "cs1_dq28_rx_de-skew", + "cs1_dq28_tx_de-skew", + "cs1_dq29_rx_de-skew", + "cs1_dq29_tx_de-skew", + "cs1_dq30_rx_de-skew", + "cs1_dq30_tx_de-skew", + "cs1_dq31_rx_de-skew", + "cs1_dq31_tx_de-skew", + "cs1_dqs3_rx_de-skew", + "cs1_dqs3p_tx_de-skew", + "cs1_dqs3n_tx_de-skew", +}; + +struct rk3328_ddr_dts_config_timing { + unsigned int ddr3_speed_bin; + unsigned int ddr4_speed_bin; + unsigned int pd_idle; + unsigned int sr_idle; + unsigned int sr_mc_gate_idle; + unsigned int srpd_lite_idle; + unsigned int standby_idle; + + unsigned int auto_pd_dis_freq; + unsigned int auto_sr_dis_freq; + /* for ddr3 only */ + unsigned int ddr3_dll_dis_freq; + /* for ddr4 only */ + unsigned int ddr4_dll_dis_freq; + unsigned int phy_dll_dis_freq; + + unsigned int ddr3_odt_dis_freq; + unsigned int phy_ddr3_odt_dis_freq; + unsigned int ddr3_drv; + unsigned int ddr3_odt; + unsigned int phy_ddr3_ca_drv; + unsigned int phy_ddr3_ck_drv; + unsigned int phy_ddr3_dq_drv; + unsigned int phy_ddr3_odt; + + unsigned int lpddr3_odt_dis_freq; + unsigned int phy_lpddr3_odt_dis_freq; + unsigned int lpddr3_drv; + unsigned int lpddr3_odt; + unsigned int phy_lpddr3_ca_drv; + unsigned int phy_lpddr3_ck_drv; + unsigned int phy_lpddr3_dq_drv; + unsigned int phy_lpddr3_odt; + + unsigned int lpddr4_odt_dis_freq; + unsigned int phy_lpddr4_odt_dis_freq; + unsigned int lpddr4_drv; + unsigned int lpddr4_dq_odt; + unsigned int lpddr4_ca_odt; + unsigned int phy_lpddr4_ca_drv; + unsigned int phy_lpddr4_ck_cs_drv; + unsigned int phy_lpddr4_dq_drv; + unsigned int phy_lpddr4_odt; + + unsigned int ddr4_odt_dis_freq; + unsigned int phy_ddr4_odt_dis_freq; + unsigned int ddr4_drv; + unsigned int ddr4_odt; + unsigned int phy_ddr4_ca_drv; + unsigned int phy_ddr4_ck_drv; + unsigned int phy_ddr4_dq_drv; + unsigned int phy_ddr4_odt; + + unsigned int ca_skew[15]; + unsigned int cs0_skew[44]; + unsigned int cs1_skew[44]; + + unsigned int available; +}; + +struct rk3328_ddr_de_skew_setting { + unsigned int ca_de_skew[30]; + unsigned int cs0_de_skew[84]; + unsigned int cs1_de_skew[84]; +}; + +struct rk3328_dmcfreq { + struct device *dev; + struct devfreq *devfreq; + struct devfreq_simple_ondemand_data ondemand_data; + struct clk *dmc_clk; + struct devfreq_event_dev *edev; + struct mutex lock; + struct regulator *vdd_center; + unsigned long rate, target_rate; + unsigned long volt, target_volt; + + int (*set_auto_self_refresh)(u32 en); +}; + +static void +rk3328_de_skew_setting_2_register(struct rk3328_ddr_de_skew_setting *de_skew, + struct rk3328_ddr_dts_config_timing *tim) +{ + u32 n; + u32 offset; + u32 shift; + + memset_io(tim->ca_skew, 0, sizeof(tim->ca_skew)); + memset_io(tim->cs0_skew, 0, sizeof(tim->cs0_skew)); + memset_io(tim->cs1_skew, 0, sizeof(tim->cs1_skew)); + + /* CA de-skew */ + for (n = 0; n < ARRAY_SIZE(de_skew->ca_de_skew); n++) { + offset = n / 2; + shift = n % 2; + /* 0 => 4; 1 => 0 */ + shift = (shift == 0) ? 4 : 0; + tim->ca_skew[offset] &= ~(0xf << shift); + tim->ca_skew[offset] |= (de_skew->ca_de_skew[n] << shift); + } + + /* CS0 data de-skew */ + for (n = 0; n < ARRAY_SIZE(de_skew->cs0_de_skew); n++) { + offset = ((n / 21) * 11) + ((n % 21) / 2); + shift = ((n % 21) % 2); + if ((n % 21) == 20) + shift = 0; + else + /* 0 => 4; 1 => 0 */ + shift = (shift == 0) ? 4 : 0; + tim->cs0_skew[offset] &= ~(0xf << shift); + tim->cs0_skew[offset] |= (de_skew->cs0_de_skew[n] << shift); + } + + /* CS1 data de-skew */ + for (n = 0; n < ARRAY_SIZE(de_skew->cs1_de_skew); n++) { + offset = ((n / 21) * 11) + ((n % 21) / 2); + shift = ((n % 21) % 2); + if ((n % 21) == 20) + shift = 0; + else + /* 0 => 4; 1 => 0 */ + shift = (shift == 0) ? 4 : 0; + tim->cs1_skew[offset] &= ~(0xf << shift); + tim->cs1_skew[offset] |= (de_skew->cs1_de_skew[n] << shift); + } +} + +static void of_get_rk3328_timings(struct device *dev, + struct device_node *np, uint32_t *timing) +{ + struct device_node *np_tim; + u32 *p; + struct rk3328_ddr_dts_config_timing *dts_timing; + struct rk3328_ddr_de_skew_setting *de_skew; + int ret = 0; + u32 i; + + dts_timing = + (struct rk3328_ddr_dts_config_timing *)(timing + + DTS_PAR_OFFSET / 4); + + np_tim = of_parse_phandle(np, "ddr_timing", 0); + if (!np_tim) { + ret = -EINVAL; + goto end; + } + de_skew = kmalloc(sizeof(*de_skew), GFP_KERNEL); + if (!de_skew) { + ret = -ENOMEM; + goto end; + } + + p = (u32 *)dts_timing; + for (i = 0; i < ARRAY_SIZE(rk3328_dts_timing); i++) { + ret |= of_property_read_u32(np_tim, rk3328_dts_timing[i], + p + i); + } + p = (u32 *)de_skew->ca_de_skew; + for (i = 0; i < ARRAY_SIZE(rk3328_dts_ca_timing); i++) { + ret |= of_property_read_u32(np_tim, rk3328_dts_ca_timing[i], + p + i); + } + p = (u32 *)de_skew->cs0_de_skew; + for (i = 0; i < ARRAY_SIZE(rk3328_dts_cs0_timing); i++) { + ret |= of_property_read_u32(np_tim, rk3328_dts_cs0_timing[i], + p + i); + } + p = (u32 *)de_skew->cs1_de_skew; + for (i = 0; i < ARRAY_SIZE(rk3328_dts_cs1_timing); i++) { + ret |= of_property_read_u32(np_tim, rk3328_dts_cs1_timing[i], + p + i); + } + if (!ret) + rk3328_de_skew_setting_2_register(de_skew, dts_timing); + + kfree(de_skew); +end: + if (!ret) { + dts_timing->available = 1; + } else { + dts_timing->available = 0; + dev_err(dev, "of_get_ddr_timings: fail\n"); + } + + of_node_put(np_tim); +} + +static int rockchip_ddr_set_auto_self_refresh(uint32_t en) +{ + struct arm_smccc_res res; + + ddr_psci_param->sr_idle_en = en; + + arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, + SHARE_PAGE_TYPE_DDR, 0, ROCKCHIP_SIP_CONFIG_DRAM_SET_AT_SR, + 0, 0, 0, 0, &res); + + return res.a0; +} + +static int rk3328_dmc_init(struct platform_device *pdev, + struct rk3328_dmcfreq *dmcfreq) +{ + struct arm_smccc_res res; + u32 size, page_num; + + arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, + 0, 0, ROCKCHIP_SIP_CONFIG_DRAM_GET_VERSION, + 0, 0, 0, 0, &res); + if (res.a0 || (res.a1 < 0x101)) { + dev_err(&pdev->dev, + "trusted firmware need to update or is invalid\n"); + return -ENXIO; + } + + dev_notice(&pdev->dev, "current ATF version 0x%lx\n", res.a1); + + /* + * first 4KB is used for interface parameters + * after 4KB * N is dts parameters + */ + size = sizeof(struct rk3328_ddr_dts_config_timing); + page_num = DIV_ROUND_UP(size, 4096) + 1; + + arm_smccc_smc(ROCKCHIP_SIP_SHARE_MEM, + page_num, SHARE_PAGE_TYPE_DDR, 0, + 0, 0, 0, 0, &res); + if (res.a0 != 0) { + dev_err(&pdev->dev, "no ATF memory for init\n"); + return -ENOMEM; + } + + ddr_psci_param = ioremap(res.a1, page_num << 12); + of_get_rk3328_timings(&pdev->dev, pdev->dev.of_node, + (uint32_t *)ddr_psci_param); + + arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, + SHARE_PAGE_TYPE_DDR, 0, ROCKCHIP_SIP_CONFIG_DRAM_INIT, + 0, 0, 0, 0, &res); + if (res.a0) { + dev_err(&pdev->dev, "Rockchip dram init error %lx\n", res.a0); + return -ENOMEM; + } + + dmcfreq->set_auto_self_refresh = rockchip_ddr_set_auto_self_refresh; + + return 0; +} + +static int rk3328_dmcfreq_target(struct device *dev, unsigned long *freq, + u32 flags) +{ + struct rk3328_dmcfreq *dmcfreq = dev_get_drvdata(dev); + struct dev_pm_opp *opp; + unsigned long old_clk_rate = dmcfreq->rate; + unsigned long target_volt, target_rate; + int err; + + opp = devfreq_recommended_opp(dev, freq, flags); + if (IS_ERR(opp)) + return PTR_ERR(opp); + + target_rate = dev_pm_opp_get_freq(opp); + target_volt = dev_pm_opp_get_voltage(opp); + dev_pm_opp_put(opp); + + if (dmcfreq->rate == target_rate) + return 0; + + mutex_lock(&dmcfreq->lock); + + /* + * If frequency scaling from low to high, adjust voltage first. + * If frequency scaling from high to low, adjust frequency first. + */ + if (old_clk_rate < target_rate) { + err = regulator_set_voltage(dmcfreq->vdd_center, target_volt, + target_volt); + if (err) { + dev_err(dev, "Cannot set voltage %lu uV\n", + target_volt); + goto out; + } + } + + err = clk_set_rate(dmcfreq->dmc_clk, target_rate); + if (err) { + dev_err(dev, "Cannot set frequency %lu (%d)\n", target_rate, + err); + regulator_set_voltage(dmcfreq->vdd_center, dmcfreq->volt, + dmcfreq->volt); + goto out; + } + + /* + * Check the dpll rate, + * There only two result we will get, + * 1. Ddr frequency scaling fail, we still get the old rate. + * 2. Ddr frequency scaling sucessful, we get the rate we set. + */ + dmcfreq->rate = clk_get_rate(dmcfreq->dmc_clk); + + /* If get the incorrect rate, set voltage to old value. */ + if (dmcfreq->rate != target_rate) { + dev_err(dev, "Got wrong frequency, Request %lu, Current %lu\n", + target_rate, dmcfreq->rate); + regulator_set_voltage(dmcfreq->vdd_center, dmcfreq->volt, + dmcfreq->volt); + goto out; + } else if (old_clk_rate > target_rate) + err = regulator_set_voltage(dmcfreq->vdd_center, target_volt, + target_volt); + if (err) + dev_err(dev, "Cannot set voltage %lu uV\n", target_volt); + + dmcfreq->rate = target_rate; + dmcfreq->volt = target_volt; + +out: + mutex_unlock(&dmcfreq->lock); + return err; +} + +static int rk3328_dmcfreq_get_dev_status(struct device *dev, + struct devfreq_dev_status *stat) +{ + struct rk3328_dmcfreq *dmcfreq = dev_get_drvdata(dev); + struct devfreq_event_data edata; + int ret = 0; + + ret = devfreq_event_get_event(dmcfreq->edev, &edata); + if (ret < 0) + return ret; + + stat->current_frequency = dmcfreq->rate; + stat->busy_time = edata.load_count; + stat->total_time = edata.total_count; + + return ret; +} + +static int rk3328_dmcfreq_get_cur_freq(struct device *dev, unsigned long *freq) +{ + struct rk3328_dmcfreq *dmcfreq = dev_get_drvdata(dev); + + *freq = dmcfreq->rate; + + return 0; +} + +static struct devfreq_dev_profile rk3328_devfreq_dmc_profile = { + .polling_ms = 200, + .target = rk3328_dmcfreq_target, + .get_dev_status = rk3328_dmcfreq_get_dev_status, + .get_cur_freq = rk3328_dmcfreq_get_cur_freq, +}; + +static __maybe_unused int rk3328_dmcfreq_suspend(struct device *dev) +{ + struct rk3328_dmcfreq *dmcfreq = dev_get_drvdata(dev); + int ret = 0; + + ret = devfreq_event_disable_edev(dmcfreq->edev); + if (ret < 0) { + dev_err(dev, "failed to disable the devfreq-event devices\n"); + return ret; + } + + ret = devfreq_suspend_device(dmcfreq->devfreq); + if (ret < 0) { + dev_err(dev, "failed to suspend the devfreq devices\n"); + return ret; + } + + return 0; +} + +static __maybe_unused int rk3328_dmcfreq_resume(struct device *dev) +{ + struct rk3328_dmcfreq *dmcfreq = dev_get_drvdata(dev); + int ret = 0; + + ret = devfreq_event_enable_edev(dmcfreq->edev); + if (ret < 0) { + dev_err(dev, "failed to enable the devfreq-event devices\n"); + return ret; + } + + ret = devfreq_resume_device(dmcfreq->devfreq); + if (ret < 0) { + dev_err(dev, "failed to resume the devfreq devices\n"); + return ret; + } + return ret; +} + +static SIMPLE_DEV_PM_OPS(rk3328_dmcfreq_pm, rk3328_dmcfreq_suspend, + rk3328_dmcfreq_resume); + +static int rk3328_dmcfreq_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = pdev->dev.of_node; + struct rk3328_dmcfreq *data; + struct dev_pm_opp *opp; + int ret; + + data = devm_kzalloc(dev, sizeof(struct rk3328_dmcfreq), GFP_KERNEL); + if (!data) + return -ENOMEM; + + mutex_init(&data->lock); + + data->vdd_center = devm_regulator_get(dev, "center"); + if (IS_ERR(data->vdd_center)) { + if (PTR_ERR(data->vdd_center) == -EPROBE_DEFER) + return -EPROBE_DEFER; + + dev_err(dev, "Cannot get the regulator \"center\"\n"); + return PTR_ERR(data->vdd_center); + } + + data->dmc_clk = devm_clk_get(dev, "dmc_clk"); + if (IS_ERR(data->dmc_clk)) { + if (PTR_ERR(data->dmc_clk) == -EPROBE_DEFER) + return -EPROBE_DEFER; + + dev_err(dev, "Cannot get the clk dmc_clk\n"); + return PTR_ERR(data->dmc_clk); + } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0) + data->edev = devfreq_event_get_edev_by_phandle(dev, 0); +#else + data->edev = devfreq_event_get_edev_by_phandle(dev, "devfreq-events", 0); +#endif + if (IS_ERR(data->edev)) + return -EPROBE_DEFER; + + ret = devfreq_event_enable_edev(data->edev); + if (ret < 0) { + dev_err(dev, "failed to enable devfreq-event devices\n"); + return ret; + } + + ret = rk3328_dmc_init(pdev, data); + if (ret) + return ret; + + /* + * We add a devfreq driver to our parent since it has a device tree node + * with operating points. + */ + if (dev_pm_opp_of_add_table(dev)) { + dev_err(dev, "Invalid operating-points in device tree.\n"); + return -EINVAL; + } + + of_property_read_u32(np, "upthreshold", + &data->ondemand_data.upthreshold); + of_property_read_u32(np, "downdifferential", + &data->ondemand_data.downdifferential); + + data->rate = clk_get_rate(data->dmc_clk); + + opp = devfreq_recommended_opp(dev, &data->rate, 0); + if (IS_ERR(opp)) { + ret = PTR_ERR(opp); + goto err_free_opp; + } + + data->rate = dev_pm_opp_get_freq(opp); + data->volt = dev_pm_opp_get_voltage(opp); + dev_pm_opp_put(opp); + + rk3328_devfreq_dmc_profile.initial_freq = data->rate; + + data->devfreq = devm_devfreq_add_device(dev, + &rk3328_devfreq_dmc_profile, + DEVFREQ_GOV_SIMPLE_ONDEMAND, + &data->ondemand_data); + if (IS_ERR(data->devfreq)) { + ret = PTR_ERR(data->devfreq); + goto err_free_opp; + } + + devm_devfreq_register_opp_notifier(dev, data->devfreq); + + data->dev = dev; + platform_set_drvdata(pdev, data); + + return 0; + +err_free_opp: + dev_pm_opp_of_remove_table(&pdev->dev); + return ret; +} + +static int rk3328_dmcfreq_remove(struct platform_device *pdev) +{ + struct rk3328_dmcfreq *dmcfreq = dev_get_drvdata(&pdev->dev); + + /* + * Before remove the opp table we need to unregister the opp notifier. + */ + devm_devfreq_unregister_opp_notifier(dmcfreq->dev, dmcfreq->devfreq); + dev_pm_opp_of_remove_table(dmcfreq->dev); + + return 0; +} + +static const struct of_device_id rk3328dmc_devfreq_of_match[] = { + { .compatible = "rockchip,rk3328-dmc" }, + { }, +}; +MODULE_DEVICE_TABLE(of, rk3328dmc_devfreq_of_match); + +static struct platform_driver rk3328_dmcfreq_driver = { + .probe = rk3328_dmcfreq_probe, + .remove = rk3328_dmcfreq_remove, + .driver = { + .name = "rk3328-dmc-freq", + .pm = &rk3328_dmcfreq_pm, + .of_match_table = rk3328dmc_devfreq_of_match, + }, +}; +module_platform_driver(rk3328_dmcfreq_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Lin Huang "); +MODULE_DESCRIPTION("RK3328 dmcfreq driver with devfreq framework"); diff --git a/root/target/linux/rockchip/files/include/dt-bindings/clock/rk3568-cru.h b/root/target/linux/rockchip/files/include/dt-bindings/clock/rk3568-cru.h new file mode 100644 index 00000000..d2989086 --- /dev/null +++ b/root/target/linux/rockchip/files/include/dt-bindings/clock/rk3568-cru.h @@ -0,0 +1,926 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2021 Rockchip Electronics Co. Ltd. + * Author: Elaine Zhang + */ + +#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3568_H +#define _DT_BINDINGS_CLK_ROCKCHIP_RK3568_H + +/* pmucru-clocks indices */ + +/* pmucru plls */ +#define PLL_PPLL 1 +#define PLL_HPLL 2 + +/* pmucru clocks */ +#define XIN_OSC0_DIV 4 +#define CLK_RTC_32K 5 +#define CLK_PMU 6 +#define CLK_I2C0 7 +#define CLK_RTC32K_FRAC 8 +#define CLK_UART0_DIV 9 +#define CLK_UART0_FRAC 10 +#define SCLK_UART0 11 +#define DBCLK_GPIO0 12 +#define CLK_PWM0 13 +#define CLK_CAPTURE_PWM0_NDFT 14 +#define CLK_PMUPVTM 15 +#define CLK_CORE_PMUPVTM 16 +#define CLK_REF24M 17 +#define XIN_OSC0_USBPHY0_G 18 +#define CLK_USBPHY0_REF 19 +#define XIN_OSC0_USBPHY1_G 20 +#define CLK_USBPHY1_REF 21 +#define XIN_OSC0_MIPIDSIPHY0_G 22 +#define CLK_MIPIDSIPHY0_REF 23 +#define XIN_OSC0_MIPIDSIPHY1_G 24 +#define CLK_MIPIDSIPHY1_REF 25 +#define CLK_WIFI_DIV 26 +#define CLK_WIFI_OSC0 27 +#define CLK_WIFI 28 +#define CLK_PCIEPHY0_DIV 29 +#define CLK_PCIEPHY0_OSC0 30 +#define CLK_PCIEPHY0_REF 31 +#define CLK_PCIEPHY1_DIV 32 +#define CLK_PCIEPHY1_OSC0 33 +#define CLK_PCIEPHY1_REF 34 +#define CLK_PCIEPHY2_DIV 35 +#define CLK_PCIEPHY2_OSC0 36 +#define CLK_PCIEPHY2_REF 37 +#define CLK_PCIE30PHY_REF_M 38 +#define CLK_PCIE30PHY_REF_N 39 +#define CLK_HDMI_REF 40 +#define XIN_OSC0_EDPPHY_G 41 +#define PCLK_PDPMU 42 +#define PCLK_PMU 43 +#define PCLK_UART0 44 +#define PCLK_I2C0 45 +#define PCLK_GPIO0 46 +#define PCLK_PMUPVTM 47 +#define PCLK_PWM0 48 +#define CLK_PDPMU 49 +#define SCLK_32K_IOE 50 + +#define CLKPMU_NR_CLKS (SCLK_32K_IOE + 1) + +/* cru-clocks indices */ + +/* cru plls */ +#define PLL_APLL 1 +#define PLL_DPLL 2 +#define PLL_CPLL 3 +#define PLL_GPLL 4 +#define PLL_VPLL 5 +#define PLL_NPLL 6 + +/* cru clocks */ +#define CPLL_333M 9 +#define ARMCLK 10 +#define USB480M 11 +#define ACLK_CORE_NIU2BUS 18 +#define CLK_CORE_PVTM 19 +#define CLK_CORE_PVTM_CORE 20 +#define CLK_CORE_PVTPLL 21 +#define CLK_GPU_SRC 22 +#define CLK_GPU_PRE_NDFT 23 +#define CLK_GPU_PRE_MUX 24 +#define ACLK_GPU_PRE 25 +#define PCLK_GPU_PRE 26 +#define CLK_GPU 27 +#define CLK_GPU_NP5 28 +#define PCLK_GPU_PVTM 29 +#define CLK_GPU_PVTM 30 +#define CLK_GPU_PVTM_CORE 31 +#define CLK_GPU_PVTPLL 32 +#define CLK_NPU_SRC 33 +#define CLK_NPU_PRE_NDFT 34 +#define CLK_NPU 35 +#define CLK_NPU_NP5 36 +#define HCLK_NPU_PRE 37 +#define PCLK_NPU_PRE 38 +#define ACLK_NPU_PRE 39 +#define ACLK_NPU 40 +#define HCLK_NPU 41 +#define PCLK_NPU_PVTM 42 +#define CLK_NPU_PVTM 43 +#define CLK_NPU_PVTM_CORE 44 +#define CLK_NPU_PVTPLL 45 +#define CLK_DDRPHY1X_SRC 46 +#define CLK_DDRPHY1X_HWFFC_SRC 47 +#define CLK_DDR1X 48 +#define CLK_MSCH 49 +#define CLK24_DDRMON 50 +#define ACLK_GIC_AUDIO 51 +#define HCLK_GIC_AUDIO 52 +#define HCLK_SDMMC_BUFFER 53 +#define DCLK_SDMMC_BUFFER 54 +#define ACLK_GIC600 55 +#define ACLK_SPINLOCK 56 +#define HCLK_I2S0_8CH 57 +#define HCLK_I2S1_8CH 58 +#define HCLK_I2S2_2CH 59 +#define HCLK_I2S3_2CH 60 +#define CLK_I2S0_8CH_TX_SRC 61 +#define CLK_I2S0_8CH_TX_FRAC 62 +#define MCLK_I2S0_8CH_TX 63 +#define I2S0_MCLKOUT_TX 64 +#define CLK_I2S0_8CH_RX_SRC 65 +#define CLK_I2S0_8CH_RX_FRAC 66 +#define MCLK_I2S0_8CH_RX 67 +#define I2S0_MCLKOUT_RX 68 +#define CLK_I2S1_8CH_TX_SRC 69 +#define CLK_I2S1_8CH_TX_FRAC 70 +#define MCLK_I2S1_8CH_TX 71 +#define I2S1_MCLKOUT_TX 72 +#define CLK_I2S1_8CH_RX_SRC 73 +#define CLK_I2S1_8CH_RX_FRAC 74 +#define MCLK_I2S1_8CH_RX 75 +#define I2S1_MCLKOUT_RX 76 +#define CLK_I2S2_2CH_SRC 77 +#define CLK_I2S2_2CH_FRAC 78 +#define MCLK_I2S2_2CH 79 +#define I2S2_MCLKOUT 80 +#define CLK_I2S3_2CH_TX_SRC 81 +#define CLK_I2S3_2CH_TX_FRAC 82 +#define MCLK_I2S3_2CH_TX 83 +#define I2S3_MCLKOUT_TX 84 +#define CLK_I2S3_2CH_RX_SRC 85 +#define CLK_I2S3_2CH_RX_FRAC 86 +#define MCLK_I2S3_2CH_RX 87 +#define I2S3_MCLKOUT_RX 88 +#define HCLK_PDM 89 +#define MCLK_PDM 90 +#define HCLK_VAD 91 +#define HCLK_SPDIF_8CH 92 +#define MCLK_SPDIF_8CH_SRC 93 +#define MCLK_SPDIF_8CH_FRAC 94 +#define MCLK_SPDIF_8CH 95 +#define HCLK_AUDPWM 96 +#define SCLK_AUDPWM_SRC 97 +#define SCLK_AUDPWM_FRAC 98 +#define SCLK_AUDPWM 99 +#define HCLK_ACDCDIG 100 +#define CLK_ACDCDIG_I2C 101 +#define CLK_ACDCDIG_DAC 102 +#define CLK_ACDCDIG_ADC 103 +#define ACLK_SECURE_FLASH 104 +#define HCLK_SECURE_FLASH 105 +#define ACLK_CRYPTO_NS 106 +#define HCLK_CRYPTO_NS 107 +#define CLK_CRYPTO_NS_CORE 108 +#define CLK_CRYPTO_NS_PKA 109 +#define CLK_CRYPTO_NS_RNG 110 +#define HCLK_TRNG_NS 111 +#define CLK_TRNG_NS 112 +#define PCLK_OTPC_NS 113 +#define CLK_OTPC_NS_SBPI 114 +#define CLK_OTPC_NS_USR 115 +#define HCLK_NANDC 116 +#define NCLK_NANDC 117 +#define HCLK_SFC 118 +#define HCLK_SFC_XIP 119 +#define SCLK_SFC 120 +#define ACLK_EMMC 121 +#define HCLK_EMMC 122 +#define BCLK_EMMC 123 +#define CCLK_EMMC 124 +#define TCLK_EMMC 125 +#define ACLK_PIPE 126 +#define PCLK_PIPE 127 +#define PCLK_PIPE_GRF 128 +#define ACLK_PCIE20_MST 129 +#define ACLK_PCIE20_SLV 130 +#define ACLK_PCIE20_DBI 131 +#define PCLK_PCIE20 132 +#define CLK_PCIE20_AUX_NDFT 133 +#define CLK_PCIE20_AUX_DFT 134 +#define CLK_PCIE20_PIPE_DFT 135 +#define ACLK_PCIE30X1_MST 136 +#define ACLK_PCIE30X1_SLV 137 +#define ACLK_PCIE30X1_DBI 138 +#define PCLK_PCIE30X1 139 +#define CLK_PCIE30X1_AUX_NDFT 140 +#define CLK_PCIE30X1_AUX_DFT 141 +#define CLK_PCIE30X1_PIPE_DFT 142 +#define ACLK_PCIE30X2_MST 143 +#define ACLK_PCIE30X2_SLV 144 +#define ACLK_PCIE30X2_DBI 145 +#define PCLK_PCIE30X2 146 +#define CLK_PCIE30X2_AUX_NDFT 147 +#define CLK_PCIE30X2_AUX_DFT 148 +#define CLK_PCIE30X2_PIPE_DFT 149 +#define ACLK_SATA0 150 +#define CLK_SATA0_PMALIVE 151 +#define CLK_SATA0_RXOOB 152 +#define CLK_SATA0_PIPE_NDFT 153 +#define CLK_SATA0_PIPE_DFT 154 +#define ACLK_SATA1 155 +#define CLK_SATA1_PMALIVE 156 +#define CLK_SATA1_RXOOB 157 +#define CLK_SATA1_PIPE_NDFT 158 +#define CLK_SATA1_PIPE_DFT 159 +#define ACLK_SATA2 160 +#define CLK_SATA2_PMALIVE 161 +#define CLK_SATA2_RXOOB 162 +#define CLK_SATA2_PIPE_NDFT 163 +#define CLK_SATA2_PIPE_DFT 164 +#define ACLK_USB3OTG0 165 +#define CLK_USB3OTG0_REF 166 +#define CLK_USB3OTG0_SUSPEND 167 +#define ACLK_USB3OTG1 168 +#define CLK_USB3OTG1_REF 169 +#define CLK_USB3OTG1_SUSPEND 170 +#define CLK_XPCS_EEE 171 +#define PCLK_XPCS 172 +#define ACLK_PHP 173 +#define HCLK_PHP 174 +#define PCLK_PHP 175 +#define HCLK_SDMMC0 176 +#define CLK_SDMMC0 177 +#define HCLK_SDMMC1 178 +#define CLK_SDMMC1 179 +#define ACLK_GMAC0 180 +#define PCLK_GMAC0 181 +#define CLK_MAC0_2TOP 182 +#define CLK_MAC0_OUT 183 +#define CLK_MAC0_REFOUT 184 +#define CLK_GMAC0_PTP_REF 185 +#define ACLK_USB 186 +#define HCLK_USB 187 +#define PCLK_USB 188 +#define HCLK_USB2HOST0 189 +#define HCLK_USB2HOST0_ARB 190 +#define HCLK_USB2HOST1 191 +#define HCLK_USB2HOST1_ARB 192 +#define HCLK_SDMMC2 193 +#define CLK_SDMMC2 194 +#define ACLK_GMAC1 195 +#define PCLK_GMAC1 196 +#define CLK_MAC1_2TOP 197 +#define CLK_MAC1_OUT 198 +#define CLK_MAC1_REFOUT 199 +#define CLK_GMAC1_PTP_REF 200 +#define ACLK_PERIMID 201 +#define HCLK_PERIMID 202 +#define ACLK_VI 203 +#define HCLK_VI 204 +#define PCLK_VI 205 +#define ACLK_VICAP 206 +#define HCLK_VICAP 207 +#define DCLK_VICAP 208 +#define ICLK_VICAP_G 209 +#define ACLK_ISP 210 +#define HCLK_ISP 211 +#define CLK_ISP 212 +#define PCLK_CSI2HOST1 213 +#define CLK_CIF_OUT 214 +#define CLK_CAM0_OUT 215 +#define CLK_CAM1_OUT 216 +#define ACLK_VO 217 +#define HCLK_VO 218 +#define PCLK_VO 219 +#define ACLK_VOP_PRE 220 +#define ACLK_VOP 221 +#define HCLK_VOP 222 +#define DCLK_VOP0 223 +#define DCLK_VOP1 224 +#define DCLK_VOP2 225 +#define CLK_VOP_PWM 226 +#define ACLK_HDCP 227 +#define HCLK_HDCP 228 +#define PCLK_HDCP 229 +#define PCLK_HDMI_HOST 230 +#define CLK_HDMI_SFR 231 +#define PCLK_DSITX_0 232 +#define PCLK_DSITX_1 233 +#define PCLK_EDP_CTRL 234 +#define CLK_EDP_200M 235 +#define ACLK_VPU_PRE 236 +#define HCLK_VPU_PRE 237 +#define ACLK_VPU 238 +#define HCLK_VPU 239 +#define ACLK_RGA_PRE 240 +#define HCLK_RGA_PRE 241 +#define PCLK_RGA_PRE 242 +#define ACLK_RGA 243 +#define HCLK_RGA 244 +#define CLK_RGA_CORE 245 +#define ACLK_IEP 246 +#define HCLK_IEP 247 +#define CLK_IEP_CORE 248 +#define HCLK_EBC 249 +#define DCLK_EBC 250 +#define ACLK_JDEC 251 +#define HCLK_JDEC 252 +#define ACLK_JENC 253 +#define HCLK_JENC 254 +#define PCLK_EINK 255 +#define HCLK_EINK 256 +#define ACLK_RKVENC_PRE 257 +#define HCLK_RKVENC_PRE 258 +#define ACLK_RKVENC 259 +#define HCLK_RKVENC 260 +#define CLK_RKVENC_CORE 261 +#define ACLK_RKVDEC_PRE 262 +#define HCLK_RKVDEC_PRE 263 +#define ACLK_RKVDEC 264 +#define HCLK_RKVDEC 265 +#define CLK_RKVDEC_CA 266 +#define CLK_RKVDEC_CORE 267 +#define CLK_RKVDEC_HEVC_CA 268 +#define ACLK_BUS 269 +#define PCLK_BUS 270 +#define PCLK_TSADC 271 +#define CLK_TSADC_TSEN 272 +#define CLK_TSADC 273 +#define PCLK_SARADC 274 +#define CLK_SARADC 275 +#define PCLK_SCR 276 +#define PCLK_WDT_NS 277 +#define TCLK_WDT_NS 278 +#define ACLK_DMAC0 279 +#define ACLK_DMAC1 280 +#define ACLK_MCU 281 +#define PCLK_INTMUX 282 +#define PCLK_MAILBOX 283 +#define PCLK_UART1 284 +#define CLK_UART1_SRC 285 +#define CLK_UART1_FRAC 286 +#define SCLK_UART1 287 +#define PCLK_UART2 288 +#define CLK_UART2_SRC 289 +#define CLK_UART2_FRAC 290 +#define SCLK_UART2 291 +#define PCLK_UART3 292 +#define CLK_UART3_SRC 293 +#define CLK_UART3_FRAC 294 +#define SCLK_UART3 295 +#define PCLK_UART4 296 +#define CLK_UART4_SRC 297 +#define CLK_UART4_FRAC 298 +#define SCLK_UART4 299 +#define PCLK_UART5 300 +#define CLK_UART5_SRC 301 +#define CLK_UART5_FRAC 302 +#define SCLK_UART5 303 +#define PCLK_UART6 304 +#define CLK_UART6_SRC 305 +#define CLK_UART6_FRAC 306 +#define SCLK_UART6 307 +#define PCLK_UART7 308 +#define CLK_UART7_SRC 309 +#define CLK_UART7_FRAC 310 +#define SCLK_UART7 311 +#define PCLK_UART8 312 +#define CLK_UART8_SRC 313 +#define CLK_UART8_FRAC 314 +#define SCLK_UART8 315 +#define PCLK_UART9 316 +#define CLK_UART9_SRC 317 +#define CLK_UART9_FRAC 318 +#define SCLK_UART9 319 +#define PCLK_CAN0 320 +#define CLK_CAN0 321 +#define PCLK_CAN1 322 +#define CLK_CAN1 323 +#define PCLK_CAN2 324 +#define CLK_CAN2 325 +#define CLK_I2C 326 +#define PCLK_I2C1 327 +#define CLK_I2C1 328 +#define PCLK_I2C2 329 +#define CLK_I2C2 330 +#define PCLK_I2C3 331 +#define CLK_I2C3 332 +#define PCLK_I2C4 333 +#define CLK_I2C4 334 +#define PCLK_I2C5 335 +#define CLK_I2C5 336 +#define PCLK_SPI0 337 +#define CLK_SPI0 338 +#define PCLK_SPI1 339 +#define CLK_SPI1 340 +#define PCLK_SPI2 341 +#define CLK_SPI2 342 +#define PCLK_SPI3 343 +#define CLK_SPI3 344 +#define PCLK_PWM1 345 +#define CLK_PWM1 346 +#define CLK_PWM1_CAPTURE 347 +#define PCLK_PWM2 348 +#define CLK_PWM2 349 +#define CLK_PWM2_CAPTURE 350 +#define PCLK_PWM3 351 +#define CLK_PWM3 352 +#define CLK_PWM3_CAPTURE 353 +#define DBCLK_GPIO 354 +#define PCLK_GPIO1 355 +#define DBCLK_GPIO1 356 +#define PCLK_GPIO2 357 +#define DBCLK_GPIO2 358 +#define PCLK_GPIO3 359 +#define DBCLK_GPIO3 360 +#define PCLK_GPIO4 361 +#define DBCLK_GPIO4 362 +#define OCC_SCAN_CLK_GPIO 363 +#define PCLK_TIMER 364 +#define CLK_TIMER0 365 +#define CLK_TIMER1 366 +#define CLK_TIMER2 367 +#define CLK_TIMER3 368 +#define CLK_TIMER4 369 +#define CLK_TIMER5 370 +#define ACLK_TOP_HIGH 371 +#define ACLK_TOP_LOW 372 +#define HCLK_TOP 373 +#define PCLK_TOP 374 +#define PCLK_PCIE30PHY 375 +#define CLK_OPTC_ARB 376 +#define PCLK_MIPICSIPHY 377 +#define PCLK_MIPIDSIPHY0 378 +#define PCLK_MIPIDSIPHY1 379 +#define PCLK_PIPEPHY0 380 +#define PCLK_PIPEPHY1 381 +#define PCLK_PIPEPHY2 382 +#define PCLK_CPU_BOOST 383 +#define CLK_CPU_BOOST 384 +#define PCLK_OTPPHY 385 +#define SCLK_GMAC0 386 +#define SCLK_GMAC0_RGMII_SPEED 387 +#define SCLK_GMAC0_RMII_SPEED 388 +#define SCLK_GMAC0_RX_TX 389 +#define SCLK_GMAC1 390 +#define SCLK_GMAC1_RGMII_SPEED 391 +#define SCLK_GMAC1_RMII_SPEED 392 +#define SCLK_GMAC1_RX_TX 393 +#define SCLK_SDMMC0_DRV 394 +#define SCLK_SDMMC0_SAMPLE 395 +#define SCLK_SDMMC1_DRV 396 +#define SCLK_SDMMC1_SAMPLE 397 +#define SCLK_SDMMC2_DRV 398 +#define SCLK_SDMMC2_SAMPLE 399 +#define SCLK_EMMC_DRV 400 +#define SCLK_EMMC_SAMPLE 401 +#define PCLK_EDPPHY_GRF 402 +#define CLK_HDMI_CEC 403 +#define CLK_I2S0_8CH_TX 404 +#define CLK_I2S0_8CH_RX 405 +#define CLK_I2S1_8CH_TX 406 +#define CLK_I2S1_8CH_RX 407 +#define CLK_I2S2_2CH 408 +#define CLK_I2S3_2CH_TX 409 +#define CLK_I2S3_2CH_RX 410 +#define CPLL_500M 411 +#define CPLL_250M 412 +#define CPLL_125M 413 +#define CPLL_62P5M 414 +#define CPLL_50M 415 +#define CPLL_25M 416 +#define CPLL_100M 417 +#define SCLK_DDRCLK 418 + +#define PCLK_CORE_PVTM 450 + +#define CLK_NR_CLKS (PCLK_CORE_PVTM + 1) + +/* pmu soft-reset indices */ +/* pmucru_softrst_con0 */ +#define SRST_P_PDPMU_NIU 0 +#define SRST_P_PMUCRU 1 +#define SRST_P_PMUGRF 2 +#define SRST_P_I2C0 3 +#define SRST_I2C0 4 +#define SRST_P_UART0 5 +#define SRST_S_UART0 6 +#define SRST_P_PWM0 7 +#define SRST_PWM0 8 +#define SRST_P_GPIO0 9 +#define SRST_GPIO0 10 +#define SRST_P_PMUPVTM 11 +#define SRST_PMUPVTM 12 + +/* soft-reset indices */ + +/* cru_softrst_con0 */ +#define SRST_NCORERESET0 0 +#define SRST_NCORERESET1 1 +#define SRST_NCORERESET2 2 +#define SRST_NCORERESET3 3 +#define SRST_NCPUPORESET0 4 +#define SRST_NCPUPORESET1 5 +#define SRST_NCPUPORESET2 6 +#define SRST_NCPUPORESET3 7 +#define SRST_NSRESET 8 +#define SRST_NSPORESET 9 +#define SRST_NATRESET 10 +#define SRST_NGICRESET 11 +#define SRST_NPRESET 12 +#define SRST_NPERIPHRESET 13 + +/* cru_softrst_con1 */ +#define SRST_A_CORE_NIU2DDR 16 +#define SRST_A_CORE_NIU2BUS 17 +#define SRST_P_DBG_NIU 18 +#define SRST_P_DBG 19 +#define SRST_P_DBG_DAPLITE 20 +#define SRST_DAP 21 +#define SRST_A_ADB400_CORE2GIC 22 +#define SRST_A_ADB400_GIC2CORE 23 +#define SRST_P_CORE_GRF 24 +#define SRST_P_CORE_PVTM 25 +#define SRST_CORE_PVTM 26 +#define SRST_CORE_PVTPLL 27 + +/* cru_softrst_con2 */ +#define SRST_GPU 32 +#define SRST_A_GPU_NIU 33 +#define SRST_P_GPU_NIU 34 +#define SRST_P_GPU_PVTM 35 +#define SRST_GPU_PVTM 36 +#define SRST_GPU_PVTPLL 37 +#define SRST_A_NPU_NIU 40 +#define SRST_H_NPU_NIU 41 +#define SRST_P_NPU_NIU 42 +#define SRST_A_NPU 43 +#define SRST_H_NPU 44 +#define SRST_P_NPU_PVTM 45 +#define SRST_NPU_PVTM 46 +#define SRST_NPU_PVTPLL 47 + +/* cru_softrst_con3 */ +#define SRST_A_MSCH 51 +#define SRST_HWFFC_CTRL 52 +#define SRST_DDR_ALWAYSON 53 +#define SRST_A_DDRSPLIT 54 +#define SRST_DDRDFI_CTL 55 +#define SRST_A_DMA2DDR 57 + +/* cru_softrst_con4 */ +#define SRST_A_PERIMID_NIU 64 +#define SRST_H_PERIMID_NIU 65 +#define SRST_A_GIC_AUDIO_NIU 66 +#define SRST_H_GIC_AUDIO_NIU 67 +#define SRST_A_GIC600 68 +#define SRST_A_GIC600_DEBUG 69 +#define SRST_A_GICADB_CORE2GIC 70 +#define SRST_A_GICADB_GIC2CORE 71 +#define SRST_A_SPINLOCK 72 +#define SRST_H_SDMMC_BUFFER 73 +#define SRST_D_SDMMC_BUFFER 74 +#define SRST_H_I2S0_8CH 75 +#define SRST_H_I2S1_8CH 76 +#define SRST_H_I2S2_2CH 77 +#define SRST_H_I2S3_2CH 78 + +/* cru_softrst_con5 */ +#define SRST_M_I2S0_8CH_TX 80 +#define SRST_M_I2S0_8CH_RX 81 +#define SRST_M_I2S1_8CH_TX 82 +#define SRST_M_I2S1_8CH_RX 83 +#define SRST_M_I2S2_2CH 84 +#define SRST_M_I2S3_2CH_TX 85 +#define SRST_M_I2S3_2CH_RX 86 +#define SRST_H_PDM 87 +#define SRST_M_PDM 88 +#define SRST_H_VAD 89 +#define SRST_H_SPDIF_8CH 90 +#define SRST_M_SPDIF_8CH 91 +#define SRST_H_AUDPWM 92 +#define SRST_S_AUDPWM 93 +#define SRST_H_ACDCDIG 94 +#define SRST_ACDCDIG 95 + +/* cru_softrst_con6 */ +#define SRST_A_SECURE_FLASH_NIU 96 +#define SRST_H_SECURE_FLASH_NIU 97 +#define SRST_A_CRYPTO_NS 103 +#define SRST_H_CRYPTO_NS 104 +#define SRST_CRYPTO_NS_CORE 105 +#define SRST_CRYPTO_NS_PKA 106 +#define SRST_CRYPTO_NS_RNG 107 +#define SRST_H_TRNG_NS 108 +#define SRST_TRNG_NS 109 + +/* cru_softrst_con7 */ +#define SRST_H_NANDC 112 +#define SRST_N_NANDC 113 +#define SRST_H_SFC 114 +#define SRST_H_SFC_XIP 115 +#define SRST_S_SFC 116 +#define SRST_A_EMMC 117 +#define SRST_H_EMMC 118 +#define SRST_B_EMMC 119 +#define SRST_C_EMMC 120 +#define SRST_T_EMMC 121 + +/* cru_softrst_con8 */ +#define SRST_A_PIPE_NIU 128 +#define SRST_P_PIPE_NIU 130 +#define SRST_P_PIPE_GRF 133 +#define SRST_A_SATA0 134 +#define SRST_SATA0_PIPE 135 +#define SRST_SATA0_PMALIVE 136 +#define SRST_SATA0_RXOOB 137 +#define SRST_A_SATA1 138 +#define SRST_SATA1_PIPE 139 +#define SRST_SATA1_PMALIVE 140 +#define SRST_SATA1_RXOOB 141 + +/* cru_softrst_con9 */ +#define SRST_A_SATA2 144 +#define SRST_SATA2_PIPE 145 +#define SRST_SATA2_PMALIVE 146 +#define SRST_SATA2_RXOOB 147 +#define SRST_USB3OTG0 148 +#define SRST_USB3OTG1 149 +#define SRST_XPCS 150 +#define SRST_XPCS_TX_DIV10 151 +#define SRST_XPCS_RX_DIV10 152 +#define SRST_XPCS_XGXS_RX 153 + +/* cru_softrst_con10 */ +#define SRST_P_PCIE20 160 +#define SRST_PCIE20_POWERUP 161 +#define SRST_MSTR_ARESET_PCIE20 162 +#define SRST_SLV_ARESET_PCIE20 163 +#define SRST_DBI_ARESET_PCIE20 164 +#define SRST_BRESET_PCIE20 165 +#define SRST_PERST_PCIE20 166 +#define SRST_CORE_RST_PCIE20 167 +#define SRST_NSTICKY_RST_PCIE20 168 +#define SRST_STICKY_RST_PCIE20 169 +#define SRST_PWR_RST_PCIE20 170 + +/* cru_softrst_con11 */ +#define SRST_P_PCIE30X1 176 +#define SRST_PCIE30X1_POWERUP 177 +#define SRST_M_ARESET_PCIE30X1 178 +#define SRST_S_ARESET_PCIE30X1 179 +#define SRST_D_ARESET_PCIE30X1 180 +#define SRST_BRESET_PCIE30X1 181 +#define SRST_PERST_PCIE30X1 182 +#define SRST_CORE_RST_PCIE30X1 183 +#define SRST_NSTC_RST_PCIE30X1 184 +#define SRST_STC_RST_PCIE30X1 185 +#define SRST_PWR_RST_PCIE30X1 186 + +/* cru_softrst_con12 */ +#define SRST_P_PCIE30X2 192 +#define SRST_PCIE30X2_POWERUP 193 +#define SRST_M_ARESET_PCIE30X2 194 +#define SRST_S_ARESET_PCIE30X2 195 +#define SRST_D_ARESET_PCIE30X2 196 +#define SRST_BRESET_PCIE30X2 197 +#define SRST_PERST_PCIE30X2 198 +#define SRST_CORE_RST_PCIE30X2 199 +#define SRST_NSTC_RST_PCIE30X2 200 +#define SRST_STC_RST_PCIE30X2 201 +#define SRST_PWR_RST_PCIE30X2 202 + +/* cru_softrst_con13 */ +#define SRST_A_PHP_NIU 208 +#define SRST_H_PHP_NIU 209 +#define SRST_P_PHP_NIU 210 +#define SRST_H_SDMMC0 211 +#define SRST_SDMMC0 212 +#define SRST_H_SDMMC1 213 +#define SRST_SDMMC1 214 +#define SRST_A_GMAC0 215 +#define SRST_GMAC0_TIMESTAMP 216 + +/* cru_softrst_con14 */ +#define SRST_A_USB_NIU 224 +#define SRST_H_USB_NIU 225 +#define SRST_P_USB_NIU 226 +#define SRST_P_USB_GRF 227 +#define SRST_H_USB2HOST0 228 +#define SRST_H_USB2HOST0_ARB 229 +#define SRST_USB2HOST0_UTMI 230 +#define SRST_H_USB2HOST1 231 +#define SRST_H_USB2HOST1_ARB 232 +#define SRST_USB2HOST1_UTMI 233 +#define SRST_H_SDMMC2 234 +#define SRST_SDMMC2 235 +#define SRST_A_GMAC1 236 +#define SRST_GMAC1_TIMESTAMP 237 + +/* cru_softrst_con15 */ +#define SRST_A_VI_NIU 240 +#define SRST_H_VI_NIU 241 +#define SRST_P_VI_NIU 242 +#define SRST_A_VICAP 247 +#define SRST_H_VICAP 248 +#define SRST_D_VICAP 249 +#define SRST_I_VICAP 250 +#define SRST_P_VICAP 251 +#define SRST_H_ISP 252 +#define SRST_ISP 253 +#define SRST_P_CSI2HOST1 255 + +/* cru_softrst_con16 */ +#define SRST_A_VO_NIU 256 +#define SRST_H_VO_NIU 257 +#define SRST_P_VO_NIU 258 +#define SRST_A_VOP_NIU 259 +#define SRST_A_VOP 260 +#define SRST_H_VOP 261 +#define SRST_VOP0 262 +#define SRST_VOP1 263 +#define SRST_VOP2 264 +#define SRST_VOP_PWM 265 +#define SRST_A_HDCP 266 +#define SRST_H_HDCP 267 +#define SRST_P_HDCP 268 +#define SRST_P_HDMI_HOST 270 +#define SRST_HDMI_HOST 271 + +/* cru_softrst_con17 */ +#define SRST_P_DSITX_0 272 +#define SRST_P_DSITX_1 273 +#define SRST_P_EDP_CTRL 274 +#define SRST_EDP_24M 275 +#define SRST_A_VPU_NIU 280 +#define SRST_H_VPU_NIU 281 +#define SRST_A_VPU 282 +#define SRST_H_VPU 283 +#define SRST_H_EINK 286 +#define SRST_P_EINK 287 + +/* cru_softrst_con18 */ +#define SRST_A_RGA_NIU 288 +#define SRST_H_RGA_NIU 289 +#define SRST_P_RGA_NIU 290 +#define SRST_A_RGA 292 +#define SRST_H_RGA 293 +#define SRST_RGA_CORE 294 +#define SRST_A_IEP 295 +#define SRST_H_IEP 296 +#define SRST_IEP_CORE 297 +#define SRST_H_EBC 298 +#define SRST_D_EBC 299 +#define SRST_A_JDEC 300 +#define SRST_H_JDEC 301 +#define SRST_A_JENC 302 +#define SRST_H_JENC 303 + +/* cru_softrst_con19 */ +#define SRST_A_VENC_NIU 304 +#define SRST_H_VENC_NIU 305 +#define SRST_A_RKVENC 307 +#define SRST_H_RKVENC 308 +#define SRST_RKVENC_CORE 309 + +/* cru_softrst_con20 */ +#define SRST_A_RKVDEC_NIU 320 +#define SRST_H_RKVDEC_NIU 321 +#define SRST_A_RKVDEC 322 +#define SRST_H_RKVDEC 323 +#define SRST_RKVDEC_CA 324 +#define SRST_RKVDEC_CORE 325 +#define SRST_RKVDEC_HEVC_CA 326 + +/* cru_softrst_con21 */ +#define SRST_A_BUS_NIU 336 +#define SRST_P_BUS_NIU 338 +#define SRST_P_CAN0 340 +#define SRST_CAN0 341 +#define SRST_P_CAN1 342 +#define SRST_CAN1 343 +#define SRST_P_CAN2 344 +#define SRST_CAN2 345 +#define SRST_P_GPIO1 346 +#define SRST_GPIO1 347 +#define SRST_P_GPIO2 348 +#define SRST_GPIO2 349 +#define SRST_P_GPIO3 350 +#define SRST_GPIO3 351 + +/* cru_softrst_con22 */ +#define SRST_P_GPIO4 352 +#define SRST_GPIO4 353 +#define SRST_P_I2C1 354 +#define SRST_I2C1 355 +#define SRST_P_I2C2 356 +#define SRST_I2C2 357 +#define SRST_P_I2C3 358 +#define SRST_I2C3 359 +#define SRST_P_I2C4 360 +#define SRST_I2C4 361 +#define SRST_P_I2C5 362 +#define SRST_I2C5 363 +#define SRST_P_OTPC_NS 364 +#define SRST_OTPC_NS_SBPI 365 +#define SRST_OTPC_NS_USR 366 + +/* cru_softrst_con23 */ +#define SRST_P_PWM1 368 +#define SRST_PWM1 369 +#define SRST_P_PWM2 370 +#define SRST_PWM2 371 +#define SRST_P_PWM3 372 +#define SRST_PWM3 373 +#define SRST_P_SPI0 374 +#define SRST_SPI0 375 +#define SRST_P_SPI1 376 +#define SRST_SPI1 377 +#define SRST_P_SPI2 378 +#define SRST_SPI2 379 +#define SRST_P_SPI3 380 +#define SRST_SPI3 381 + +/* cru_softrst_con24 */ +#define SRST_P_SARADC 384 +#define SRST_P_TSADC 385 +#define SRST_TSADC 386 +#define SRST_P_TIMER 387 +#define SRST_TIMER0 388 +#define SRST_TIMER1 389 +#define SRST_TIMER2 390 +#define SRST_TIMER3 391 +#define SRST_TIMER4 392 +#define SRST_TIMER5 393 +#define SRST_P_UART1 394 +#define SRST_S_UART1 395 + +/* cru_softrst_con25 */ +#define SRST_P_UART2 400 +#define SRST_S_UART2 401 +#define SRST_P_UART3 402 +#define SRST_S_UART3 403 +#define SRST_P_UART4 404 +#define SRST_S_UART4 405 +#define SRST_P_UART5 406 +#define SRST_S_UART5 407 +#define SRST_P_UART6 408 +#define SRST_S_UART6 409 +#define SRST_P_UART7 410 +#define SRST_S_UART7 411 +#define SRST_P_UART8 412 +#define SRST_S_UART8 413 +#define SRST_P_UART9 414 +#define SRST_S_UART9 415 + +/* cru_softrst_con26 */ +#define SRST_P_GRF 416 +#define SRST_P_GRF_VCCIO12 417 +#define SRST_P_GRF_VCCIO34 418 +#define SRST_P_GRF_VCCIO567 419 +#define SRST_P_SCR 420 +#define SRST_P_WDT_NS 421 +#define SRST_T_WDT_NS 422 +#define SRST_P_DFT2APB 423 +#define SRST_A_MCU 426 +#define SRST_P_INTMUX 427 +#define SRST_P_MAILBOX 428 + +/* cru_softrst_con27 */ +#define SRST_A_TOP_HIGH_NIU 432 +#define SRST_A_TOP_LOW_NIU 433 +#define SRST_H_TOP_NIU 434 +#define SRST_P_TOP_NIU 435 +#define SRST_P_TOP_CRU 438 +#define SRST_P_DDRPHY 439 +#define SRST_DDRPHY 440 +#define SRST_P_MIPICSIPHY 442 +#define SRST_P_MIPIDSIPHY0 443 +#define SRST_P_MIPIDSIPHY1 444 +#define SRST_P_PCIE30PHY 445 +#define SRST_PCIE30PHY 446 +#define SRST_P_PCIE30PHY_GRF 447 + +/* cru_softrst_con28 */ +#define SRST_P_APB2ASB_LEFT 448 +#define SRST_P_APB2ASB_BOTTOM 449 +#define SRST_P_ASB2APB_LEFT 450 +#define SRST_P_ASB2APB_BOTTOM 451 +#define SRST_P_PIPEPHY0 452 +#define SRST_PIPEPHY0 453 +#define SRST_P_PIPEPHY1 454 +#define SRST_PIPEPHY1 455 +#define SRST_P_PIPEPHY2 456 +#define SRST_PIPEPHY2 457 +#define SRST_P_USB2PHY0_GRF 458 +#define SRST_P_USB2PHY1_GRF 459 +#define SRST_P_CPU_BOOST 460 +#define SRST_CPU_BOOST 461 +#define SRST_P_OTPPHY 462 +#define SRST_OTPPHY 463 + +/* cru_softrst_con29 */ +#define SRST_USB2PHY0_POR 464 +#define SRST_USB2PHY0_USB3OTG0 465 +#define SRST_USB2PHY0_USB3OTG1 466 +#define SRST_USB2PHY1_POR 467 +#define SRST_USB2PHY1_USB2HOST0 468 +#define SRST_USB2PHY1_USB2HOST1 469 +#define SRST_P_EDPPHY_GRF 470 +#define SRST_TSADCPHY 471 +#define SRST_GMAC0_DELAYLINE 472 +#define SRST_GMAC1_DELAYLINE 473 +#define SRST_OTPC_ARB 474 +#define SRST_P_PIPEPHY0_GRF 475 +#define SRST_P_PIPEPHY1_GRF 476 +#define SRST_P_PIPEPHY2_GRF 477 + +#endif diff --git a/root/target/linux/rockchip/files/include/dt-bindings/clock/rockchip-ddr.h b/root/target/linux/rockchip/files/include/dt-bindings/clock/rockchip-ddr.h new file mode 100644 index 00000000..b065432e --- /dev/null +++ b/root/target/linux/rockchip/files/include/dt-bindings/clock/rockchip-ddr.h @@ -0,0 +1,63 @@ +/* + * + * Copyright (C) 2017 ROCKCHIP, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _DT_BINDINGS_CLOCK_ROCKCHIP_DDR_H +#define _DT_BINDINGS_CLOCK_ROCKCHIP_DDR_H + +#define DDR2_DEFAULT (0) + +#define DDR3_800D (0) /* 5-5-5 */ +#define DDR3_800E (1) /* 6-6-6 */ +#define DDR3_1066E (2) /* 6-6-6 */ +#define DDR3_1066F (3) /* 7-7-7 */ +#define DDR3_1066G (4) /* 8-8-8 */ +#define DDR3_1333F (5) /* 7-7-7 */ +#define DDR3_1333G (6) /* 8-8-8 */ +#define DDR3_1333H (7) /* 9-9-9 */ +#define DDR3_1333J (8) /* 10-10-10 */ +#define DDR3_1600G (9) /* 8-8-8 */ +#define DDR3_1600H (10) /* 9-9-9 */ +#define DDR3_1600J (11) /* 10-10-10 */ +#define DDR3_1600K (12) /* 11-11-11 */ +#define DDR3_1866J (13) /* 10-10-10 */ +#define DDR3_1866K (14) /* 11-11-11 */ +#define DDR3_1866L (15) /* 12-12-12 */ +#define DDR3_1866M (16) /* 13-13-13 */ +#define DDR3_2133K (17) /* 11-11-11 */ +#define DDR3_2133L (18) /* 12-12-12 */ +#define DDR3_2133M (19) /* 13-13-13 */ +#define DDR3_2133N (20) /* 14-14-14 */ +#define DDR3_DEFAULT (21) +#define DDR_DDR2 (22) +#define DDR_LPDDR (23) +#define DDR_LPDDR2 (24) + +#define DDR4_1600J (0) /* 10-10-10 */ +#define DDR4_1600K (1) /* 11-11-11 */ +#define DDR4_1600L (2) /* 12-12-12 */ +#define DDR4_1866L (3) /* 12-12-12 */ +#define DDR4_1866M (4) /* 13-13-13 */ +#define DDR4_1866N (5) /* 14-14-14 */ +#define DDR4_2133N (6) /* 14-14-14 */ +#define DDR4_2133P (7) /* 15-15-15 */ +#define DDR4_2133R (8) /* 16-16-16 */ +#define DDR4_2400P (9) /* 15-15-15 */ +#define DDR4_2400R (10) /* 16-16-16 */ +#define DDR4_2400U (11) /* 18-18-18 */ +#define DDR4_DEFAULT (12) + +#define PAUSE_CPU_STACK_SIZE 16 + +#endif diff --git a/root/target/linux/rockchip/files/include/dt-bindings/memory/rk3328-dram.h b/root/target/linux/rockchip/files/include/dt-bindings/memory/rk3328-dram.h new file mode 100644 index 00000000..171f41c2 --- /dev/null +++ b/root/target/linux/rockchip/files/include/dt-bindings/memory/rk3328-dram.h @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef _DT_BINDINGS_DRAM_ROCKCHIP_RK3328_H +#define _DT_BINDINGS_DRAM_ROCKCHIP_RK3328_H + +#define DDR3_DS_34ohm (34) +#define DDR3_DS_40ohm (40) + +#define DDR3_ODT_DIS (0) +#define DDR3_ODT_40ohm (40) +#define DDR3_ODT_60ohm (60) +#define DDR3_ODT_120ohm (120) + +#define LP2_DS_34ohm (34) +#define LP2_DS_40ohm (40) +#define LP2_DS_48ohm (48) +#define LP2_DS_60ohm (60) +#define LP2_DS_68_6ohm (68) /* optional */ +#define LP2_DS_80ohm (80) +#define LP2_DS_120ohm (120) /* optional */ + +#define LP3_DS_34ohm (34) +#define LP3_DS_40ohm (40) +#define LP3_DS_48ohm (48) +#define LP3_DS_60ohm (60) +#define LP3_DS_80ohm (80) +#define LP3_DS_34D_40U (3440) +#define LP3_DS_40D_48U (4048) +#define LP3_DS_34D_48U (3448) + +#define LP3_ODT_DIS (0) +#define LP3_ODT_60ohm (60) +#define LP3_ODT_120ohm (120) +#define LP3_ODT_240ohm (240) + +#define LP4_PDDS_40ohm (40) +#define LP4_PDDS_48ohm (48) +#define LP4_PDDS_60ohm (60) +#define LP4_PDDS_80ohm (80) +#define LP4_PDDS_120ohm (120) +#define LP4_PDDS_240ohm (240) + +#define LP4_DQ_ODT_40ohm (40) +#define LP4_DQ_ODT_48ohm (48) +#define LP4_DQ_ODT_60ohm (60) +#define LP4_DQ_ODT_80ohm (80) +#define LP4_DQ_ODT_120ohm (120) +#define LP4_DQ_ODT_240ohm (240) +#define LP4_DQ_ODT_DIS (0) + +#define LP4_CA_ODT_40ohm (40) +#define LP4_CA_ODT_48ohm (48) +#define LP4_CA_ODT_60ohm (60) +#define LP4_CA_ODT_80ohm (80) +#define LP4_CA_ODT_120ohm (120) +#define LP4_CA_ODT_240ohm (240) +#define LP4_CA_ODT_DIS (0) + +#define DDR4_DS_34ohm (34) +#define DDR4_DS_48ohm (48) +#define DDR4_RTT_NOM_DIS (0) +#define DDR4_RTT_NOM_60ohm (60) +#define DDR4_RTT_NOM_120ohm (120) +#define DDR4_RTT_NOM_40ohm (40) +#define DDR4_RTT_NOM_240ohm (240) +#define DDR4_RTT_NOM_48ohm (48) +#define DDR4_RTT_NOM_80ohm (80) +#define DDR4_RTT_NOM_34ohm (34) + +#define PHY_DDR3_RON_RTT_DISABLE (0) +#define PHY_DDR3_RON_RTT_451ohm (1) +#define PHY_DDR3_RON_RTT_225ohm (2) +#define PHY_DDR3_RON_RTT_150ohm (3) +#define PHY_DDR3_RON_RTT_112ohm (4) +#define PHY_DDR3_RON_RTT_90ohm (5) +#define PHY_DDR3_RON_RTT_75ohm (6) +#define PHY_DDR3_RON_RTT_64ohm (7) +#define PHY_DDR3_RON_RTT_56ohm (16) +#define PHY_DDR3_RON_RTT_50ohm (17) +#define PHY_DDR3_RON_RTT_45ohm (18) +#define PHY_DDR3_RON_RTT_41ohm (19) +#define PHY_DDR3_RON_RTT_37ohm (20) +#define PHY_DDR3_RON_RTT_34ohm (21) +#define PHY_DDR3_RON_RTT_33ohm (22) +#define PHY_DDR3_RON_RTT_30ohm (23) +#define PHY_DDR3_RON_RTT_28ohm (24) +#define PHY_DDR3_RON_RTT_26ohm (25) +#define PHY_DDR3_RON_RTT_25ohm (26) +#define PHY_DDR3_RON_RTT_23ohm (27) +#define PHY_DDR3_RON_RTT_22ohm (28) +#define PHY_DDR3_RON_RTT_21ohm (29) +#define PHY_DDR3_RON_RTT_20ohm (30) +#define PHY_DDR3_RON_RTT_19ohm (31) + +#define PHY_DDR4_LPDDR3_RON_RTT_DISABLE (0) +#define PHY_DDR4_LPDDR3_RON_RTT_480ohm (1) +#define PHY_DDR4_LPDDR3_RON_RTT_240ohm (2) +#define PHY_DDR4_LPDDR3_RON_RTT_160ohm (3) +#define PHY_DDR4_LPDDR3_RON_RTT_120ohm (4) +#define PHY_DDR4_LPDDR3_RON_RTT_96ohm (5) +#define PHY_DDR4_LPDDR3_RON_RTT_80ohm (6) +#define PHY_DDR4_LPDDR3_RON_RTT_68ohm (7) +#define PHY_DDR4_LPDDR3_RON_RTT_60ohm (16) +#define PHY_DDR4_LPDDR3_RON_RTT_53ohm (17) +#define PHY_DDR4_LPDDR3_RON_RTT_48ohm (18) +#define PHY_DDR4_LPDDR3_RON_RTT_43ohm (19) +#define PHY_DDR4_LPDDR3_RON_RTT_40ohm (20) +#define PHY_DDR4_LPDDR3_RON_RTT_37ohm (21) +#define PHY_DDR4_LPDDR3_RON_RTT_34ohm (22) +#define PHY_DDR4_LPDDR3_RON_RTT_32ohm (23) +#define PHY_DDR4_LPDDR3_RON_RTT_30ohm (24) +#define PHY_DDR4_LPDDR3_RON_RTT_28ohm (25) +#define PHY_DDR4_LPDDR3_RON_RTT_26ohm (26) +#define PHY_DDR4_LPDDR3_RON_RTT_25ohm (27) +#define PHY_DDR4_LPDDR3_RON_RTT_24ohm (28) +#define PHY_DDR4_LPDDR3_RON_RTT_22ohm (29) +#define PHY_DDR4_LPDDR3_RON_RTT_21ohm (30) +#define PHY_DDR4_LPDDR3_RON_RTT_20ohm (31) + +#endif /*_DT_BINDINGS_DRAM_ROCKCHIP_RK3328_H*/ diff --git a/root/target/linux/rockchip/files/include/dt-bindings/power/rk3568-power.h b/root/target/linux/rockchip/files/include/dt-bindings/power/rk3568-power.h new file mode 100644 index 00000000..6cc1af1a --- /dev/null +++ b/root/target/linux/rockchip/files/include/dt-bindings/power/rk3568-power.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __DT_BINDINGS_POWER_RK3568_POWER_H__ +#define __DT_BINDINGS_POWER_RK3568_POWER_H__ + +/* VD_CORE */ +#define RK3568_PD_CPU_0 0 +#define RK3568_PD_CPU_1 1 +#define RK3568_PD_CPU_2 2 +#define RK3568_PD_CPU_3 3 +#define RK3568_PD_CORE_ALIVE 4 + +/* VD_PMU */ +#define RK3568_PD_PMU 5 + +/* VD_NPU */ +#define RK3568_PD_NPU 6 + +/* VD_GPU */ +#define RK3568_PD_GPU 7 + +/* VD_LOGIC */ +#define RK3568_PD_VI 8 +#define RK3568_PD_VO 9 +#define RK3568_PD_RGA 10 +#define RK3568_PD_VPU 11 +#define RK3568_PD_CENTER 12 +#define RK3568_PD_RKVDEC 13 +#define RK3568_PD_RKVENC 14 +#define RK3568_PD_PIPE 15 +#define RK3568_PD_LOGIC_ALIVE 16 + +#endif diff --git a/root/target/linux/rockchip/image/Makefile b/root/target/linux/rockchip/image/Makefile new file mode 100644 index 00000000..0278ec51 --- /dev/null +++ b/root/target/linux/rockchip/image/Makefile @@ -0,0 +1,82 @@ +# SPDX-License-Identifier: GPL-2.0-only + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/image.mk + +DEVICE_VARS += UBOOT_DEVICE_NAME + +define Build/Compile + $(CP) $(LINUX_DIR)/COPYING $(KDIR)/COPYING.linux +endef + +### Image scripts ### +define Build/boot-common + # This creates a new folder copies the dtb (as rockchip.dtb) + # and the kernel image (as kernel.img) + rm -fR $@.boot + mkdir -p $@.boot + + $(CP) $(DTS_DIR)/$(DEVICE_DTS).dtb $@.boot/rockchip.dtb + $(CP) $(IMAGE_KERNEL) $@.boot/kernel.img +endef + +define Build/boot-script + # Make an U-boot image and copy it to the boot partition + mkimage -A arm -O linux -T script -C none -a 0 -e 0 -d $(if $(1),$(1),mmc).bootscript $@.boot/boot.scr +endef + +define Build/pine64-img + # Creates the final SD/eMMC images, + # combining boot partition, root partition as well as the u-boot bootloader + + # Generate a new partition table in $@ with 32 MiB of + # alignment padding for the idbloader and u-boot to fit: + # http://opensource.rock-chips.com/wiki_Boot_option#Boot_flow + # + # U-Boot SPL expects the U-Boot ITB to be located at sector 0x4000 (8 MiB) on the MMC storage + PADDING=1 $(SCRIPT_DIR)/gen_image_generic.sh \ + $@ \ + $(CONFIG_TARGET_KERNEL_PARTSIZE) $@.boot \ + $(CONFIG_TARGET_ROOTFS_PARTSIZE) $(IMAGE_ROOTFS) \ + 32768 + + # Copy the idbloader and the u-boot image to the image at sector 0x40 and 0x4000 + dd if="$(STAGING_DIR_IMAGE)"/$(UBOOT_DEVICE_NAME)-idbloader.img of="$@" seek=64 conv=notrunc + dd if="$(STAGING_DIR_IMAGE)"/$(UBOOT_DEVICE_NAME)-u-boot.itb of="$@" seek=16384 conv=notrunc +endef + +define Build/pine64-bin + # Typical Rockchip boot flow with Rockchip miniloader + # Rockchp idbLoader which is combinded by Rockchip ddr init bin + # and miniloader bin from Rockchip rkbin project + + # Generate a new partition table in $@ with 32 MiB of alignment + # padding for the idbloader, uboot and trust image to fit: + # http://opensource.rock-chips.com/wiki_Boot_option#Boot_flow + PADDING=1 $(SCRIPT_DIR)/gen_image_generic.sh \ + $@ \ + $(CONFIG_TARGET_KERNEL_PARTSIZE) $@.boot \ + $(CONFIG_TARGET_ROOTFS_PARTSIZE) $(IMAGE_ROOTFS) \ + 32768 + + # Copy the idbloader, uboot and trust image to the image at sector 0x40, 0x4000 and 0x6000 + dd if="$(STAGING_DIR_IMAGE)"/$(SOC)-idbloader.bin of="$@" seek=64 conv=notrunc + dd if="$(STAGING_DIR_IMAGE)"/$(UBOOT_DEVICE_NAME)-uboot.img of="$@" seek=16384 conv=notrunc + dd if="$(STAGING_DIR_IMAGE)"/$(SOC)-trust.bin of="$@" seek=24576 conv=notrunc +endef + +### Devices ### +define Device/Default + PROFILES := Default + KERNEL := kernel-bin + IMAGES := sysupgrade.img.gz + DEVICE_DTS = rockchip/$$(SOC)-$(lastword $(subst _, ,$(1))) +endef + +ifdef CONFIG_LINUX_6_0 + DTS_CPPFLAGS += -DDTS_NO_LEGACY +endif + +include $(SUBTARGET).mk + +$(eval $(call BuildImage)) diff --git a/root/target/linux/rockchip/image/armv8.mk b/root/target/linux/rockchip/image/armv8.mk index 75798f8a..c50245e1 100644 --- a/root/target/linux/rockchip/image/armv8.mk +++ b/root/target/linux/rockchip/image/armv8.mk @@ -2,12 +2,71 @@ # # Copyright (C) 2020 Tobias Maedel +define Device/ezpro_mrkaio-m68s + DEVICE_VENDOR := EZPRO + DEVICE_MODEL := Mrkaio M68S + SOC := rk3568 + UBOOT_DEVICE_NAME := mrkaio-m68s-rk3568 + IMAGE/sysupgrade.img.gz := boot-common | boot-script nanopi-r5s | pine64-img | gzip | append-metadata + DEVICE_PACKAGES := kmod-ata-ahci kmod-ata-ahci-platform +endef +TARGET_DEVICES += ezpro_mrkaio-m68s + +define Device/hinlink_opc-h68k + DEVICE_VENDOR := HINLINK + DEVICE_MODEL := OPC-H68K + SOC := rk3568 + UBOOT_DEVICE_NAME := opc-h68k-rk3568 + IMAGE/sysupgrade.img.gz := boot-common | boot-script nanopi-r5s | pine64-img | gzip | append-metadata + DEVICE_PACKAGES := kmod-mt7921e kmod-r8125 +endef +TARGET_DEVICES += hinlink_opc-h68k + +define Device/fastrhino_common + DEVICE_VENDOR := FastRhino + SOC := rk3568 + UBOOT_DEVICE_NAME := r66s-rk3568 + IMAGE/sysupgrade.img.gz := boot-common | boot-script nanopi-r5s | pine64-img | gzip | append-metadata + DEVICE_PACKAGES := kmod-r8125 +endef + +define Device/fastrhino_r66s +$(call Device/fastrhino_common) + DEVICE_MODEL := R66S +endef +TARGET_DEVICES += fastrhino_r66s + +define Device/fastrhino_r68s +$(call Device/fastrhino_common) + DEVICE_MODEL := R68S +endef +TARGET_DEVICES += fastrhino_r68s + +define Device/friendlyarm_nanopi-neo3 + DEVICE_VENDOR := FriendlyARM + DEVICE_MODEL := NanoPi NEO3 + SOC := rk3328 + UBOOT_DEVICE_NAME := nanopi-r2s-rk3328 + IMAGE/sysupgrade.img.gz := boot-common | boot-script nanopi-r2s | pine64-bin | gzip | append-metadata +endef +TARGET_DEVICES += friendlyarm_nanopi-neo3 + +define Device/friendlyarm_nanopi-r2c + DEVICE_VENDOR := FriendlyARM + DEVICE_MODEL := NanoPi R2C + SOC := rk3328 + UBOOT_DEVICE_NAME := nanopi-r2c-rk3328 + IMAGE/sysupgrade.img.gz := boot-common | boot-script nanopi-r2s | pine64-bin | gzip | append-metadata + DEVICE_PACKAGES := kmod-usb-net-rtl8152 +endef +TARGET_DEVICES += friendlyarm_nanopi-r2c + define Device/friendlyarm_nanopi-r2s DEVICE_VENDOR := FriendlyARM DEVICE_MODEL := NanoPi R2S SOC := rk3328 UBOOT_DEVICE_NAME := nanopi-r2s-rk3328 - IMAGE/sysupgrade.img.gz := boot-common | boot-script nanopi-r2s | pine64-img | gzip | append-metadata + IMAGE/sysupgrade.img.gz := boot-common | boot-script nanopi-r2s | pine64-bin | gzip | append-metadata DEVICE_PACKAGES := kmod-usb-net-rtl8152 endef TARGET_DEVICES += friendlyarm_nanopi-r2s @@ -17,20 +76,61 @@ define Device/friendlyarm_nanopi-r4s DEVICE_MODEL := NanoPi R4S SOC := rk3399 UBOOT_DEVICE_NAME := nanopi-r4s-rk3399 - IMAGE/sysupgrade.img.gz := boot-common | boot-script nanopi-r4s | pine64-img | gzip | append-metadata - DEVICE_PACKAGES := kmod-r8169 + IMAGE/sysupgrade.img.gz := boot-common | boot-script nanopi-r4s | pine64-bin | gzip | append-metadata + DEVICE_PACKAGES := kmod-r8168 -urngd endef TARGET_DEVICES += friendlyarm_nanopi-r4s +define Device/friendlyarm_nanopi-r4se + DEVICE_VENDOR := FriendlyARM + DEVICE_MODEL := NanoPi R4SE + SOC := rk3399 + UBOOT_DEVICE_NAME := nanopi-r4se-rk3399 + IMAGE/sysupgrade.img.gz := boot-common | boot-script nanopi-r4s | pine64-bin | gzip | append-metadata + DEVICE_PACKAGES := kmod-r8168 -urngd +endef +TARGET_DEVICES += friendlyarm_nanopi-r4se + +define Device/friendlyarm_nanopi-r5s + DEVICE_VENDOR := FriendlyARM + DEVICE_MODEL := NanoPi R5S + SOC := rk3568 + UBOOT_DEVICE_NAME := nanopi-r5s-rk3568 + IMAGE/sysupgrade.img.gz := boot-common | boot-script nanopi-r5s | pine64-img | gzip | append-metadata + DEVICE_PACKAGES := kmod-r8125 kmod-nvme kmod-scsi-core +endef +TARGET_DEVICES += friendlyarm_nanopi-r5s + +define Device/firefly_station-p2 + DEVICE_VENDOR := Firefly + DEVICE_MODEL := Station P2 + DEVICE_DTS := rockchip/rk3568-roc-pc + UBOOT_DEVICE_NAME := station-p2-rk3568 + IMAGE/sysupgrade.img.gz := boot-common | boot-script nanopi-r5s | pine64-img | gzip | append-metadata + DEVICE_PACKAGES := kmod-brcmfmac kmod-ikconfig kmod-ata-ahci-platform station-p2-firmware wpad-openssl +endef +TARGET_DEVICES += firefly_station-p2 + define Device/pine64_rockpro64 DEVICE_VENDOR := Pine64 DEVICE_MODEL := RockPro64 SOC := rk3399 UBOOT_DEVICE_NAME := rockpro64-rk3399 IMAGE/sysupgrade.img.gz := boot-common | boot-script | pine64-img | gzip | append-metadata + DEVICE_PACKAGES := -urngd endef TARGET_DEVICES += pine64_rockpro64 +define Device/radxa_rock-3a + DEVICE_VENDOR := Radxa + DEVICE_MODEL := ROCK3 A + SOC := rk3568 + SUPPORTED_DEVICES := radxa,rock3a + UBOOT_DEVICE_NAME := rock-3a-rk3568 + IMAGE/sysupgrade.img.gz := boot-common | boot-script nanopi-r5s | pine64-img | gzip | append-metadata +endef +TARGET_DEVICES += radxa_rock-3a + define Device/radxa_rock-pi-4 DEVICE_VENDOR := Radxa DEVICE_MODEL := ROCK Pi 4 @@ -38,5 +138,47 @@ define Device/radxa_rock-pi-4 SUPPORTED_DEVICES := radxa,rockpi4 UBOOT_DEVICE_NAME := rock-pi-4-rk3399 IMAGE/sysupgrade.img.gz := boot-common | boot-script | pine64-img | gzip | append-metadata + DEVICE_PACKAGES := -urngd endef TARGET_DEVICES += radxa_rock-pi-4 + +define Device/radxa_rock-pi-e25 + DEVICE_VENDOR := Radxa + DEVICE_MODEL := ROCK Pi E25 + SOC := rk3568 + SUPPORTED_DEVICES := radxa,rockpi-e25 + UBOOT_DEVICE_NAME := rock-pi-e25-rk3568 + IMAGE/sysupgrade.img.gz := boot-common | boot-script nanopi-r5s | pine64-img | gzip | append-metadata + DEVICE_PACKAGES := kmod-r8125 +endef +TARGET_DEVICES += radxa_rock-pi-e25 + +define Device/sharevdi_guangmiao-g4c + DEVICE_VENDOR := SHAREVDI + DEVICE_MODEL := GuangMiao G4C + SOC := rk3399 + UBOOT_DEVICE_NAME := guangmiao-g4c-rk3399 + IMAGE/sysupgrade.img.gz := boot-common | boot-script nanopi-r4s | pine64-img | gzip | append-metadata + DEVICE_PACKAGES := kmod-r8168 -urngd +endef +TARGET_DEVICES += sharevdi_guangmiao-g4c + +define Device/xunlong_orangepi-r1-plus + DEVICE_VENDOR := Xunlong + DEVICE_MODEL := Orange Pi R1 Plus + SOC := rk3328 + UBOOT_DEVICE_NAME := orangepi-r1-plus-rk3328 + IMAGE/sysupgrade.img.gz := boot-common | boot-script nanopi-r2s | pine64-bin | gzip | append-metadata + DEVICE_PACKAGES := kmod-usb-net-rtl8152 +endef +TARGET_DEVICES += xunlong_orangepi-r1-plus + +define Device/xunlong_orangepi-r1-plus-lts + DEVICE_VENDOR := Xunlong + DEVICE_MODEL := Orange Pi R1 Plus LTS + SOC := rk3328 + UBOOT_DEVICE_NAME := orangepi-r1-plus-lts-rk3328 + IMAGE/sysupgrade.img.gz := boot-common | boot-script nanopi-r2s | pine64-bin | gzip | append-metadata + DEVICE_PACKAGES := kmod-usb-net-rtl8152 +endef +TARGET_DEVICES += xunlong_orangepi-r1-plus-lts diff --git a/root/target/linux/rockchip/image/nanopi-r5s.bootscript b/root/target/linux/rockchip/image/nanopi-r5s.bootscript new file mode 100644 index 00000000..2907e619 --- /dev/null +++ b/root/target/linux/rockchip/image/nanopi-r5s.bootscript @@ -0,0 +1,8 @@ +part uuid mmc ${devnum}:2 uuid + +setenv bootargs "console=ttyS2,1500000 earlycon=uart8250,mmio32,0xfe660000 root=PARTUUID=${uuid} rw rootwait" + +load mmc ${devnum}:1 ${fdt_addr_r} rockchip.dtb +load mmc ${devnum}:1 ${kernel_addr_r} kernel.img + +booti ${kernel_addr_r} - ${fdt_addr_r} diff --git a/root/target/linux/rockchip/patches-5.15/005-rockchip-rk3328-add-compatible-to-NanoPi-R2S-etherne.patch b/root/target/linux/rockchip/patches-5.15/005-rockchip-rk3328-add-compatible-to-NanoPi-R2S-etherne.patch new file mode 100644 index 00000000..6434ef41 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/005-rockchip-rk3328-add-compatible-to-NanoPi-R2S-etherne.patch @@ -0,0 +1,25 @@ +From bc6c96d850419e71dbc9b0094ccc9b668ba9be43 Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Mon, 28 Sep 2020 22:54:52 +0200 +Subject: [PATCH] rockchip: rk3328: add compatible to NanoPi R2S ethernet PHY + +This adds the compatible property to the NanoPi R2S ethernet PHY node. +Otherwise, the PHY might not be probed, as the PHY ID reads all 0xff +when it is still in reset. + +Signed-off-by: David Bauer +--- + arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts +@@ -156,6 +156,8 @@ + #size-cells = <0>; + + rtl8211e: ethernet-phy@1 { ++ compatible = "ethernet-phy-id001c.c915", ++ "ethernet-phy-ieee802.3-c22"; + reg = <1>; + pinctrl-0 = <ð_phy_reset_pin>; + pinctrl-names = "default"; diff --git a/root/target/linux/rockchip/patches-5.15/009-v5.16-drivers-rockchip-thermal-Allow-more-resets-for-tsadc.patch b/root/target/linux/rockchip/patches-5.15/009-v5.16-drivers-rockchip-thermal-Allow-more-resets-for-tsadc.patch new file mode 100644 index 00000000..c63c7f02 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/009-v5.16-drivers-rockchip-thermal-Allow-more-resets-for-tsadc.patch @@ -0,0 +1,28 @@ +From 02832ed8ae2c8b130efea4e43d3ecac50b4b7933 Mon Sep 17 00:00:00 2001 +From: Johan Jonker +Date: Thu, 30 Sep 2021 13:05:16 +0200 +Subject: [PATCH] thermal/drivers/rockchip_thermal: Allow more resets for tsadc + node + +The tsadc node in rk356x.dtsi has more resets then currently supported +by the rockchip_thermal.c driver, so use +devm_reset_control_array_get() to reset them all. + +Signed-off-by: Johan Jonker +Link: https://lore.kernel.org/r/20210930110517.14323-3-jbx6244@gmail.com +Signed-off-by: Daniel Lezcano +--- + drivers/thermal/rockchip_thermal.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/thermal/rockchip_thermal.c ++++ b/drivers/thermal/rockchip_thermal.c +@@ -1383,7 +1383,7 @@ static int rockchip_thermal_probe(struct + if (IS_ERR(thermal->regs)) + return PTR_ERR(thermal->regs); + +- thermal->reset = devm_reset_control_get(&pdev->dev, "tsadc-apb"); ++ thermal->reset = devm_reset_control_array_get(&pdev->dev, false, false); + if (IS_ERR(thermal->reset)) { + error = PTR_ERR(thermal->reset); + dev_err(&pdev->dev, "failed to get tsadc reset: %d\n", error); diff --git a/root/target/linux/rockchip/patches-5.15/010-v5.16-net-stmmac-Add-GFP_DMA32-for-rx-buffers-if-no-64.patch b/root/target/linux/rockchip/patches-5.15/010-v5.16-net-stmmac-Add-GFP_DMA32-for-rx-buffers-if-no-64.patch new file mode 100644 index 00000000..085913e6 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/010-v5.16-net-stmmac-Add-GFP_DMA32-for-rx-buffers-if-no-64.patch @@ -0,0 +1,67 @@ +From 884d2b845477cd0a18302444dc20fe2d9a01743e Mon Sep 17 00:00:00 2001 +From: David Wu +Date: Mon, 13 Dec 2021 19:15:15 +0800 +Subject: [PATCH] net: stmmac: Add GFP_DMA32 for rx buffers if no 64 capability + +Use page_pool_alloc_pages instead of page_pool_dev_alloc_pages, which +can give the gfp parameter, in the case of not supporting 64-bit width, +using 32-bit address memory can reduce a copy from swiotlb. + +Signed-off-by: David Wu +Signed-off-by: David S. Miller +--- + .../net/ethernet/stmicro/stmmac/stmmac_main.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -1472,16 +1472,20 @@ static int stmmac_init_rx_buffers(struct + { + struct stmmac_rx_queue *rx_q = &dma_conf->rx_queue[queue]; + struct stmmac_rx_buffer *buf = &rx_q->buf_pool[i]; ++ gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN); ++ ++ if (priv->dma_cap.addr64 <= 32) ++ gfp |= GFP_DMA32; + + if (!buf->page) { +- buf->page = page_pool_dev_alloc_pages(rx_q->page_pool); ++ buf->page = page_pool_alloc_pages(rx_q->page_pool, gfp); + if (!buf->page) + return -ENOMEM; + buf->page_offset = stmmac_rx_offset(priv); + } + + if (priv->sph && !buf->sec_page) { +- buf->sec_page = page_pool_dev_alloc_pages(rx_q->page_pool); ++ buf->sec_page = page_pool_alloc_pages(rx_q->page_pool, gfp); + if (!buf->sec_page) + return -ENOMEM; + +@@ -4618,6 +4622,10 @@ static inline void stmmac_rx_refill(stru + struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[queue]; + int dirty = stmmac_rx_dirty(priv, queue); + unsigned int entry = rx_q->dirty_rx; ++ gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN); ++ ++ if (priv->dma_cap.addr64 <= 32) ++ gfp |= GFP_DMA32; + + while (dirty-- > 0) { + struct stmmac_rx_buffer *buf = &rx_q->buf_pool[entry]; +@@ -4630,13 +4638,13 @@ static inline void stmmac_rx_refill(stru + p = rx_q->dma_rx + entry; + + if (!buf->page) { +- buf->page = page_pool_dev_alloc_pages(rx_q->page_pool); ++ buf->page = page_pool_alloc_pages(rx_q->page_pool, gfp); + if (!buf->page) + break; + } + + if (priv->sph && !buf->sec_page) { +- buf->sec_page = page_pool_dev_alloc_pages(rx_q->page_pool); ++ buf->sec_page = page_pool_alloc_pages(rx_q->page_pool, gfp); + if (!buf->sec_page) + break; + diff --git a/root/target/linux/rockchip/patches-5.15/015-v5.16-arm64-dts-rockchip-add-rk3566-dtsi.patch b/root/target/linux/rockchip/patches-5.15/015-v5.16-arm64-dts-rockchip-add-rk3566-dtsi.patch new file mode 100644 index 00000000..6fe9ccd8 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/015-v5.16-arm64-dts-rockchip-add-rk3566-dtsi.patch @@ -0,0 +1,39 @@ +From 016c0e8a7a6e7820fb54d8ff8a4a2928a3016421 Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Sat, 10 Jul 2021 11:10:33 -0400 +Subject: [PATCH] arm64: dts: rockchip: add rk3566 dtsi + +Add the rk3566 dtsi which includes the soc specific changes for this +chip. + +Signed-off-by: Peter Geis +Link: https://lore.kernel.org/r/20210710151034.32857-4-pgwipeout@gmail.com +Signed-off-by: Heiko Stuebner +--- + arch/arm64/boot/dts/rockchip/rk3566.dtsi | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + create mode 100644 arch/arm64/boot/dts/rockchip/rk3566.dtsi + +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3566.dtsi +@@ -0,0 +1,20 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++#include "rk356x.dtsi" ++ ++/ { ++ compatible = "rockchip,rk3566"; ++}; ++ ++&power { ++ power-domain@RK3568_PD_PIPE { ++ reg = ; ++ clocks = <&cru PCLK_PIPE>; ++ pm_qos = <&qos_pcie2x1>, ++ <&qos_sata1>, ++ <&qos_sata2>, ++ <&qos_usb3_0>, ++ <&qos_usb3_1>; ++ #power-domain-cells = <0>; ++ }; ++}; diff --git a/root/target/linux/rockchip/patches-5.15/020-v5.16-arm64-dts-rockchip-add-gmac0-node-to-rk3568.patch b/root/target/linux/rockchip/patches-5.15/020-v5.16-arm64-dts-rockchip-add-gmac0-node-to-rk3568.patch new file mode 100644 index 00000000..99b81f75 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/020-v5.16-arm64-dts-rockchip-add-gmac0-node-to-rk3568.patch @@ -0,0 +1,73 @@ +From b8d41e5053cd823817344cc5e7a2bfda508effff Mon Sep 17 00:00:00 2001 +From: Michael Riesch +Date: Thu, 29 Jul 2021 11:39:12 +0200 +Subject: [PATCH] arm64: dts: rockchip: add gmac0 node to rk3568 + +While both RK3566 and RK3568 feature the gmac1 node, the gmac0 +node is exclusive to the RK3568. + +Signed-off-by: Michael Riesch +Link: https://lore.kernel.org/r/20210729093913.8917-2-michael.riesch@wolfvision.net +Signed-off-by: Heiko Stuebner +--- + arch/arm64/boot/dts/rockchip/rk3568.dtsi | 49 ++++++++++++++++++++++++ + 1 file changed, 49 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3568.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3568.dtsi +@@ -22,6 +22,55 @@ + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe190200 0x0 0x20>; + }; ++ ++ gmac0: ethernet@fe2a0000 { ++ compatible = "rockchip,rk3568-gmac", "snps,dwmac-4.20a"; ++ reg = <0x0 0xfe2a0000 0x0 0x10000>; ++ interrupts = , ++ ; ++ interrupt-names = "macirq", "eth_wake_irq"; ++ clocks = <&cru SCLK_GMAC0>, <&cru SCLK_GMAC0_RX_TX>, ++ <&cru SCLK_GMAC0_RX_TX>, <&cru CLK_MAC0_REFOUT>, ++ <&cru ACLK_GMAC0>, <&cru PCLK_GMAC0>, ++ <&cru SCLK_GMAC0_RX_TX>, <&cru CLK_GMAC0_PTP_REF>, ++ <&cru PCLK_XPCS>; ++ clock-names = "stmmaceth", "mac_clk_rx", ++ "mac_clk_tx", "clk_mac_refout", ++ "aclk_mac", "pclk_mac", ++ "clk_mac_speed", "ptp_ref", ++ "pclk_xpcs"; ++ resets = <&cru SRST_A_GMAC0>; ++ reset-names = "stmmaceth"; ++ rockchip,grf = <&grf>; ++ snps,axi-config = <&gmac0_stmmac_axi_setup>; ++ snps,mixed-burst; ++ snps,mtl-rx-config = <&gmac0_mtl_rx_setup>; ++ snps,mtl-tx-config = <&gmac0_mtl_tx_setup>; ++ snps,tso; ++ status = "disabled"; ++ ++ mdio0: mdio { ++ compatible = "snps,dwmac-mdio"; ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ }; ++ ++ gmac0_stmmac_axi_setup: stmmac-axi-config { ++ snps,blen = <0 0 0 0 16 8 4>; ++ snps,rd_osr_lmt = <8>; ++ snps,wr_osr_lmt = <4>; ++ }; ++ ++ gmac0_mtl_rx_setup: rx-queues-config { ++ snps,rx-queues-to-use = <1>; ++ queue0 {}; ++ }; ++ ++ gmac0_mtl_tx_setup: tx-queues-config { ++ snps,tx-queues-to-use = <1>; ++ queue0 {}; ++ }; ++ }; + }; + + &cpu0_opp_table { diff --git a/root/target/linux/rockchip/patches-5.15/031-v5.17-arm64-dts-rockchip-drop-pclk_xpcs-from-gmac0-on.patch b/root/target/linux/rockchip/patches-5.15/031-v5.17-arm64-dts-rockchip-drop-pclk_xpcs-from-gmac0-on.patch new file mode 100644 index 00000000..fccec455 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/031-v5.17-arm64-dts-rockchip-drop-pclk_xpcs-from-gmac0-on.patch @@ -0,0 +1,54 @@ +From 85a8bccfa945680dc561f06b65ea01341d2033fc Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sun, 23 Jan 2022 14:35:10 +0100 +Subject: [PATCH] arm64: dts: rockchip: drop pclk_xpcs from gmac0 on rk3568 + +pclk_xpcs is not supported by mainline driver and breaks dtbs_check + +following warnings occour, and many more + +rk3568-evb1-v10.dt.yaml: ethernet@fe2a0000: clocks: + [[15, 386], [15, 389], [15, 389], [15, 184], [15, 180], [15, 181], + [15, 389], [15, 185], [15, 172]] is too long + From schema: Documentation/devicetree/bindings/net/snps,dwmac.yaml +rk3568-evb1-v10.dt.yaml: ethernet@fe2a0000: clock-names: + ['stmmaceth', 'mac_clk_rx', 'mac_clk_tx', 'clk_mac_refout', 'aclk_mac', + 'pclk_mac', 'clk_mac_speed', 'ptp_ref', 'pclk_xpcs'] is too long + From schema: Documentation/devicetree/bindings/net/snps,dwmac.yaml + +after removing it, the clock and other warnings are gone. + +pclk_xpcs on gmac is used to support QSGMII, but this requires a driver +supporting it. +Once xpcs support is introduced, the clock can be added to the +documentation and both controllers. + +Fixes: b8d41e5053cd ("arm64: dts: rockchip: add gmac0 node to rk3568") +Co-developed-by: Peter Geis +Signed-off-by: Peter Geis +Signed-off-by: Frank Wunderlich +Acked-by: Michael Riesch +Link: https://lore.kernel.org/r/20220123133510.135651-1-linux@fw-web.de +Signed-off-by: Heiko Stuebner +--- + arch/arm64/boot/dts/rockchip/rk3568.dtsi | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +--- a/arch/arm64/boot/dts/rockchip/rk3568.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3568.dtsi +@@ -32,13 +32,11 @@ + clocks = <&cru SCLK_GMAC0>, <&cru SCLK_GMAC0_RX_TX>, + <&cru SCLK_GMAC0_RX_TX>, <&cru CLK_MAC0_REFOUT>, + <&cru ACLK_GMAC0>, <&cru PCLK_GMAC0>, +- <&cru SCLK_GMAC0_RX_TX>, <&cru CLK_GMAC0_PTP_REF>, +- <&cru PCLK_XPCS>; ++ <&cru SCLK_GMAC0_RX_TX>, <&cru CLK_GMAC0_PTP_REF>; + clock-names = "stmmaceth", "mac_clk_rx", + "mac_clk_tx", "clk_mac_refout", + "aclk_mac", "pclk_mac", +- "clk_mac_speed", "ptp_ref", +- "pclk_xpcs"; ++ "clk_mac_speed", "ptp_ref"; + resets = <&cru SRST_A_GMAC0>; + reset-names = "stmmaceth"; + rockchip,grf = <&grf>; diff --git a/root/target/linux/rockchip/patches-5.15/032-v5.17-phy-rockchip-inno-usb2-support-address-cells.patch b/root/target/linux/rockchip/patches-5.15/032-v5.17-phy-rockchip-inno-usb2-support-address-cells.patch new file mode 100644 index 00000000..8ee043d5 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/032-v5.17-phy-rockchip-inno-usb2-support-address-cells.patch @@ -0,0 +1,45 @@ +From 9c19c531dc98d7ba49b44802a607042e763ebe21 Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Wed, 15 Dec 2021 16:02:47 -0500 +Subject: [PATCH] phy: phy-rockchip-inno-usb2: support #address_cells = 2 + +New Rockchip devices have the usb phy nodes as standalone devices. +These nodes have register nodes with #address_cells = 2, but only use 32 +bit addresses. + +Adjust the driver to check if the returned address is "0", and adjust +the index in that case. + +Signed-off-by: Peter Geis +Tested-by: Michael Riesch +Link: https://lore.kernel.org/r/20211215210252.120923-4-pgwipeout@gmail.com +Signed-off-by: Vinod Koul +--- + drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +@@ -1098,12 +1098,21 @@ static int rockchip_usb2phy_probe(struct + rphy->usbgrf = NULL; + } + +- if (of_property_read_u32(np, "reg", ®)) { ++ if (of_property_read_u32_index(np, "reg", 0, ®)) { + dev_err(dev, "the reg property is not assigned in %pOFn node\n", + np); + return -EINVAL; + } + ++ /* support address_cells=2 */ ++ if (reg == 0) { ++ if (of_property_read_u32_index(np, "reg", 1, ®)) { ++ dev_err(dev, "the reg property is not assigned in %pOFn node\n", ++ np); ++ return -EINVAL; ++ } ++ } ++ + rphy->dev = dev; + phy_cfgs = match->data; + rphy->chg_state = USB_CHG_STATE_UNDEFINED; diff --git a/root/target/linux/rockchip/patches-5.15/033-v5.17-phy-rockchip-inno-usb2-support-standalone-phy-nodes.patch b/root/target/linux/rockchip/patches-5.15/033-v5.17-phy-rockchip-inno-usb2-support-standalone-phy-nodes.patch new file mode 100644 index 00000000..40d1fa8f --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/033-v5.17-phy-rockchip-inno-usb2-support-standalone-phy-nodes.patch @@ -0,0 +1,44 @@ +From e6915e1acca57bc4fdb61dccd5cc2e49f72ef743 Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Wed, 15 Dec 2021 16:02:48 -0500 +Subject: [PATCH] phy: phy-rockchip-inno-usb2: support standalone phy nodes + +New Rockchip devices have the usb2 phy devices as standalone nodes +instead of children of the grf node. +Allow the driver to find the grf node from a phandle. + +Signed-off-by: Peter Geis +Tested-by: Michael Riesch +Link: https://lore.kernel.org/r/20211215210252.120923-5-pgwipeout@gmail.com +Signed-off-by: Vinod Koul +--- + drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +@@ -1081,12 +1081,19 @@ static int rockchip_usb2phy_probe(struct + return -EINVAL; + } + +- if (!dev->parent || !dev->parent->of_node) +- return -EINVAL; ++ if (!dev->parent || !dev->parent->of_node) { ++ rphy->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,usbgrf"); ++ if (IS_ERR(rphy->grf)) { ++ dev_err(dev, "failed to locate usbgrf\n"); ++ return PTR_ERR(rphy->grf); ++ } ++ } + +- rphy->grf = syscon_node_to_regmap(dev->parent->of_node); +- if (IS_ERR(rphy->grf)) +- return PTR_ERR(rphy->grf); ++ else { ++ rphy->grf = syscon_node_to_regmap(dev->parent->of_node); ++ if (IS_ERR(rphy->grf)) ++ return PTR_ERR(rphy->grf); ++ } + + if (of_device_is_compatible(np, "rockchip,rv1108-usb2phy")) { + rphy->usbgrf = diff --git a/root/target/linux/rockchip/patches-5.15/034-v5.17-phy-rockchip-inno-usb2-support-muxed-interrupts.patch b/root/target/linux/rockchip/patches-5.15/034-v5.17-phy-rockchip-inno-usb2-support-muxed-interrupts.patch new file mode 100644 index 00000000..57853705 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/034-v5.17-phy-rockchip-inno-usb2-support-muxed-interrupts.patch @@ -0,0 +1,237 @@ +From ed2b5a8e6b98d042b323afbe177a5dc618921b31 Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Wed, 15 Dec 2021 16:02:49 -0500 +Subject: [PATCH] phy: phy-rockchip-inno-usb2: support muxed interrupts + +The rk3568 usb2phy has a single muxed interrupt that handles all +interrupts. +Allow the driver to plug in only a single interrupt as necessary. + +Signed-off-by: Peter Geis +Tested-by: Michael Riesch +Link: https://lore.kernel.org/r/20211215210252.120923-6-pgwipeout@gmail.com +Signed-off-by: Vinod Koul +--- + drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 168 +++++++++++++----- + 1 file changed, 119 insertions(+), 49 deletions(-) + +--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +@@ -204,6 +204,7 @@ struct rockchip_usb2phy_port { + * @dcd_retries: The retry count used to track Data contact + * detection process. + * @edev: extcon device for notification registration ++ * @irq: muxed interrupt for single irq configuration + * @phy_cfg: phy register configuration, assigned by driver data. + * @ports: phy port instance. + */ +@@ -218,6 +219,7 @@ struct rockchip_usb2phy { + enum power_supply_type chg_type; + u8 dcd_retries; + struct extcon_dev *edev; ++ int irq; + const struct rockchip_usb2phy_cfg *phy_cfg; + struct rockchip_usb2phy_port ports[USB2PHY_NUM_PORTS]; + }; +@@ -934,6 +936,102 @@ static irqreturn_t rockchip_usb2phy_otg_ + return IRQ_NONE; + } + ++static irqreturn_t rockchip_usb2phy_irq(int irq, void *data) ++{ ++ struct rockchip_usb2phy *rphy = data; ++ struct rockchip_usb2phy_port *rport; ++ irqreturn_t ret = IRQ_NONE; ++ unsigned int index; ++ ++ for (index = 0; index < rphy->phy_cfg->num_ports; index++) { ++ rport = &rphy->ports[index]; ++ if (!rport->phy) ++ continue; ++ ++ /* Handle linestate irq for both otg port and host port */ ++ ret = rockchip_usb2phy_linestate_irq(irq, rport); ++ } ++ ++ return ret; ++} ++ ++static int rockchip_usb2phy_port_irq_init(struct rockchip_usb2phy *rphy, ++ struct rockchip_usb2phy_port *rport, ++ struct device_node *child_np) ++{ ++ int ret; ++ ++ /* ++ * If the usb2 phy used combined irq for otg and host port, ++ * don't need to init otg and host port irq separately. ++ */ ++ if (rphy->irq > 0) ++ return 0; ++ ++ switch (rport->port_id) { ++ case USB2PHY_PORT_HOST: ++ rport->ls_irq = of_irq_get_byname(child_np, "linestate"); ++ if (rport->ls_irq < 0) { ++ dev_err(rphy->dev, "no linestate irq provided\n"); ++ return rport->ls_irq; ++ } ++ ++ ret = devm_request_threaded_irq(rphy->dev, rport->ls_irq, NULL, ++ rockchip_usb2phy_linestate_irq, ++ IRQF_ONESHOT, ++ "rockchip_usb2phy", rport); ++ if (ret) { ++ dev_err(rphy->dev, "failed to request linestate irq handle\n"); ++ return ret; ++ } ++ break; ++ case USB2PHY_PORT_OTG: ++ /* ++ * Some SoCs use one interrupt with otg-id/otg-bvalid/linestate ++ * interrupts muxed together, so probe the otg-mux interrupt first, ++ * if not found, then look for the regular interrupts one by one. ++ */ ++ rport->otg_mux_irq = of_irq_get_byname(child_np, "otg-mux"); ++ if (rport->otg_mux_irq > 0) { ++ ret = devm_request_threaded_irq(rphy->dev, rport->otg_mux_irq, ++ NULL, ++ rockchip_usb2phy_otg_mux_irq, ++ IRQF_ONESHOT, ++ "rockchip_usb2phy_otg", ++ rport); ++ if (ret) { ++ dev_err(rphy->dev, ++ "failed to request otg-mux irq handle\n"); ++ return ret; ++ } ++ } else { ++ rport->bvalid_irq = of_irq_get_byname(child_np, "otg-bvalid"); ++ if (rport->bvalid_irq < 0) { ++ dev_err(rphy->dev, "no vbus valid irq provided\n"); ++ ret = rport->bvalid_irq; ++ return ret; ++ } ++ ++ ret = devm_request_threaded_irq(rphy->dev, rport->bvalid_irq, ++ NULL, ++ rockchip_usb2phy_bvalid_irq, ++ IRQF_ONESHOT, ++ "rockchip_usb2phy_bvalid", ++ rport); ++ if (ret) { ++ dev_err(rphy->dev, ++ "failed to request otg-bvalid irq handle\n"); ++ return ret; ++ } ++ } ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ + static int rockchip_usb2phy_host_port_init(struct rockchip_usb2phy *rphy, + struct rockchip_usb2phy_port *rport, + struct device_node *child_np) +@@ -947,18 +1045,9 @@ static int rockchip_usb2phy_host_port_in + mutex_init(&rport->mutex); + INIT_DELAYED_WORK(&rport->sm_work, rockchip_usb2phy_sm_work); + +- rport->ls_irq = of_irq_get_byname(child_np, "linestate"); +- if (rport->ls_irq < 0) { +- dev_err(rphy->dev, "no linestate irq provided\n"); +- return rport->ls_irq; +- } +- +- ret = devm_request_threaded_irq(rphy->dev, rport->ls_irq, NULL, +- rockchip_usb2phy_linestate_irq, +- IRQF_ONESHOT, +- "rockchip_usb2phy", rport); ++ ret = rockchip_usb2phy_port_irq_init(rphy, rport, child_np); + if (ret) { +- dev_err(rphy->dev, "failed to request linestate irq handle\n"); ++ dev_err(rphy->dev, "failed to setup host irq\n"); + return ret; + } + +@@ -1007,44 +1096,10 @@ static int rockchip_usb2phy_otg_port_ini + INIT_DELAYED_WORK(&rport->chg_work, rockchip_chg_detect_work); + INIT_DELAYED_WORK(&rport->otg_sm_work, rockchip_usb2phy_otg_sm_work); + +- /* +- * Some SoCs use one interrupt with otg-id/otg-bvalid/linestate +- * interrupts muxed together, so probe the otg-mux interrupt first, +- * if not found, then look for the regular interrupts one by one. +- */ +- rport->otg_mux_irq = of_irq_get_byname(child_np, "otg-mux"); +- if (rport->otg_mux_irq > 0) { +- ret = devm_request_threaded_irq(rphy->dev, rport->otg_mux_irq, +- NULL, +- rockchip_usb2phy_otg_mux_irq, +- IRQF_ONESHOT, +- "rockchip_usb2phy_otg", +- rport); +- if (ret) { +- dev_err(rphy->dev, +- "failed to request otg-mux irq handle\n"); +- goto out; +- } +- } else { +- rport->bvalid_irq = of_irq_get_byname(child_np, "otg-bvalid"); +- if (rport->bvalid_irq < 0) { +- dev_err(rphy->dev, "no vbus valid irq provided\n"); +- ret = rport->bvalid_irq; +- goto out; +- } +- +- ret = devm_request_threaded_irq(rphy->dev, rport->bvalid_irq, +- NULL, +- rockchip_usb2phy_bvalid_irq, +- IRQF_ONESHOT, +- "rockchip_usb2phy_bvalid", +- rport); +- if (ret) { +- dev_err(rphy->dev, +- "failed to request otg-bvalid irq handle\n"); +- goto out; +- } +- } ++ ret = rockchip_usb2phy_port_irq_init(rphy, rport, child_np); ++ if (ret) { ++ dev_err(rphy->dev, "failed to init irq for host port\n"); ++ goto out; + + if (!IS_ERR(rphy->edev)) { + rport->event_nb.notifier_call = rockchip_otg_event; +@@ -1124,6 +1179,7 @@ static int rockchip_usb2phy_probe(struct + phy_cfgs = match->data; + rphy->chg_state = USB_CHG_STATE_UNDEFINED; + rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN; ++ rphy->irq = platform_get_irq_optional(pdev, 0); + platform_set_drvdata(pdev, rphy); + + ret = rockchip_usb2phy_extcon_register(rphy); +@@ -1203,6 +1259,20 @@ next_child: + } + + provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); ++ ++ if (rphy->irq > 0) { ++ ret = devm_request_threaded_irq(rphy->dev, rphy->irq, NULL, ++ rockchip_usb2phy_irq, ++ IRQF_ONESHOT, ++ "rockchip_usb2phy", ++ rphy); ++ if (ret) { ++ dev_err(rphy->dev, ++ "failed to request usb2phy irq handle\n"); ++ goto put_child; ++ } ++ } ++ + return PTR_ERR_OR_ZERO(provider); + + put_child: diff --git a/root/target/linux/rockchip/patches-5.15/035-v5.17-phy-rockchip-inno-usb2-add-rk3568-support.patch b/root/target/linux/rockchip/patches-5.15/035-v5.17-phy-rockchip-inno-usb2-add-rk3568-support.patch new file mode 100644 index 00000000..8de87e13 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/035-v5.17-phy-rockchip-inno-usb2-add-rk3568-support.patch @@ -0,0 +1,104 @@ +From 42b559727a45d79c811f493515eb9b7e56016421 Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Wed, 15 Dec 2021 16:02:50 -0500 +Subject: [PATCH] phy: phy-rockchip-inno-usb2: add rk3568 support + +The rk3568 usb2phy is a standalone device with a single muxed interrupt. +Add support for the registers to the usb2phy driver. + +Signed-off-by: Peter Geis +Tested-by: Michael Riesch +Link: https://lore.kernel.org/r/20211215210252.120923-7-pgwipeout@gmail.com +Signed-off-by: Vinod Koul +--- + drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 65 +++++++++++++++++++ + 1 file changed, 65 insertions(+) + +--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +@@ -1100,6 +1100,7 @@ static int rockchip_usb2phy_otg_port_ini + if (ret) { + dev_err(rphy->dev, "failed to init irq for host port\n"); + goto out; ++ } + + if (!IS_ERR(rphy->edev)) { + rport->event_nb.notifier_call = rockchip_otg_event; +@@ -1511,6 +1512,69 @@ static const struct rockchip_usb2phy_cfg + { /* sentinel */ } + }; + ++static const struct rockchip_usb2phy_cfg rk3568_phy_cfgs[] = { ++ { ++ .reg = 0xfe8a0000, ++ .num_ports = 2, ++ .clkout_ctl = { 0x0008, 4, 4, 1, 0 }, ++ .port_cfgs = { ++ [USB2PHY_PORT_OTG] = { ++ .phy_sus = { 0x0000, 8, 0, 0, 0x1d1 }, ++ .bvalid_det_en = { 0x0080, 2, 2, 0, 1 }, ++ .bvalid_det_st = { 0x0084, 2, 2, 0, 1 }, ++ .bvalid_det_clr = { 0x0088, 2, 2, 0, 1 }, ++ .utmi_avalid = { 0x00c0, 10, 10, 0, 1 }, ++ .utmi_bvalid = { 0x00c0, 9, 9, 0, 1 }, ++ }, ++ [USB2PHY_PORT_HOST] = { ++ /* Select suspend control from controller */ ++ .phy_sus = { 0x0004, 8, 0, 0x1d2, 0x1d2 }, ++ .ls_det_en = { 0x0080, 1, 1, 0, 1 }, ++ .ls_det_st = { 0x0084, 1, 1, 0, 1 }, ++ .ls_det_clr = { 0x0088, 1, 1, 0, 1 }, ++ .utmi_ls = { 0x00c0, 17, 16, 0, 1 }, ++ .utmi_hstdet = { 0x00c0, 19, 19, 0, 1 } ++ } ++ }, ++ .chg_det = { ++ .opmode = { 0x0000, 3, 0, 5, 1 }, ++ .cp_det = { 0x00c0, 24, 24, 0, 1 }, ++ .dcp_det = { 0x00c0, 23, 23, 0, 1 }, ++ .dp_det = { 0x00c0, 25, 25, 0, 1 }, ++ .idm_sink_en = { 0x0008, 8, 8, 0, 1 }, ++ .idp_sink_en = { 0x0008, 7, 7, 0, 1 }, ++ .idp_src_en = { 0x0008, 9, 9, 0, 1 }, ++ .rdm_pdwn_en = { 0x0008, 10, 10, 0, 1 }, ++ .vdm_src_en = { 0x0008, 12, 12, 0, 1 }, ++ .vdp_src_en = { 0x0008, 11, 11, 0, 1 }, ++ }, ++ }, ++ { ++ .reg = 0xfe8b0000, ++ .num_ports = 2, ++ .clkout_ctl = { 0x0008, 4, 4, 1, 0 }, ++ .port_cfgs = { ++ [USB2PHY_PORT_OTG] = { ++ .phy_sus = { 0x0000, 8, 0, 0x1d2, 0x1d1 }, ++ .ls_det_en = { 0x0080, 0, 0, 0, 1 }, ++ .ls_det_st = { 0x0084, 0, 0, 0, 1 }, ++ .ls_det_clr = { 0x0088, 0, 0, 0, 1 }, ++ .utmi_ls = { 0x00c0, 5, 4, 0, 1 }, ++ .utmi_hstdet = { 0x00c0, 7, 7, 0, 1 } ++ }, ++ [USB2PHY_PORT_HOST] = { ++ .phy_sus = { 0x0004, 8, 0, 0x1d2, 0x1d1 }, ++ .ls_det_en = { 0x0080, 1, 1, 0, 1 }, ++ .ls_det_st = { 0x0084, 1, 1, 0, 1 }, ++ .ls_det_clr = { 0x0088, 1, 1, 0, 1 }, ++ .utmi_ls = { 0x00c0, 17, 16, 0, 1 }, ++ .utmi_hstdet = { 0x00c0, 19, 19, 0, 1 } ++ } ++ }, ++ }, ++ { /* sentinel */ } ++}; ++ + static const struct rockchip_usb2phy_cfg rv1108_phy_cfgs[] = { + { + .reg = 0x100, +@@ -1560,6 +1624,7 @@ static const struct of_device_id rockchi + { .compatible = "rockchip,rk3328-usb2phy", .data = &rk3328_phy_cfgs }, + { .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs }, + { .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs }, ++ { .compatible = "rockchip,rk3568-usb2phy", .data = &rk3568_phy_cfgs }, + { .compatible = "rockchip,rv1108-usb2phy", .data = &rv1108_phy_cfgs }, + {} + }; diff --git a/root/target/linux/rockchip/patches-5.15/037-v5.18-phy-rockchip-add-naneng-combo-phy-for-RK3568.patch b/root/target/linux/rockchip/patches-5.15/037-v5.18-phy-rockchip-add-naneng-combo-phy-for-RK3568.patch new file mode 100644 index 00000000..e8fbf7f2 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/037-v5.18-phy-rockchip-add-naneng-combo-phy-for-RK3568.patch @@ -0,0 +1,633 @@ +From 7160820d742a16313f7802e33c2956c19548e488 Mon Sep 17 00:00:00 2001 +From: Yifeng Zhao +Date: Tue, 8 Feb 2022 17:13:25 +0800 +Subject: [PATCH] phy: rockchip: add naneng combo phy for RK3568 + +This patch implements a combo phy driver for Rockchip SoCs +with NaNeng IP block. This phy can be used as pcie-phy, usb3-phy, +sata-phy or sgmii-phy. + +Signed-off-by: Yifeng Zhao +Signed-off-by: Johan Jonker +Tested-by: Peter Geis +Tested-by: Frank Wunderlich +Link: https://lore.kernel.org/r/20220208091326.12495-4-yifeng.zhao@rock-chips.com +Signed-off-by: Vinod Koul +--- + drivers/phy/rockchip/Kconfig | 8 + + drivers/phy/rockchip/Makefile | 1 + + .../rockchip/phy-rockchip-naneng-combphy.c | 581 ++++++++++++++++++ + 3 files changed, 590 insertions(+) + create mode 100644 drivers/phy/rockchip/phy-rockchip-naneng-combphy.c + +--- a/drivers/phy/rockchip/Kconfig ++++ b/drivers/phy/rockchip/Kconfig +@@ -66,6 +66,14 @@ config PHY_ROCKCHIP_INNO_DSIDPHY + Enable this to support the Rockchip MIPI/LVDS/TTL PHY with + Innosilicon IP block. + ++config PHY_ROCKCHIP_NANENG_COMBO_PHY ++ tristate "Rockchip NANENG COMBO PHY Driver" ++ depends on ARCH_ROCKCHIP && OF ++ select GENERIC_PHY ++ help ++ Enable this to support the Rockchip PCIe/USB3.0/SATA/QSGMII ++ combo PHY with NaNeng IP block. ++ + config PHY_ROCKCHIP_PCIE + tristate "Rockchip PCIe PHY Driver" + depends on (ARCH_ROCKCHIP && OF) || COMPILE_TEST +--- a/drivers/phy/rockchip/Makefile ++++ b/drivers/phy/rockchip/Makefile +@@ -6,6 +6,7 @@ obj-$(CONFIG_PHY_ROCKCHIP_INNO_CSIDPHY) + obj-$(CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY) += phy-rockchip-inno-dsidphy.o + obj-$(CONFIG_PHY_ROCKCHIP_INNO_HDMI) += phy-rockchip-inno-hdmi.o + obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o ++obj-$(CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY) += phy-rockchip-naneng-combphy.o + obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o + obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o + obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o +--- /dev/null ++++ b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c +@@ -0,0 +1,581 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Rockchip PIPE USB3.0 PCIE SATA Combo Phy driver ++ * ++ * Copyright (C) 2021 Rockchip Electronics Co., Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define BIT_WRITEABLE_SHIFT 16 ++#define REF_CLOCK_24MHz (24 * HZ_PER_MHZ) ++#define REF_CLOCK_25MHz (25 * HZ_PER_MHZ) ++#define REF_CLOCK_100MHz (100 * HZ_PER_MHZ) ++ ++/* COMBO PHY REG */ ++#define PHYREG6 0x14 ++#define PHYREG6_PLL_DIV_MASK GENMASK(7, 6) ++#define PHYREG6_PLL_DIV_SHIFT 6 ++#define PHYREG6_PLL_DIV_2 1 ++ ++#define PHYREG7 0x18 ++#define PHYREG7_TX_RTERM_MASK GENMASK(7, 4) ++#define PHYREG7_TX_RTERM_SHIFT 4 ++#define PHYREG7_TX_RTERM_50OHM 8 ++#define PHYREG7_RX_RTERM_MASK GENMASK(3, 0) ++#define PHYREG7_RX_RTERM_SHIFT 0 ++#define PHYREG7_RX_RTERM_44OHM 15 ++ ++#define PHYREG8 0x1C ++#define PHYREG8_SSC_EN BIT(4) ++ ++#define PHYREG11 0x28 ++#define PHYREG11_SU_TRIM_0_7 0xF0 ++ ++#define PHYREG12 0x2C ++#define PHYREG12_PLL_LPF_ADJ_VALUE 4 ++ ++#define PHYREG13 0x30 ++#define PHYREG13_RESISTER_MASK GENMASK(5, 4) ++#define PHYREG13_RESISTER_SHIFT 0x4 ++#define PHYREG13_RESISTER_HIGH_Z 3 ++#define PHYREG13_CKRCV_AMP0 BIT(7) ++ ++#define PHYREG14 0x34 ++#define PHYREG14_CKRCV_AMP1 BIT(0) ++ ++#define PHYREG15 0x38 ++#define PHYREG15_CTLE_EN BIT(0) ++#define PHYREG15_SSC_CNT_MASK GENMASK(7, 6) ++#define PHYREG15_SSC_CNT_SHIFT 6 ++#define PHYREG15_SSC_CNT_VALUE 1 ++ ++#define PHYREG16 0x3C ++#define PHYREG16_SSC_CNT_VALUE 0x5f ++ ++#define PHYREG18 0x44 ++#define PHYREG18_PLL_LOOP 0x32 ++ ++#define PHYREG32 0x7C ++#define PHYREG32_SSC_MASK GENMASK(7, 4) ++#define PHYREG32_SSC_DIR_SHIFT 4 ++#define PHYREG32_SSC_UPWARD 0 ++#define PHYREG32_SSC_DOWNWARD 1 ++#define PHYREG32_SSC_OFFSET_SHIFT 6 ++#define PHYREG32_SSC_OFFSET_500PPM 1 ++ ++#define PHYREG33 0x80 ++#define PHYREG33_PLL_KVCO_MASK GENMASK(4, 2) ++#define PHYREG33_PLL_KVCO_SHIFT 2 ++#define PHYREG33_PLL_KVCO_VALUE 2 ++ ++struct rockchip_combphy_priv; ++ ++struct combphy_reg { ++ u16 offset; ++ u16 bitend; ++ u16 bitstart; ++ u16 disable; ++ u16 enable; ++}; ++ ++struct rockchip_combphy_grfcfg { ++ struct combphy_reg pcie_mode_set; ++ struct combphy_reg usb_mode_set; ++ struct combphy_reg sgmii_mode_set; ++ struct combphy_reg qsgmii_mode_set; ++ struct combphy_reg pipe_rxterm_set; ++ struct combphy_reg pipe_txelec_set; ++ struct combphy_reg pipe_txcomp_set; ++ struct combphy_reg pipe_clk_25m; ++ struct combphy_reg pipe_clk_100m; ++ struct combphy_reg pipe_phymode_sel; ++ struct combphy_reg pipe_rate_sel; ++ struct combphy_reg pipe_rxterm_sel; ++ struct combphy_reg pipe_txelec_sel; ++ struct combphy_reg pipe_txcomp_sel; ++ struct combphy_reg pipe_clk_ext; ++ struct combphy_reg pipe_sel_usb; ++ struct combphy_reg pipe_sel_qsgmii; ++ struct combphy_reg pipe_phy_status; ++ struct combphy_reg con0_for_pcie; ++ struct combphy_reg con1_for_pcie; ++ struct combphy_reg con2_for_pcie; ++ struct combphy_reg con3_for_pcie; ++ struct combphy_reg con0_for_sata; ++ struct combphy_reg con1_for_sata; ++ struct combphy_reg con2_for_sata; ++ struct combphy_reg con3_for_sata; ++ struct combphy_reg pipe_con0_for_sata; ++ struct combphy_reg pipe_xpcs_phy_ready; ++}; ++ ++struct rockchip_combphy_cfg { ++ const struct rockchip_combphy_grfcfg *grfcfg; ++ int (*combphy_cfg)(struct rockchip_combphy_priv *priv); ++}; ++ ++struct rockchip_combphy_priv { ++ u8 type; ++ void __iomem *mmio; ++ int num_clks; ++ struct clk_bulk_data *clks; ++ struct device *dev; ++ struct regmap *pipe_grf; ++ struct regmap *phy_grf; ++ struct phy *phy; ++ struct reset_control *phy_rst; ++ const struct rockchip_combphy_cfg *cfg; ++ bool enable_ssc; ++ bool ext_refclk; ++ struct clk *refclk; ++}; ++ ++static void rockchip_combphy_updatel(struct rockchip_combphy_priv *priv, ++ int mask, int val, int reg) ++{ ++ unsigned int temp; ++ ++ temp = readl(priv->mmio + reg); ++ temp = (temp & ~(mask)) | val; ++ writel(temp, priv->mmio + reg); ++} ++ ++static int rockchip_combphy_param_write(struct regmap *base, ++ const struct combphy_reg *reg, bool en) ++{ ++ u32 val, mask, tmp; ++ ++ tmp = en ? reg->enable : reg->disable; ++ mask = GENMASK(reg->bitend, reg->bitstart); ++ val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT); ++ ++ return regmap_write(base, reg->offset, val); ++} ++ ++static u32 rockchip_combphy_is_ready(struct rockchip_combphy_priv *priv) ++{ ++ const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; ++ u32 mask, val; ++ ++ mask = GENMASK(cfg->pipe_phy_status.bitend, ++ cfg->pipe_phy_status.bitstart); ++ ++ regmap_read(priv->phy_grf, cfg->pipe_phy_status.offset, &val); ++ val = (val & mask) >> cfg->pipe_phy_status.bitstart; ++ ++ return val; ++} ++ ++static int rockchip_combphy_init(struct phy *phy) ++{ ++ struct rockchip_combphy_priv *priv = phy_get_drvdata(phy); ++ const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; ++ u32 val; ++ int ret; ++ ++ ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks); ++ if (ret) { ++ dev_err(priv->dev, "failed to enable clks\n"); ++ return ret; ++ } ++ ++ switch (priv->type) { ++ case PHY_TYPE_PCIE: ++ case PHY_TYPE_USB3: ++ case PHY_TYPE_SATA: ++ case PHY_TYPE_SGMII: ++ case PHY_TYPE_QSGMII: ++ if (priv->cfg->combphy_cfg) ++ ret = priv->cfg->combphy_cfg(priv); ++ break; ++ default: ++ dev_err(priv->dev, "incompatible PHY type\n"); ++ ret = -EINVAL; ++ break; ++ } ++ ++ if (ret) { ++ dev_err(priv->dev, "failed to init phy for phy type %x\n", priv->type); ++ goto err_clk; ++ } ++ ++ ret = reset_control_deassert(priv->phy_rst); ++ if (ret) ++ goto err_clk; ++ ++ if (priv->type == PHY_TYPE_USB3) { ++ ret = readx_poll_timeout_atomic(rockchip_combphy_is_ready, ++ priv, val, ++ val == cfg->pipe_phy_status.enable, ++ 10, 1000); ++ if (ret) ++ dev_warn(priv->dev, "wait phy status ready timeout\n"); ++ } ++ ++ return 0; ++ ++err_clk: ++ clk_bulk_disable_unprepare(priv->num_clks, priv->clks); ++ ++ return ret; ++} ++ ++static int rockchip_combphy_exit(struct phy *phy) ++{ ++ struct rockchip_combphy_priv *priv = phy_get_drvdata(phy); ++ ++ clk_bulk_disable_unprepare(priv->num_clks, priv->clks); ++ reset_control_assert(priv->phy_rst); ++ ++ return 0; ++} ++ ++static const struct phy_ops rochchip_combphy_ops = { ++ .init = rockchip_combphy_init, ++ .exit = rockchip_combphy_exit, ++ .owner = THIS_MODULE, ++}; ++ ++static struct phy *rockchip_combphy_xlate(struct device *dev, struct of_phandle_args *args) ++{ ++ struct rockchip_combphy_priv *priv = dev_get_drvdata(dev); ++ ++ if (args->args_count != 1) { ++ dev_err(dev, "invalid number of arguments\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ if (priv->type != PHY_NONE && priv->type != args->args[0]) ++ dev_warn(dev, "phy type select %d overwriting type %d\n", ++ args->args[0], priv->type); ++ ++ priv->type = args->args[0]; ++ ++ return priv->phy; ++} ++ ++static int rockchip_combphy_parse_dt(struct device *dev, struct rockchip_combphy_priv *priv) ++{ ++ int i; ++ ++ priv->num_clks = devm_clk_bulk_get_all(dev, &priv->clks); ++ if (priv->num_clks < 1) ++ return -EINVAL; ++ ++ priv->refclk = NULL; ++ for (i = 0; i < priv->num_clks; i++) { ++ if (!strncmp(priv->clks[i].id, "ref", 3)) { ++ priv->refclk = priv->clks[i].clk; ++ break; ++ } ++ } ++ ++ if (!priv->refclk) { ++ dev_err(dev, "no refclk found\n"); ++ return -EINVAL; ++ } ++ ++ priv->pipe_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,pipe-grf"); ++ if (IS_ERR(priv->pipe_grf)) { ++ dev_err(dev, "failed to find peri_ctrl pipe-grf regmap\n"); ++ return PTR_ERR(priv->pipe_grf); ++ } ++ ++ priv->phy_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,pipe-phy-grf"); ++ if (IS_ERR(priv->phy_grf)) { ++ dev_err(dev, "failed to find peri_ctrl pipe-phy-grf regmap\n"); ++ return PTR_ERR(priv->phy_grf); ++ } ++ ++ priv->enable_ssc = device_property_present(dev, "rockchip,enable-ssc"); ++ ++ priv->ext_refclk = device_property_present(dev, "rockchip,ext-refclk"); ++ ++ priv->phy_rst = devm_reset_control_array_get_exclusive(dev); ++ if (IS_ERR(priv->phy_rst)) ++ return dev_err_probe(dev, PTR_ERR(priv->phy_rst), "failed to get phy reset\n"); ++ ++ return 0; ++} ++ ++static int rockchip_combphy_probe(struct platform_device *pdev) ++{ ++ struct phy_provider *phy_provider; ++ struct device *dev = &pdev->dev; ++ struct rockchip_combphy_priv *priv; ++ const struct rockchip_combphy_cfg *phy_cfg; ++ struct resource *res; ++ int ret; ++ ++ phy_cfg = of_device_get_match_data(dev); ++ if (!phy_cfg) { ++ dev_err(dev, "no OF match data provided\n"); ++ return -EINVAL; ++ } ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->mmio = devm_platform_get_and_ioremap_resource(pdev, 0, &res); ++ if (IS_ERR(priv->mmio)) { ++ ret = PTR_ERR(priv->mmio); ++ return ret; ++ } ++ ++ priv->dev = dev; ++ priv->type = PHY_NONE; ++ priv->cfg = phy_cfg; ++ ++ ret = rockchip_combphy_parse_dt(dev, priv); ++ if (ret) ++ return ret; ++ ++ ret = reset_control_assert(priv->phy_rst); ++ if (ret) { ++ dev_err(dev, "failed to reset phy\n"); ++ return ret; ++ } ++ ++ priv->phy = devm_phy_create(dev, NULL, &rochchip_combphy_ops); ++ if (IS_ERR(priv->phy)) { ++ dev_err(dev, "failed to create combphy\n"); ++ return PTR_ERR(priv->phy); ++ } ++ ++ dev_set_drvdata(dev, priv); ++ phy_set_drvdata(priv->phy, priv); ++ ++ phy_provider = devm_of_phy_provider_register(dev, rockchip_combphy_xlate); ++ ++ return PTR_ERR_OR_ZERO(phy_provider); ++} ++ ++static int rk3568_combphy_cfg(struct rockchip_combphy_priv *priv) ++{ ++ const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; ++ unsigned long rate; ++ u32 val; ++ ++ switch (priv->type) { ++ case PHY_TYPE_PCIE: ++ /* Set SSC downward spread spectrum. */ ++ rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, ++ PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT, ++ PHYREG32); ++ ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_pcie, true); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_pcie, true); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_pcie, true); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_pcie, true); ++ break; ++ ++ case PHY_TYPE_USB3: ++ /* Set SSC downward spread spectrum. */ ++ rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, ++ PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT, ++ PHYREG32); ++ ++ /* Enable adaptive CTLE for USB3.0 Rx. */ ++ val = readl(priv->mmio + PHYREG15); ++ val |= PHYREG15_CTLE_EN; ++ writel(val, priv->mmio + PHYREG15); ++ ++ /* Set PLL KVCO fine tuning signals. */ ++ rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK, ++ PHYREG33_PLL_KVCO_VALUE << PHYREG33_PLL_KVCO_SHIFT, ++ PHYREG33); ++ ++ /* Enable controlling random jitter. */ ++ writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12); ++ ++ /* Set PLL input clock divider 1/2. */ ++ rockchip_combphy_updatel(priv, PHYREG6_PLL_DIV_MASK, ++ PHYREG6_PLL_DIV_2 << PHYREG6_PLL_DIV_SHIFT, ++ PHYREG6); ++ ++ writel(PHYREG18_PLL_LOOP, priv->mmio + PHYREG18); ++ writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11); ++ ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_usb, true); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->usb_mode_set, true); ++ break; ++ ++ case PHY_TYPE_SATA: ++ /* Enable adaptive CTLE for SATA Rx. */ ++ val = readl(priv->mmio + PHYREG15); ++ val |= PHYREG15_CTLE_EN; ++ writel(val, priv->mmio + PHYREG15); ++ /* ++ * Set tx_rterm=50ohm and rx_rterm=44ohm for SATA. ++ * 0: 60ohm, 8: 50ohm 15: 44ohm (by step abort 1ohm) ++ */ ++ val = PHYREG7_TX_RTERM_50OHM << PHYREG7_TX_RTERM_SHIFT; ++ val |= PHYREG7_RX_RTERM_44OHM << PHYREG7_RX_RTERM_SHIFT; ++ writel(val, priv->mmio + PHYREG7); ++ ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_sata, true); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_sata, true); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_sata, true); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_sata, true); ++ rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true); ++ break; ++ ++ case PHY_TYPE_SGMII: ++ rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->sgmii_mode_set, true); ++ break; ++ ++ case PHY_TYPE_QSGMII: ++ rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_rate_sel, true); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->qsgmii_mode_set, true); ++ break; ++ ++ default: ++ dev_err(priv->dev, "incompatible PHY type\n"); ++ return -EINVAL; ++ } ++ ++ rate = clk_get_rate(priv->refclk); ++ ++ switch (rate) { ++ case REF_CLOCK_24MHz: ++ if (priv->type == PHY_TYPE_USB3 || priv->type == PHY_TYPE_SATA) { ++ /* Set ssc_cnt[9:0]=0101111101 & 31.5KHz. */ ++ val = PHYREG15_SSC_CNT_VALUE << PHYREG15_SSC_CNT_SHIFT; ++ rockchip_combphy_updatel(priv, PHYREG15_SSC_CNT_MASK, ++ val, PHYREG15); ++ ++ writel(PHYREG16_SSC_CNT_VALUE, priv->mmio + PHYREG16); ++ } ++ break; ++ ++ case REF_CLOCK_25MHz: ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_25m, true); ++ break; ++ ++ case REF_CLOCK_100MHz: ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_100m, true); ++ if (priv->type == PHY_TYPE_PCIE) { ++ /* PLL KVCO fine tuning. */ ++ val = PHYREG33_PLL_KVCO_VALUE << PHYREG33_PLL_KVCO_SHIFT; ++ rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK, ++ val, PHYREG33); ++ ++ /* Enable controlling random jitter. */ ++ writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12); ++ ++ val = PHYREG6_PLL_DIV_2 << PHYREG6_PLL_DIV_SHIFT; ++ rockchip_combphy_updatel(priv, PHYREG6_PLL_DIV_MASK, ++ val, PHYREG6); ++ ++ writel(PHYREG18_PLL_LOOP, priv->mmio + PHYREG18); ++ writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11); ++ } else if (priv->type == PHY_TYPE_SATA) { ++ /* downward spread spectrum +500ppm */ ++ val = PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT; ++ val |= PHYREG32_SSC_OFFSET_500PPM << PHYREG32_SSC_OFFSET_SHIFT; ++ rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, val, PHYREG32); ++ } ++ break; ++ ++ default: ++ dev_err(priv->dev, "unsupported rate: %lu\n", rate); ++ return -EINVAL; ++ } ++ ++ if (priv->ext_refclk) { ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_ext, true); ++ if (priv->type == PHY_TYPE_PCIE && rate == REF_CLOCK_100MHz) { ++ val = PHYREG13_RESISTER_HIGH_Z << PHYREG13_RESISTER_SHIFT; ++ val |= PHYREG13_CKRCV_AMP0; ++ rockchip_combphy_updatel(priv, PHYREG13_RESISTER_MASK, val, PHYREG13); ++ ++ val = readl(priv->mmio + PHYREG14); ++ val |= PHYREG14_CKRCV_AMP1; ++ writel(val, priv->mmio + PHYREG14); ++ } ++ } ++ ++ if (priv->enable_ssc) { ++ val = readl(priv->mmio + PHYREG8); ++ val |= PHYREG8_SSC_EN; ++ writel(val, priv->mmio + PHYREG8); ++ } ++ ++ return 0; ++} ++ ++static const struct rockchip_combphy_grfcfg rk3568_combphy_grfcfgs = { ++ /* pipe-phy-grf */ ++ .pcie_mode_set = { 0x0000, 5, 0, 0x00, 0x11 }, ++ .usb_mode_set = { 0x0000, 5, 0, 0x00, 0x04 }, ++ .sgmii_mode_set = { 0x0000, 5, 0, 0x00, 0x01 }, ++ .qsgmii_mode_set = { 0x0000, 5, 0, 0x00, 0x21 }, ++ .pipe_rxterm_set = { 0x0000, 12, 12, 0x00, 0x01 }, ++ .pipe_txelec_set = { 0x0004, 1, 1, 0x00, 0x01 }, ++ .pipe_txcomp_set = { 0x0004, 4, 4, 0x00, 0x01 }, ++ .pipe_clk_25m = { 0x0004, 14, 13, 0x00, 0x01 }, ++ .pipe_clk_100m = { 0x0004, 14, 13, 0x00, 0x02 }, ++ .pipe_phymode_sel = { 0x0008, 1, 1, 0x00, 0x01 }, ++ .pipe_rate_sel = { 0x0008, 2, 2, 0x00, 0x01 }, ++ .pipe_rxterm_sel = { 0x0008, 8, 8, 0x00, 0x01 }, ++ .pipe_txelec_sel = { 0x0008, 12, 12, 0x00, 0x01 }, ++ .pipe_txcomp_sel = { 0x0008, 15, 15, 0x00, 0x01 }, ++ .pipe_clk_ext = { 0x000c, 9, 8, 0x02, 0x01 }, ++ .pipe_sel_usb = { 0x000c, 14, 13, 0x00, 0x01 }, ++ .pipe_sel_qsgmii = { 0x000c, 15, 13, 0x00, 0x07 }, ++ .pipe_phy_status = { 0x0034, 6, 6, 0x01, 0x00 }, ++ .con0_for_pcie = { 0x0000, 15, 0, 0x00, 0x1000 }, ++ .con1_for_pcie = { 0x0004, 15, 0, 0x00, 0x0000 }, ++ .con2_for_pcie = { 0x0008, 15, 0, 0x00, 0x0101 }, ++ .con3_for_pcie = { 0x000c, 15, 0, 0x00, 0x0200 }, ++ .con0_for_sata = { 0x0000, 15, 0, 0x00, 0x0119 }, ++ .con1_for_sata = { 0x0004, 15, 0, 0x00, 0x0040 }, ++ .con2_for_sata = { 0x0008, 15, 0, 0x00, 0x80c3 }, ++ .con3_for_sata = { 0x000c, 15, 0, 0x00, 0x4407 }, ++ /* pipe-grf */ ++ .pipe_con0_for_sata = { 0x0000, 15, 0, 0x00, 0x2220 }, ++ .pipe_xpcs_phy_ready = { 0x0040, 2, 2, 0x00, 0x01 }, ++}; ++ ++static const struct rockchip_combphy_cfg rk3568_combphy_cfgs = { ++ .grfcfg = &rk3568_combphy_grfcfgs, ++ .combphy_cfg = rk3568_combphy_cfg, ++}; ++ ++static const struct of_device_id rockchip_combphy_of_match[] = { ++ { ++ .compatible = "rockchip,rk3568-naneng-combphy", ++ .data = &rk3568_combphy_cfgs, ++ }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, rockchip_combphy_of_match); ++ ++static struct platform_driver rockchip_combphy_driver = { ++ .probe = rockchip_combphy_probe, ++ .driver = { ++ .name = "rockchip-naneng-combphy", ++ .of_match_table = rockchip_combphy_of_match, ++ }, ++}; ++module_platform_driver(rockchip_combphy_driver); ++ ++MODULE_DESCRIPTION("Rockchip NANENG COMBPHY driver"); ++MODULE_LICENSE("GPL v2"); diff --git a/root/target/linux/rockchip/patches-5.15/040-v5.18-usb-dwc3-core-do-not-use-3.0-clock-when-operating-in-2.0.patch b/root/target/linux/rockchip/patches-5.15/040-v5.18-usb-dwc3-core-do-not-use-3.0-clock-when-operating-in-2.0.patch new file mode 100644 index 00000000..95c29a28 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/040-v5.18-usb-dwc3-core-do-not-use-3.0-clock-when-operating-in-2.0.patch @@ -0,0 +1,46 @@ +From 62b20e6e0dde8d5633e3d94b028f86fb24b31d22 Mon Sep 17 00:00:00 2001 +From: Bin Yang +Date: Mon, 28 Feb 2022 08:56:56 -0500 +Subject: [PATCH] usb: dwc3: core: do not use 3.0 clock when operating in 2.0 + mode + +In the 3.0 device core, if the core is programmed to operate in +2.0 only, then setting the GUCTL1.DEV_FORCE_20_CLK_FOR_30_CLK makes +the internal 2.0(utmi/ulpi) clock to be routed as the 3.0 (pipe) +clock. Enabling this feature allows the pipe3 clock to be not-running +when forcibly operating in 2.0 device mode. + +Tested-by: Michael Riesch +Signed-off-by: Bin Yang +Signed-off-by: Peter Geis +Link: https://lore.kernel.org/r/20220228135700.1089526-6-pgwipeout@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/dwc3/core.c | 5 +++++ + drivers/usb/dwc3/core.h | 1 + + 2 files changed, 6 insertions(+) + +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -1081,6 +1081,11 @@ static int dwc3_core_init(struct dwc3 *d + if (dwc->parkmode_disable_ss_quirk) + reg |= DWC3_GUCTL1_PARKMODE_DISABLE_SS; + ++ if (DWC3_VER_IS_WITHIN(DWC3, 290A, ANY) && ++ (dwc->maximum_speed == USB_SPEED_HIGH || ++ dwc->maximum_speed == USB_SPEED_FULL)) ++ reg |= DWC3_GUCTL1_DEV_FORCE_20_CLK_FOR_30_CLK; ++ + dwc3_writel(dwc->regs, DWC3_GUCTL1, reg); + } + +--- a/drivers/usb/dwc3/core.h ++++ b/drivers/usb/dwc3/core.h +@@ -258,6 +258,7 @@ + /* Global User Control 1 Register */ + #define DWC3_GUCTL1_DEV_DECOUPLE_L1L2_EVT BIT(31) + #define DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS BIT(28) ++#define DWC3_GUCTL1_DEV_FORCE_20_CLK_FOR_30_CLK BIT(26) + #define DWC3_GUCTL1_DEV_L1_EXIT_BY_HW BIT(24) + #define DWC3_GUCTL1_PARKMODE_DISABLE_SS BIT(17) + #define DWC3_GUCTL1_RESUME_OPMODE_HS_HOST BIT(10) diff --git a/root/target/linux/rockchip/patches-5.15/050-v5.18-mmc-dw_mmc-Support-setting-f_min-from-host-drivers.patch b/root/target/linux/rockchip/patches-5.15/050-v5.18-mmc-dw_mmc-Support-setting-f_min-from-host-drivers.patch new file mode 100644 index 00000000..6588068c --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/050-v5.18-mmc-dw_mmc-Support-setting-f_min-from-host-drivers.patch @@ -0,0 +1,54 @@ +From c4313e75001492f8a288d3ffd595544cbc880821 Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Sat, 5 Mar 2022 16:58:34 -0500 +Subject: [PATCH] mmc: dw_mmc: Support setting f_min from host drivers + +Host drivers may not be able to support frequencies as low as dw-mmc +supports. Unfortunately f_min isn't available when the drv_data->init +function is called, as the mmc_host struct hasn't been set up yet. + +Support the host drivers saving the requested minimum frequency, so we +can later set f_min when it is available. + +Signed-off-by: Peter Geis +Link: https://lore.kernel.org/r/20220305215835.2210388-2-pgwipeout@gmail.com +Signed-off-by: Ulf Hansson +--- + drivers/mmc/host/dw_mmc.c | 7 ++++++- + drivers/mmc/host/dw_mmc.h | 2 ++ + 2 files changed, 8 insertions(+), 1 deletion(-) + +--- a/drivers/mmc/host/dw_mmc.c ++++ b/drivers/mmc/host/dw_mmc.c +@@ -2853,7 +2853,12 @@ static int dw_mci_init_slot_caps(struct + if (host->pdata->caps2) + mmc->caps2 = host->pdata->caps2; + +- mmc->f_min = DW_MCI_FREQ_MIN; ++ /* if host has set a minimum_freq, we should respect it */ ++ if (host->minimum_speed) ++ mmc->f_min = host->minimum_speed; ++ else ++ mmc->f_min = DW_MCI_FREQ_MIN; ++ + if (!mmc->f_max) + mmc->f_max = DW_MCI_FREQ_MAX; + +--- a/drivers/mmc/host/dw_mmc.h ++++ b/drivers/mmc/host/dw_mmc.h +@@ -99,6 +99,7 @@ struct dw_mci_dma_slave { + * @bus_hz: The rate of @mck in Hz. This forms the basis for MMC bus + * rate and timeout calculations. + * @current_speed: Configured rate of the controller. ++ * @minimum_speed: Stored minimum rate of the controller. + * @fifoth_val: The value of FIFOTH register. + * @verid: Denote Version ID. + * @dev: Device associated with the MMC controller. +@@ -200,6 +201,7 @@ struct dw_mci { + + u32 bus_hz; + u32 current_speed; ++ u32 minimum_speed; + u32 fifoth_val; + u16 verid; + struct device *dev; diff --git a/root/target/linux/rockchip/patches-5.15/051-v5.18-mmc-dw-mmc-rockchip-Fix-handling-invalid-clock-rates.patch b/root/target/linux/rockchip/patches-5.15/051-v5.18-mmc-dw-mmc-rockchip-Fix-handling-invalid-clock-rates.patch new file mode 100644 index 00000000..f86a6cdf --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/051-v5.18-mmc-dw-mmc-rockchip-Fix-handling-invalid-clock-rates.patch @@ -0,0 +1,79 @@ +From 52c92286b71e28d88642a4a416f40fbdb6cbb46f Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Sat, 5 Mar 2022 16:58:35 -0500 +Subject: [PATCH] mmc: dw-mmc-rockchip: Fix handling invalid clock rates + +The Rockchip rk356x ciu clock cannot be set as low as the dw-mmc +hardware supports. This leads to a situation during card initialization +where the clock is set lower than the clock driver can support. The +dw-mmc-rockchip driver spews errors when this happens. +For normal operation this only happens a few times during boot, but when +cd-broken is enabled (in cases such as the SoQuartz module) this fires +multiple times each poll cycle. + +Fix this by testing the lowest possible frequency that the clock driver +can support which is within the mmc specification. Divide that rate by +the internal divider and set f_min to this. + +Signed-off-by: Peter Geis +Link: https://lore.kernel.org/r/20220305215835.2210388-3-pgwipeout@gmail.com +Signed-off-by: Ulf Hansson +--- + drivers/mmc/host/dw_mmc-rockchip.c | 27 +++++++++++++++++++++++---- + 1 file changed, 23 insertions(+), 4 deletions(-) + +--- a/drivers/mmc/host/dw_mmc-rockchip.c ++++ b/drivers/mmc/host/dw_mmc-rockchip.c +@@ -15,7 +15,9 @@ + #include "dw_mmc.h" + #include "dw_mmc-pltfm.h" + +-#define RK3288_CLKGEN_DIV 2 ++#define RK3288_CLKGEN_DIV 2 ++ ++static const unsigned int freqs[] = { 100000, 200000, 300000, 400000 }; + + struct dw_mci_rockchip_priv_data { + struct clk *drv_clk; +@@ -51,7 +53,7 @@ static void dw_mci_rk3288_set_ios(struct + + ret = clk_set_rate(host->ciu_clk, cclkin); + if (ret) +- dev_warn(host->dev, "failed to set rate %uHz\n", ios->clock); ++ dev_warn(host->dev, "failed to set rate %uHz err: %d\n", cclkin, ret); + + bus_hz = clk_get_rate(host->ciu_clk) / RK3288_CLKGEN_DIV; + if (bus_hz != host->bus_hz) { +@@ -290,13 +292,30 @@ static int dw_mci_rk3288_parse_dt(struct + + static int dw_mci_rockchip_init(struct dw_mci *host) + { ++ int ret, i; ++ + /* It is slot 8 on Rockchip SoCs */ + host->sdio_id0 = 8; + +- if (of_device_is_compatible(host->dev->of_node, +- "rockchip,rk3288-dw-mshc")) ++ if (of_device_is_compatible(host->dev->of_node, "rockchip,rk3288-dw-mshc")) { + host->bus_hz /= RK3288_CLKGEN_DIV; + ++ /* clock driver will fail if the clock is less than the lowest source clock ++ * divided by the internal clock divider. Test for the lowest available ++ * clock and set the minimum freq to clock / clock divider. ++ */ ++ ++ for (i = 0; i < ARRAY_SIZE(freqs); i++) { ++ ret = clk_round_rate(host->ciu_clk, freqs[i] * RK3288_CLKGEN_DIV); ++ if (ret > 0) { ++ host->minimum_speed = ret / RK3288_CLKGEN_DIV; ++ break; ++ } ++ } ++ if (ret < 0) ++ dev_warn(host->dev, "no valid minimum freq: %d\n", ret); ++ } ++ + return 0; + } + diff --git a/root/target/linux/rockchip/patches-5.15/052-v5.16-mfd-rk808-Add-support-for-power-off-on-RK817.patch b/root/target/linux/rockchip/patches-5.15/052-v5.16-mfd-rk808-Add-support-for-power-off-on-RK817.patch new file mode 100644 index 00000000..74f99511 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/052-v5.16-mfd-rk808-Add-support-for-power-off-on-RK817.patch @@ -0,0 +1,27 @@ +From 4d94b98f2e2407e3f053b2546f86c76179fea644 Mon Sep 17 00:00:00 2001 +From: Ondrej Jirman +Date: Sun, 29 Aug 2021 04:51:53 +0200 +Subject: [PATCH] mfd: rk808: Add support for power off on RK817 + +RK817 has a power-off bit in SYS_CFG3. Add support for powering +off the PMIC. + +Signed-off-by: Ondrej Jirman +Signed-off-by: Lee Jones +--- + drivers/mfd/rk808.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/mfd/rk808.c ++++ b/drivers/mfd/rk808.c +@@ -543,6 +543,10 @@ static void rk808_pm_power_off(void) + reg = RK808_DEVCTRL_REG, + bit = DEV_OFF_RST; + break; ++ case RK817_ID: ++ reg = RK817_SYS_CFG(3); ++ bit = DEV_OFF; ++ break; + case RK818_ID: + reg = RK818_DEVCTRL_REG; + bit = DEV_OFF; diff --git a/root/target/linux/rockchip/patches-5.15/053-v5.18-mfd-rk808-Add-reboot-support-to-rk808.c.patch b/root/target/linux/rockchip/patches-5.15/053-v5.18-mfd-rk808-Add-reboot-support-to-rk808.c.patch new file mode 100644 index 00000000..f4de9b7a --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/053-v5.18-mfd-rk808-Add-reboot-support-to-rk808.c.patch @@ -0,0 +1,110 @@ +From 56f216d8efbc1212bf5ff8a6ff5e29927965e8db Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Tue, 8 Feb 2022 14:40:23 -0500 +Subject: [PATCH] mfd: rk808: Add reboot support to rk808.c + +This adds reboot support to the rk808 pmic driver and enables it for +the rk809 and rk817 devices. +This only enables if the rockchip,system-power-controller flag is set. + +Signed-off-by: Peter Geis +Signed-off-by: Frank Wunderlich +Reviewed-by: Dmitry Osipenko +Signed-off-by: Lee Jones +Link: https://lore.kernel.org/r/20220208194023.929720-1-pgwipeout@gmail.com +--- + drivers/mfd/rk808.c | 44 +++++++++++++++++++++++++++++++++++++++ + include/linux/mfd/rk808.h | 1 + + 2 files changed, 45 insertions(+) + +--- a/drivers/mfd/rk808.c ++++ b/drivers/mfd/rk808.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + + struct rk808_reg_data { + int addr; +@@ -543,6 +544,7 @@ static void rk808_pm_power_off(void) + reg = RK808_DEVCTRL_REG, + bit = DEV_OFF_RST; + break; ++ case RK809_ID: + case RK817_ID: + reg = RK817_SYS_CFG(3); + bit = DEV_OFF; +@@ -559,6 +561,34 @@ static void rk808_pm_power_off(void) + dev_err(&rk808_i2c_client->dev, "Failed to shutdown device!\n"); + } + ++static int rk808_restart_notify(struct notifier_block *this, unsigned long mode, void *cmd) ++{ ++ struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); ++ unsigned int reg, bit; ++ int ret; ++ ++ switch (rk808->variant) { ++ case RK809_ID: ++ case RK817_ID: ++ reg = RK817_SYS_CFG(3); ++ bit = DEV_RST; ++ break; ++ ++ default: ++ return NOTIFY_DONE; ++ } ++ ret = regmap_update_bits(rk808->regmap, reg, bit, bit); ++ if (ret) ++ dev_err(&rk808_i2c_client->dev, "Failed to restart device!\n"); ++ ++ return NOTIFY_DONE; ++} ++ ++static struct notifier_block rk808_restart_handler = { ++ .notifier_call = rk808_restart_notify, ++ .priority = 192, ++}; ++ + static void rk8xx_shutdown(struct i2c_client *client) + { + struct rk808 *rk808 = i2c_get_clientdata(client); +@@ -727,6 +757,18 @@ static int rk808_probe(struct i2c_client + if (of_property_read_bool(np, "rockchip,system-power-controller")) { + rk808_i2c_client = client; + pm_power_off = rk808_pm_power_off; ++ ++ switch (rk808->variant) { ++ case RK809_ID: ++ case RK817_ID: ++ ret = register_restart_handler(&rk808_restart_handler); ++ if (ret) ++ dev_warn(&client->dev, "failed to register rst handler, %d\n", ret); ++ break; ++ default: ++ dev_dbg(&client->dev, "pmic controlled board reset not supported\n"); ++ break; ++ } + } + + return 0; +@@ -749,6 +791,8 @@ static int rk808_remove(struct i2c_clien + if (pm_power_off == rk808_pm_power_off) + pm_power_off = NULL; + ++ unregister_restart_handler(&rk808_restart_handler); ++ + return 0; + } + +--- a/include/linux/mfd/rk808.h ++++ b/include/linux/mfd/rk808.h +@@ -373,6 +373,7 @@ enum rk805_reg { + #define SWITCH2_EN BIT(6) + #define SWITCH1_EN BIT(5) + #define DEV_OFF_RST BIT(3) ++#define DEV_RST BIT(2) + #define DEV_OFF BIT(0) + #define RTC_STOP BIT(0) + diff --git a/root/target/linux/rockchip/patches-5.15/054-v5.19-soc-rockchip-set-dwc3-clock-for-rk3566.patch b/root/target/linux/rockchip/patches-5.15/054-v5.19-soc-rockchip-set-dwc3-clock-for-rk3566.patch new file mode 100644 index 00000000..f2288c75 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/054-v5.19-soc-rockchip-set-dwc3-clock-for-rk3566.patch @@ -0,0 +1,51 @@ +From 5c0bb71138770d85ea840acd379edc6471b867ee Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Fri, 8 Apr 2022 11:12:34 -0400 +Subject: [PATCH] soc: rockchip: set dwc3 clock for rk3566 + +The rk3566 dwc3 otg port clock is unavailable at boot, as it defaults to +the combophy as the clock source. As combophy0 doesn't exist on rk3566, +we need to set the clock source to the usb2 phy instead. + +Add handling to the grf driver to handle this on boot. + +Signed-off-by: Peter Geis +Link: https://lore.kernel.org/r/20220408151237.3165046-3-pgwipeout@gmail.com +Signed-off-by: Heiko Stuebner +--- + drivers/soc/rockchip/grf.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +--- a/drivers/soc/rockchip/grf.c ++++ b/drivers/soc/rockchip/grf.c +@@ -108,6 +108,20 @@ static const struct rockchip_grf_info rk + .num_values = ARRAY_SIZE(rk3399_defaults), + }; + ++#define RK3566_GRF_USB3OTG0_CON1 0x0104 ++ ++static const struct rockchip_grf_value rk3566_defaults[] __initconst = { ++ { "usb3otg port switch", RK3566_GRF_USB3OTG0_CON1, HIWORD_UPDATE(0, 1, 12) }, ++ { "usb3otg clock switch", RK3566_GRF_USB3OTG0_CON1, HIWORD_UPDATE(1, 1, 7) }, ++ { "usb3otg disable usb3", RK3566_GRF_USB3OTG0_CON1, HIWORD_UPDATE(1, 1, 0) }, ++}; ++ ++static const struct rockchip_grf_info rk3566_pipegrf __initconst = { ++ .values = rk3566_defaults, ++ .num_values = ARRAY_SIZE(rk3566_defaults), ++}; ++ ++ + static const struct of_device_id rockchip_grf_dt_match[] __initconst = { + { + .compatible = "rockchip,rk3036-grf", +@@ -130,6 +144,9 @@ static const struct of_device_id rockchi + }, { + .compatible = "rockchip,rk3399-grf", + .data = (void *)&rk3399_grf, ++ }, { ++ .compatible = "rockchip,rk3566-pipe-grf", ++ .data = (void *)&rk3566_pipegrf, + }, + { /* sentinel */ }, + }; diff --git a/root/target/linux/rockchip/patches-5.15/056-v5.19-PCI-rockchip-dwc-Reset-core-at-driver-probe.patch b/root/target/linux/rockchip/patches-5.15/056-v5.19-PCI-rockchip-dwc-Reset-core-at-driver-probe.patch new file mode 100644 index 00000000..fd380bef --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/056-v5.19-PCI-rockchip-dwc-Reset-core-at-driver-probe.patch @@ -0,0 +1,72 @@ +From 431e7d2eece5b906578926d15ee22a70504c364d Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Fri, 29 Apr 2022 08:38:28 -0400 +Subject: [PATCH] PCI: rockchip-dwc: Reset core at driver probe + +The PCIe controller is in an unknown state at driver probe. This can +lead to undesireable effects when the driver attempts to configure the +controller. + +Prevent issues in the future by resetting the core during probe. + +Link: https://lore.kernel.org/r/20220429123832.2376381-3-pgwipeout@gmail.com +Tested-by: Nicolas Frattaroli +Signed-off-by: Peter Geis +Signed-off-by: Lorenzo Pieralisi +--- + drivers/pci/controller/dwc/pcie-dw-rockchip.c | 23 ++++++++----------- + 1 file changed, 10 insertions(+), 13 deletions(-) + +--- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c ++++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c +@@ -152,6 +152,11 @@ static int rockchip_pcie_resource_get(st + if (IS_ERR(rockchip->rst_gpio)) + return PTR_ERR(rockchip->rst_gpio); + ++ rockchip->rst = devm_reset_control_array_get_exclusive(&pdev->dev); ++ if (IS_ERR(rockchip->rst)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(rockchip->rst), ++ "failed to get reset lines\n"); ++ + return 0; + } + +@@ -182,18 +187,6 @@ static void rockchip_pcie_phy_deinit(str + phy_power_off(rockchip->phy); + } + +-static int rockchip_pcie_reset_control_release(struct rockchip_pcie *rockchip) +-{ +- struct device *dev = rockchip->pci.dev; +- +- rockchip->rst = devm_reset_control_array_get_exclusive(dev); +- if (IS_ERR(rockchip->rst)) +- return dev_err_probe(dev, PTR_ERR(rockchip->rst), +- "failed to get reset lines\n"); +- +- return reset_control_deassert(rockchip->rst); +-} +- + static const struct dw_pcie_ops dw_pcie_ops = { + .link_up = rockchip_pcie_link_up, + .start_link = rockchip_pcie_start_link, +@@ -222,6 +215,10 @@ static int rockchip_pcie_probe(struct pl + if (ret) + return ret; + ++ ret = reset_control_assert(rockchip->rst); ++ if (ret) ++ return ret; ++ + /* DON'T MOVE ME: must be enable before PHY init */ + rockchip->vpcie3v3 = devm_regulator_get_optional(dev, "vpcie3v3"); + if (IS_ERR(rockchip->vpcie3v3)) { +@@ -241,7 +238,7 @@ static int rockchip_pcie_probe(struct pl + if (ret) + goto disable_regulator; + +- ret = rockchip_pcie_reset_control_release(rockchip); ++ ret = reset_control_deassert(rockchip->rst); + if (ret) + goto deinit_phy; + diff --git a/root/target/linux/rockchip/patches-5.15/057-v5.19-PCI-rockchip-dwc-Add-legacy-interrupt-support.patch b/root/target/linux/rockchip/patches-5.15/057-v5.19-PCI-rockchip-dwc-Add-legacy-interrupt-support.patch new file mode 100644 index 00000000..05b762ff --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/057-v5.19-PCI-rockchip-dwc-Add-legacy-interrupt-support.patch @@ -0,0 +1,163 @@ +From e8aae154df6121167e5b4f156cfc2402e651d2b1 Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Fri, 29 Apr 2022 08:38:29 -0400 +Subject: [PATCH] PCI: rockchip-dwc: Add legacy interrupt support + +The legacy interrupts on the rk356x PCIe controller are handled by a +single muxed interrupt. Add IRQ domain support to the pcie-dw-rockchip +driver to support the virtual domain. + +Link: https://lore.kernel.org/r/20220429123832.2376381-4-pgwipeout@gmail.com +Signed-off-by: Peter Geis +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Marc Zyngier +--- + drivers/pci/controller/dwc/pcie-dw-rockchip.c | 96 ++++++++++++++++++- + 1 file changed, 94 insertions(+), 2 deletions(-) + +--- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c ++++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c +@@ -10,9 +10,12 @@ + + #include + #include ++#include ++#include + #include + #include + #include ++#include + #include + #include + #include +@@ -26,6 +29,7 @@ + */ + #define HIWORD_UPDATE(mask, val) (((mask) << 16) | (val)) + #define HIWORD_UPDATE_BIT(val) HIWORD_UPDATE(val, val) ++#define HIWORD_DISABLE_BIT(val) HIWORD_UPDATE(val, ~val) + + #define to_rockchip_pcie(x) dev_get_drvdata((x)->dev) + +@@ -36,10 +40,12 @@ + #define PCIE_LINKUP (PCIE_SMLH_LINKUP | PCIE_RDLH_LINKUP) + #define PCIE_L0S_ENTRY 0x11 + #define PCIE_CLIENT_GENERAL_CONTROL 0x0 ++#define PCIE_CLIENT_INTR_STATUS_LEGACY 0x8 ++#define PCIE_CLIENT_INTR_MASK_LEGACY 0x1c + #define PCIE_CLIENT_GENERAL_DEBUG 0x104 +-#define PCIE_CLIENT_HOT_RESET_CTRL 0x180 ++#define PCIE_CLIENT_HOT_RESET_CTRL 0x180 + #define PCIE_CLIENT_LTSSM_STATUS 0x300 +-#define PCIE_LTSSM_ENABLE_ENHANCE BIT(4) ++#define PCIE_LTSSM_ENABLE_ENHANCE BIT(4) + #define PCIE_LTSSM_STATUS_MASK GENMASK(5, 0) + + struct rockchip_pcie { +@@ -51,6 +57,7 @@ struct rockchip_pcie { + struct reset_control *rst; + struct gpio_desc *rst_gpio; + struct regulator *vpcie3v3; ++ struct irq_domain *irq_domain; + }; + + static int rockchip_pcie_readl_apb(struct rockchip_pcie *rockchip, +@@ -65,6 +72,78 @@ static void rockchip_pcie_writel_apb(str + writel_relaxed(val, rockchip->apb_base + reg); + } + ++static void rockchip_pcie_legacy_int_handler(struct irq_desc *desc) ++{ ++ struct irq_chip *chip = irq_desc_get_chip(desc); ++ struct rockchip_pcie *rockchip = irq_desc_get_handler_data(desc); ++ unsigned long reg, hwirq; ++ ++ chained_irq_enter(chip, desc); ++ ++ reg = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_INTR_STATUS_LEGACY); ++ ++ for_each_set_bit(hwirq, ®, 4) ++ generic_handle_domain_irq(rockchip->irq_domain, hwirq); ++ ++ chained_irq_exit(chip, desc); ++} ++ ++static void rockchip_intx_mask(struct irq_data *data) ++{ ++ rockchip_pcie_writel_apb(irq_data_get_irq_chip_data(data), ++ HIWORD_UPDATE_BIT(BIT(data->hwirq)), ++ PCIE_CLIENT_INTR_MASK_LEGACY); ++}; ++ ++static void rockchip_intx_unmask(struct irq_data *data) ++{ ++ rockchip_pcie_writel_apb(irq_data_get_irq_chip_data(data), ++ HIWORD_DISABLE_BIT(BIT(data->hwirq)), ++ PCIE_CLIENT_INTR_MASK_LEGACY); ++}; ++ ++static struct irq_chip rockchip_intx_irq_chip = { ++ .name = "INTx", ++ .irq_mask = rockchip_intx_mask, ++ .irq_unmask = rockchip_intx_unmask, ++ .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND, ++}; ++ ++static int rockchip_pcie_intx_map(struct irq_domain *domain, unsigned int irq, ++ irq_hw_number_t hwirq) ++{ ++ irq_set_chip_and_handler(irq, &rockchip_intx_irq_chip, handle_level_irq); ++ irq_set_chip_data(irq, domain->host_data); ++ ++ return 0; ++} ++ ++static const struct irq_domain_ops intx_domain_ops = { ++ .map = rockchip_pcie_intx_map, ++}; ++ ++static int rockchip_pcie_init_irq_domain(struct rockchip_pcie *rockchip) ++{ ++ struct device *dev = rockchip->pci.dev; ++ struct device_node *intc; ++ ++ intc = of_get_child_by_name(dev->of_node, "legacy-interrupt-controller"); ++ if (!intc) { ++ dev_err(dev, "missing child interrupt-controller node\n"); ++ return -EINVAL; ++ } ++ ++ rockchip->irq_domain = irq_domain_add_linear(intc, PCI_NUM_INTX, ++ &intx_domain_ops, rockchip); ++ of_node_put(intc); ++ if (!rockchip->irq_domain) { ++ dev_err(dev, "failed to get a INTx IRQ domain\n"); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ + static void rockchip_pcie_enable_ltssm(struct rockchip_pcie *rockchip) + { + rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_ENABLE_LTSSM, +@@ -111,7 +190,20 @@ static int rockchip_pcie_host_init(struc + { + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct rockchip_pcie *rockchip = to_rockchip_pcie(pci); ++ struct device *dev = rockchip->pci.dev; + u32 val = HIWORD_UPDATE_BIT(PCIE_LTSSM_ENABLE_ENHANCE); ++ int irq, ret; ++ ++ irq = of_irq_get_byname(dev->of_node, "legacy"); ++ if (irq < 0) ++ return irq; ++ ++ ret = rockchip_pcie_init_irq_domain(rockchip); ++ if (ret < 0) ++ dev_err(dev, "failed to init irq domain\n"); ++ ++ irq_set_chained_handler_and_data(irq, rockchip_pcie_legacy_int_handler, ++ rockchip); + + /* LTSSM enable control mode */ + rockchip_pcie_writel_apb(rockchip, val, PCIE_CLIENT_HOT_RESET_CTRL); diff --git a/root/target/linux/rockchip/patches-5.15/061-v5.20-arm64-enable-THP_SWAP-for-arm64.patch b/root/target/linux/rockchip/patches-5.15/061-v5.20-arm64-enable-THP_SWAP-for-arm64.patch new file mode 100644 index 00000000..036a87b4 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/061-v5.20-arm64-enable-THP_SWAP-for-arm64.patch @@ -0,0 +1,123 @@ +From d0637c505f8a1d8c4088642f1f3e9e3b22da14f6 Mon Sep 17 00:00:00 2001 +From: Barry Song +Date: Wed, 20 Jul 2022 21:37:37 +1200 +Subject: [PATCH] arm64: enable THP_SWAP for arm64 + +THP_SWAP has been proven to improve the swap throughput significantly +on x86_64 according to commit bd4c82c22c367e ("mm, THP, swap: delay +splitting THP after swapped out"). +As long as arm64 uses 4K page size, it is quite similar with x86_64 +by having 2MB PMD THP. THP_SWAP is architecture-independent, thus, +enabling it on arm64 will benefit arm64 as well. +A corner case is that MTE has an assumption that only base pages +can be swapped. We won't enable THP_SWAP for ARM64 hardware with +MTE support until MTE is reworked to coexist with THP_SWAP. + +A micro-benchmark is written to measure thp swapout throughput as +below, + + unsigned long long tv_to_ms(struct timeval tv) + { + return tv.tv_sec * 1000 + tv.tv_usec / 1000; + } + + main() + { + struct timeval tv_b, tv_e;; + #define SIZE 400*1024*1024 + volatile void *p = mmap(NULL, SIZE, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (!p) { + perror("fail to get memory"); + exit(-1); + } + + madvise(p, SIZE, MADV_HUGEPAGE); + memset(p, 0x11, SIZE); /* write to get mem */ + + gettimeofday(&tv_b, NULL); + madvise(p, SIZE, MADV_PAGEOUT); + gettimeofday(&tv_e, NULL); + + printf("swp out bandwidth: %ld bytes/ms\n", + SIZE/(tv_to_ms(tv_e) - tv_to_ms(tv_b))); + } + +Testing is done on rk3568 64bit Quad Core Cortex-A55 platform - +ROCK 3A. +thp swp throughput w/o patch: 2734bytes/ms (mean of 10 tests) +thp swp throughput w/ patch: 3331bytes/ms (mean of 10 tests) + +Cc: "Huang, Ying" +Cc: Minchan Kim +Cc: Johannes Weiner +Cc: Hugh Dickins +Cc: Andrea Arcangeli +Cc: Steven Price +Cc: Yang Shi +Reviewed-by: Anshuman Khandual +Signed-off-by: Barry Song +Link: https://lore.kernel.org/r/20220720093737.133375-1-21cnbao@gmail.com +Signed-off-by: Will Deacon +--- + arch/arm64/Kconfig | 1 + + arch/arm64/include/asm/pgtable.h | 6 ++++++ + include/linux/huge_mm.h | 12 ++++++++++++ + mm/swap_slots.c | 2 +- + 4 files changed, 20 insertions(+), 1 deletion(-) + +--- a/arch/arm64/Kconfig ++++ b/arch/arm64/Kconfig +@@ -95,6 +95,7 @@ config ARM64 + select ARCH_WANT_HUGE_PMD_SHARE if ARM64_4K_PAGES || (ARM64_16K_PAGES && !ARM64_VA_BITS_36) + select ARCH_WANT_LD_ORPHAN_WARN + select ARCH_WANTS_NO_INSTR ++ select ARCH_WANTS_THP_SWAP if ARM64_4K_PAGES + select ARCH_HAS_UBSAN_SANITIZE_ALL + select ARM_AMBA + select ARM_ARCH_TIMER +--- a/arch/arm64/include/asm/pgtable.h ++++ b/arch/arm64/include/asm/pgtable.h +@@ -44,6 +44,12 @@ + __flush_tlb_range(vma, addr, end, PUD_SIZE, false, 1) + #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ + ++static inline bool arch_thp_swp_supported(void) ++{ ++ return !system_supports_mte(); ++} ++#define arch_thp_swp_supported arch_thp_swp_supported ++ + /* + * Outside of a few very special situations (e.g. hibernation), we always + * use broadcast TLB invalidation instructions, therefore a spurious page +--- a/include/linux/huge_mm.h ++++ b/include/linux/huge_mm.h +@@ -495,4 +495,16 @@ static inline unsigned long thp_size(str + return PAGE_SIZE << thp_order(page); + } + ++/* ++ * archs that select ARCH_WANTS_THP_SWAP but don't support THP_SWP due to ++ * limitations in the implementation like arm64 MTE can override this to ++ * false ++ */ ++#ifndef arch_thp_swp_supported ++static inline bool arch_thp_swp_supported(void) ++{ ++ return true; ++} ++#endif ++ + #endif /* _LINUX_HUGE_MM_H */ +--- a/mm/swap_slots.c ++++ b/mm/swap_slots.c +@@ -308,7 +308,7 @@ swp_entry_t get_swap_page(struct page *p + entry.val = 0; + + if (PageTransHuge(page)) { +- if (IS_ENABLED(CONFIG_THP_SWAP)) ++ if (IS_ENABLED(CONFIG_THP_SWAP) && arch_thp_swp_supported()) + get_swap_pages(1, &entry, HPAGE_PMD_NR); + goto out; + } diff --git a/root/target/linux/rockchip/patches-5.15/069-v5.19-drm-rockchip-Add-VOP2-driver.patch b/root/target/linux/rockchip/patches-5.15/069-v5.19-drm-rockchip-Add-VOP2-driver.patch new file mode 100644 index 00000000..cdd63eff --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/069-v5.19-drm-rockchip-Add-VOP2-driver.patch @@ -0,0 +1,67 @@ +From 604be85547ce4d61b89292d2f9a78c721b778c16 Mon Sep 17 00:00:00 2001 +From: Andy Yan +Date: Fri, 22 Apr 2022 09:28:39 +0200 +Subject: [PATCH] drm/rockchip: Add VOP2 driver + +The VOP2 unit is found on Rockchip SoCs beginning with rk3566/rk3568. +It replaces the VOP unit found in the older Rockchip SoCs. + +This driver has been derived from the downstream Rockchip Kernel and +heavily modified: + +- All nonstandard DRM properties have been removed +- dropped struct vop2_plane_state and pass around less data between + functions +- Dropped all DRM_FORMAT_* not known on upstream +- rework register access to get rid of excessively used macros +- Drop all waiting for framesyncs + +The driver is tested with HDMI and MIPI-DSI display on a RK3568-EVB +board. Overlay support is tested with the modetest utility. AFBC support +on the cluster windows is tested with weston-simple-dmabuf-egl on +weston using the (yet to be upstreamed) panfrost driver support. + +Signed-off-by: Andy Yan +Co-Developed-by: Sascha Hauer +Signed-off-by: Sascha Hauer +Tested-by: Michael Riesch +[dt-binding-header:] +Acked-by: Rob Herring +[moved dt-binding header from dt-nodes patch to here + and made checkpatch --strict happier] +Signed-off-by: Heiko Stuebner +Link: https://patchwork.freedesktop.org/patch/msgid/20220422072841.2206452-23-s.hauer@pengutronix.de +--- + drivers/gpu/drm/rockchip/Kconfig | 6 + + drivers/gpu/drm/rockchip/Makefile | 1 + + drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 1 + + drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 6 +- + drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 2 + + drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 14 + + drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 2706 ++++++++++++++++++ + drivers/gpu/drm/rockchip/rockchip_drm_vop2.h | 477 +++ + drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 281 ++ + include/dt-bindings/soc/rockchip,vop2.h | 14 + + 10 files changed, 3507 insertions(+), 1 deletion(-) + create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c + create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_vop2.h + create mode 100644 drivers/gpu/drm/rockchip/rockchip_vop2_reg.c + create mode 100644 include/dt-bindings/soc/rockchip,vop2.h + +--- /dev/null ++++ b/include/dt-bindings/soc/rockchip,vop2.h +@@ -0,0 +1,14 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ ++ ++#ifndef __DT_BINDINGS_ROCKCHIP_VOP2_H ++#define __DT_BINDINGS_ROCKCHIP_VOP2_H ++ ++#define ROCKCHIP_VOP2_EP_RGB0 1 ++#define ROCKCHIP_VOP2_EP_HDMI0 2 ++#define ROCKCHIP_VOP2_EP_EDP0 3 ++#define ROCKCHIP_VOP2_EP_MIPI0 4 ++#define ROCKCHIP_VOP2_EP_LVDS0 5 ++#define ROCKCHIP_VOP2_EP_MIPI1 6 ++#define ROCKCHIP_VOP2_EP_LVDS1 7 ++ ++#endif /* __DT_BINDINGS_ROCKCHIP_VOP2_H */ diff --git a/root/target/linux/rockchip/patches-5.15/070-v6.1-phy-rockchip-Support-PCIe-v3.patch b/root/target/linux/rockchip/patches-5.15/070-v6.1-phy-rockchip-Support-PCIe-v3.patch new file mode 100644 index 00000000..b3648eaa --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/070-v6.1-phy-rockchip-Support-PCIe-v3.patch @@ -0,0 +1,394 @@ +From 2e9bffc4f713db465177238f6033f7d367d6f151 Mon Sep 17 00:00:00 2001 +From: Shawn Lin +Date: Thu, 25 Aug 2022 21:38:34 +0200 +Subject: [PATCH] phy: rockchip: Support PCIe v3 + +RK3568 supports PCIe v3 using not Combphy like PCIe v2 on rk3566. +It use a dedicated PCIe-phy. Add support for this. + +Initial support by Shawn Lin, modifications by Peter Geis and Frank +Wunderlich. + +Add data-lanes property for splitting pcie-lanes across controllers. + +The data-lanes is an array where x=0 means lane is disabled and x > 0 +means controller x is assigned to phy lane. + +Signed-off-by: Shawn Lin +Suggested-by: Peter Geis +Signed-off-by: Frank Wunderlich +Link: https://lore.kernel.org/r/20220825193836.54262-4-linux@fw-web.de +Signed-off-by: Vinod Koul +--- + drivers/phy/rockchip/Kconfig | 9 + + drivers/phy/rockchip/Makefile | 1 + + .../phy/rockchip/phy-rockchip-snps-pcie3.c | 319 ++++++++++++++++++ + include/linux/phy/pcie.h | 12 + + 4 files changed, 341 insertions(+) + create mode 100644 drivers/phy/rockchip/phy-rockchip-snps-pcie3.c + create mode 100644 include/linux/phy/pcie.h + +--- a/drivers/phy/rockchip/Kconfig ++++ b/drivers/phy/rockchip/Kconfig +@@ -83,6 +83,15 @@ config PHY_ROCKCHIP_PCIE + help + Enable this to support the Rockchip PCIe PHY. + ++config PHY_ROCKCHIP_SNPS_PCIE3 ++ tristate "Rockchip Snps PCIe3 PHY Driver" ++ depends on (ARCH_ROCKCHIP && OF) || COMPILE_TEST ++ depends on HAS_IOMEM ++ select GENERIC_PHY ++ select MFD_SYSCON ++ help ++ Enable this to support the Rockchip snps PCIe3 PHY. ++ + config PHY_ROCKCHIP_TYPEC + tristate "Rockchip TYPEC PHY Driver" + depends on OF && (ARCH_ROCKCHIP || COMPILE_TEST) +--- a/drivers/phy/rockchip/Makefile ++++ b/drivers/phy/rockchip/Makefile +@@ -8,5 +8,6 @@ obj-$(CONFIG_PHY_ROCKCHIP_INNO_HDMI) += + obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o + obj-$(CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY) += phy-rockchip-naneng-combphy.o + obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o ++obj-$(CONFIG_PHY_ROCKCHIP_SNPS_PCIE3) += phy-rockchip-snps-pcie3.o + obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o + obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o +--- /dev/null ++++ b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c +@@ -0,0 +1,319 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Rockchip PCIE3.0 phy driver ++ * ++ * Copyright (C) 2022 Rockchip Electronics Co., Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Register for RK3568 */ ++#define GRF_PCIE30PHY_CON1 0x4 ++#define GRF_PCIE30PHY_CON6 0x18 ++#define GRF_PCIE30PHY_CON9 0x24 ++#define GRF_PCIE30PHY_DA_OCM (BIT(15) | BIT(31)) ++#define GRF_PCIE30PHY_STATUS0 0x80 ++#define GRF_PCIE30PHY_WR_EN (0xf << 16) ++#define SRAM_INIT_DONE(reg) (reg & BIT(14)) ++ ++#define RK3568_BIFURCATION_LANE_0_1 BIT(0) ++ ++/* Register for RK3588 */ ++#define PHP_GRF_PCIESEL_CON 0x100 ++#define RK3588_PCIE3PHY_GRF_CMN_CON0 0x0 ++#define RK3588_PCIE3PHY_GRF_PHY0_STATUS1 0x904 ++#define RK3588_PCIE3PHY_GRF_PHY1_STATUS1 0xa04 ++#define RK3588_SRAM_INIT_DONE(reg) (reg & BIT(0)) ++ ++#define RK3588_BIFURCATION_LANE_0_1 BIT(0) ++#define RK3588_BIFURCATION_LANE_2_3 BIT(1) ++#define RK3588_LANE_AGGREGATION BIT(2) ++ ++struct rockchip_p3phy_ops; ++ ++struct rockchip_p3phy_priv { ++ const struct rockchip_p3phy_ops *ops; ++ void __iomem *mmio; ++ /* mode: RC, EP */ ++ int mode; ++ /* pcie30_phymode: Aggregation, Bifurcation */ ++ int pcie30_phymode; ++ struct regmap *phy_grf; ++ struct regmap *pipe_grf; ++ struct reset_control *p30phy; ++ struct phy *phy; ++ struct clk_bulk_data *clks; ++ int num_clks; ++ int num_lanes; ++ u32 lanes[4]; ++}; ++ ++struct rockchip_p3phy_ops { ++ int (*phy_init)(struct rockchip_p3phy_priv *priv); ++}; ++ ++static int rockchip_p3phy_set_mode(struct phy *phy, enum phy_mode mode, int submode) ++{ ++ struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy); ++ ++ /* Actually We don't care EP/RC mode, but just record it */ ++ switch (submode) { ++ case PHY_MODE_PCIE_RC: ++ priv->mode = PHY_MODE_PCIE_RC; ++ break; ++ case PHY_MODE_PCIE_EP: ++ priv->mode = PHY_MODE_PCIE_EP; ++ break; ++ default: ++ dev_err(&phy->dev, "%s, invalid mode\n", __func__); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int rockchip_p3phy_rk3568_init(struct rockchip_p3phy_priv *priv) ++{ ++ struct phy *phy = priv->phy; ++ bool bifurcation = false; ++ int ret, i; ++ u32 reg; ++ ++ /* Deassert PCIe PMA output clamp mode */ ++ regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON9, GRF_PCIE30PHY_DA_OCM); ++ ++ for (i = 0; i < priv->num_lanes; i++) { ++ dev_info(&phy->dev, "lane number %d, val %d\n", i, priv->lanes[i]); ++ if (priv->lanes[i] > 1) ++ bifurcation = true; ++ } ++ ++ /* Set bifurcation if needed, and it doesn't care RC/EP */ ++ if (bifurcation) { ++ dev_info(&phy->dev, "bifurcation enabled\n"); ++ regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON6, ++ GRF_PCIE30PHY_WR_EN | RK3568_BIFURCATION_LANE_0_1); ++ regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON1, ++ GRF_PCIE30PHY_DA_OCM); ++ } else { ++ dev_dbg(&phy->dev, "bifurcation disabled\n"); ++ regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON6, ++ GRF_PCIE30PHY_WR_EN & ~RK3568_BIFURCATION_LANE_0_1); ++ } ++ ++ reset_control_deassert(priv->p30phy); ++ ++ ret = regmap_read_poll_timeout(priv->phy_grf, ++ GRF_PCIE30PHY_STATUS0, ++ reg, SRAM_INIT_DONE(reg), ++ 0, 500); ++ if (ret) ++ dev_err(&priv->phy->dev, "%s: lock failed 0x%x, check input refclk and power supply\n", ++ __func__, reg); ++ return ret; ++} ++ ++static const struct rockchip_p3phy_ops rk3568_ops = { ++ .phy_init = rockchip_p3phy_rk3568_init, ++}; ++ ++static int rockchip_p3phy_rk3588_init(struct rockchip_p3phy_priv *priv) ++{ ++ u32 reg = 0; ++ u8 mode = 0; ++ int i, ret; ++ ++ /* Deassert PCIe PMA output clamp mode */ ++ regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0, BIT(8) | BIT(24)); ++ ++ /* Set bifurcation if needed */ ++ for (i = 0; i < priv->num_lanes; i++) { ++ if (!priv->lanes[i]) ++ mode |= (BIT(i) << 3); ++ ++ if (priv->lanes[i] > 1) ++ mode |= (BIT(i) >> 1); ++ } ++ ++ if (!mode) ++ reg = RK3588_LANE_AGGREGATION; ++ else { ++ if (mode & (BIT(0) | BIT(1))) ++ reg |= RK3588_BIFURCATION_LANE_0_1; ++ ++ if (mode & (BIT(2) | BIT(3))) ++ reg |= RK3588_BIFURCATION_LANE_2_3; ++ } ++ ++ regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0, (0x7<<16) | reg); ++ ++ /* Set pcie1ln_sel in PHP_GRF_PCIESEL_CON */ ++ if (!IS_ERR(priv->pipe_grf)) { ++ reg = (mode & (BIT(6) | BIT(7))) >> 6; ++ if (reg) ++ regmap_write(priv->pipe_grf, PHP_GRF_PCIESEL_CON, ++ (reg << 16) | reg); ++ } ++ ++ reset_control_deassert(priv->p30phy); ++ ++ ret = regmap_read_poll_timeout(priv->phy_grf, ++ RK3588_PCIE3PHY_GRF_PHY0_STATUS1, ++ reg, RK3588_SRAM_INIT_DONE(reg), ++ 0, 500); ++ ret |= regmap_read_poll_timeout(priv->phy_grf, ++ RK3588_PCIE3PHY_GRF_PHY1_STATUS1, ++ reg, RK3588_SRAM_INIT_DONE(reg), ++ 0, 500); ++ if (ret) ++ dev_err(&priv->phy->dev, "lock failed 0x%x, check input refclk and power supply\n", ++ reg); ++ return ret; ++} ++ ++static const struct rockchip_p3phy_ops rk3588_ops = { ++ .phy_init = rockchip_p3phy_rk3588_init, ++}; ++ ++static int rochchip_p3phy_init(struct phy *phy) ++{ ++ struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy); ++ int ret; ++ ++ ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks); ++ if (ret) { ++ dev_err(&priv->phy->dev, "failed to enable PCIe bulk clks %d\n", ret); ++ return ret; ++ } ++ ++ reset_control_assert(priv->p30phy); ++ udelay(1); ++ ++ if (priv->ops->phy_init) { ++ ret = priv->ops->phy_init(priv); ++ if (ret) ++ clk_bulk_disable_unprepare(priv->num_clks, priv->clks); ++ } ++ ++ return ret; ++} ++ ++static int rochchip_p3phy_exit(struct phy *phy) ++{ ++ struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy); ++ ++ clk_bulk_disable_unprepare(priv->num_clks, priv->clks); ++ reset_control_assert(priv->p30phy); ++ return 0; ++} ++ ++static const struct phy_ops rochchip_p3phy_ops = { ++ .init = rochchip_p3phy_init, ++ .exit = rochchip_p3phy_exit, ++ .set_mode = rockchip_p3phy_set_mode, ++ .owner = THIS_MODULE, ++}; ++ ++static int rockchip_p3phy_probe(struct platform_device *pdev) ++{ ++ struct phy_provider *phy_provider; ++ struct device *dev = &pdev->dev; ++ struct rockchip_p3phy_priv *priv; ++ struct device_node *np = dev->of_node; ++ struct resource *res; ++ int ret; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ priv->mmio = devm_ioremap_resource(dev, res); ++ if (IS_ERR(priv->mmio)) { ++ ret = PTR_ERR(priv->mmio); ++ return ret; ++ } ++ ++ priv->ops = of_device_get_match_data(&pdev->dev); ++ if (!priv->ops) { ++ dev_err(dev, "no of match data provided\n"); ++ return -EINVAL; ++ } ++ ++ priv->phy_grf = syscon_regmap_lookup_by_phandle(np, "rockchip,phy-grf"); ++ if (IS_ERR(priv->phy_grf)) { ++ dev_err(dev, "failed to find rockchip,phy_grf regmap\n"); ++ return PTR_ERR(priv->phy_grf); ++ } ++ ++ priv->pipe_grf = syscon_regmap_lookup_by_phandle(dev->of_node, ++ "rockchip,pipe-grf"); ++ if (IS_ERR(priv->pipe_grf)) ++ dev_info(dev, "failed to find rockchip,pipe_grf regmap\n"); ++ ++ priv->num_lanes = of_property_read_variable_u32_array(dev->of_node, "data-lanes", ++ priv->lanes, 2, ++ ARRAY_SIZE(priv->lanes)); ++ ++ /* if no data-lanes assume aggregation */ ++ if (priv->num_lanes == -EINVAL) { ++ dev_dbg(dev, "no data-lanes property found\n"); ++ priv->num_lanes = 1; ++ priv->lanes[0] = 1; ++ } else if (priv->num_lanes < 0) { ++ dev_err(dev, "failed to read data-lanes property %d\n", priv->num_lanes); ++ return priv->num_lanes; ++ } ++ ++ priv->phy = devm_phy_create(dev, NULL, &rochchip_p3phy_ops); ++ if (IS_ERR(priv->phy)) { ++ dev_err(dev, "failed to create combphy\n"); ++ return PTR_ERR(priv->phy); ++ } ++ ++ priv->p30phy = devm_reset_control_get_optional_exclusive(dev, "phy"); ++ if (IS_ERR(priv->p30phy)) { ++ return dev_err_probe(dev, PTR_ERR(priv->p30phy), ++ "failed to get phy reset control\n"); ++ } ++ if (!priv->p30phy) ++ dev_info(dev, "no phy reset control specified\n"); ++ ++ priv->num_clks = devm_clk_bulk_get_all(dev, &priv->clks); ++ if (priv->num_clks < 1) ++ return -ENODEV; ++ ++ dev_set_drvdata(dev, priv); ++ phy_set_drvdata(priv->phy, priv); ++ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); ++ return PTR_ERR_OR_ZERO(phy_provider); ++} ++ ++static const struct of_device_id rockchip_p3phy_of_match[] = { ++ { .compatible = "rockchip,rk3568-pcie3-phy", .data = &rk3568_ops }, ++ { .compatible = "rockchip,rk3588-pcie3-phy", .data = &rk3588_ops }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, rockchip_p3phy_of_match); ++ ++static struct platform_driver rockchip_p3phy_driver = { ++ .probe = rockchip_p3phy_probe, ++ .driver = { ++ .name = "rockchip-snps-pcie3-phy", ++ .of_match_table = rockchip_p3phy_of_match, ++ }, ++}; ++module_platform_driver(rockchip_p3phy_driver); ++MODULE_DESCRIPTION("Rockchip Synopsys PCIe 3.0 PHY driver"); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/include/linux/phy/pcie.h +@@ -0,0 +1,12 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (c) 2022 Rockchip Electronics Co., Ltd. ++ */ ++#ifndef __PHY_PCIE_H ++#define __PHY_PCIE_H ++ ++#define PHY_MODE_PCIE_RC 20 ++#define PHY_MODE_PCIE_EP 21 ++#define PHY_MODE_PCIE_BIFURCATION 22 ++ ++#endif diff --git a/root/target/linux/rockchip/patches-5.15/071-v6.1-arm64-dts-rockchip-Add-PCIe-v3-nodes-to-rk3568.patch b/root/target/linux/rockchip/patches-5.15/071-v6.1-arm64-dts-rockchip-Add-PCIe-v3-nodes-to-rk3568.patch new file mode 100644 index 00000000..670c3772 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/071-v6.1-arm64-dts-rockchip-Add-PCIe-v3-nodes-to-rk3568.patch @@ -0,0 +1,146 @@ +From faedfa5b40f095d09040c3a040e2f8dee4a36b4b Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Thu, 25 Aug 2022 21:38:35 +0200 +Subject: [PATCH] arm64: dts: rockchip: Add PCIe v3 nodes to rk3568 + +Add nodes to rk356x devicetree to support PCIe v3. + +Signed-off-by: Peter Geis +Signed-off-by: Frank Wunderlich +Link: https://lore.kernel.org/r/20220825193836.54262-5-linux@fw-web.de +Signed-off-by: Heiko Stuebner +--- + arch/arm64/boot/dts/rockchip/rk3568.dtsi | 122 +++++++++++++++++++++++ + 1 file changed, 122 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3568.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3568.dtsi +@@ -42,6 +42,128 @@ + reg = <0x0 0xfe190200 0x0 0x20>; + }; + ++ pcie30_phy_grf: syscon@fdcb8000 { ++ compatible = "rockchip,rk3568-pcie3-phy-grf", "syscon"; ++ reg = <0x0 0xfdcb8000 0x0 0x10000>; ++ }; ++ ++ pcie30phy: phy@fe8c0000 { ++ compatible = "rockchip,rk3568-pcie3-phy"; ++ reg = <0x0 0xfe8c0000 0x0 0x20000>; ++ #phy-cells = <0>; ++ clocks = <&pmucru CLK_PCIE30PHY_REF_M>, <&pmucru CLK_PCIE30PHY_REF_N>, ++ <&cru PCLK_PCIE30PHY>; ++ clock-names = "refclk_m", "refclk_n", "pclk"; ++ resets = <&cru SRST_PCIE30PHY>; ++ reset-names = "phy"; ++ rockchip,phy-grf = <&pcie30_phy_grf>; ++ status = "disabled"; ++ }; ++ ++ pcie3x1: pcie@fe270000 { ++ compatible = "rockchip,rk3568-pcie"; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ bus-range = <0x0 0xf>; ++ clocks = <&cru ACLK_PCIE30X1_MST>, <&cru ACLK_PCIE30X1_SLV>, ++ <&cru ACLK_PCIE30X1_DBI>, <&cru PCLK_PCIE30X1>, ++ <&cru CLK_PCIE30X1_AUX_NDFT>; ++ clock-names = "aclk_mst", "aclk_slv", ++ "aclk_dbi", "pclk", "aux"; ++ device_type = "pci"; ++ interrupts = , ++ , ++ , ++ , ++ ; ++ interrupt-names = "sys", "pmc", "msg", "legacy", "err"; ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 7>; ++ interrupt-map = <0 0 0 1 &pcie3x1_intc 0>, ++ <0 0 0 2 &pcie3x1_intc 1>, ++ <0 0 0 3 &pcie3x1_intc 2>, ++ <0 0 0 4 &pcie3x1_intc 3>; ++ linux,pci-domain = <1>; ++ num-ib-windows = <6>; ++ num-ob-windows = <2>; ++ max-link-speed = <3>; ++ msi-map = <0x0 &gic 0x1000 0x1000>; ++ num-lanes = <1>; ++ phys = <&pcie30phy>; ++ phy-names = "pcie-phy"; ++ power-domains = <&power RK3568_PD_PIPE>; ++ reg = <0x3 0xc0400000 0x0 0x00400000>, ++ <0x0 0xfe270000 0x0 0x00010000>, ++ <0x3 0x7f000000 0x0 0x01000000>; ++ ranges = <0x01000000 0x0 0x3ef00000 0x3 0x7ef00000 0x0 0x00100000>, ++ <0x02000000 0x0 0x00000000 0x3 0x40000000 0x0 0x3ef00000>; ++ reg-names = "dbi", "apb", "config"; ++ resets = <&cru SRST_PCIE30X1_POWERUP>; ++ reset-names = "pipe"; ++ /* bifurcation; lane1 when using 1+1 */ ++ status = "disabled"; ++ ++ pcie3x1_intc: legacy-interrupt-controller { ++ interrupt-controller; ++ #address-cells = <0>; ++ #interrupt-cells = <1>; ++ interrupt-parent = <&gic>; ++ interrupts = ; ++ }; ++ }; ++ ++ pcie3x2: pcie@fe280000 { ++ compatible = "rockchip,rk3568-pcie"; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ bus-range = <0x0 0xf>; ++ clocks = <&cru ACLK_PCIE30X2_MST>, <&cru ACLK_PCIE30X2_SLV>, ++ <&cru ACLK_PCIE30X2_DBI>, <&cru PCLK_PCIE30X2>, ++ <&cru CLK_PCIE30X2_AUX_NDFT>; ++ clock-names = "aclk_mst", "aclk_slv", ++ "aclk_dbi", "pclk", "aux"; ++ device_type = "pci"; ++ interrupts = , ++ , ++ , ++ , ++ ; ++ interrupt-names = "sys", "pmc", "msg", "legacy", "err"; ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 7>; ++ interrupt-map = <0 0 0 1 &pcie3x2_intc 0>, ++ <0 0 0 2 &pcie3x2_intc 1>, ++ <0 0 0 3 &pcie3x2_intc 2>, ++ <0 0 0 4 &pcie3x2_intc 3>; ++ linux,pci-domain = <2>; ++ num-ib-windows = <6>; ++ num-ob-windows = <2>; ++ max-link-speed = <3>; ++ msi-map = <0x0 &gic 0x2000 0x1000>; ++ num-lanes = <2>; ++ phys = <&pcie30phy>; ++ phy-names = "pcie-phy"; ++ power-domains = <&power RK3568_PD_PIPE>; ++ reg = <0x3 0xc0800000 0x0 0x00400000>, ++ <0x0 0xfe280000 0x0 0x00010000>, ++ <0x3 0xbf000000 0x0 0x01000000>; ++ ranges = <0x01000000 0x0 0x3ef00000 0x3 0xbef00000 0x0 0x00100000>, ++ <0x02000000 0x0 0x00000000 0x3 0x80000000 0x0 0x3ef00000>; ++ reg-names = "dbi", "apb", "config"; ++ resets = <&cru SRST_PCIE30X2_POWERUP>; ++ reset-names = "pipe"; ++ /* bifurcation; lane0 when using 1+1 */ ++ status = "disabled"; ++ ++ pcie3x2_intc: legacy-interrupt-controller { ++ interrupt-controller; ++ #address-cells = <0>; ++ #interrupt-cells = <1>; ++ interrupt-parent = <&gic>; ++ interrupts = ; ++ }; ++ }; ++ + gmac0: ethernet@fe2a0000 { + compatible = "rockchip,rk3568-gmac", "snps,dwmac-4.20a"; + reg = <0x0 0xfe2a0000 0x0 0x10000>; diff --git a/root/target/linux/rockchip/patches-5.15/100-rockchip-use-system-LED-for-OpenWrt.patch b/root/target/linux/rockchip/patches-5.15/100-rockchip-use-system-LED-for-OpenWrt.patch deleted file mode 100644 index 7b3b50ff..00000000 --- a/root/target/linux/rockchip/patches-5.15/100-rockchip-use-system-LED-for-OpenWrt.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 6731d2c9039fbe1ecf21915eab3acee0a999508a Mon Sep 17 00:00:00 2001 -From: David Bauer -Date: Fri, 10 Jul 2020 21:38:20 +0200 -Subject: [PATCH] rockchip: use system LED for OpenWrt - -Use the SYS LED on the casing for showing system status. - -This patch is kept separate from the NanoPi R2S support patch, as i plan -on submitting the device support upstream. - -Signed-off-by: David Bauer ---- - arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts | 9 ++++++++- - 1 file changed, 8 insertions(+), 1 deletion(-) - ---- a/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts -@@ -13,6 +13,13 @@ - model = "FriendlyElec NanoPi R2S"; - compatible = "friendlyarm,nanopi-r2s", "rockchip,rk3328"; - -+ aliases { -+ led-boot = &sys_led; -+ led-failsafe = &sys_led; -+ led-running = &sys_led; -+ led-upgrade = &sys_led; -+ }; -+ - chosen { - stdout-path = "serial2:1500000n8"; - }; diff --git a/root/target/linux/rockchip/patches-5.15/106-arm64-rockchip-add-OF-node-for-pcie-eth-on-NanoPi-R4S.patch b/root/target/linux/rockchip/patches-5.15/106-arm64-rockchip-add-OF-node-for-pcie-eth-on-NanoPi-R4S.patch new file mode 100644 index 00000000..67465759 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/106-arm64-rockchip-add-OF-node-for-pcie-eth-on-NanoPi-R4S.patch @@ -0,0 +1,22 @@ +--- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts +@@ -96,6 +96,19 @@ + max-link-speed = <1>; + num-lanes = <1>; + vpcie3v3-supply = <&vcc3v3_sys>; ++ ++ pcie@0 { ++ reg = <0x00000000 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ ++ pcie-eth@0,0 { ++ compatible = "pci10ec,8168"; ++ reg = <0x000000 0 0 0 0>; ++ ++ realtek,led-data = <0x870>; ++ }; ++ }; + }; + + &pinctrl { diff --git a/root/target/linux/rockchip/patches-5.15/107-mmc-core-set-initial-signal-voltage-on-power-off.patch b/root/target/linux/rockchip/patches-5.15/107-mmc-core-set-initial-signal-voltage-on-power-off.patch new file mode 100644 index 00000000..d6694b51 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/107-mmc-core-set-initial-signal-voltage-on-power-off.patch @@ -0,0 +1,35 @@ +From 0d329112c709d6cfedf0fffb19f0cc6b19043f6b Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 20 Feb 2019 07:38:34 +0000 +Subject: [PATCH] mmc: core: set initial signal voltage on power off + +Some boards have SD card connectors where the power rail cannot be switched +off by the driver. If the card has not been power cycled, it may still be +using 1.8V signaling after a warm re-boot. Bootroms expecting 3.3V signaling +will fail to boot from a UHS card that continue to use 1.8V signaling. + +Set initial signal voltage in mmc_power_off() to allow re-boot to function. + +This fixes re-boot with UHS cards on Asus Tinker Board (Rockchip RK3288), +same issue have been seen on some Rockchip RK3399 boards. + +I am sending this as a RFC because I have no insights into SD/MMC subsystem, +this change fix a re-boot issue on my boards and does not break emmc/sdio. +Is this an acceptable workaround? Any advice is appreciated. + +Signed-off-by: Jonas Karlman +--- + drivers/mmc/core/core.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/mmc/core/core.c ++++ b/drivers/mmc/core/core.c +@@ -1358,6 +1358,8 @@ void mmc_power_off(struct mmc_host *host + + mmc_pwrseq_power_off(host); + ++ mmc_set_initial_signal_voltage(host); ++ + host->ios.clock = 0; + host->ios.vdd = 0; + diff --git a/root/target/linux/rockchip/patches-5.15/108-net-phy-add-support-for-Motorcomm-yt8531C-phy.patch b/root/target/linux/rockchip/patches-5.15/108-net-phy-add-support-for-Motorcomm-yt8531C-phy.patch new file mode 100644 index 00000000..66dc8972 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/108-net-phy-add-support-for-Motorcomm-yt8531C-phy.patch @@ -0,0 +1,141 @@ +From cfb1aa4c805e58287dd0ce292b5c64309e3dba2f Mon Sep 17 00:00:00 2001 +From: Furkan Kardame +Date: Sun, 9 Oct 2022 22:24:05 +0300 +Subject: [PATCH] net: phy: add support for Motorcomm yt8531C phy + +This patch adds support for Motorcomm YT8531C which is +used in OrangePi 3 LTS, OrangePi 4 LTS and OrangePi 800 +Currently being used by Manjaro Arm kernel + +Signed-off-by: Peter Geis +Signed-off-by: Furkan Kardame +--- + drivers/net/phy/motorcomm.c | 90 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 90 insertions(+) + +--- a/drivers/net/phy/motorcomm.c ++++ b/drivers/net/phy/motorcomm.c +@@ -10,6 +10,7 @@ + #include + + #define PHY_ID_YT8511 0x0000010a ++#define PHY_ID_YT8531 0x4f51e91b + + #define YT8511_PAGE_SELECT 0x1e + #define YT8511_PAGE 0x1f +@@ -38,6 +39,38 @@ + #define YT8511_DELAY_FE_TX_EN (0xf << 12) + #define YT8511_DELAY_FE_TX_DIS (0x2 << 12) + ++#define YT8531_RGMII_CONFIG1 0xa003 ++ ++/* TX Gig-E Delay is bits 3:0, default 0x1 ++ * TX Fast-E Delay is bits 7:4, default 0xf ++ * RX Delay is bits 13:10, default 0x0 ++ * Delay = 150ps * N ++ * On = 2000ps, off = 50ps ++ */ ++#define YT8531_DELAY_GE_TX_EN (0xd << 0) ++#define YT8531_DELAY_GE_TX_DIS (0x0 << 0) ++#define YT8531_DELAY_FE_TX_EN (0xd << 4) ++#define YT8531_DELAY_FE_TX_DIS (0x0 << 4) ++#define YT8531_DELAY_RX_EN (0xd << 10) ++#define YT8531_DELAY_RX_DIS (0x0 << 10) ++#define YT8531_DELAY_MASK (GENMASK(13, 10) | GENMASK(7, 0)) ++ ++#define YT8531_SYNCE_CFG 0xa012 ++ ++/* Clk src config is bits 3:1 ++ * 3b000 src from pll ++ * 3b001 src from rx_clk ++ * 3b010 src from serdes ++ * 3b011 src from ptp_in ++ * 3b100 src from 25mhz refclk *default* ++ * 3b101 src from 25mhz ssc ++ * Clk rate select is bit 4 ++ * 1b0 25mhz clk output *default* ++ * 1b1 125mhz clk output ++ * Clkout enable is bit 6 ++ */ ++#define YT8531_CLKCFG_125M (BIT(6) | BIT(4) | (0x0 < 1)) ++ + static int yt8511_read_page(struct phy_device *phydev) + { + return __phy_read(phydev, YT8511_PAGE_SELECT); +@@ -111,6 +144,51 @@ err_restore_page: + return phy_restore_page(phydev, oldpage, ret); + } + ++static int yt8531_config_init(struct phy_device *phydev) ++{ ++ int oldpage, ret = 0; ++ unsigned int val; ++ ++ oldpage = phy_select_page(phydev, YT8531_RGMII_CONFIG1); ++ if (oldpage < 0) ++ goto err_restore_page; ++ ++ /* set rgmii delay mode */ ++ switch (phydev->interface) { ++ case PHY_INTERFACE_MODE_RGMII: ++ val = YT8531_DELAY_RX_DIS | YT8531_DELAY_GE_TX_DIS | YT8531_DELAY_FE_TX_DIS; ++ break; ++ case PHY_INTERFACE_MODE_RGMII_RXID: ++ val = YT8531_DELAY_RX_EN | YT8531_DELAY_GE_TX_DIS | YT8531_DELAY_FE_TX_DIS; ++ break; ++ case PHY_INTERFACE_MODE_RGMII_TXID: ++ val = YT8531_DELAY_RX_DIS | YT8531_DELAY_GE_TX_EN | YT8531_DELAY_FE_TX_EN; ++ break; ++ case PHY_INTERFACE_MODE_RGMII_ID: ++ val = YT8531_DELAY_RX_EN | YT8531_DELAY_GE_TX_EN | YT8531_DELAY_FE_TX_EN; ++ break; ++ default: /* do not support other modes */ ++ ret = -EOPNOTSUPP; ++ goto err_restore_page; ++ } ++ ++ ret = __phy_modify(phydev, YT8511_PAGE, YT8531_DELAY_MASK, val); ++ if (ret < 0) ++ goto err_restore_page; ++ ++ /* set clock mode to 125mhz */ ++ ret = __phy_write(phydev, YT8511_PAGE_SELECT, YT8531_SYNCE_CFG); ++ if (ret < 0) ++ goto err_restore_page; ++ ++ ret = __phy_write(phydev, YT8511_PAGE, YT8531_CLKCFG_125M); ++ if (ret < 0) ++ goto err_restore_page; ++ ++err_restore_page: ++ return phy_restore_page(phydev, oldpage, ret); ++} ++ + static struct phy_driver motorcomm_phy_drvs[] = { + { + PHY_ID_MATCH_EXACT(PHY_ID_YT8511), +@@ -120,7 +198,16 @@ static struct phy_driver motorcomm_phy_d + .resume = genphy_resume, + .read_page = yt8511_read_page, + .write_page = yt8511_write_page, ++ }, { ++ PHY_ID_MATCH_EXACT(PHY_ID_YT8531), ++ .name = "YT8531 Gigabit Ethernet", ++ .config_init = yt8531_config_init, ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, ++ .read_page = yt8511_read_page, ++ .write_page = yt8511_write_page, + }, ++ + }; + + module_phy_driver(motorcomm_phy_drvs); +@@ -131,6 +218,7 @@ MODULE_LICENSE("GPL"); + + static const struct mdio_device_id __maybe_unused motorcomm_tbl[] = { + { PHY_ID_MATCH_EXACT(PHY_ID_YT8511) }, ++ { PHY_ID_MATCH_EXACT(PHY_ID_YT8531) }, + { /* sentinal */ } + }; + diff --git a/root/target/linux/rockchip/patches-5.15/201-rockchip-rk3328-add-i2c0-controller-for-nanopi-r2s.patch b/root/target/linux/rockchip/patches-5.15/201-rockchip-rk3328-add-i2c0-controller-for-nanopi-r2s.patch new file mode 100644 index 00000000..013e1498 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/201-rockchip-rk3328-add-i2c0-controller-for-nanopi-r2s.patch @@ -0,0 +1,22 @@ +From 3b7eb946b1d640d684a921e53e1e50985ab7eb89 Mon Sep 17 00:00:00 2001 +From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> +Date: Tue, 4 Aug 2020 20:17:53 +0800 +Subject: [PATCH] rockchip: rk3328: add i2c0 controller for nanopi r2s + +--- + arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts | 4 ++++ + 1 files changed, 4 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts +@@ -173,6 +173,10 @@ + }; + }; + ++&i2c0 { ++ status = "okay"; ++}; ++ + &i2c1 { + status = "okay"; + diff --git a/root/target/linux/rockchip/patches-5.15/202-rockchip-rk3328-Add-support-for-OrangePi-R1-Plus.patch b/root/target/linux/rockchip/patches-5.15/202-rockchip-rk3328-Add-support-for-OrangePi-R1-Plus.patch new file mode 100644 index 00000000..3eb92318 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/202-rockchip-rk3328-Add-support-for-OrangePi-R1-Plus.patch @@ -0,0 +1,52 @@ +--- a/arch/arm64/boot/dts/rockchip/Makefile ++++ b/arch/arm64/boot/dts/rockchip/Makefile +@@ -10,6 +10,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3326-od + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-a1.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-evb.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-r2s.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-orangepi-r1-plus.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-rock64.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-rock-pi-e.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-roc-cc.dtb +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus.dts +@@ -0,0 +1,39 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++#include "rk3328-nanopi-r2s.dts" ++ ++/ { ++ model = "Xunlong Orange Pi R1 Plus"; ++ compatible = "xunlong,orangepi-r1-plus", "rockchip,rk3328"; ++}; ++ ++&lan_led { ++ label = "orangepi-r1-plus:green:lan"; ++}; ++ ++&spi0 { ++ max-freq = <48000000>; ++ status = "okay"; ++ ++ flash@0 { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <10000000>; ++ }; ++}; ++ ++&sys_led { ++ gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; ++ label = "orangepi-r1-plus:red:sys"; ++}; ++ ++&sys_led_pin { ++ rockchip,pins = <3 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>; ++}; ++ ++&uart1 { ++ status = "okay"; ++}; ++ ++&wan_led { ++ label = "orangepi-r1-plus:green:wan"; ++}; diff --git a/root/target/linux/rockchip/patches-5.15/203-rockchip-rk3328-Add-support-for-OrangePi-R1-Plus-LTS.patch b/root/target/linux/rockchip/patches-5.15/203-rockchip-rk3328-Add-support-for-OrangePi-R1-Plus-LTS.patch new file mode 100644 index 00000000..637d88d5 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/203-rockchip-rk3328-Add-support-for-OrangePi-R1-Plus-LTS.patch @@ -0,0 +1,79 @@ +--- a/arch/arm64/boot/dts/rockchip/Makefile ++++ b/arch/arm64/boot/dts/rockchip/Makefile +@@ -11,6 +11,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-a1 + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-evb.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-r2s.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-orangepi-r1-plus.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-orangepi-r1-plus-lts.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-rock64.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-rock-pi-e.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-roc-cc.dtb +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus-lts.dts +@@ -0,0 +1,66 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2016 Xunlong Software. Co., Ltd. ++ * (http://www.orangepi.org) ++ * ++ * Copyright (c) 2021 Tianling Shen ++ */ ++ ++#include "rk3328-orangepi-r1-plus.dts" ++ ++/ { ++ model = "Xunlong Orange Pi R1 Plus LTS"; ++ compatible = "xunlong,orangepi-r1-plus-lts", "rockchip,rk3328"; ++}; ++ ++&dmc_opp_table { ++ opp-798000000 { ++ status = "disabled"; ++ }; ++ opp-840000000 { ++ status = "disabled"; ++ }; ++ opp-924000000 { ++ status = "disabled"; ++ }; ++ opp-1056000000 { ++ status = "disabled"; ++ }; ++}; ++ ++&gmac2io { ++ phy-handle = <&yt8531c>; ++ tx_delay = <0x19>; ++ rx_delay = <0x05>; ++ ++ mdio { ++ /delete-node/ ethernet-phy@1; ++ ++ yt8531c: ethernet-phy@0 { ++ compatible = "ethernet-phy-id4f51.e91b", ++ "ethernet-phy-ieee802.3-c22"; ++ reg = <0>; ++ pinctrl-0 = <ð_phy_reset_pin>; ++ pinctrl-names = "default"; ++ reset-assert-us = <15000>; ++ reset-deassert-us = <50000>; ++ reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; ++ ++&lan_led { ++ label = "orangepi-r1-plus-lts:green:lan"; ++}; ++ ++&rtl8153 { ++ realtek,led-data = <0x78>; ++}; ++ ++&sys_led { ++ label = "orangepi-r1-plus-lts:red:sys"; ++}; ++ ++&wan_led { ++ label = "orangepi-r1-plus-lts:green:wan"; ++}; diff --git a/root/target/linux/rockchip/patches-5.15/204-rockchip-rk3328-Add-support-for-FriendlyARM-NanoPi-R.patch b/root/target/linux/rockchip/patches-5.15/204-rockchip-rk3328-Add-support-for-FriendlyARM-NanoPi-R.patch new file mode 100644 index 00000000..369fef90 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/204-rockchip-rk3328-Add-support-for-FriendlyARM-NanoPi-R.patch @@ -0,0 +1,64 @@ +--- a/arch/arm64/boot/dts/rockchip/Makefile ++++ b/arch/arm64/boot/dts/rockchip/Makefile +@@ -9,6 +9,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3318-a9 + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3326-odroid-go2.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-a1.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-evb.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-r2c.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-r2s.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-orangepi-r1-plus.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-orangepi-r1-plus-lts.dtb +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2c.dts +@@ -0,0 +1,51 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2021 FriendlyElec Computer Tech. Co., Ltd. ++ * (http://www.friendlyarm.com) ++ * ++ * Copyright (c) 2021 Tianling Shen ++ */ ++ ++/dts-v1/; ++ ++#include "rk3328-nanopi-r2s.dts" ++ ++/ { ++ model = "FriendlyElec NanoPi R2C"; ++ compatible = "friendlyarm,nanopi-r2c", "rockchip,rk3328"; ++}; ++ ++&gmac2io { ++ phy-handle = <&yt8521s>; ++ ++ mdio { ++ /delete-node/ ethernet-phy@1; ++ ++ yt8521s: ethernet-phy@3 { ++ compatible = "ethernet-phy-id0000.011a", ++ "ethernet-phy-ieee802.3-c22"; ++ reg = <3>; ++ pinctrl-0 = <ð_phy_reset_pin>; ++ pinctrl-names = "default"; ++ reset-assert-us = <10000>; ++ reset-deassert-us = <50000>; ++ reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; ++ ++&lan_led { ++ label = "nanopi-r2c:green:lan"; ++}; ++ ++&rtl8153 { ++ realtek,led-data = <0x78>; ++}; ++ ++&sys_led { ++ label = "nanopi-r2c:red:sys"; ++}; ++ ++&wan_led { ++ label = "nanopi-r2c:green:wan"; ++}; diff --git a/root/target/linux/rockchip/patches-5.15/205-rockchip-rk3328-add-support-for-FriendlyARM-NanoPi-Neo3.patch b/root/target/linux/rockchip/patches-5.15/205-rockchip-rk3328-add-support-for-FriendlyARM-NanoPi-Neo3.patch new file mode 100644 index 00000000..0d1c6406 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/205-rockchip-rk3328-add-support-for-FriendlyARM-NanoPi-Neo3.patch @@ -0,0 +1,442 @@ +From 0f989817a4c1d2c3d196d550ff05cda98bc91324 Mon Sep 17 00:00:00 2001 +From: Julian Pidancet +Date: Sun, 23 Jan 2022 16:34:08 +0100 +Subject: [PATCH v2] rockchip: rk3328: add support for FriendlyARM NanoPi NEO3 + +This patch adds support for FriendlyARM NanoPi NEO3 + +Soc: RockChip RK3328 +RAM: 1GB/2GB DDR4 +LAN: 10/100/1000M Ethernet with unique MAC +USB Host: 1x USB3.0 Type A and 2x USB2.0 on 2.54mm pin header +MicroSD: x 1 for system boot and storage +LED: Power LED x 1, System LED x 1 +Key: User Button x 1 +Fan: 2 Pin JST ZH 1.5mm Connector for 5V Fan +GPIO: 26 pin-header, include I2C, UART, SPI, I2S, GPIO +Power: 5V/1A, via Type-C or GPIO + +Signed-off-by: Julian Pidancet +--- + +This is another shot at previous work submitted by Marty Jones + (https://lore.kernel.org/linux-arm-kernel/20201228152836.02795e09.mj8263788@gmail.com/), +which is now a year old. + +v2: Following up on Robin Murphy's comments, the NEO3 DTS is now +standalone and no longer includes the nanopi R2S one. The lan_led and +wan_len nodes have been removed, and the sys_led node has been renamed +to status_led in accordance with the board schematics. + + arch/arm64/boot/dts/rockchip/Makefile | 1 + + .../boot/dts/rockchip/rk3328-nanopi-neo3.dts | 396 ++++++++++++++++++ + 2 files changed, 397 insertions(+) + create mode 100644 arch/arm64/boot/dts/rockchip/rk3328-nanopi-neo3.dts + +--- a/arch/arm64/boot/dts/rockchip/Makefile ++++ b/arch/arm64/boot/dts/rockchip/Makefile +@@ -11,6 +11,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-a1 + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-evb.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-r2c.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-r2s.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-neo3.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-orangepi-r1-plus.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-orangepi-r1-plus-lts.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-rock64.dtb +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-neo3.dts +@@ -0,0 +1,394 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2020 David Bauer ++ * Copyright (c) 2022 Julian Pidancet ++ */ ++ ++/dts-v1/; ++ ++#include ++#include ++#include "rk3328.dtsi" ++ ++/ { ++ model = "FriendlyElec NanoPi NEO3"; ++ compatible = "friendlyarm,nanopi-neo3", "rockchip,rk3328"; ++ ++ aliases { ++ led-boot = &status_led; ++ led-failsafe = &status_led; ++ led-running = &status_led; ++ led-upgrade = &status_led; ++ }; ++ ++ chosen { ++ stdout-path = "serial2:1500000n8"; ++ }; ++ ++ gmac_clk: gmac-clock { ++ compatible = "fixed-clock"; ++ clock-frequency = <125000000>; ++ clock-output-names = "gmac_clkin"; ++ #clock-cells = <0>; ++ }; ++ ++ keys { ++ compatible = "gpio-keys"; ++ pinctrl-0 = <&reset_button_pin>; ++ pinctrl-names = "default"; ++ ++ reset { ++ label = "reset"; ++ gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_LOW>; ++ linux,code = ; ++ debounce-interval = <50>; ++ }; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ pinctrl-0 = <&status_led_pin>; ++ pinctrl-names = "default"; ++ ++ status_led: led-0 { ++ gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; ++ label = "nanopi-neo3:green:status"; ++ }; ++ }; ++ ++ vcc_io_sdio: sdmmcio-regulator { ++ compatible = "regulator-gpio"; ++ enable-active-high; ++ gpios = <&gpio1 RK_PD4 GPIO_ACTIVE_HIGH>; ++ pinctrl-0 = <&sdio_vcc_pin>; ++ pinctrl-names = "default"; ++ regulator-name = "vcc_io_sdio"; ++ regulator-always-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-settling-time-us = <5000>; ++ regulator-type = "voltage"; ++ startup-delay-us = <2000>; ++ states = <1800000 0x1>, ++ <3300000 0x0>; ++ vin-supply = <&vcc_io_33>; ++ }; ++ ++ vcc_sd: sdmmc-regulator { ++ compatible = "regulator-fixed"; ++ gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>; ++ pinctrl-0 = <&sdmmc0m1_pin>; ++ pinctrl-names = "default"; ++ regulator-name = "vcc_sd"; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc_io_33>; ++ }; ++ ++ vdd_5v: vdd-5v { ++ compatible = "regulator-fixed"; ++ regulator-name = "vdd_5v"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ }; ++ ++ vcc_rtl8153: vcc-rtl8153-regulator { ++ compatible = "regulator-fixed"; ++ gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rtl8153_en_drv>; ++ regulator-always-on; ++ regulator-name = "vcc_rtl8153"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ enable-active-high; ++ }; ++}; ++ ++&cpu0 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu2 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu3 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&display_subsystem { ++ status = "disabled"; ++}; ++ ++&gmac2io { ++ assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>; ++ assigned-clock-parents = <&gmac_clk>, <&gmac_clk>; ++ clock_in_out = "input"; ++ phy-handle = <&rtl8211e>; ++ phy-mode = "rgmii"; ++ phy-supply = <&vcc_io_33>; ++ pinctrl-0 = <&rgmiim1_pins>; ++ pinctrl-names = "default"; ++ rx_delay = <0x18>; ++ snps,aal; ++ tx_delay = <0x24>; ++ status = "okay"; ++ ++ mdio { ++ compatible = "snps,dwmac-mdio"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ rtl8211e: ethernet-phy@1 { ++ reg = <1>; ++ pinctrl-0 = <ð_phy_reset_pin>; ++ pinctrl-names = "default"; ++ reset-assert-us = <10000>; ++ reset-deassert-us = <50000>; ++ reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; ++ ++&i2c1 { ++ status = "okay"; ++ ++ rk805: pmic@18 { ++ compatible = "rockchip,rk805"; ++ reg = <0x18>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <24 IRQ_TYPE_LEVEL_LOW>; ++ #clock-cells = <1>; ++ clock-output-names = "xin32k", "rk805-clkout2"; ++ gpio-controller; ++ #gpio-cells = <2>; ++ pinctrl-0 = <&pmic_int_l>; ++ pinctrl-names = "default"; ++ rockchip,system-power-controller; ++ wakeup-source; ++ ++ vcc1-supply = <&vdd_5v>; ++ vcc2-supply = <&vdd_5v>; ++ vcc3-supply = <&vdd_5v>; ++ vcc4-supply = <&vdd_5v>; ++ vcc5-supply = <&vcc_io_33>; ++ vcc6-supply = <&vdd_5v>; ++ ++ regulators { ++ vdd_log: DCDC_REG1 { ++ regulator-name = "vdd_log"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1450000>; ++ regulator-ramp-delay = <12500>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1000000>; ++ }; ++ }; ++ ++ vdd_arm: DCDC_REG2 { ++ regulator-name = "vdd_arm"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1450000>; ++ regulator-ramp-delay = <12500>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <950000>; ++ }; ++ }; ++ ++ vcc_ddr: DCDC_REG3 { ++ regulator-name = "vcc_ddr"; ++ regulator-always-on; ++ regulator-boot-on; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc_io_33: DCDC_REG4 { ++ regulator-name = "vcc_io_33"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vcc_18: LDO_REG1 { ++ regulator-name = "vcc_18"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcc18_emmc: LDO_REG2 { ++ regulator-name = "vcc18_emmc"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vdd_10: LDO_REG3 { ++ regulator-name = "vdd_10"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1000000>; ++ regulator-max-microvolt = <1000000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1000000>; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&io_domains { ++ pmuio-supply = <&vcc_io_33>; ++ vccio1-supply = <&vcc_io_33>; ++ vccio2-supply = <&vcc18_emmc>; ++ vccio3-supply = <&vcc_io_sdio>; ++ vccio4-supply = <&vcc_18>; ++ vccio5-supply = <&vcc_io_33>; ++ vccio6-supply = <&vcc_io_33>; ++ status = "okay"; ++}; ++ ++&pinctrl { ++ button { ++ reset_button_pin: reset-button-pin { ++ rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ ethernet-phy { ++ eth_phy_reset_pin: eth-phy-reset-pin { ++ rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>; ++ }; ++ }; ++ ++ leds { ++ status_led_pin: status-led-pin { ++ rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ pmic { ++ pmic_int_l: pmic-int-l { ++ rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ sd { ++ sdio_vcc_pin: sdio-vcc-pin { ++ rockchip,pins = <1 RK_PD4 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ usb { ++ rtl8153_en_drv: rtl8153-en-drv { ++ rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++}; ++ ++&pwm2 { ++ status = "okay"; ++}; ++ ++&sdmmc { ++ bus-width = <4>; ++ cap-sd-highspeed; ++ disable-wp; ++ pinctrl-0 = <&sdmmc0_clk>, <&sdmmc0_cmd>, <&sdmmc0_dectn>, <&sdmmc0_bus4>; ++ pinctrl-names = "default"; ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ sd-uhs-sdr104; ++ vmmc-supply = <&vcc_sd>; ++ vqmmc-supply = <&vcc_io_sdio>; ++ status = "okay"; ++}; ++ ++&tsadc { ++ rockchip,hw-tshut-mode = <0>; ++ rockchip,hw-tshut-polarity = <0>; ++ status = "okay"; ++}; ++ ++&u2phy { ++ status = "okay"; ++}; ++ ++&u2phy_host { ++ status = "okay"; ++}; ++ ++&u2phy_otg { ++ status = "okay"; ++}; ++ ++&uart2 { ++ status = "okay"; ++}; ++ ++&usb20_otg { ++ status = "okay"; ++ dr_mode = "host"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usbdrd3 { ++ dr_mode = "host"; ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ usb-eth@2 { ++ compatible = "realtek,rtl8153"; ++ reg = <2>; ++ ++ realtek,led-data = <0x87>; ++ }; ++}; diff --git a/root/target/linux/rockchip/patches-5.15/210-rockchip-rk356x-add-support-for-new-boards.patch b/root/target/linux/rockchip/patches-5.15/210-rockchip-rk356x-add-support-for-new-boards.patch new file mode 100644 index 00000000..fa83343a --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/210-rockchip-rk356x-add-support-for-new-boards.patch @@ -0,0 +1,14 @@ +--- a/arch/arm64/boot/dts/rockchip/Makefile ++++ b/arch/arm64/boot/dts/rockchip/Makefile +@@ -59,3 +59,11 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-sa + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-sapphire-excavator.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399pro-rock-pi-n10.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb1-v10.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-rock-pi-e25.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-mrkaio-m68s.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-nanopi-r5s.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-opc-h68k.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-rock-3a.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-roc-pc.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-r66s.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-r68s.dtb diff --git a/root/target/linux/rockchip/patches-5.15/211-rockchip-rk3399-add-support-for-Rongpin-King3399.patch b/root/target/linux/rockchip/patches-5.15/211-rockchip-rk3399-add-support-for-Rongpin-King3399.patch new file mode 100644 index 00000000..f84f4821 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/211-rockchip-rk3399-add-support-for-Rongpin-King3399.patch @@ -0,0 +1,10 @@ +--- a/arch/arm64/boot/dts/rockchip/Makefile ++++ b/arch/arm64/boot/dts/rockchip/Makefile +@@ -58,6 +58,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-ro + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-sapphire.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-sapphire-excavator.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399pro-rock-pi-n10.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-king3399.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb1-v10.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-mrkaio-m68s.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-nanopi-r5s.dtb diff --git a/root/target/linux/rockchip/patches-5.15/801-char-add-support-for-rockchip-hardware-random-number.patch b/root/target/linux/rockchip/patches-5.15/801-char-add-support-for-rockchip-hardware-random-number.patch new file mode 100644 index 00000000..e1415bfa --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/801-char-add-support-for-rockchip-hardware-random-number.patch @@ -0,0 +1,45 @@ +From e5b5361651940ff5c0c1784dfd0130abec7ab535 Mon Sep 17 00:00:00 2001 +From: wevsty +Date: Mon, 24 Aug 2020 02:27:11 +0800 +Subject: [PATCH] char: add support for rockchip hardware random number + generator + +This patch provides hardware random number generator support for all rockchip SOC. + +rockchip-rng.c from https://github.com/rockchip-linux/kernel/blob/develop-4.4/drivers/char/hw_random/rockchip-rng.c + +Signed-off-by: wevsty +--- + +--- a/drivers/char/hw_random/Kconfig ++++ b/drivers/char/hw_random/Kconfig +@@ -385,6 +385,19 @@ config HW_RANDOM_STM32 + + If unsure, say N. + ++config HW_RANDOM_ROCKCHIP ++ tristate "Rockchip Random Number Generator support" ++ depends on ARCH_ROCKCHIP ++ default HW_RANDOM ++ help ++ This driver provides kernel-side support for the Random Number ++ Generator hardware found on Rockchip cpus. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called rockchip-rng. ++ ++ If unsure, say Y. ++ + config HW_RANDOM_PIC32 + tristate "Microchip PIC32 Random Number Generator support" + depends on HW_RANDOM && MACH_PIC32 +--- a/drivers/char/hw_random/Makefile ++++ b/drivers/char/hw_random/Makefile +@@ -35,6 +35,7 @@ obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += + obj-$(CONFIG_HW_RANDOM_ST) += st-rng.o + obj-$(CONFIG_HW_RANDOM_XGENE) += xgene-rng.o + obj-$(CONFIG_HW_RANDOM_STM32) += stm32-rng.o ++obj-$(CONFIG_HW_RANDOM_ROCKCHIP) += rockchip-rng.o + obj-$(CONFIG_HW_RANDOM_PIC32) += pic32-rng.o + obj-$(CONFIG_HW_RANDOM_MESON) += meson-rng.o + obj-$(CONFIG_HW_RANDOM_CAVIUM) += cavium-rng.o cavium-rng-vf.o diff --git a/root/target/linux/rockchip/patches-5.15/802-arm64-dts-rockchip-add-hardware-random-number-genera.patch b/root/target/linux/rockchip/patches-5.15/802-arm64-dts-rockchip-add-hardware-random-number-genera.patch new file mode 100644 index 00000000..7157acd2 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/802-arm64-dts-rockchip-add-hardware-random-number-genera.patch @@ -0,0 +1,69 @@ +From e5b5361651940ff5c0c1784dfd0130abec7ab535 Mon Sep 17 00:00:00 2001 +From: wevsty +Date: Mon, 24 Aug 2020 02:27:11 +0800 +Subject: [PATCH] arm64: dts: rockchip: add hardware random number generator + for RK3328 and RK3399 + +Adding Hardware Random Number Generator Resources to the RK3328 and RK3399. + +Signed-off-by: wevsty +--- + +--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +@@ -279,6 +279,17 @@ + status = "disabled"; + }; + ++ rng: rng@ff060000 { ++ compatible = "rockchip,cryptov1-rng"; ++ reg = <0x0 0xff060000 0x0 0x4000>; ++ ++ clocks = <&cru SCLK_CRYPTO>, <&cru HCLK_CRYPTO_SLV>; ++ clock-names = "clk_crypto", "hclk_crypto"; ++ assigned-clocks = <&cru SCLK_CRYPTO>, <&cru HCLK_CRYPTO_SLV>; ++ assigned-clock-rates = <150000000>, <100000000>; ++ status = "disabled"; ++ }; ++ + grf: syscon@ff100000 { + compatible = "rockchip,rk3328-grf", "syscon", "simple-mfd"; + reg = <0x0 0xff100000 0x0 0x1000>; +--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +@@ -1937,6 +1937,16 @@ + }; + }; + ++ rng: rng@ff8b8000 { ++ compatible = "rockchip,cryptov1-rng"; ++ reg = <0x0 0xff8b8000 0x0 0x1000>; ++ clocks = <&cru SCLK_CRYPTO1>, <&cru HCLK_S_CRYPTO1>; ++ clock-names = "clk_crypto", "hclk_crypto"; ++ assigned-clocks = <&cru SCLK_CRYPTO1>, <&cru HCLK_S_CRYPTO1>; ++ assigned-clock-rates = <150000000>, <100000000>; ++ status = "okay"; ++ }; ++ + gpu: gpu@ff9a0000 { + compatible = "rockchip,rk3399-mali", "arm,mali-t860"; + reg = <0x0 0xff9a0000 0x0 0x10000>; +--- a/arch/arm64/boot/dts/rockchip/rk3568.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3568.dtsi +@@ -211,6 +211,16 @@ + }; + }; + ++ rng: rng@fe388000 { ++ compatible = "rockchip,cryptov2-rng"; ++ reg = <0x0 0xfe388000 0x0 0x2000>; ++ clocks = <&cru CLK_TRNG_NS>, <&cru HCLK_TRNG_NS>; ++ clock-names = "clk_trng", "hclk_trng"; ++ resets = <&cru SRST_TRNG_NS>; ++ reset-names = "reset"; ++ status = "disabled"; ++ }; ++ + combphy0: phy@fe820000 { + compatible = "rockchip,rk3568-naneng-combphy"; + reg = <0x0 0xfe820000 0x0 0x100>; diff --git a/root/target/linux/rockchip/patches-5.15/803-PM-devfreq-rockchip-add-devfreq-driver-for-rk3328-dmc.patch b/root/target/linux/rockchip/patches-5.15/803-PM-devfreq-rockchip-add-devfreq-driver-for-rk3328-dmc.patch new file mode 100644 index 00000000..ef06b0d5 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/803-PM-devfreq-rockchip-add-devfreq-driver-for-rk3328-dmc.patch @@ -0,0 +1,44 @@ +From fcd9629c05f373771e85920e1c1d0ab252617878 Mon Sep 17 00:00:00 2001 +From: hmz007 +Date: Tue, 19 Nov 2019 13:53:25 +0800 +Subject: [PATCH] PM / devfreq: rockchip: add devfreq driver for rk3328 dmc + +Signed-off-by: hmz007 +--- + drivers/devfreq/Kconfig | 18 +- + drivers/devfreq/Makefile | 1 + + drivers/devfreq/rk3328_dmc.c | 846 +++++++++++++++++++++++++++++++++++ + 3 files changed, 862 insertions(+), 3 deletions(-) + create mode 100644 drivers/devfreq/rk3328_dmc.c + +--- a/drivers/devfreq/Kconfig ++++ b/drivers/devfreq/Kconfig +@@ -120,6 +120,18 @@ config ARM_TEGRA_DEVFREQ + It reads ACTMON counters of memory controllers and adjusts the + operating frequencies and voltages with OPP support. + ++config ARM_RK3328_DMC_DEVFREQ ++ tristate "ARM RK3328 DMC DEVFREQ Driver" ++ depends on ARCH_ROCKCHIP ++ select DEVFREQ_EVENT_ROCKCHIP_DFI ++ select DEVFREQ_GOV_SIMPLE_ONDEMAND ++ select PM_DEVFREQ_EVENT ++ select PM_OPP ++ help ++ This adds the DEVFREQ driver for the RK3328 DMC(Dynamic Memory Controller). ++ It sets the frequency for the memory controller and reads the usage counts ++ from hardware. ++ + config ARM_RK3399_DMC_DEVFREQ + tristate "ARM RK3399 DMC DEVFREQ Driver" + depends on (ARCH_ROCKCHIP && HAVE_ARM_SMCCC) || \ +--- a/drivers/devfreq/Makefile ++++ b/drivers/devfreq/Makefile +@@ -11,6 +11,7 @@ obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += gov + obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o + obj-$(CONFIG_ARM_IMX_BUS_DEVFREQ) += imx-bus.o + obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) += imx8m-ddrc.o ++obj-$(CONFIG_ARM_RK3328_DMC_DEVFREQ) += rk3328_dmc.o + obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o + obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o + diff --git a/root/target/linux/rockchip/patches-5.15/804-clk-rockchip-support-setting-ddr-clock-via-SIP-Version-2-.patch b/root/target/linux/rockchip/patches-5.15/804-clk-rockchip-support-setting-ddr-clock-via-SIP-Version-2-.patch new file mode 100644 index 00000000..0408a0a7 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/804-clk-rockchip-support-setting-ddr-clock-via-SIP-Version-2-.patch @@ -0,0 +1,210 @@ +From ce6d3614888e6358466f0e84e248177a6bca5258 Mon Sep 17 00:00:00 2001 +From: Tang Yun ping +Date: Thu, 4 May 2017 20:49:58 +0800 +Subject: [PATCH] clk: rockchip: support setting ddr clock via SIP Version 2 + APIs + +commit 764e893ee82321938fc6f4349e9e7caf06a04410 rockchip. + +Signed-off-by: Tang Yun ping +Signed-off-by: hmz007 +--- + drivers/clk/rockchip/clk-ddr.c | 130 ++++++++++++++++++++++++++++ + drivers/clk/rockchip/clk-rk3328.c | 7 +- + drivers/clk/rockchip/clk.h | 3 +- + include/soc/rockchip/rockchip_sip.h | 11 +++ + 4 files changed, 147 insertions(+), 4 deletions(-) + +--- a/drivers/clk/rockchip/clk-ddr.c ++++ b/drivers/clk/rockchip/clk-ddr.c +@@ -87,6 +87,133 @@ static const struct clk_ops rockchip_ddr + .get_parent = rockchip_ddrclk_get_parent, + }; + ++/* See v4.4/include/dt-bindings/display/rk_fb.h */ ++#define SCREEN_NULL 0 ++#define SCREEN_HDMI 6 ++ ++static inline int rk_drm_get_lcdc_type(void) ++{ ++ return SCREEN_NULL; ++} ++ ++struct share_params { ++ u32 hz; ++ u32 lcdc_type; ++ u32 vop; ++ u32 vop_dclk_mode; ++ u32 sr_idle_en; ++ u32 addr_mcu_el3; ++ /* ++ * 1: need to wait flag1 ++ * 0: never wait flag1 ++ */ ++ u32 wait_flag1; ++ /* ++ * 1: need to wait flag1 ++ * 0: never wait flag1 ++ */ ++ u32 wait_flag0; ++ u32 complt_hwirq; ++ /* if need, add parameter after */ ++}; ++ ++struct rockchip_ddrclk_data { ++ u32 inited_flag; ++ void __iomem *share_memory; ++}; ++ ++static struct rockchip_ddrclk_data ddr_data; ++ ++static void rockchip_ddrclk_data_init(void) ++{ ++ struct arm_smccc_res res; ++ ++ arm_smccc_smc(ROCKCHIP_SIP_SHARE_MEM, ++ 1, SHARE_PAGE_TYPE_DDR, 0, ++ 0, 0, 0, 0, &res); ++ ++ if (!res.a0) { ++ ddr_data.share_memory = (void __iomem *)ioremap(res.a1, 1<<12); ++ ddr_data.inited_flag = 1; ++ } ++} ++ ++static int rockchip_ddrclk_sip_set_rate_v2(struct clk_hw *hw, ++ unsigned long drate, ++ unsigned long prate) ++{ ++ struct share_params *p; ++ struct arm_smccc_res res; ++ ++ if (!ddr_data.inited_flag) ++ rockchip_ddrclk_data_init(); ++ ++ p = (struct share_params *)ddr_data.share_memory; ++ ++ p->hz = drate; ++ p->lcdc_type = rk_drm_get_lcdc_type(); ++ p->wait_flag1 = 1; ++ p->wait_flag0 = 1; ++ ++ arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, ++ SHARE_PAGE_TYPE_DDR, 0, ++ ROCKCHIP_SIP_CONFIG_DRAM_SET_RATE, ++ 0, 0, 0, 0, &res); ++ ++ if ((int)res.a1 == -6) { ++ pr_err("%s: timeout, drate = %lumhz\n", __func__, drate/1000000); ++ /* TODO: rockchip_dmcfreq_wait_complete(); */ ++ } ++ ++ return res.a0; ++} ++ ++static unsigned long rockchip_ddrclk_sip_recalc_rate_v2 ++ (struct clk_hw *hw, unsigned long parent_rate) ++{ ++ struct arm_smccc_res res; ++ ++ arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, ++ SHARE_PAGE_TYPE_DDR, 0, ++ ROCKCHIP_SIP_CONFIG_DRAM_GET_RATE, ++ 0, 0, 0, 0, &res); ++ if (!res.a0) ++ return res.a1; ++ else ++ return 0; ++} ++ ++static long rockchip_ddrclk_sip_round_rate_v2(struct clk_hw *hw, ++ unsigned long rate, ++ unsigned long *prate) ++{ ++ struct share_params *p; ++ struct arm_smccc_res res; ++ ++ if (!ddr_data.inited_flag) ++ rockchip_ddrclk_data_init(); ++ ++ p = (struct share_params *)ddr_data.share_memory; ++ ++ p->hz = rate; ++ ++ arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, ++ SHARE_PAGE_TYPE_DDR, 0, ++ ROCKCHIP_SIP_CONFIG_DRAM_ROUND_RATE, ++ 0, 0, 0, 0, &res); ++ if (!res.a0) ++ return res.a1; ++ else ++ return 0; ++} ++ ++static const struct clk_ops rockchip_ddrclk_sip_ops_v2 = { ++ .recalc_rate = rockchip_ddrclk_sip_recalc_rate_v2, ++ .set_rate = rockchip_ddrclk_sip_set_rate_v2, ++ .round_rate = rockchip_ddrclk_sip_round_rate_v2, ++ .get_parent = rockchip_ddrclk_get_parent, ++}; ++ + struct clk *rockchip_clk_register_ddrclk(const char *name, int flags, + const char *const *parent_names, + u8 num_parents, int mux_offset, +@@ -114,6 +241,9 @@ struct clk *rockchip_clk_register_ddrclk + case ROCKCHIP_DDRCLK_SIP: + init.ops = &rockchip_ddrclk_sip_ops; + break; ++ case ROCKCHIP_DDRCLK_SIP_V2: ++ init.ops = &rockchip_ddrclk_sip_ops_v2; ++ break; + default: + pr_err("%s: unsupported ddrclk type %d\n", __func__, ddr_flag); + kfree(ddrclk); +--- a/drivers/clk/rockchip/clk-rk3328.c ++++ b/drivers/clk/rockchip/clk-rk3328.c +@@ -315,9 +315,10 @@ static struct rockchip_clk_branch rk3328 + RK3328_CLKGATE_CON(14), 1, GFLAGS), + + /* PD_DDR */ +- COMPOSITE(0, "clk_ddr", mux_ddrphy_p, CLK_IGNORE_UNUSED, +- RK3328_CLKSEL_CON(3), 8, 2, MFLAGS, 0, 3, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, +- RK3328_CLKGATE_CON(0), 4, GFLAGS), ++ COMPOSITE_DDRCLK(SCLK_DDRCLK, "sclk_ddrc", mux_ddrphy_p, 0, ++ RK3328_CLKSEL_CON(3), 8, 2, 0, 3, ++ ROCKCHIP_DDRCLK_SIP_V2), ++ + GATE(0, "clk_ddrmsch", "clk_ddr", CLK_IGNORE_UNUSED, + RK3328_CLKGATE_CON(18), 6, GFLAGS), + GATE(0, "clk_ddrupctl", "clk_ddr", CLK_IGNORE_UNUSED, +--- a/drivers/clk/rockchip/clk.h ++++ b/drivers/clk/rockchip/clk.h +@@ -399,7 +399,8 @@ struct clk *rockchip_clk_register_mmc(co + * DDRCLK flags, including method of setting the rate + * ROCKCHIP_DDRCLK_SIP: use SIP call to bl31 to change ddrclk rate. + */ +-#define ROCKCHIP_DDRCLK_SIP BIT(0) ++#define ROCKCHIP_DDRCLK_SIP 0x01 ++#define ROCKCHIP_DDRCLK_SIP_V2 0x03 + + struct clk *rockchip_clk_register_ddrclk(const char *name, int flags, + const char *const *parent_names, +--- a/include/soc/rockchip/rockchip_sip.h ++++ b/include/soc/rockchip/rockchip_sip.h +@@ -16,5 +16,16 @@ + #define ROCKCHIP_SIP_CONFIG_DRAM_CLR_IRQ 0x06 + #define ROCKCHIP_SIP_CONFIG_DRAM_SET_PARAM 0x07 + #define ROCKCHIP_SIP_CONFIG_DRAM_SET_ODT_PD 0x08 ++#define ROCKCHIP_SIP_CONFIG_DRAM_GET_VERSION 0x08 ++ ++#define ROCKCHIP_SIP_SHARE_MEM 0x82000009 ++ ++/* Share mem page types */ ++typedef enum { ++ SHARE_PAGE_TYPE_INVALID = 0, ++ SHARE_PAGE_TYPE_UARTDBG, ++ SHARE_PAGE_TYPE_DDR, ++ SHARE_PAGE_TYPE_MAX, ++} share_page_type_t; + + #endif diff --git a/root/target/linux/rockchip/patches-5.15/805-PM-devfreq-rockchip-dfi-add-more-soc-support.patch b/root/target/linux/rockchip/patches-5.15/805-PM-devfreq-rockchip-dfi-add-more-soc-support.patch new file mode 100644 index 00000000..283e4abd --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/805-PM-devfreq-rockchip-dfi-add-more-soc-support.patch @@ -0,0 +1,662 @@ +From 4db93c6dad0c71750b86163df2fdb21c35f00d9a Mon Sep 17 00:00:00 2001 +From: hmz007 +Date: Tue, 19 Nov 2019 12:49:48 +0800 +Subject: [PATCH] PM / devfreq: rockchip-dfi: add more soc support + +Signed-off-by: hmz007 +--- + drivers/devfreq/event/rockchip-dfi.c | 554 ++++++++++++++++++++++++--- + 1 file changed, 505 insertions(+), 49 deletions(-) + +--- a/drivers/devfreq/event/rockchip-dfi.c ++++ b/drivers/devfreq/event/rockchip-dfi.c +@@ -18,25 +18,66 @@ + #include + #include + +-#include +- +-#define RK3399_DMC_NUM_CH 2 ++#define PX30_PMUGRF_OS_REG2 0x208 + ++#define RK3128_GRF_SOC_CON0 0x140 ++#define RK3128_GRF_OS_REG1 0x1cc ++#define RK3128_GRF_DFI_WRNUM 0x220 ++#define RK3128_GRF_DFI_RDNUM 0x224 ++#define RK3128_GRF_DFI_TIMERVAL 0x22c ++#define RK3128_DDR_MONITOR_EN ((1 << (16 + 6)) + (1 << 6)) ++#define RK3128_DDR_MONITOR_DISB ((1 << (16 + 6)) + (0 << 6)) ++ ++#define RK3288_PMU_SYS_REG2 0x9c ++#define RK3288_GRF_SOC_CON4 0x254 ++#define RK3288_GRF_SOC_STATUS(n) (0x280 + (n) * 4) ++#define RK3288_DFI_EN (0x30003 << 14) ++#define RK3288_DFI_DIS (0x30000 << 14) ++#define RK3288_LPDDR_SEL (0x10001 << 13) ++#define RK3288_DDR3_SEL (0x10000 << 13) ++ ++#define RK3328_GRF_OS_REG2 0x5d0 ++ ++#define RK3368_GRF_DDRC0_CON0 0x600 ++#define RK3368_GRF_SOC_STATUS5 0x494 ++#define RK3368_GRF_SOC_STATUS6 0x498 ++#define RK3368_GRF_SOC_STATUS8 0x4a0 ++#define RK3368_GRF_SOC_STATUS9 0x4a4 ++#define RK3368_GRF_SOC_STATUS10 0x4a8 ++#define RK3368_DFI_EN (0x30003 << 5) ++#define RK3368_DFI_DIS (0x30000 << 5) ++ ++#define MAX_DMC_NUM_CH 2 ++#define READ_DRAMTYPE_INFO(n) (((n) >> 13) & 0x7) ++#define READ_CH_INFO(n) (((n) >> 28) & 0x3) + /* DDRMON_CTRL */ +-#define DDRMON_CTRL 0x04 +-#define CLR_DDRMON_CTRL (0x1f0000 << 0) +-#define LPDDR4_EN (0x10001 << 4) +-#define HARDWARE_EN (0x10001 << 3) +-#define LPDDR3_EN (0x10001 << 2) +-#define SOFTWARE_EN (0x10001 << 1) +-#define SOFTWARE_DIS (0x10000 << 1) +-#define TIME_CNT_EN (0x10001 << 0) ++#define DDRMON_CTRL 0x04 ++#define CLR_DDRMON_CTRL (0x3f0000 << 0) ++#define DDR4_EN (0x10001 << 5) ++#define LPDDR4_EN (0x10001 << 4) ++#define HARDWARE_EN (0x10001 << 3) ++#define LPDDR2_3_EN (0x10001 << 2) ++#define SOFTWARE_EN (0x10001 << 1) ++#define SOFTWARE_DIS (0x10000 << 1) ++#define TIME_CNT_EN (0x10001 << 0) + + #define DDRMON_CH0_COUNT_NUM 0x28 + #define DDRMON_CH0_DFI_ACCESS_NUM 0x2c + #define DDRMON_CH1_COUNT_NUM 0x3c + #define DDRMON_CH1_DFI_ACCESS_NUM 0x40 + ++/* pmu grf */ ++#define PMUGRF_OS_REG2 0x308 ++ ++enum { ++ DDR4 = 0, ++ DDR3 = 3, ++ LPDDR2 = 5, ++ LPDDR3 = 6, ++ LPDDR4 = 7, ++ UNUSED = 0xFF ++}; ++ + struct dmc_usage { + u32 access; + u32 total; +@@ -50,33 +91,261 @@ struct dmc_usage { + struct rockchip_dfi { + struct devfreq_event_dev *edev; + struct devfreq_event_desc *desc; +- struct dmc_usage ch_usage[RK3399_DMC_NUM_CH]; ++ struct dmc_usage ch_usage[MAX_DMC_NUM_CH]; + struct device *dev; + void __iomem *regs; + struct regmap *regmap_pmu; ++ struct regmap *regmap_grf; ++ struct regmap *regmap_pmugrf; + struct clk *clk; ++ u32 dram_type; ++ /* ++ * available mask, 1: available, 0: not available ++ * each bit represent a channel ++ */ ++ u32 ch_msk; ++}; ++ ++static void rk3128_dfi_start_hardware_counter(struct devfreq_event_dev *edev) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ ++ regmap_write(info->regmap_grf, ++ RK3128_GRF_SOC_CON0, ++ RK3128_DDR_MONITOR_EN); ++} ++ ++static void rk3128_dfi_stop_hardware_counter(struct devfreq_event_dev *edev) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ ++ regmap_write(info->regmap_grf, ++ RK3128_GRF_SOC_CON0, ++ RK3128_DDR_MONITOR_DISB); ++} ++ ++static int rk3128_dfi_disable(struct devfreq_event_dev *edev) ++{ ++ rk3128_dfi_stop_hardware_counter(edev); ++ ++ return 0; ++} ++ ++static int rk3128_dfi_enable(struct devfreq_event_dev *edev) ++{ ++ rk3128_dfi_start_hardware_counter(edev); ++ ++ return 0; ++} ++ ++static int rk3128_dfi_set_event(struct devfreq_event_dev *edev) ++{ ++ return 0; ++} ++ ++static int rk3128_dfi_get_event(struct devfreq_event_dev *edev, ++ struct devfreq_event_data *edata) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ unsigned long flags; ++ u32 dfi_wr, dfi_rd, dfi_timer; ++ ++ local_irq_save(flags); ++ ++ rk3128_dfi_stop_hardware_counter(edev); ++ ++ regmap_read(info->regmap_grf, RK3128_GRF_DFI_WRNUM, &dfi_wr); ++ regmap_read(info->regmap_grf, RK3128_GRF_DFI_RDNUM, &dfi_rd); ++ regmap_read(info->regmap_grf, RK3128_GRF_DFI_TIMERVAL, &dfi_timer); ++ ++ edata->load_count = (dfi_wr + dfi_rd) * 4; ++ edata->total_count = dfi_timer; ++ ++ rk3128_dfi_start_hardware_counter(edev); ++ ++ local_irq_restore(flags); ++ ++ return 0; ++} ++ ++static const struct devfreq_event_ops rk3128_dfi_ops = { ++ .disable = rk3128_dfi_disable, ++ .enable = rk3128_dfi_enable, ++ .get_event = rk3128_dfi_get_event, ++ .set_event = rk3128_dfi_set_event, ++}; ++ ++static void rk3288_dfi_start_hardware_counter(struct devfreq_event_dev *edev) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ ++ regmap_write(info->regmap_grf, RK3288_GRF_SOC_CON4, RK3288_DFI_EN); ++} ++ ++static void rk3288_dfi_stop_hardware_counter(struct devfreq_event_dev *edev) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ ++ regmap_write(info->regmap_grf, RK3288_GRF_SOC_CON4, RK3288_DFI_DIS); ++} ++ ++static int rk3288_dfi_disable(struct devfreq_event_dev *edev) ++{ ++ rk3288_dfi_stop_hardware_counter(edev); ++ ++ return 0; ++} ++ ++static int rk3288_dfi_enable(struct devfreq_event_dev *edev) ++{ ++ rk3288_dfi_start_hardware_counter(edev); ++ ++ return 0; ++} ++ ++static int rk3288_dfi_set_event(struct devfreq_event_dev *edev) ++{ ++ return 0; ++} ++ ++static int rk3288_dfi_get_busier_ch(struct devfreq_event_dev *edev) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ u32 tmp, max = 0; ++ u32 i, busier_ch = 0; ++ u32 rd_count, wr_count, total_count; ++ ++ rk3288_dfi_stop_hardware_counter(edev); ++ ++ /* Find out which channel is busier */ ++ for (i = 0; i < MAX_DMC_NUM_CH; i++) { ++ if (!(info->ch_msk & BIT(i))) ++ continue; ++ regmap_read(info->regmap_grf, ++ RK3288_GRF_SOC_STATUS(11 + i * 4), &wr_count); ++ regmap_read(info->regmap_grf, ++ RK3288_GRF_SOC_STATUS(12 + i * 4), &rd_count); ++ regmap_read(info->regmap_grf, ++ RK3288_GRF_SOC_STATUS(14 + i * 4), &total_count); ++ info->ch_usage[i].access = (wr_count + rd_count) * 4; ++ info->ch_usage[i].total = total_count; ++ tmp = info->ch_usage[i].access; ++ if (tmp > max) { ++ busier_ch = i; ++ max = tmp; ++ } ++ } ++ rk3288_dfi_start_hardware_counter(edev); ++ ++ return busier_ch; ++} ++ ++static int rk3288_dfi_get_event(struct devfreq_event_dev *edev, ++ struct devfreq_event_data *edata) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ int busier_ch; ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ busier_ch = rk3288_dfi_get_busier_ch(edev); ++ local_irq_restore(flags); ++ ++ edata->load_count = info->ch_usage[busier_ch].access; ++ edata->total_count = info->ch_usage[busier_ch].total; ++ ++ return 0; ++} ++ ++static const struct devfreq_event_ops rk3288_dfi_ops = { ++ .disable = rk3288_dfi_disable, ++ .enable = rk3288_dfi_enable, ++ .get_event = rk3288_dfi_get_event, ++ .set_event = rk3288_dfi_set_event, ++}; ++ ++static void rk3368_dfi_start_hardware_counter(struct devfreq_event_dev *edev) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ ++ regmap_write(info->regmap_grf, RK3368_GRF_DDRC0_CON0, RK3368_DFI_EN); ++} ++ ++static void rk3368_dfi_stop_hardware_counter(struct devfreq_event_dev *edev) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ ++ regmap_write(info->regmap_grf, RK3368_GRF_DDRC0_CON0, RK3368_DFI_DIS); ++} ++ ++static int rk3368_dfi_disable(struct devfreq_event_dev *edev) ++{ ++ rk3368_dfi_stop_hardware_counter(edev); ++ ++ return 0; ++} ++ ++static int rk3368_dfi_enable(struct devfreq_event_dev *edev) ++{ ++ rk3368_dfi_start_hardware_counter(edev); ++ ++ return 0; ++} ++ ++static int rk3368_dfi_set_event(struct devfreq_event_dev *edev) ++{ ++ return 0; ++} ++ ++static int rk3368_dfi_get_event(struct devfreq_event_dev *edev, ++ struct devfreq_event_data *edata) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ unsigned long flags; ++ u32 dfi0_wr, dfi0_rd, dfi1_wr, dfi1_rd, dfi_timer; ++ ++ local_irq_save(flags); ++ ++ rk3368_dfi_stop_hardware_counter(edev); ++ ++ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS5, &dfi0_wr); ++ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS6, &dfi0_rd); ++ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS9, &dfi1_wr); ++ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS10, &dfi1_rd); ++ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS8, &dfi_timer); ++ ++ edata->load_count = (dfi0_wr + dfi0_rd + dfi1_wr + dfi1_rd) * 2; ++ edata->total_count = dfi_timer; ++ ++ rk3368_dfi_start_hardware_counter(edev); ++ ++ local_irq_restore(flags); ++ ++ return 0; ++} ++ ++static const struct devfreq_event_ops rk3368_dfi_ops = { ++ .disable = rk3368_dfi_disable, ++ .enable = rk3368_dfi_enable, ++ .get_event = rk3368_dfi_get_event, ++ .set_event = rk3368_dfi_set_event, + }; + + static void rockchip_dfi_start_hardware_counter(struct devfreq_event_dev *edev) + { + struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); + void __iomem *dfi_regs = info->regs; +- u32 val; +- u32 ddr_type; +- +- /* get ddr type */ +- regmap_read(info->regmap_pmu, RK3399_PMUGRF_OS_REG2, &val); +- ddr_type = (val >> RK3399_PMUGRF_DDRTYPE_SHIFT) & +- RK3399_PMUGRF_DDRTYPE_MASK; + + /* clear DDRMON_CTRL setting */ + writel_relaxed(CLR_DDRMON_CTRL, dfi_regs + DDRMON_CTRL); + + /* set ddr type to dfi */ +- if (ddr_type == RK3399_PMUGRF_DDRTYPE_LPDDR3) +- writel_relaxed(LPDDR3_EN, dfi_regs + DDRMON_CTRL); +- else if (ddr_type == RK3399_PMUGRF_DDRTYPE_LPDDR4) ++ if (info->dram_type == LPDDR3 || info->dram_type == LPDDR2) ++ writel_relaxed(LPDDR2_3_EN, dfi_regs + DDRMON_CTRL); ++ else if (info->dram_type == LPDDR4) + writel_relaxed(LPDDR4_EN, dfi_regs + DDRMON_CTRL); ++ else if (info->dram_type == DDR4) ++ writel_relaxed(DDR4_EN, dfi_regs + DDRMON_CTRL); + + /* enable count, use software mode */ + writel_relaxed(SOFTWARE_EN, dfi_regs + DDRMON_CTRL); +@@ -100,12 +369,22 @@ static int rockchip_dfi_get_busier_ch(st + rockchip_dfi_stop_hardware_counter(edev); + + /* Find out which channel is busier */ +- for (i = 0; i < RK3399_DMC_NUM_CH; i++) { +- info->ch_usage[i].access = readl_relaxed(dfi_regs + +- DDRMON_CH0_DFI_ACCESS_NUM + i * 20) * 4; ++ for (i = 0; i < MAX_DMC_NUM_CH; i++) { ++ if (!(info->ch_msk & BIT(i))) ++ continue; ++ + info->ch_usage[i].total = readl_relaxed(dfi_regs + + DDRMON_CH0_COUNT_NUM + i * 20); +- tmp = info->ch_usage[i].access; ++ ++ /* LPDDR4 BL = 16,other DDR type BL = 8 */ ++ tmp = readl_relaxed(dfi_regs + ++ DDRMON_CH0_DFI_ACCESS_NUM + i * 20); ++ if (info->dram_type == LPDDR4) ++ tmp *= 8; ++ else ++ tmp *= 4; ++ info->ch_usage[i].access = tmp; ++ + if (tmp > max) { + busier_ch = i; + max = tmp; +@@ -121,7 +400,8 @@ static int rockchip_dfi_disable(struct d + struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); + + rockchip_dfi_stop_hardware_counter(edev); +- clk_disable_unprepare(info->clk); ++ if (info->clk) ++ clk_disable_unprepare(info->clk); + + return 0; + } +@@ -131,10 +411,13 @@ static int rockchip_dfi_enable(struct de + struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); + int ret; + +- ret = clk_prepare_enable(info->clk); +- if (ret) { +- dev_err(&edev->dev, "failed to enable dfi clk: %d\n", ret); +- return ret; ++ if (info->clk) { ++ ret = clk_prepare_enable(info->clk); ++ if (ret) { ++ dev_err(&edev->dev, "failed to enable dfi clk: %d\n", ++ ret); ++ return ret; ++ } + } + + rockchip_dfi_start_hardware_counter(edev); +@@ -151,8 +434,11 @@ static int rockchip_dfi_get_event(struct + { + struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); + int busier_ch; ++ unsigned long flags; + ++ local_irq_save(flags); + busier_ch = rockchip_dfi_get_busier_ch(edev); ++ local_irq_restore(flags); + + edata->load_count = info->ch_usage[busier_ch].access; + edata->total_count = info->ch_usage[busier_ch].total; +@@ -167,22 +453,116 @@ static const struct devfreq_event_ops ro + .set_event = rockchip_dfi_set_event, + }; + +-static const struct of_device_id rockchip_dfi_id_match[] = { +- { .compatible = "rockchip,rk3399-dfi" }, +- { }, +-}; +-MODULE_DEVICE_TABLE(of, rockchip_dfi_id_match); ++static __init int px30_dfi_init(struct platform_device *pdev, ++ struct rockchip_dfi *data, ++ struct devfreq_event_desc *desc) ++{ ++ struct device_node *np = pdev->dev.of_node, *node; ++ struct resource *res; ++ u32 val; + +-static int rockchip_dfi_probe(struct platform_device *pdev) ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ data->regs = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(data->regs)) ++ return PTR_ERR(data->regs); ++ ++ node = of_parse_phandle(np, "rockchip,pmugrf", 0); ++ if (node) { ++ data->regmap_pmugrf = syscon_node_to_regmap(node); ++ if (IS_ERR(data->regmap_pmugrf)) ++ return PTR_ERR(data->regmap_pmugrf); ++ } ++ ++ regmap_read(data->regmap_pmugrf, PX30_PMUGRF_OS_REG2, &val); ++ data->dram_type = READ_DRAMTYPE_INFO(val); ++ data->ch_msk = 1; ++ data->clk = NULL; ++ ++ desc->ops = &rockchip_dfi_ops; ++ ++ return 0; ++} ++ ++static __init int rk3128_dfi_init(struct platform_device *pdev, ++ struct rockchip_dfi *data, ++ struct devfreq_event_desc *desc) + { +- struct device *dev = &pdev->dev; +- struct rockchip_dfi *data; +- struct devfreq_event_desc *desc; + struct device_node *np = pdev->dev.of_node, *node; + +- data = devm_kzalloc(dev, sizeof(struct rockchip_dfi), GFP_KERNEL); +- if (!data) +- return -ENOMEM; ++ node = of_parse_phandle(np, "rockchip,grf", 0); ++ if (node) { ++ data->regmap_grf = syscon_node_to_regmap(node); ++ if (IS_ERR(data->regmap_grf)) ++ return PTR_ERR(data->regmap_grf); ++ } ++ ++ desc->ops = &rk3128_dfi_ops; ++ ++ return 0; ++} ++ ++static __init int rk3288_dfi_init(struct platform_device *pdev, ++ struct rockchip_dfi *data, ++ struct devfreq_event_desc *desc) ++{ ++ struct device_node *np = pdev->dev.of_node, *node; ++ u32 val; ++ ++ node = of_parse_phandle(np, "rockchip,pmu", 0); ++ if (node) { ++ data->regmap_pmu = syscon_node_to_regmap(node); ++ if (IS_ERR(data->regmap_pmu)) ++ return PTR_ERR(data->regmap_pmu); ++ } ++ ++ node = of_parse_phandle(np, "rockchip,grf", 0); ++ if (node) { ++ data->regmap_grf = syscon_node_to_regmap(node); ++ if (IS_ERR(data->regmap_grf)) ++ return PTR_ERR(data->regmap_grf); ++ } ++ ++ regmap_read(data->regmap_pmu, RK3288_PMU_SYS_REG2, &val); ++ data->dram_type = READ_DRAMTYPE_INFO(val); ++ data->ch_msk = READ_CH_INFO(val); ++ ++ if (data->dram_type == DDR3) ++ regmap_write(data->regmap_grf, RK3288_GRF_SOC_CON4, ++ RK3288_DDR3_SEL); ++ else ++ regmap_write(data->regmap_grf, RK3288_GRF_SOC_CON4, ++ RK3288_LPDDR_SEL); ++ ++ desc->ops = &rk3288_dfi_ops; ++ ++ return 0; ++} ++ ++static __init int rk3368_dfi_init(struct platform_device *pdev, ++ struct rockchip_dfi *data, ++ struct devfreq_event_desc *desc) ++{ ++ struct device *dev = &pdev->dev; ++ ++ if (!dev->parent || !dev->parent->of_node) ++ return -EINVAL; ++ ++ data->regmap_grf = syscon_node_to_regmap(dev->parent->of_node); ++ if (IS_ERR(data->regmap_grf)) ++ return PTR_ERR(data->regmap_grf); ++ ++ desc->ops = &rk3368_dfi_ops; ++ ++ return 0; ++} ++ ++static __init int rockchip_dfi_init(struct platform_device *pdev, ++ struct rockchip_dfi *data, ++ struct devfreq_event_desc *desc) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *np = pdev->dev.of_node, *node; ++ u32 val; + + data->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(data->regs)) +@@ -202,21 +582,97 @@ static int rockchip_dfi_probe(struct pla + if (IS_ERR(data->regmap_pmu)) + return PTR_ERR(data->regmap_pmu); + } +- data->dev = dev; ++ ++ regmap_read(data->regmap_pmu, PMUGRF_OS_REG2, &val); ++ data->dram_type = READ_DRAMTYPE_INFO(val); ++ data->ch_msk = READ_CH_INFO(val); ++ ++ desc->ops = &rockchip_dfi_ops; ++ ++ return 0; ++} ++ ++static __init int rk3328_dfi_init(struct platform_device *pdev, ++ struct rockchip_dfi *data, ++ struct devfreq_event_desc *desc) ++{ ++ struct device_node *np = pdev->dev.of_node, *node; ++ struct resource *res; ++ u32 val; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ data->regs = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(data->regs)) ++ return PTR_ERR(data->regs); ++ ++ node = of_parse_phandle(np, "rockchip,grf", 0); ++ if (node) { ++ data->regmap_grf = syscon_node_to_regmap(node); ++ if (IS_ERR(data->regmap_grf)) ++ return PTR_ERR(data->regmap_grf); ++ } ++ ++ regmap_read(data->regmap_grf, RK3328_GRF_OS_REG2, &val); ++ data->dram_type = READ_DRAMTYPE_INFO(val); ++ data->ch_msk = 1; ++ data->clk = NULL; ++ ++ desc->ops = &rockchip_dfi_ops; ++ ++ return 0; ++} ++ ++static const struct of_device_id rockchip_dfi_id_match[] = { ++ { .compatible = "rockchip,px30-dfi", .data = px30_dfi_init }, ++ { .compatible = "rockchip,rk1808-dfi", .data = px30_dfi_init }, ++ { .compatible = "rockchip,rk3128-dfi", .data = rk3128_dfi_init }, ++ { .compatible = "rockchip,rk3288-dfi", .data = rk3288_dfi_init }, ++ { .compatible = "rockchip,rk3328-dfi", .data = rk3328_dfi_init }, ++ { .compatible = "rockchip,rk3368-dfi", .data = rk3368_dfi_init }, ++ { .compatible = "rockchip,rk3399-dfi", .data = rockchip_dfi_init }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, rockchip_dfi_id_match); ++ ++static int rockchip_dfi_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct rockchip_dfi *data; ++ struct devfreq_event_desc *desc; ++ struct device_node *np = pdev->dev.of_node; ++ const struct of_device_id *match; ++ int (*init)(struct platform_device *pdev, struct rockchip_dfi *data, ++ struct devfreq_event_desc *desc); ++ ++ data = devm_kzalloc(dev, sizeof(struct rockchip_dfi), GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; + + desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL); + if (!desc) + return -ENOMEM; + +- desc->ops = &rockchip_dfi_ops; ++ match = of_match_node(rockchip_dfi_id_match, pdev->dev.of_node); ++ if (match) { ++ init = match->data; ++ if (init) { ++ if (init(pdev, data, desc)) ++ return -EINVAL; ++ } else { ++ return 0; ++ } ++ } else { ++ return 0; ++ } ++ + desc->driver_data = data; + desc->name = np->name; + data->desc = desc; ++ data->dev = dev; + +- data->edev = devm_devfreq_event_add_edev(&pdev->dev, desc); ++ data->edev = devm_devfreq_event_add_edev(dev, desc); + if (IS_ERR(data->edev)) { +- dev_err(&pdev->dev, +- "failed to add devfreq-event device\n"); ++ dev_err(dev, "failed to add devfreq-event device\n"); + return PTR_ERR(data->edev); + } + diff --git a/root/target/linux/rockchip/patches-5.15/806-arm64-dts-rockchip-rk3328-add-dfi-node.patch b/root/target/linux/rockchip/patches-5.15/806-arm64-dts-rockchip-rk3328-add-dfi-node.patch new file mode 100644 index 00000000..d9c5f944 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/806-arm64-dts-rockchip-rk3328-add-dfi-node.patch @@ -0,0 +1,27 @@ +From f9ae6e992d3d9e80357fee7d65ba0fe2dd37ae1f Mon Sep 17 00:00:00 2001 +From: hmz007 +Date: Tue, 19 Nov 2019 14:21:51 +0800 +Subject: [PATCH] arm64: dts: rockchip: rk3328: add dfi node + +Signed-off-by: hmz007 +[adjusted commit title] +Signed-off-by: Tianling Shen +--- + arch/arm64/boot/dts/rockchip/rk3328.dtsi | 7 +++++++ + +--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +@@ -1010,6 +1010,13 @@ + status = "disabled"; + }; + ++ dfi: dfi@ff790000 { ++ reg = <0x00 0xff790000 0x00 0x400>; ++ compatible = "rockchip,rk3328-dfi"; ++ rockchip,grf = <&grf>; ++ status = "disabled"; ++ }; ++ + gic: interrupt-controller@ff811000 { + compatible = "arm,gic-400"; + #interrupt-cells = <3>; diff --git a/root/target/linux/rockchip/patches-5.15/807-arm64-dts-nanopi-r2s-add-rk3328-dmc-relate-node.patch b/root/target/linux/rockchip/patches-5.15/807-arm64-dts-nanopi-r2s-add-rk3328-dmc-relate-node.patch new file mode 100644 index 00000000..53635665 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/807-arm64-dts-nanopi-r2s-add-rk3328-dmc-relate-node.patch @@ -0,0 +1,126 @@ +From f9ae6e992d3d9e80357fee7d65ba0fe2dd37ae1f Mon Sep 17 00:00:00 2001 +From: hmz007 +Date: Tue, 19 Nov 2019 14:21:51 +0800 +Subject: [PATCH] arm64: dts: nanopi-r2: add rk3328-dmc relate node + +Signed-off-by: hmz007 +--- + .../rockchip/rk3328-dram-default-timing.dtsi | 311 ++++++++++++++++++ + .../dts/rockchip/rk3328-nanopi-r2-common.dtsi | 85 ++++- + include/dt-bindings/clock/rockchip-ddr.h | 63 ++++ + include/dt-bindings/memory/rk3328-dram.h | 159 +++++++++ + 4 files changed, 617 insertions(+), 1 deletion(-) + create mode 100644 arch/arm64/boot/dts/rockchip/rk3328-dram-default-timing.dtsi + create mode 100644 include/dt-bindings/clock/rockchip-ddr.h + create mode 100644 include/dt-bindings/memory/rk3328-dram.h + +--- a/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts +@@ -7,6 +7,7 @@ + + #include + #include ++#include "rk3328-dram-default-timing.dtsi" + #include "rk3328.dtsi" + + / { +@@ -119,6 +120,72 @@ + regulator-boot-on; + vin-supply = <&vdd_5v>; + }; ++ ++ dmc: dmc { ++ compatible = "rockchip,rk3328-dmc"; ++ devfreq-events = <&dfi>; ++ center-supply = <&vdd_log>; ++ clocks = <&cru SCLK_DDRCLK>; ++ clock-names = "dmc_clk"; ++ operating-points-v2 = <&dmc_opp_table>; ++ ddr_timing = <&ddr_timing>; ++ upthreshold = <40>; ++ downdifferential = <20>; ++ auto-min-freq = <786000>; ++ auto-freq-en = <0>; ++ #cooling-cells = <2>; ++ status = "okay"; ++ ++ ddr_power_model: ddr_power_model { ++ compatible = "ddr_power_model"; ++ dynamic-power-coefficient = <120>; ++ static-power-coefficient = <200>; ++ ts = <32000 4700 (-80) 2>; ++ thermal-zone = "soc-thermal"; ++ }; ++ }; ++ ++ dmc_opp_table: dmc-opp-table { ++ compatible = "operating-points-v2"; ++ ++ rockchip,leakage-voltage-sel = < ++ 1 10 0 ++ 11 254 1 ++ >; ++ nvmem-cells = <&logic_leakage>; ++ nvmem-cell-names = "ddr_leakage"; ++ ++ opp-786000000 { ++ opp-hz = /bits/ 64 <786000000>; ++ opp-microvolt = <1075000>; ++ opp-microvolt-L0 = <1075000>; ++ opp-microvolt-L1 = <1050000>; ++ }; ++ opp-798000000 { ++ opp-hz = /bits/ 64 <798000000>; ++ opp-microvolt = <1075000>; ++ opp-microvolt-L0 = <1075000>; ++ opp-microvolt-L1 = <1050000>; ++ }; ++ opp-840000000 { ++ opp-hz = /bits/ 64 <840000000>; ++ opp-microvolt = <1075000>; ++ opp-microvolt-L0 = <1075000>; ++ opp-microvolt-L1 = <1050000>; ++ }; ++ opp-924000000 { ++ opp-hz = /bits/ 64 <924000000>; ++ opp-microvolt = <1100000>; ++ opp-microvolt-L0 = <1100000>; ++ opp-microvolt-L1 = <1075000>; ++ }; ++ opp-1056000000 { ++ opp-hz = /bits/ 64 <1056000000>; ++ opp-microvolt = <1175000>; ++ opp-microvolt-L0 = <1175000>; ++ opp-microvolt-L1 = <1150000>; ++ }; ++ }; + }; + + &cpu0 { +@@ -137,6 +204,10 @@ + cpu-supply = <&vdd_arm>; + }; + ++&dfi { ++ status = "okay"; ++}; ++ + &display_subsystem { + status = "disabled"; + }; +@@ -206,6 +277,7 @@ + regulator-name = "vdd_log"; + regulator-always-on; + regulator-boot-on; ++ regulator-init-microvolt = <1075000>; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1450000>; + regulator-ramp-delay = <12500>; +@@ -220,6 +292,7 @@ + regulator-name = "vdd_arm"; + regulator-always-on; + regulator-boot-on; ++ regulator-init-microvolt = <1225000>; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1450000>; + regulator-ramp-delay = <12500>; diff --git a/root/target/linux/rockchip/patches-5.15/991-arm64-dts-rockchip-add-more-cpu-operating-points-for.patch b/root/target/linux/rockchip/patches-5.15/991-arm64-dts-rockchip-add-more-cpu-operating-points-for.patch new file mode 100644 index 00000000..315ac0e3 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/991-arm64-dts-rockchip-add-more-cpu-operating-points-for.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Leonidas P. Papadakos +Date: Fri, 1 Mar 2019 21:55:53 +0200 +Subject: [PATCH v2] arm64: dts: rockchip: add more cpu operating points for + RK3328 + +This allows for greater max frequency on rk3328 boards, +increasing performance. + +It has been included in Armbian (a linux distibution for ARM boards) +for a while now without any reported issues + +https://github.com/armbian/build/blob/master/patch/kernel/rockchip64-default/enable-1392mhz-opp.patch +https://github.com/armbian/build/blob/master/patch/kernel/rockchip64-default/enable-1512mhz-opp.patch + +Signed-off-by: Leonidas P. Papadakos +--- + arch/arm64/boot/dts/rockchip/rk3328.dtsi | 15 +++++++++++++++ + 1 files changed, 15 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +@@ -140,6 +140,21 @@ + opp-microvolt = <1300000>; + clock-latency-ns = <40000>; + }; ++ opp-1392000000 { ++ opp-hz = /bits/ 64 <1392000000>; ++ opp-microvolt = <1350000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1512000000 { ++ opp-hz = /bits/ 64 <1512000000>; ++ opp-microvolt = <1400000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1608000000 { ++ opp-hz = /bits/ 64 <1608000000>; ++ opp-microvolt = <1450000>; ++ clock-latency-ns = <40000>; ++ }; + }; + + analog_sound: analog-sound { diff --git a/root/target/linux/rockchip/patches-5.15/992-rockchip-rk3399-overclock-to-2.2-1.8-GHz.patch b/root/target/linux/rockchip/patches-5.15/992-rockchip-rk3399-overclock-to-2.2-1.8-GHz.patch new file mode 100644 index 00000000..9090e96d --- /dev/null +++ b/root/target/linux/rockchip/patches-5.15/992-rockchip-rk3399-overclock-to-2.2-1.8-GHz.patch @@ -0,0 +1,46 @@ +From 04202df5cb497b1934c95211cf43784ef62245a4 Mon Sep 17 00:00:00 2001 +From: Tianling Shen +Date: Mon, 18 Oct 2021 12:47:30 +0800 +Subject: [PATCH] rockchip: rk3399: overclock to 2.2/1.8 GHz + +It's stable enough to overclock cpu frequency to 2.2/1.8 GHz, +and for better performance. + +Co-development-by: gzelvis +Signed-off-by: Tianling Shen +--- + arch/arm64/boot/dts/rockchip/rk3399-opp.dtsi | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3399-opp.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-opp.dtsi +@@ -33,6 +33,14 @@ + opp-hz = /bits/ 64 <1416000000>; + opp-microvolt = <1125000 1125000 1250000>; + }; ++ opp06 { ++ opp-hz = /bits/ 64 <1608000000>; ++ opp-microvolt = <1225000>; ++ }; ++ opp07 { ++ opp-hz = /bits/ 64 <1800000000>; ++ opp-microvolt = <1275000>; ++ }; + }; + + cluster1_opp: opp-table1 { +@@ -72,6 +80,14 @@ + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <1200000 1200000 1250000>; + }; ++ opp08 { ++ opp-hz = /bits/ 64 <2016000000>; ++ opp-microvolt = <1250000>; ++ }; ++ opp09 { ++ opp-hz = /bits/ 64 <2208000000>; ++ opp-microvolt = <1325000>; ++ }; + }; + + gpu_opp_table: opp-table2 { diff --git a/root/target/linux/rockchip/patches-5.4/007-arm64-dts-rockchip-Add-RK3328-idle-state.patch b/root/target/linux/rockchip/patches-5.4/007-arm64-dts-rockchip-Add-RK3328-idle-state.patch new file mode 100644 index 00000000..874d4ddd --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/007-arm64-dts-rockchip-Add-RK3328-idle-state.patch @@ -0,0 +1,69 @@ +From 4f279f9fbca54464173240f7e73b145a136dfa1e Mon Sep 17 00:00:00 2001 +From: Robin Murphy +Date: Sun, 29 Dec 2019 20:16:17 +0000 +Subject: arm64: dts: rockchip: Add RK3328 idle state + +Downstream RK3328 DTBs describe a CPU idle state matching that present +on other SoCs like RK3399. This works with upstream Trusted Firmware-A +too, so let's add it here. + +Signed-off-by: Robin Murphy +Link: https://lore.kernel.org/r/a8c83e705d387446ea8121516d410e38b2d9c57b.1577640736.git.robin.murphy@arm.com +Signed-off-by: Heiko Stuebner +--- + arch/arm64/boot/dts/rockchip/rk3328.dtsi | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +@@ -41,6 +41,7 @@ + reg = <0x0 0x0>; + clocks = <&cru ARMCLK>; + #cooling-cells = <2>; ++ cpu-idle-states = <&CPU_SLEEP>; + dynamic-power-coefficient = <120>; + enable-method = "psci"; + next-level-cache = <&l2>; +@@ -53,6 +54,7 @@ + reg = <0x0 0x1>; + clocks = <&cru ARMCLK>; + #cooling-cells = <2>; ++ cpu-idle-states = <&CPU_SLEEP>; + dynamic-power-coefficient = <120>; + enable-method = "psci"; + next-level-cache = <&l2>; +@@ -65,6 +67,7 @@ + reg = <0x0 0x2>; + clocks = <&cru ARMCLK>; + #cooling-cells = <2>; ++ cpu-idle-states = <&CPU_SLEEP>; + dynamic-power-coefficient = <120>; + enable-method = "psci"; + next-level-cache = <&l2>; +@@ -77,12 +80,26 @@ + reg = <0x0 0x3>; + clocks = <&cru ARMCLK>; + #cooling-cells = <2>; ++ cpu-idle-states = <&CPU_SLEEP>; + dynamic-power-coefficient = <120>; + enable-method = "psci"; + next-level-cache = <&l2>; + operating-points-v2 = <&cpu0_opp_table>; + }; + ++ idle-states { ++ entry-method = "psci"; ++ ++ CPU_SLEEP: cpu-sleep { ++ compatible = "arm,idle-state"; ++ local-timer-stop; ++ arm,psci-suspend-param = <0x0010000>; ++ entry-latency-us = <120>; ++ exit-latency-us = <250>; ++ min-residency-us = <900>; ++ }; ++ }; ++ + l2: l2-cache0 { + compatible = "cache"; + }; diff --git a/root/target/linux/rockchip/patches-5.4/008-rockchip-add-hwmon-support-for-SoCs-and-GPUs.patch b/root/target/linux/rockchip/patches-5.4/008-rockchip-add-hwmon-support-for-SoCs-and-GPUs.patch new file mode 100644 index 00000000..7ea18e41 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/008-rockchip-add-hwmon-support-for-SoCs-and-GPUs.patch @@ -0,0 +1,53 @@ +From d27970b82a0f552f70e76fab154855b3192aac23 Mon Sep 17 00:00:00 2001 +From: Stefan Schaeckeler +Date: Wed, 11 Dec 2019 22:17:02 -0800 +Subject: thermal: rockchip: Enable hwmon + +By default, of-based thermal drivers do not enable hwmon. +Explicitly enable hwmon for both, the soc and gpu temperature +sensor. + +Signed-off-by: Stefan Schaeckeler +Tested-by: Daniel Lezcano +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20191212061702.BFE2D6E85603@corona.crabdance.com +--- + drivers/thermal/rockchip_thermal.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +--- a/drivers/thermal/rockchip_thermal.c ++++ b/drivers/thermal/rockchip_thermal.c +@@ -58,6 +58,8 @@ enum adc_sort_mode { + ADC_INCREMENT, + }; + ++#include "thermal_hwmon.h" ++ + /** + * The max sensors is two in rockchip SoCs. + * Two sensors: CPU and GPU sensor. +@@ -1321,8 +1323,15 @@ static int rockchip_thermal_probe(struct + + thermal->chip->control(thermal->regs, true); + +- for (i = 0; i < thermal->chip->chn_num; i++) ++ for (i = 0; i < thermal->chip->chn_num; i++) { + rockchip_thermal_toggle_sensor(&thermal->sensors[i], true); ++ thermal->sensors[i].tzd->tzp->no_hwmon = false; ++ error = thermal_add_hwmon_sysfs(thermal->sensors[i].tzd); ++ if (error) ++ dev_warn(&pdev->dev, ++ "failed to register sensor %d with hwmon: %d\n", ++ i, error); ++ } + + platform_set_drvdata(pdev, thermal); + +@@ -1344,6 +1353,7 @@ static int rockchip_thermal_remove(struc + for (i = 0; i < thermal->chip->chn_num; i++) { + struct rockchip_thermal_sensor *sensor = &thermal->sensors[i]; + ++ thermal_remove_hwmon_sysfs(sensor->tzd); + rockchip_thermal_toggle_sensor(sensor, false); + } + diff --git a/root/target/linux/rockchip/patches-5.4/007-v5.13-rockchip-rk3399-Add-support-for-FriendlyARM-NanoPi-R.patch b/root/target/linux/rockchip/patches-5.4/009-rockchip-rk3399-Add-support-for-FriendlyARM-NanoPi-R.patch similarity index 97% rename from root/target/linux/rockchip/patches-5.4/007-v5.13-rockchip-rk3399-Add-support-for-FriendlyARM-NanoPi-R.patch rename to root/target/linux/rockchip/patches-5.4/009-rockchip-rk3399-Add-support-for-FriendlyARM-NanoPi-R.patch index c508d713..720840b3 100644 --- a/root/target/linux/rockchip/patches-5.4/007-v5.13-rockchip-rk3399-Add-support-for-FriendlyARM-NanoPi-R.patch +++ b/root/target/linux/rockchip/patches-5.4/009-rockchip-rk3399-Add-support-for-FriendlyARM-NanoPi-R.patch @@ -31,11 +31,12 @@ Signed-off-by: Heiko Stuebner --- a/arch/arm64/boot/dts/rockchip/Makefile +++ b/arch/arm64/boot/dts/rockchip/Makefile -@@ -25,6 +25,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-le +@@ -25,6 +25,8 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-le dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopc-t4.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopi-m4.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopi-neo4.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopi-r4s.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-guangmiao-g4c.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-orangepi.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-puma-haikou.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-roc-pc.dtb diff --git a/root/target/linux/rockchip/patches-5.15/005-arm64-dts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch b/root/target/linux/rockchip/patches-5.4/010-arm64-dts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch similarity index 69% rename from root/target/linux/rockchip/patches-5.15/005-arm64-dts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch rename to root/target/linux/rockchip/patches-5.4/010-arm64-dts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch index 792028b2..c2caa814 100644 --- a/root/target/linux/rockchip/patches-5.15/005-arm64-dts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch +++ b/root/target/linux/rockchip/patches-5.4/010-arm64-dts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch @@ -1,4 +1,4 @@ -From af20b3384e8723077cc6484160b0cf4e9be321de Mon Sep 17 00:00:00 2001 +From 43f3999d1836117ab2e601aec9a9e6f292ce4958 Mon Sep 17 00:00:00 2001 From: Tianling Shen Date: Mon, 7 Jun 2021 15:45:37 +0800 Subject: [PATCH] arm64: dts: rockchip: add EEPROM node for NanoPi R4S @@ -8,12 +8,12 @@ stores the MAC address. Signed-off-by: Tianling Shen --- - arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts | 9 +++++++++ - 1 file changed, 9 insertions(+) + .../boot/dts/rockchip/rk3399-nanopi-r4s.dts | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) --- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts -@@ -68,6 +68,15 @@ +@@ -68,6 +68,19 @@ status = "disabled"; }; @@ -22,7 +22,11 @@ Signed-off-by: Tianling Shen + compatible = "microchip,24c02", "atmel,24c02"; + reg = <0x51>; + pagesize = <16>; -+ read-only; /* This holds our MAC */ ++ size = <256>; ++ ++ mac_address: mac-address@fa { ++ reg = <0xfa 0x06>; ++ }; + }; +}; + diff --git a/root/target/linux/rockchip/patches-5.4/012-resync-rk3566-device-tree-with-mainline.patch b/root/target/linux/rockchip/patches-5.4/012-resync-rk3566-device-tree-with-mainline.patch new file mode 100644 index 00000000..b16b522c --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/012-resync-rk3566-device-tree-with-mainline.patch @@ -0,0 +1,28 @@ +--- a/include/dt-bindings/clock/rk3368-cru.h ++++ b/include/dt-bindings/clock/rk3368-cru.h +@@ -157,6 +157,8 @@ + #define PCLK_VIP 367 + #define PCLK_WDT 368 + #define PCLK_EFUSE256 369 ++#define PCLK_DPHYRX 370 ++#define PCLK_DPHYTX0 371 + + /* hclk gates */ + #define HCLK_SFC 448 +--- /dev/null ++++ b/include/dt-bindings/soc/rockchip,vop2.h +@@ -0,0 +1,14 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ ++ ++#ifndef __DT_BINDINGS_ROCKCHIP_VOP2_H ++#define __DT_BINDINGS_ROCKCHIP_VOP2_H ++ ++#define RK3568_VOP2_EP_RGB 0 ++#define RK3568_VOP2_EP_HDMI 1 ++#define RK3568_VOP2_EP_EDP 2 ++#define RK3568_VOP2_EP_MIPI0 3 ++#define RK3568_VOP2_EP_LVDS0 4 ++#define RK3568_VOP2_EP_MIPI1 5 ++#define RK3568_VOP2_EP_LVDS1 6 ++ ++#endif /* __DT_BINDINGS_ROCKCHIP_VOP2_H */ diff --git a/root/target/linux/rockchip/patches-5.4/015-v5.16-arm64-dts-rockchip-add-rk3566-dtsi.patch b/root/target/linux/rockchip/patches-5.4/015-v5.16-arm64-dts-rockchip-add-rk3566-dtsi.patch new file mode 100644 index 00000000..6fe9ccd8 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/015-v5.16-arm64-dts-rockchip-add-rk3566-dtsi.patch @@ -0,0 +1,39 @@ +From 016c0e8a7a6e7820fb54d8ff8a4a2928a3016421 Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Sat, 10 Jul 2021 11:10:33 -0400 +Subject: [PATCH] arm64: dts: rockchip: add rk3566 dtsi + +Add the rk3566 dtsi which includes the soc specific changes for this +chip. + +Signed-off-by: Peter Geis +Link: https://lore.kernel.org/r/20210710151034.32857-4-pgwipeout@gmail.com +Signed-off-by: Heiko Stuebner +--- + arch/arm64/boot/dts/rockchip/rk3566.dtsi | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + create mode 100644 arch/arm64/boot/dts/rockchip/rk3566.dtsi + +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3566.dtsi +@@ -0,0 +1,20 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++#include "rk356x.dtsi" ++ ++/ { ++ compatible = "rockchip,rk3566"; ++}; ++ ++&power { ++ power-domain@RK3568_PD_PIPE { ++ reg = ; ++ clocks = <&cru PCLK_PIPE>; ++ pm_qos = <&qos_pcie2x1>, ++ <&qos_sata1>, ++ <&qos_sata2>, ++ <&qos_usb3_0>, ++ <&qos_usb3_1>; ++ #power-domain-cells = <0>; ++ }; ++}; diff --git a/root/target/linux/rockchip/patches-5.4/020-v5.16-arm64-dts-rockchip-add-gmac0-node-to-rk3568.patch b/root/target/linux/rockchip/patches-5.4/020-v5.16-arm64-dts-rockchip-add-gmac0-node-to-rk3568.patch new file mode 100644 index 00000000..99b81f75 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/020-v5.16-arm64-dts-rockchip-add-gmac0-node-to-rk3568.patch @@ -0,0 +1,73 @@ +From b8d41e5053cd823817344cc5e7a2bfda508effff Mon Sep 17 00:00:00 2001 +From: Michael Riesch +Date: Thu, 29 Jul 2021 11:39:12 +0200 +Subject: [PATCH] arm64: dts: rockchip: add gmac0 node to rk3568 + +While both RK3566 and RK3568 feature the gmac1 node, the gmac0 +node is exclusive to the RK3568. + +Signed-off-by: Michael Riesch +Link: https://lore.kernel.org/r/20210729093913.8917-2-michael.riesch@wolfvision.net +Signed-off-by: Heiko Stuebner +--- + arch/arm64/boot/dts/rockchip/rk3568.dtsi | 49 ++++++++++++++++++++++++ + 1 file changed, 49 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3568.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3568.dtsi +@@ -22,6 +22,55 @@ + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe190200 0x0 0x20>; + }; ++ ++ gmac0: ethernet@fe2a0000 { ++ compatible = "rockchip,rk3568-gmac", "snps,dwmac-4.20a"; ++ reg = <0x0 0xfe2a0000 0x0 0x10000>; ++ interrupts = , ++ ; ++ interrupt-names = "macirq", "eth_wake_irq"; ++ clocks = <&cru SCLK_GMAC0>, <&cru SCLK_GMAC0_RX_TX>, ++ <&cru SCLK_GMAC0_RX_TX>, <&cru CLK_MAC0_REFOUT>, ++ <&cru ACLK_GMAC0>, <&cru PCLK_GMAC0>, ++ <&cru SCLK_GMAC0_RX_TX>, <&cru CLK_GMAC0_PTP_REF>, ++ <&cru PCLK_XPCS>; ++ clock-names = "stmmaceth", "mac_clk_rx", ++ "mac_clk_tx", "clk_mac_refout", ++ "aclk_mac", "pclk_mac", ++ "clk_mac_speed", "ptp_ref", ++ "pclk_xpcs"; ++ resets = <&cru SRST_A_GMAC0>; ++ reset-names = "stmmaceth"; ++ rockchip,grf = <&grf>; ++ snps,axi-config = <&gmac0_stmmac_axi_setup>; ++ snps,mixed-burst; ++ snps,mtl-rx-config = <&gmac0_mtl_rx_setup>; ++ snps,mtl-tx-config = <&gmac0_mtl_tx_setup>; ++ snps,tso; ++ status = "disabled"; ++ ++ mdio0: mdio { ++ compatible = "snps,dwmac-mdio"; ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ }; ++ ++ gmac0_stmmac_axi_setup: stmmac-axi-config { ++ snps,blen = <0 0 0 0 16 8 4>; ++ snps,rd_osr_lmt = <8>; ++ snps,wr_osr_lmt = <4>; ++ }; ++ ++ gmac0_mtl_rx_setup: rx-queues-config { ++ snps,rx-queues-to-use = <1>; ++ queue0 {}; ++ }; ++ ++ gmac0_mtl_tx_setup: tx-queues-config { ++ snps,tx-queues-to-use = <1>; ++ queue0 {}; ++ }; ++ }; + }; + + &cpu0_opp_table { diff --git a/root/target/linux/rockchip/patches-5.4/031-v5.17-arm64-dts-rockchip-drop-pclk_xpcs-from-gmac0-on.patch b/root/target/linux/rockchip/patches-5.4/031-v5.17-arm64-dts-rockchip-drop-pclk_xpcs-from-gmac0-on.patch new file mode 100644 index 00000000..fccec455 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/031-v5.17-arm64-dts-rockchip-drop-pclk_xpcs-from-gmac0-on.patch @@ -0,0 +1,54 @@ +From 85a8bccfa945680dc561f06b65ea01341d2033fc Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sun, 23 Jan 2022 14:35:10 +0100 +Subject: [PATCH] arm64: dts: rockchip: drop pclk_xpcs from gmac0 on rk3568 + +pclk_xpcs is not supported by mainline driver and breaks dtbs_check + +following warnings occour, and many more + +rk3568-evb1-v10.dt.yaml: ethernet@fe2a0000: clocks: + [[15, 386], [15, 389], [15, 389], [15, 184], [15, 180], [15, 181], + [15, 389], [15, 185], [15, 172]] is too long + From schema: Documentation/devicetree/bindings/net/snps,dwmac.yaml +rk3568-evb1-v10.dt.yaml: ethernet@fe2a0000: clock-names: + ['stmmaceth', 'mac_clk_rx', 'mac_clk_tx', 'clk_mac_refout', 'aclk_mac', + 'pclk_mac', 'clk_mac_speed', 'ptp_ref', 'pclk_xpcs'] is too long + From schema: Documentation/devicetree/bindings/net/snps,dwmac.yaml + +after removing it, the clock and other warnings are gone. + +pclk_xpcs on gmac is used to support QSGMII, but this requires a driver +supporting it. +Once xpcs support is introduced, the clock can be added to the +documentation and both controllers. + +Fixes: b8d41e5053cd ("arm64: dts: rockchip: add gmac0 node to rk3568") +Co-developed-by: Peter Geis +Signed-off-by: Peter Geis +Signed-off-by: Frank Wunderlich +Acked-by: Michael Riesch +Link: https://lore.kernel.org/r/20220123133510.135651-1-linux@fw-web.de +Signed-off-by: Heiko Stuebner +--- + arch/arm64/boot/dts/rockchip/rk3568.dtsi | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +--- a/arch/arm64/boot/dts/rockchip/rk3568.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3568.dtsi +@@ -32,13 +32,11 @@ + clocks = <&cru SCLK_GMAC0>, <&cru SCLK_GMAC0_RX_TX>, + <&cru SCLK_GMAC0_RX_TX>, <&cru CLK_MAC0_REFOUT>, + <&cru ACLK_GMAC0>, <&cru PCLK_GMAC0>, +- <&cru SCLK_GMAC0_RX_TX>, <&cru CLK_GMAC0_PTP_REF>, +- <&cru PCLK_XPCS>; ++ <&cru SCLK_GMAC0_RX_TX>, <&cru CLK_GMAC0_PTP_REF>; + clock-names = "stmmaceth", "mac_clk_rx", + "mac_clk_tx", "clk_mac_refout", + "aclk_mac", "pclk_mac", +- "clk_mac_speed", "ptp_ref", +- "pclk_xpcs"; ++ "clk_mac_speed", "ptp_ref"; + resets = <&cru SRST_A_GMAC0>; + reset-names = "stmmaceth"; + rockchip,grf = <&grf>; diff --git a/root/target/linux/rockchip/patches-5.4/032-v5.17-phy-rockchip-inno-usb2-support-address-cells.patch b/root/target/linux/rockchip/patches-5.4/032-v5.17-phy-rockchip-inno-usb2-support-address-cells.patch new file mode 100644 index 00000000..8ee043d5 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/032-v5.17-phy-rockchip-inno-usb2-support-address-cells.patch @@ -0,0 +1,45 @@ +From 9c19c531dc98d7ba49b44802a607042e763ebe21 Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Wed, 15 Dec 2021 16:02:47 -0500 +Subject: [PATCH] phy: phy-rockchip-inno-usb2: support #address_cells = 2 + +New Rockchip devices have the usb phy nodes as standalone devices. +These nodes have register nodes with #address_cells = 2, but only use 32 +bit addresses. + +Adjust the driver to check if the returned address is "0", and adjust +the index in that case. + +Signed-off-by: Peter Geis +Tested-by: Michael Riesch +Link: https://lore.kernel.org/r/20211215210252.120923-4-pgwipeout@gmail.com +Signed-off-by: Vinod Koul +--- + drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +@@ -1098,12 +1098,21 @@ static int rockchip_usb2phy_probe(struct + rphy->usbgrf = NULL; + } + +- if (of_property_read_u32(np, "reg", ®)) { ++ if (of_property_read_u32_index(np, "reg", 0, ®)) { + dev_err(dev, "the reg property is not assigned in %pOFn node\n", + np); + return -EINVAL; + } + ++ /* support address_cells=2 */ ++ if (reg == 0) { ++ if (of_property_read_u32_index(np, "reg", 1, ®)) { ++ dev_err(dev, "the reg property is not assigned in %pOFn node\n", ++ np); ++ return -EINVAL; ++ } ++ } ++ + rphy->dev = dev; + phy_cfgs = match->data; + rphy->chg_state = USB_CHG_STATE_UNDEFINED; diff --git a/root/target/linux/rockchip/patches-5.4/033-v5.17-phy-rockchip-inno-usb2-support-standalone-phy-nodes.patch b/root/target/linux/rockchip/patches-5.4/033-v5.17-phy-rockchip-inno-usb2-support-standalone-phy-nodes.patch new file mode 100644 index 00000000..40d1fa8f --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/033-v5.17-phy-rockchip-inno-usb2-support-standalone-phy-nodes.patch @@ -0,0 +1,44 @@ +From e6915e1acca57bc4fdb61dccd5cc2e49f72ef743 Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Wed, 15 Dec 2021 16:02:48 -0500 +Subject: [PATCH] phy: phy-rockchip-inno-usb2: support standalone phy nodes + +New Rockchip devices have the usb2 phy devices as standalone nodes +instead of children of the grf node. +Allow the driver to find the grf node from a phandle. + +Signed-off-by: Peter Geis +Tested-by: Michael Riesch +Link: https://lore.kernel.org/r/20211215210252.120923-5-pgwipeout@gmail.com +Signed-off-by: Vinod Koul +--- + drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +@@ -1081,12 +1081,19 @@ static int rockchip_usb2phy_probe(struct + return -EINVAL; + } + +- if (!dev->parent || !dev->parent->of_node) +- return -EINVAL; ++ if (!dev->parent || !dev->parent->of_node) { ++ rphy->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,usbgrf"); ++ if (IS_ERR(rphy->grf)) { ++ dev_err(dev, "failed to locate usbgrf\n"); ++ return PTR_ERR(rphy->grf); ++ } ++ } + +- rphy->grf = syscon_node_to_regmap(dev->parent->of_node); +- if (IS_ERR(rphy->grf)) +- return PTR_ERR(rphy->grf); ++ else { ++ rphy->grf = syscon_node_to_regmap(dev->parent->of_node); ++ if (IS_ERR(rphy->grf)) ++ return PTR_ERR(rphy->grf); ++ } + + if (of_device_is_compatible(np, "rockchip,rv1108-usb2phy")) { + rphy->usbgrf = diff --git a/root/target/linux/rockchip/patches-5.4/034-v5.17-phy-rockchip-inno-usb2-support-muxed-interrupts.patch b/root/target/linux/rockchip/patches-5.4/034-v5.17-phy-rockchip-inno-usb2-support-muxed-interrupts.patch new file mode 100644 index 00000000..57853705 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/034-v5.17-phy-rockchip-inno-usb2-support-muxed-interrupts.patch @@ -0,0 +1,237 @@ +From ed2b5a8e6b98d042b323afbe177a5dc618921b31 Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Wed, 15 Dec 2021 16:02:49 -0500 +Subject: [PATCH] phy: phy-rockchip-inno-usb2: support muxed interrupts + +The rk3568 usb2phy has a single muxed interrupt that handles all +interrupts. +Allow the driver to plug in only a single interrupt as necessary. + +Signed-off-by: Peter Geis +Tested-by: Michael Riesch +Link: https://lore.kernel.org/r/20211215210252.120923-6-pgwipeout@gmail.com +Signed-off-by: Vinod Koul +--- + drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 168 +++++++++++++----- + 1 file changed, 119 insertions(+), 49 deletions(-) + +--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +@@ -204,6 +204,7 @@ struct rockchip_usb2phy_port { + * @dcd_retries: The retry count used to track Data contact + * detection process. + * @edev: extcon device for notification registration ++ * @irq: muxed interrupt for single irq configuration + * @phy_cfg: phy register configuration, assigned by driver data. + * @ports: phy port instance. + */ +@@ -218,6 +219,7 @@ struct rockchip_usb2phy { + enum power_supply_type chg_type; + u8 dcd_retries; + struct extcon_dev *edev; ++ int irq; + const struct rockchip_usb2phy_cfg *phy_cfg; + struct rockchip_usb2phy_port ports[USB2PHY_NUM_PORTS]; + }; +@@ -934,6 +936,102 @@ static irqreturn_t rockchip_usb2phy_otg_ + return IRQ_NONE; + } + ++static irqreturn_t rockchip_usb2phy_irq(int irq, void *data) ++{ ++ struct rockchip_usb2phy *rphy = data; ++ struct rockchip_usb2phy_port *rport; ++ irqreturn_t ret = IRQ_NONE; ++ unsigned int index; ++ ++ for (index = 0; index < rphy->phy_cfg->num_ports; index++) { ++ rport = &rphy->ports[index]; ++ if (!rport->phy) ++ continue; ++ ++ /* Handle linestate irq for both otg port and host port */ ++ ret = rockchip_usb2phy_linestate_irq(irq, rport); ++ } ++ ++ return ret; ++} ++ ++static int rockchip_usb2phy_port_irq_init(struct rockchip_usb2phy *rphy, ++ struct rockchip_usb2phy_port *rport, ++ struct device_node *child_np) ++{ ++ int ret; ++ ++ /* ++ * If the usb2 phy used combined irq for otg and host port, ++ * don't need to init otg and host port irq separately. ++ */ ++ if (rphy->irq > 0) ++ return 0; ++ ++ switch (rport->port_id) { ++ case USB2PHY_PORT_HOST: ++ rport->ls_irq = of_irq_get_byname(child_np, "linestate"); ++ if (rport->ls_irq < 0) { ++ dev_err(rphy->dev, "no linestate irq provided\n"); ++ return rport->ls_irq; ++ } ++ ++ ret = devm_request_threaded_irq(rphy->dev, rport->ls_irq, NULL, ++ rockchip_usb2phy_linestate_irq, ++ IRQF_ONESHOT, ++ "rockchip_usb2phy", rport); ++ if (ret) { ++ dev_err(rphy->dev, "failed to request linestate irq handle\n"); ++ return ret; ++ } ++ break; ++ case USB2PHY_PORT_OTG: ++ /* ++ * Some SoCs use one interrupt with otg-id/otg-bvalid/linestate ++ * interrupts muxed together, so probe the otg-mux interrupt first, ++ * if not found, then look for the regular interrupts one by one. ++ */ ++ rport->otg_mux_irq = of_irq_get_byname(child_np, "otg-mux"); ++ if (rport->otg_mux_irq > 0) { ++ ret = devm_request_threaded_irq(rphy->dev, rport->otg_mux_irq, ++ NULL, ++ rockchip_usb2phy_otg_mux_irq, ++ IRQF_ONESHOT, ++ "rockchip_usb2phy_otg", ++ rport); ++ if (ret) { ++ dev_err(rphy->dev, ++ "failed to request otg-mux irq handle\n"); ++ return ret; ++ } ++ } else { ++ rport->bvalid_irq = of_irq_get_byname(child_np, "otg-bvalid"); ++ if (rport->bvalid_irq < 0) { ++ dev_err(rphy->dev, "no vbus valid irq provided\n"); ++ ret = rport->bvalid_irq; ++ return ret; ++ } ++ ++ ret = devm_request_threaded_irq(rphy->dev, rport->bvalid_irq, ++ NULL, ++ rockchip_usb2phy_bvalid_irq, ++ IRQF_ONESHOT, ++ "rockchip_usb2phy_bvalid", ++ rport); ++ if (ret) { ++ dev_err(rphy->dev, ++ "failed to request otg-bvalid irq handle\n"); ++ return ret; ++ } ++ } ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ + static int rockchip_usb2phy_host_port_init(struct rockchip_usb2phy *rphy, + struct rockchip_usb2phy_port *rport, + struct device_node *child_np) +@@ -947,18 +1045,9 @@ static int rockchip_usb2phy_host_port_in + mutex_init(&rport->mutex); + INIT_DELAYED_WORK(&rport->sm_work, rockchip_usb2phy_sm_work); + +- rport->ls_irq = of_irq_get_byname(child_np, "linestate"); +- if (rport->ls_irq < 0) { +- dev_err(rphy->dev, "no linestate irq provided\n"); +- return rport->ls_irq; +- } +- +- ret = devm_request_threaded_irq(rphy->dev, rport->ls_irq, NULL, +- rockchip_usb2phy_linestate_irq, +- IRQF_ONESHOT, +- "rockchip_usb2phy", rport); ++ ret = rockchip_usb2phy_port_irq_init(rphy, rport, child_np); + if (ret) { +- dev_err(rphy->dev, "failed to request linestate irq handle\n"); ++ dev_err(rphy->dev, "failed to setup host irq\n"); + return ret; + } + +@@ -1007,44 +1096,10 @@ static int rockchip_usb2phy_otg_port_ini + INIT_DELAYED_WORK(&rport->chg_work, rockchip_chg_detect_work); + INIT_DELAYED_WORK(&rport->otg_sm_work, rockchip_usb2phy_otg_sm_work); + +- /* +- * Some SoCs use one interrupt with otg-id/otg-bvalid/linestate +- * interrupts muxed together, so probe the otg-mux interrupt first, +- * if not found, then look for the regular interrupts one by one. +- */ +- rport->otg_mux_irq = of_irq_get_byname(child_np, "otg-mux"); +- if (rport->otg_mux_irq > 0) { +- ret = devm_request_threaded_irq(rphy->dev, rport->otg_mux_irq, +- NULL, +- rockchip_usb2phy_otg_mux_irq, +- IRQF_ONESHOT, +- "rockchip_usb2phy_otg", +- rport); +- if (ret) { +- dev_err(rphy->dev, +- "failed to request otg-mux irq handle\n"); +- goto out; +- } +- } else { +- rport->bvalid_irq = of_irq_get_byname(child_np, "otg-bvalid"); +- if (rport->bvalid_irq < 0) { +- dev_err(rphy->dev, "no vbus valid irq provided\n"); +- ret = rport->bvalid_irq; +- goto out; +- } +- +- ret = devm_request_threaded_irq(rphy->dev, rport->bvalid_irq, +- NULL, +- rockchip_usb2phy_bvalid_irq, +- IRQF_ONESHOT, +- "rockchip_usb2phy_bvalid", +- rport); +- if (ret) { +- dev_err(rphy->dev, +- "failed to request otg-bvalid irq handle\n"); +- goto out; +- } +- } ++ ret = rockchip_usb2phy_port_irq_init(rphy, rport, child_np); ++ if (ret) { ++ dev_err(rphy->dev, "failed to init irq for host port\n"); ++ goto out; + + if (!IS_ERR(rphy->edev)) { + rport->event_nb.notifier_call = rockchip_otg_event; +@@ -1124,6 +1179,7 @@ static int rockchip_usb2phy_probe(struct + phy_cfgs = match->data; + rphy->chg_state = USB_CHG_STATE_UNDEFINED; + rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN; ++ rphy->irq = platform_get_irq_optional(pdev, 0); + platform_set_drvdata(pdev, rphy); + + ret = rockchip_usb2phy_extcon_register(rphy); +@@ -1203,6 +1259,20 @@ next_child: + } + + provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); ++ ++ if (rphy->irq > 0) { ++ ret = devm_request_threaded_irq(rphy->dev, rphy->irq, NULL, ++ rockchip_usb2phy_irq, ++ IRQF_ONESHOT, ++ "rockchip_usb2phy", ++ rphy); ++ if (ret) { ++ dev_err(rphy->dev, ++ "failed to request usb2phy irq handle\n"); ++ goto put_child; ++ } ++ } ++ + return PTR_ERR_OR_ZERO(provider); + + put_child: diff --git a/root/target/linux/rockchip/patches-5.4/035-v5.17-phy-rockchip-inno-usb2-add-rk3568-support.patch b/root/target/linux/rockchip/patches-5.4/035-v5.17-phy-rockchip-inno-usb2-add-rk3568-support.patch new file mode 100644 index 00000000..8de87e13 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/035-v5.17-phy-rockchip-inno-usb2-add-rk3568-support.patch @@ -0,0 +1,104 @@ +From 42b559727a45d79c811f493515eb9b7e56016421 Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Wed, 15 Dec 2021 16:02:50 -0500 +Subject: [PATCH] phy: phy-rockchip-inno-usb2: add rk3568 support + +The rk3568 usb2phy is a standalone device with a single muxed interrupt. +Add support for the registers to the usb2phy driver. + +Signed-off-by: Peter Geis +Tested-by: Michael Riesch +Link: https://lore.kernel.org/r/20211215210252.120923-7-pgwipeout@gmail.com +Signed-off-by: Vinod Koul +--- + drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 65 +++++++++++++++++++ + 1 file changed, 65 insertions(+) + +--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +@@ -1100,6 +1100,7 @@ static int rockchip_usb2phy_otg_port_ini + if (ret) { + dev_err(rphy->dev, "failed to init irq for host port\n"); + goto out; ++ } + + if (!IS_ERR(rphy->edev)) { + rport->event_nb.notifier_call = rockchip_otg_event; +@@ -1511,6 +1512,69 @@ static const struct rockchip_usb2phy_cfg + { /* sentinel */ } + }; + ++static const struct rockchip_usb2phy_cfg rk3568_phy_cfgs[] = { ++ { ++ .reg = 0xfe8a0000, ++ .num_ports = 2, ++ .clkout_ctl = { 0x0008, 4, 4, 1, 0 }, ++ .port_cfgs = { ++ [USB2PHY_PORT_OTG] = { ++ .phy_sus = { 0x0000, 8, 0, 0, 0x1d1 }, ++ .bvalid_det_en = { 0x0080, 2, 2, 0, 1 }, ++ .bvalid_det_st = { 0x0084, 2, 2, 0, 1 }, ++ .bvalid_det_clr = { 0x0088, 2, 2, 0, 1 }, ++ .utmi_avalid = { 0x00c0, 10, 10, 0, 1 }, ++ .utmi_bvalid = { 0x00c0, 9, 9, 0, 1 }, ++ }, ++ [USB2PHY_PORT_HOST] = { ++ /* Select suspend control from controller */ ++ .phy_sus = { 0x0004, 8, 0, 0x1d2, 0x1d2 }, ++ .ls_det_en = { 0x0080, 1, 1, 0, 1 }, ++ .ls_det_st = { 0x0084, 1, 1, 0, 1 }, ++ .ls_det_clr = { 0x0088, 1, 1, 0, 1 }, ++ .utmi_ls = { 0x00c0, 17, 16, 0, 1 }, ++ .utmi_hstdet = { 0x00c0, 19, 19, 0, 1 } ++ } ++ }, ++ .chg_det = { ++ .opmode = { 0x0000, 3, 0, 5, 1 }, ++ .cp_det = { 0x00c0, 24, 24, 0, 1 }, ++ .dcp_det = { 0x00c0, 23, 23, 0, 1 }, ++ .dp_det = { 0x00c0, 25, 25, 0, 1 }, ++ .idm_sink_en = { 0x0008, 8, 8, 0, 1 }, ++ .idp_sink_en = { 0x0008, 7, 7, 0, 1 }, ++ .idp_src_en = { 0x0008, 9, 9, 0, 1 }, ++ .rdm_pdwn_en = { 0x0008, 10, 10, 0, 1 }, ++ .vdm_src_en = { 0x0008, 12, 12, 0, 1 }, ++ .vdp_src_en = { 0x0008, 11, 11, 0, 1 }, ++ }, ++ }, ++ { ++ .reg = 0xfe8b0000, ++ .num_ports = 2, ++ .clkout_ctl = { 0x0008, 4, 4, 1, 0 }, ++ .port_cfgs = { ++ [USB2PHY_PORT_OTG] = { ++ .phy_sus = { 0x0000, 8, 0, 0x1d2, 0x1d1 }, ++ .ls_det_en = { 0x0080, 0, 0, 0, 1 }, ++ .ls_det_st = { 0x0084, 0, 0, 0, 1 }, ++ .ls_det_clr = { 0x0088, 0, 0, 0, 1 }, ++ .utmi_ls = { 0x00c0, 5, 4, 0, 1 }, ++ .utmi_hstdet = { 0x00c0, 7, 7, 0, 1 } ++ }, ++ [USB2PHY_PORT_HOST] = { ++ .phy_sus = { 0x0004, 8, 0, 0x1d2, 0x1d1 }, ++ .ls_det_en = { 0x0080, 1, 1, 0, 1 }, ++ .ls_det_st = { 0x0084, 1, 1, 0, 1 }, ++ .ls_det_clr = { 0x0088, 1, 1, 0, 1 }, ++ .utmi_ls = { 0x00c0, 17, 16, 0, 1 }, ++ .utmi_hstdet = { 0x00c0, 19, 19, 0, 1 } ++ } ++ }, ++ }, ++ { /* sentinel */ } ++}; ++ + static const struct rockchip_usb2phy_cfg rv1108_phy_cfgs[] = { + { + .reg = 0x100, +@@ -1560,6 +1624,7 @@ static const struct of_device_id rockchi + { .compatible = "rockchip,rk3328-usb2phy", .data = &rk3328_phy_cfgs }, + { .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs }, + { .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs }, ++ { .compatible = "rockchip,rk3568-usb2phy", .data = &rk3568_phy_cfgs }, + { .compatible = "rockchip,rv1108-usb2phy", .data = &rv1108_phy_cfgs }, + {} + }; diff --git a/root/target/linux/rockchip/patches-5.4/037-v5.18-phy-rockchip-add-naneng-combo-phy-for-RK3568.patch b/root/target/linux/rockchip/patches-5.4/037-v5.18-phy-rockchip-add-naneng-combo-phy-for-RK3568.patch new file mode 100644 index 00000000..e8fbf7f2 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/037-v5.18-phy-rockchip-add-naneng-combo-phy-for-RK3568.patch @@ -0,0 +1,633 @@ +From 7160820d742a16313f7802e33c2956c19548e488 Mon Sep 17 00:00:00 2001 +From: Yifeng Zhao +Date: Tue, 8 Feb 2022 17:13:25 +0800 +Subject: [PATCH] phy: rockchip: add naneng combo phy for RK3568 + +This patch implements a combo phy driver for Rockchip SoCs +with NaNeng IP block. This phy can be used as pcie-phy, usb3-phy, +sata-phy or sgmii-phy. + +Signed-off-by: Yifeng Zhao +Signed-off-by: Johan Jonker +Tested-by: Peter Geis +Tested-by: Frank Wunderlich +Link: https://lore.kernel.org/r/20220208091326.12495-4-yifeng.zhao@rock-chips.com +Signed-off-by: Vinod Koul +--- + drivers/phy/rockchip/Kconfig | 8 + + drivers/phy/rockchip/Makefile | 1 + + .../rockchip/phy-rockchip-naneng-combphy.c | 581 ++++++++++++++++++ + 3 files changed, 590 insertions(+) + create mode 100644 drivers/phy/rockchip/phy-rockchip-naneng-combphy.c + +--- a/drivers/phy/rockchip/Kconfig ++++ b/drivers/phy/rockchip/Kconfig +@@ -66,6 +66,14 @@ config PHY_ROCKCHIP_INNO_DSIDPHY + Enable this to support the Rockchip MIPI/LVDS/TTL PHY with + Innosilicon IP block. + ++config PHY_ROCKCHIP_NANENG_COMBO_PHY ++ tristate "Rockchip NANENG COMBO PHY Driver" ++ depends on ARCH_ROCKCHIP && OF ++ select GENERIC_PHY ++ help ++ Enable this to support the Rockchip PCIe/USB3.0/SATA/QSGMII ++ combo PHY with NaNeng IP block. ++ + config PHY_ROCKCHIP_PCIE + tristate "Rockchip PCIe PHY Driver" + depends on (ARCH_ROCKCHIP && OF) || COMPILE_TEST +--- a/drivers/phy/rockchip/Makefile ++++ b/drivers/phy/rockchip/Makefile +@@ -6,6 +6,7 @@ obj-$(CONFIG_PHY_ROCKCHIP_INNO_CSIDPHY) + obj-$(CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY) += phy-rockchip-inno-dsidphy.o + obj-$(CONFIG_PHY_ROCKCHIP_INNO_HDMI) += phy-rockchip-inno-hdmi.o + obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o ++obj-$(CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY) += phy-rockchip-naneng-combphy.o + obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o + obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o + obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o +--- /dev/null ++++ b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c +@@ -0,0 +1,581 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Rockchip PIPE USB3.0 PCIE SATA Combo Phy driver ++ * ++ * Copyright (C) 2021 Rockchip Electronics Co., Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define BIT_WRITEABLE_SHIFT 16 ++#define REF_CLOCK_24MHz (24 * HZ_PER_MHZ) ++#define REF_CLOCK_25MHz (25 * HZ_PER_MHZ) ++#define REF_CLOCK_100MHz (100 * HZ_PER_MHZ) ++ ++/* COMBO PHY REG */ ++#define PHYREG6 0x14 ++#define PHYREG6_PLL_DIV_MASK GENMASK(7, 6) ++#define PHYREG6_PLL_DIV_SHIFT 6 ++#define PHYREG6_PLL_DIV_2 1 ++ ++#define PHYREG7 0x18 ++#define PHYREG7_TX_RTERM_MASK GENMASK(7, 4) ++#define PHYREG7_TX_RTERM_SHIFT 4 ++#define PHYREG7_TX_RTERM_50OHM 8 ++#define PHYREG7_RX_RTERM_MASK GENMASK(3, 0) ++#define PHYREG7_RX_RTERM_SHIFT 0 ++#define PHYREG7_RX_RTERM_44OHM 15 ++ ++#define PHYREG8 0x1C ++#define PHYREG8_SSC_EN BIT(4) ++ ++#define PHYREG11 0x28 ++#define PHYREG11_SU_TRIM_0_7 0xF0 ++ ++#define PHYREG12 0x2C ++#define PHYREG12_PLL_LPF_ADJ_VALUE 4 ++ ++#define PHYREG13 0x30 ++#define PHYREG13_RESISTER_MASK GENMASK(5, 4) ++#define PHYREG13_RESISTER_SHIFT 0x4 ++#define PHYREG13_RESISTER_HIGH_Z 3 ++#define PHYREG13_CKRCV_AMP0 BIT(7) ++ ++#define PHYREG14 0x34 ++#define PHYREG14_CKRCV_AMP1 BIT(0) ++ ++#define PHYREG15 0x38 ++#define PHYREG15_CTLE_EN BIT(0) ++#define PHYREG15_SSC_CNT_MASK GENMASK(7, 6) ++#define PHYREG15_SSC_CNT_SHIFT 6 ++#define PHYREG15_SSC_CNT_VALUE 1 ++ ++#define PHYREG16 0x3C ++#define PHYREG16_SSC_CNT_VALUE 0x5f ++ ++#define PHYREG18 0x44 ++#define PHYREG18_PLL_LOOP 0x32 ++ ++#define PHYREG32 0x7C ++#define PHYREG32_SSC_MASK GENMASK(7, 4) ++#define PHYREG32_SSC_DIR_SHIFT 4 ++#define PHYREG32_SSC_UPWARD 0 ++#define PHYREG32_SSC_DOWNWARD 1 ++#define PHYREG32_SSC_OFFSET_SHIFT 6 ++#define PHYREG32_SSC_OFFSET_500PPM 1 ++ ++#define PHYREG33 0x80 ++#define PHYREG33_PLL_KVCO_MASK GENMASK(4, 2) ++#define PHYREG33_PLL_KVCO_SHIFT 2 ++#define PHYREG33_PLL_KVCO_VALUE 2 ++ ++struct rockchip_combphy_priv; ++ ++struct combphy_reg { ++ u16 offset; ++ u16 bitend; ++ u16 bitstart; ++ u16 disable; ++ u16 enable; ++}; ++ ++struct rockchip_combphy_grfcfg { ++ struct combphy_reg pcie_mode_set; ++ struct combphy_reg usb_mode_set; ++ struct combphy_reg sgmii_mode_set; ++ struct combphy_reg qsgmii_mode_set; ++ struct combphy_reg pipe_rxterm_set; ++ struct combphy_reg pipe_txelec_set; ++ struct combphy_reg pipe_txcomp_set; ++ struct combphy_reg pipe_clk_25m; ++ struct combphy_reg pipe_clk_100m; ++ struct combphy_reg pipe_phymode_sel; ++ struct combphy_reg pipe_rate_sel; ++ struct combphy_reg pipe_rxterm_sel; ++ struct combphy_reg pipe_txelec_sel; ++ struct combphy_reg pipe_txcomp_sel; ++ struct combphy_reg pipe_clk_ext; ++ struct combphy_reg pipe_sel_usb; ++ struct combphy_reg pipe_sel_qsgmii; ++ struct combphy_reg pipe_phy_status; ++ struct combphy_reg con0_for_pcie; ++ struct combphy_reg con1_for_pcie; ++ struct combphy_reg con2_for_pcie; ++ struct combphy_reg con3_for_pcie; ++ struct combphy_reg con0_for_sata; ++ struct combphy_reg con1_for_sata; ++ struct combphy_reg con2_for_sata; ++ struct combphy_reg con3_for_sata; ++ struct combphy_reg pipe_con0_for_sata; ++ struct combphy_reg pipe_xpcs_phy_ready; ++}; ++ ++struct rockchip_combphy_cfg { ++ const struct rockchip_combphy_grfcfg *grfcfg; ++ int (*combphy_cfg)(struct rockchip_combphy_priv *priv); ++}; ++ ++struct rockchip_combphy_priv { ++ u8 type; ++ void __iomem *mmio; ++ int num_clks; ++ struct clk_bulk_data *clks; ++ struct device *dev; ++ struct regmap *pipe_grf; ++ struct regmap *phy_grf; ++ struct phy *phy; ++ struct reset_control *phy_rst; ++ const struct rockchip_combphy_cfg *cfg; ++ bool enable_ssc; ++ bool ext_refclk; ++ struct clk *refclk; ++}; ++ ++static void rockchip_combphy_updatel(struct rockchip_combphy_priv *priv, ++ int mask, int val, int reg) ++{ ++ unsigned int temp; ++ ++ temp = readl(priv->mmio + reg); ++ temp = (temp & ~(mask)) | val; ++ writel(temp, priv->mmio + reg); ++} ++ ++static int rockchip_combphy_param_write(struct regmap *base, ++ const struct combphy_reg *reg, bool en) ++{ ++ u32 val, mask, tmp; ++ ++ tmp = en ? reg->enable : reg->disable; ++ mask = GENMASK(reg->bitend, reg->bitstart); ++ val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT); ++ ++ return regmap_write(base, reg->offset, val); ++} ++ ++static u32 rockchip_combphy_is_ready(struct rockchip_combphy_priv *priv) ++{ ++ const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; ++ u32 mask, val; ++ ++ mask = GENMASK(cfg->pipe_phy_status.bitend, ++ cfg->pipe_phy_status.bitstart); ++ ++ regmap_read(priv->phy_grf, cfg->pipe_phy_status.offset, &val); ++ val = (val & mask) >> cfg->pipe_phy_status.bitstart; ++ ++ return val; ++} ++ ++static int rockchip_combphy_init(struct phy *phy) ++{ ++ struct rockchip_combphy_priv *priv = phy_get_drvdata(phy); ++ const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; ++ u32 val; ++ int ret; ++ ++ ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks); ++ if (ret) { ++ dev_err(priv->dev, "failed to enable clks\n"); ++ return ret; ++ } ++ ++ switch (priv->type) { ++ case PHY_TYPE_PCIE: ++ case PHY_TYPE_USB3: ++ case PHY_TYPE_SATA: ++ case PHY_TYPE_SGMII: ++ case PHY_TYPE_QSGMII: ++ if (priv->cfg->combphy_cfg) ++ ret = priv->cfg->combphy_cfg(priv); ++ break; ++ default: ++ dev_err(priv->dev, "incompatible PHY type\n"); ++ ret = -EINVAL; ++ break; ++ } ++ ++ if (ret) { ++ dev_err(priv->dev, "failed to init phy for phy type %x\n", priv->type); ++ goto err_clk; ++ } ++ ++ ret = reset_control_deassert(priv->phy_rst); ++ if (ret) ++ goto err_clk; ++ ++ if (priv->type == PHY_TYPE_USB3) { ++ ret = readx_poll_timeout_atomic(rockchip_combphy_is_ready, ++ priv, val, ++ val == cfg->pipe_phy_status.enable, ++ 10, 1000); ++ if (ret) ++ dev_warn(priv->dev, "wait phy status ready timeout\n"); ++ } ++ ++ return 0; ++ ++err_clk: ++ clk_bulk_disable_unprepare(priv->num_clks, priv->clks); ++ ++ return ret; ++} ++ ++static int rockchip_combphy_exit(struct phy *phy) ++{ ++ struct rockchip_combphy_priv *priv = phy_get_drvdata(phy); ++ ++ clk_bulk_disable_unprepare(priv->num_clks, priv->clks); ++ reset_control_assert(priv->phy_rst); ++ ++ return 0; ++} ++ ++static const struct phy_ops rochchip_combphy_ops = { ++ .init = rockchip_combphy_init, ++ .exit = rockchip_combphy_exit, ++ .owner = THIS_MODULE, ++}; ++ ++static struct phy *rockchip_combphy_xlate(struct device *dev, struct of_phandle_args *args) ++{ ++ struct rockchip_combphy_priv *priv = dev_get_drvdata(dev); ++ ++ if (args->args_count != 1) { ++ dev_err(dev, "invalid number of arguments\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ if (priv->type != PHY_NONE && priv->type != args->args[0]) ++ dev_warn(dev, "phy type select %d overwriting type %d\n", ++ args->args[0], priv->type); ++ ++ priv->type = args->args[0]; ++ ++ return priv->phy; ++} ++ ++static int rockchip_combphy_parse_dt(struct device *dev, struct rockchip_combphy_priv *priv) ++{ ++ int i; ++ ++ priv->num_clks = devm_clk_bulk_get_all(dev, &priv->clks); ++ if (priv->num_clks < 1) ++ return -EINVAL; ++ ++ priv->refclk = NULL; ++ for (i = 0; i < priv->num_clks; i++) { ++ if (!strncmp(priv->clks[i].id, "ref", 3)) { ++ priv->refclk = priv->clks[i].clk; ++ break; ++ } ++ } ++ ++ if (!priv->refclk) { ++ dev_err(dev, "no refclk found\n"); ++ return -EINVAL; ++ } ++ ++ priv->pipe_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,pipe-grf"); ++ if (IS_ERR(priv->pipe_grf)) { ++ dev_err(dev, "failed to find peri_ctrl pipe-grf regmap\n"); ++ return PTR_ERR(priv->pipe_grf); ++ } ++ ++ priv->phy_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,pipe-phy-grf"); ++ if (IS_ERR(priv->phy_grf)) { ++ dev_err(dev, "failed to find peri_ctrl pipe-phy-grf regmap\n"); ++ return PTR_ERR(priv->phy_grf); ++ } ++ ++ priv->enable_ssc = device_property_present(dev, "rockchip,enable-ssc"); ++ ++ priv->ext_refclk = device_property_present(dev, "rockchip,ext-refclk"); ++ ++ priv->phy_rst = devm_reset_control_array_get_exclusive(dev); ++ if (IS_ERR(priv->phy_rst)) ++ return dev_err_probe(dev, PTR_ERR(priv->phy_rst), "failed to get phy reset\n"); ++ ++ return 0; ++} ++ ++static int rockchip_combphy_probe(struct platform_device *pdev) ++{ ++ struct phy_provider *phy_provider; ++ struct device *dev = &pdev->dev; ++ struct rockchip_combphy_priv *priv; ++ const struct rockchip_combphy_cfg *phy_cfg; ++ struct resource *res; ++ int ret; ++ ++ phy_cfg = of_device_get_match_data(dev); ++ if (!phy_cfg) { ++ dev_err(dev, "no OF match data provided\n"); ++ return -EINVAL; ++ } ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->mmio = devm_platform_get_and_ioremap_resource(pdev, 0, &res); ++ if (IS_ERR(priv->mmio)) { ++ ret = PTR_ERR(priv->mmio); ++ return ret; ++ } ++ ++ priv->dev = dev; ++ priv->type = PHY_NONE; ++ priv->cfg = phy_cfg; ++ ++ ret = rockchip_combphy_parse_dt(dev, priv); ++ if (ret) ++ return ret; ++ ++ ret = reset_control_assert(priv->phy_rst); ++ if (ret) { ++ dev_err(dev, "failed to reset phy\n"); ++ return ret; ++ } ++ ++ priv->phy = devm_phy_create(dev, NULL, &rochchip_combphy_ops); ++ if (IS_ERR(priv->phy)) { ++ dev_err(dev, "failed to create combphy\n"); ++ return PTR_ERR(priv->phy); ++ } ++ ++ dev_set_drvdata(dev, priv); ++ phy_set_drvdata(priv->phy, priv); ++ ++ phy_provider = devm_of_phy_provider_register(dev, rockchip_combphy_xlate); ++ ++ return PTR_ERR_OR_ZERO(phy_provider); ++} ++ ++static int rk3568_combphy_cfg(struct rockchip_combphy_priv *priv) ++{ ++ const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; ++ unsigned long rate; ++ u32 val; ++ ++ switch (priv->type) { ++ case PHY_TYPE_PCIE: ++ /* Set SSC downward spread spectrum. */ ++ rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, ++ PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT, ++ PHYREG32); ++ ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_pcie, true); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_pcie, true); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_pcie, true); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_pcie, true); ++ break; ++ ++ case PHY_TYPE_USB3: ++ /* Set SSC downward spread spectrum. */ ++ rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, ++ PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT, ++ PHYREG32); ++ ++ /* Enable adaptive CTLE for USB3.0 Rx. */ ++ val = readl(priv->mmio + PHYREG15); ++ val |= PHYREG15_CTLE_EN; ++ writel(val, priv->mmio + PHYREG15); ++ ++ /* Set PLL KVCO fine tuning signals. */ ++ rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK, ++ PHYREG33_PLL_KVCO_VALUE << PHYREG33_PLL_KVCO_SHIFT, ++ PHYREG33); ++ ++ /* Enable controlling random jitter. */ ++ writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12); ++ ++ /* Set PLL input clock divider 1/2. */ ++ rockchip_combphy_updatel(priv, PHYREG6_PLL_DIV_MASK, ++ PHYREG6_PLL_DIV_2 << PHYREG6_PLL_DIV_SHIFT, ++ PHYREG6); ++ ++ writel(PHYREG18_PLL_LOOP, priv->mmio + PHYREG18); ++ writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11); ++ ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_usb, true); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->usb_mode_set, true); ++ break; ++ ++ case PHY_TYPE_SATA: ++ /* Enable adaptive CTLE for SATA Rx. */ ++ val = readl(priv->mmio + PHYREG15); ++ val |= PHYREG15_CTLE_EN; ++ writel(val, priv->mmio + PHYREG15); ++ /* ++ * Set tx_rterm=50ohm and rx_rterm=44ohm for SATA. ++ * 0: 60ohm, 8: 50ohm 15: 44ohm (by step abort 1ohm) ++ */ ++ val = PHYREG7_TX_RTERM_50OHM << PHYREG7_TX_RTERM_SHIFT; ++ val |= PHYREG7_RX_RTERM_44OHM << PHYREG7_RX_RTERM_SHIFT; ++ writel(val, priv->mmio + PHYREG7); ++ ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_sata, true); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_sata, true); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_sata, true); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_sata, true); ++ rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true); ++ break; ++ ++ case PHY_TYPE_SGMII: ++ rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->sgmii_mode_set, true); ++ break; ++ ++ case PHY_TYPE_QSGMII: ++ rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_rate_sel, true); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true); ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->qsgmii_mode_set, true); ++ break; ++ ++ default: ++ dev_err(priv->dev, "incompatible PHY type\n"); ++ return -EINVAL; ++ } ++ ++ rate = clk_get_rate(priv->refclk); ++ ++ switch (rate) { ++ case REF_CLOCK_24MHz: ++ if (priv->type == PHY_TYPE_USB3 || priv->type == PHY_TYPE_SATA) { ++ /* Set ssc_cnt[9:0]=0101111101 & 31.5KHz. */ ++ val = PHYREG15_SSC_CNT_VALUE << PHYREG15_SSC_CNT_SHIFT; ++ rockchip_combphy_updatel(priv, PHYREG15_SSC_CNT_MASK, ++ val, PHYREG15); ++ ++ writel(PHYREG16_SSC_CNT_VALUE, priv->mmio + PHYREG16); ++ } ++ break; ++ ++ case REF_CLOCK_25MHz: ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_25m, true); ++ break; ++ ++ case REF_CLOCK_100MHz: ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_100m, true); ++ if (priv->type == PHY_TYPE_PCIE) { ++ /* PLL KVCO fine tuning. */ ++ val = PHYREG33_PLL_KVCO_VALUE << PHYREG33_PLL_KVCO_SHIFT; ++ rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK, ++ val, PHYREG33); ++ ++ /* Enable controlling random jitter. */ ++ writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12); ++ ++ val = PHYREG6_PLL_DIV_2 << PHYREG6_PLL_DIV_SHIFT; ++ rockchip_combphy_updatel(priv, PHYREG6_PLL_DIV_MASK, ++ val, PHYREG6); ++ ++ writel(PHYREG18_PLL_LOOP, priv->mmio + PHYREG18); ++ writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11); ++ } else if (priv->type == PHY_TYPE_SATA) { ++ /* downward spread spectrum +500ppm */ ++ val = PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT; ++ val |= PHYREG32_SSC_OFFSET_500PPM << PHYREG32_SSC_OFFSET_SHIFT; ++ rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, val, PHYREG32); ++ } ++ break; ++ ++ default: ++ dev_err(priv->dev, "unsupported rate: %lu\n", rate); ++ return -EINVAL; ++ } ++ ++ if (priv->ext_refclk) { ++ rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_ext, true); ++ if (priv->type == PHY_TYPE_PCIE && rate == REF_CLOCK_100MHz) { ++ val = PHYREG13_RESISTER_HIGH_Z << PHYREG13_RESISTER_SHIFT; ++ val |= PHYREG13_CKRCV_AMP0; ++ rockchip_combphy_updatel(priv, PHYREG13_RESISTER_MASK, val, PHYREG13); ++ ++ val = readl(priv->mmio + PHYREG14); ++ val |= PHYREG14_CKRCV_AMP1; ++ writel(val, priv->mmio + PHYREG14); ++ } ++ } ++ ++ if (priv->enable_ssc) { ++ val = readl(priv->mmio + PHYREG8); ++ val |= PHYREG8_SSC_EN; ++ writel(val, priv->mmio + PHYREG8); ++ } ++ ++ return 0; ++} ++ ++static const struct rockchip_combphy_grfcfg rk3568_combphy_grfcfgs = { ++ /* pipe-phy-grf */ ++ .pcie_mode_set = { 0x0000, 5, 0, 0x00, 0x11 }, ++ .usb_mode_set = { 0x0000, 5, 0, 0x00, 0x04 }, ++ .sgmii_mode_set = { 0x0000, 5, 0, 0x00, 0x01 }, ++ .qsgmii_mode_set = { 0x0000, 5, 0, 0x00, 0x21 }, ++ .pipe_rxterm_set = { 0x0000, 12, 12, 0x00, 0x01 }, ++ .pipe_txelec_set = { 0x0004, 1, 1, 0x00, 0x01 }, ++ .pipe_txcomp_set = { 0x0004, 4, 4, 0x00, 0x01 }, ++ .pipe_clk_25m = { 0x0004, 14, 13, 0x00, 0x01 }, ++ .pipe_clk_100m = { 0x0004, 14, 13, 0x00, 0x02 }, ++ .pipe_phymode_sel = { 0x0008, 1, 1, 0x00, 0x01 }, ++ .pipe_rate_sel = { 0x0008, 2, 2, 0x00, 0x01 }, ++ .pipe_rxterm_sel = { 0x0008, 8, 8, 0x00, 0x01 }, ++ .pipe_txelec_sel = { 0x0008, 12, 12, 0x00, 0x01 }, ++ .pipe_txcomp_sel = { 0x0008, 15, 15, 0x00, 0x01 }, ++ .pipe_clk_ext = { 0x000c, 9, 8, 0x02, 0x01 }, ++ .pipe_sel_usb = { 0x000c, 14, 13, 0x00, 0x01 }, ++ .pipe_sel_qsgmii = { 0x000c, 15, 13, 0x00, 0x07 }, ++ .pipe_phy_status = { 0x0034, 6, 6, 0x01, 0x00 }, ++ .con0_for_pcie = { 0x0000, 15, 0, 0x00, 0x1000 }, ++ .con1_for_pcie = { 0x0004, 15, 0, 0x00, 0x0000 }, ++ .con2_for_pcie = { 0x0008, 15, 0, 0x00, 0x0101 }, ++ .con3_for_pcie = { 0x000c, 15, 0, 0x00, 0x0200 }, ++ .con0_for_sata = { 0x0000, 15, 0, 0x00, 0x0119 }, ++ .con1_for_sata = { 0x0004, 15, 0, 0x00, 0x0040 }, ++ .con2_for_sata = { 0x0008, 15, 0, 0x00, 0x80c3 }, ++ .con3_for_sata = { 0x000c, 15, 0, 0x00, 0x4407 }, ++ /* pipe-grf */ ++ .pipe_con0_for_sata = { 0x0000, 15, 0, 0x00, 0x2220 }, ++ .pipe_xpcs_phy_ready = { 0x0040, 2, 2, 0x00, 0x01 }, ++}; ++ ++static const struct rockchip_combphy_cfg rk3568_combphy_cfgs = { ++ .grfcfg = &rk3568_combphy_grfcfgs, ++ .combphy_cfg = rk3568_combphy_cfg, ++}; ++ ++static const struct of_device_id rockchip_combphy_of_match[] = { ++ { ++ .compatible = "rockchip,rk3568-naneng-combphy", ++ .data = &rk3568_combphy_cfgs, ++ }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, rockchip_combphy_of_match); ++ ++static struct platform_driver rockchip_combphy_driver = { ++ .probe = rockchip_combphy_probe, ++ .driver = { ++ .name = "rockchip-naneng-combphy", ++ .of_match_table = rockchip_combphy_of_match, ++ }, ++}; ++module_platform_driver(rockchip_combphy_driver); ++ ++MODULE_DESCRIPTION("Rockchip NANENG COMBPHY driver"); ++MODULE_LICENSE("GPL v2"); diff --git a/root/target/linux/rockchip/patches-5.4/050-v5.18-mmc-dw_mmc-Support-setting-f_min-from-host-drivers.patch b/root/target/linux/rockchip/patches-5.4/050-v5.18-mmc-dw_mmc-Support-setting-f_min-from-host-drivers.patch new file mode 100644 index 00000000..6588068c --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/050-v5.18-mmc-dw_mmc-Support-setting-f_min-from-host-drivers.patch @@ -0,0 +1,54 @@ +From c4313e75001492f8a288d3ffd595544cbc880821 Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Sat, 5 Mar 2022 16:58:34 -0500 +Subject: [PATCH] mmc: dw_mmc: Support setting f_min from host drivers + +Host drivers may not be able to support frequencies as low as dw-mmc +supports. Unfortunately f_min isn't available when the drv_data->init +function is called, as the mmc_host struct hasn't been set up yet. + +Support the host drivers saving the requested minimum frequency, so we +can later set f_min when it is available. + +Signed-off-by: Peter Geis +Link: https://lore.kernel.org/r/20220305215835.2210388-2-pgwipeout@gmail.com +Signed-off-by: Ulf Hansson +--- + drivers/mmc/host/dw_mmc.c | 7 ++++++- + drivers/mmc/host/dw_mmc.h | 2 ++ + 2 files changed, 8 insertions(+), 1 deletion(-) + +--- a/drivers/mmc/host/dw_mmc.c ++++ b/drivers/mmc/host/dw_mmc.c +@@ -2853,7 +2853,12 @@ static int dw_mci_init_slot_caps(struct + if (host->pdata->caps2) + mmc->caps2 = host->pdata->caps2; + +- mmc->f_min = DW_MCI_FREQ_MIN; ++ /* if host has set a minimum_freq, we should respect it */ ++ if (host->minimum_speed) ++ mmc->f_min = host->minimum_speed; ++ else ++ mmc->f_min = DW_MCI_FREQ_MIN; ++ + if (!mmc->f_max) + mmc->f_max = DW_MCI_FREQ_MAX; + +--- a/drivers/mmc/host/dw_mmc.h ++++ b/drivers/mmc/host/dw_mmc.h +@@ -99,6 +99,7 @@ struct dw_mci_dma_slave { + * @bus_hz: The rate of @mck in Hz. This forms the basis for MMC bus + * rate and timeout calculations. + * @current_speed: Configured rate of the controller. ++ * @minimum_speed: Stored minimum rate of the controller. + * @fifoth_val: The value of FIFOTH register. + * @verid: Denote Version ID. + * @dev: Device associated with the MMC controller. +@@ -200,6 +201,7 @@ struct dw_mci { + + u32 bus_hz; + u32 current_speed; ++ u32 minimum_speed; + u32 fifoth_val; + u16 verid; + struct device *dev; diff --git a/root/target/linux/rockchip/patches-5.4/051-v5.18-mmc-dw-mmc-rockchip-Fix-handling-invalid-clock-rates.patch b/root/target/linux/rockchip/patches-5.4/051-v5.18-mmc-dw-mmc-rockchip-Fix-handling-invalid-clock-rates.patch new file mode 100644 index 00000000..f86a6cdf --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/051-v5.18-mmc-dw-mmc-rockchip-Fix-handling-invalid-clock-rates.patch @@ -0,0 +1,79 @@ +From 52c92286b71e28d88642a4a416f40fbdb6cbb46f Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Sat, 5 Mar 2022 16:58:35 -0500 +Subject: [PATCH] mmc: dw-mmc-rockchip: Fix handling invalid clock rates + +The Rockchip rk356x ciu clock cannot be set as low as the dw-mmc +hardware supports. This leads to a situation during card initialization +where the clock is set lower than the clock driver can support. The +dw-mmc-rockchip driver spews errors when this happens. +For normal operation this only happens a few times during boot, but when +cd-broken is enabled (in cases such as the SoQuartz module) this fires +multiple times each poll cycle. + +Fix this by testing the lowest possible frequency that the clock driver +can support which is within the mmc specification. Divide that rate by +the internal divider and set f_min to this. + +Signed-off-by: Peter Geis +Link: https://lore.kernel.org/r/20220305215835.2210388-3-pgwipeout@gmail.com +Signed-off-by: Ulf Hansson +--- + drivers/mmc/host/dw_mmc-rockchip.c | 27 +++++++++++++++++++++++---- + 1 file changed, 23 insertions(+), 4 deletions(-) + +--- a/drivers/mmc/host/dw_mmc-rockchip.c ++++ b/drivers/mmc/host/dw_mmc-rockchip.c +@@ -15,7 +15,9 @@ + #include "dw_mmc.h" + #include "dw_mmc-pltfm.h" + +-#define RK3288_CLKGEN_DIV 2 ++#define RK3288_CLKGEN_DIV 2 ++ ++static const unsigned int freqs[] = { 100000, 200000, 300000, 400000 }; + + struct dw_mci_rockchip_priv_data { + struct clk *drv_clk; +@@ -51,7 +53,7 @@ static void dw_mci_rk3288_set_ios(struct + + ret = clk_set_rate(host->ciu_clk, cclkin); + if (ret) +- dev_warn(host->dev, "failed to set rate %uHz\n", ios->clock); ++ dev_warn(host->dev, "failed to set rate %uHz err: %d\n", cclkin, ret); + + bus_hz = clk_get_rate(host->ciu_clk) / RK3288_CLKGEN_DIV; + if (bus_hz != host->bus_hz) { +@@ -290,13 +292,30 @@ static int dw_mci_rk3288_parse_dt(struct + + static int dw_mci_rockchip_init(struct dw_mci *host) + { ++ int ret, i; ++ + /* It is slot 8 on Rockchip SoCs */ + host->sdio_id0 = 8; + +- if (of_device_is_compatible(host->dev->of_node, +- "rockchip,rk3288-dw-mshc")) ++ if (of_device_is_compatible(host->dev->of_node, "rockchip,rk3288-dw-mshc")) { + host->bus_hz /= RK3288_CLKGEN_DIV; + ++ /* clock driver will fail if the clock is less than the lowest source clock ++ * divided by the internal clock divider. Test for the lowest available ++ * clock and set the minimum freq to clock / clock divider. ++ */ ++ ++ for (i = 0; i < ARRAY_SIZE(freqs); i++) { ++ ret = clk_round_rate(host->ciu_clk, freqs[i] * RK3288_CLKGEN_DIV); ++ if (ret > 0) { ++ host->minimum_speed = ret / RK3288_CLKGEN_DIV; ++ break; ++ } ++ } ++ if (ret < 0) ++ dev_warn(host->dev, "no valid minimum freq: %d\n", ret); ++ } ++ + return 0; + } + diff --git a/root/target/linux/rockchip/patches-5.4/054-v5.19-soc-rockchip-set-dwc3-clock-for-rk3566.patch b/root/target/linux/rockchip/patches-5.4/054-v5.19-soc-rockchip-set-dwc3-clock-for-rk3566.patch new file mode 100644 index 00000000..f2288c75 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/054-v5.19-soc-rockchip-set-dwc3-clock-for-rk3566.patch @@ -0,0 +1,51 @@ +From 5c0bb71138770d85ea840acd379edc6471b867ee Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Fri, 8 Apr 2022 11:12:34 -0400 +Subject: [PATCH] soc: rockchip: set dwc3 clock for rk3566 + +The rk3566 dwc3 otg port clock is unavailable at boot, as it defaults to +the combophy as the clock source. As combophy0 doesn't exist on rk3566, +we need to set the clock source to the usb2 phy instead. + +Add handling to the grf driver to handle this on boot. + +Signed-off-by: Peter Geis +Link: https://lore.kernel.org/r/20220408151237.3165046-3-pgwipeout@gmail.com +Signed-off-by: Heiko Stuebner +--- + drivers/soc/rockchip/grf.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +--- a/drivers/soc/rockchip/grf.c ++++ b/drivers/soc/rockchip/grf.c +@@ -108,6 +108,20 @@ static const struct rockchip_grf_info rk + .num_values = ARRAY_SIZE(rk3399_defaults), + }; + ++#define RK3566_GRF_USB3OTG0_CON1 0x0104 ++ ++static const struct rockchip_grf_value rk3566_defaults[] __initconst = { ++ { "usb3otg port switch", RK3566_GRF_USB3OTG0_CON1, HIWORD_UPDATE(0, 1, 12) }, ++ { "usb3otg clock switch", RK3566_GRF_USB3OTG0_CON1, HIWORD_UPDATE(1, 1, 7) }, ++ { "usb3otg disable usb3", RK3566_GRF_USB3OTG0_CON1, HIWORD_UPDATE(1, 1, 0) }, ++}; ++ ++static const struct rockchip_grf_info rk3566_pipegrf __initconst = { ++ .values = rk3566_defaults, ++ .num_values = ARRAY_SIZE(rk3566_defaults), ++}; ++ ++ + static const struct of_device_id rockchip_grf_dt_match[] __initconst = { + { + .compatible = "rockchip,rk3036-grf", +@@ -130,6 +144,9 @@ static const struct of_device_id rockchi + }, { + .compatible = "rockchip,rk3399-grf", + .data = (void *)&rk3399_grf, ++ }, { ++ .compatible = "rockchip,rk3566-pipe-grf", ++ .data = (void *)&rk3566_pipegrf, + }, + { /* sentinel */ }, + }; diff --git a/root/target/linux/rockchip/patches-5.4/070-v6.1-phy-rockchip-Support-PCIe-v3.patch b/root/target/linux/rockchip/patches-5.4/070-v6.1-phy-rockchip-Support-PCIe-v3.patch new file mode 100644 index 00000000..b3648eaa --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/070-v6.1-phy-rockchip-Support-PCIe-v3.patch @@ -0,0 +1,394 @@ +From 2e9bffc4f713db465177238f6033f7d367d6f151 Mon Sep 17 00:00:00 2001 +From: Shawn Lin +Date: Thu, 25 Aug 2022 21:38:34 +0200 +Subject: [PATCH] phy: rockchip: Support PCIe v3 + +RK3568 supports PCIe v3 using not Combphy like PCIe v2 on rk3566. +It use a dedicated PCIe-phy. Add support for this. + +Initial support by Shawn Lin, modifications by Peter Geis and Frank +Wunderlich. + +Add data-lanes property for splitting pcie-lanes across controllers. + +The data-lanes is an array where x=0 means lane is disabled and x > 0 +means controller x is assigned to phy lane. + +Signed-off-by: Shawn Lin +Suggested-by: Peter Geis +Signed-off-by: Frank Wunderlich +Link: https://lore.kernel.org/r/20220825193836.54262-4-linux@fw-web.de +Signed-off-by: Vinod Koul +--- + drivers/phy/rockchip/Kconfig | 9 + + drivers/phy/rockchip/Makefile | 1 + + .../phy/rockchip/phy-rockchip-snps-pcie3.c | 319 ++++++++++++++++++ + include/linux/phy/pcie.h | 12 + + 4 files changed, 341 insertions(+) + create mode 100644 drivers/phy/rockchip/phy-rockchip-snps-pcie3.c + create mode 100644 include/linux/phy/pcie.h + +--- a/drivers/phy/rockchip/Kconfig ++++ b/drivers/phy/rockchip/Kconfig +@@ -83,6 +83,15 @@ config PHY_ROCKCHIP_PCIE + help + Enable this to support the Rockchip PCIe PHY. + ++config PHY_ROCKCHIP_SNPS_PCIE3 ++ tristate "Rockchip Snps PCIe3 PHY Driver" ++ depends on (ARCH_ROCKCHIP && OF) || COMPILE_TEST ++ depends on HAS_IOMEM ++ select GENERIC_PHY ++ select MFD_SYSCON ++ help ++ Enable this to support the Rockchip snps PCIe3 PHY. ++ + config PHY_ROCKCHIP_TYPEC + tristate "Rockchip TYPEC PHY Driver" + depends on OF && (ARCH_ROCKCHIP || COMPILE_TEST) +--- a/drivers/phy/rockchip/Makefile ++++ b/drivers/phy/rockchip/Makefile +@@ -8,5 +8,6 @@ obj-$(CONFIG_PHY_ROCKCHIP_INNO_HDMI) += + obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o + obj-$(CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY) += phy-rockchip-naneng-combphy.o + obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o ++obj-$(CONFIG_PHY_ROCKCHIP_SNPS_PCIE3) += phy-rockchip-snps-pcie3.o + obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o + obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o +--- /dev/null ++++ b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c +@@ -0,0 +1,319 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Rockchip PCIE3.0 phy driver ++ * ++ * Copyright (C) 2022 Rockchip Electronics Co., Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Register for RK3568 */ ++#define GRF_PCIE30PHY_CON1 0x4 ++#define GRF_PCIE30PHY_CON6 0x18 ++#define GRF_PCIE30PHY_CON9 0x24 ++#define GRF_PCIE30PHY_DA_OCM (BIT(15) | BIT(31)) ++#define GRF_PCIE30PHY_STATUS0 0x80 ++#define GRF_PCIE30PHY_WR_EN (0xf << 16) ++#define SRAM_INIT_DONE(reg) (reg & BIT(14)) ++ ++#define RK3568_BIFURCATION_LANE_0_1 BIT(0) ++ ++/* Register for RK3588 */ ++#define PHP_GRF_PCIESEL_CON 0x100 ++#define RK3588_PCIE3PHY_GRF_CMN_CON0 0x0 ++#define RK3588_PCIE3PHY_GRF_PHY0_STATUS1 0x904 ++#define RK3588_PCIE3PHY_GRF_PHY1_STATUS1 0xa04 ++#define RK3588_SRAM_INIT_DONE(reg) (reg & BIT(0)) ++ ++#define RK3588_BIFURCATION_LANE_0_1 BIT(0) ++#define RK3588_BIFURCATION_LANE_2_3 BIT(1) ++#define RK3588_LANE_AGGREGATION BIT(2) ++ ++struct rockchip_p3phy_ops; ++ ++struct rockchip_p3phy_priv { ++ const struct rockchip_p3phy_ops *ops; ++ void __iomem *mmio; ++ /* mode: RC, EP */ ++ int mode; ++ /* pcie30_phymode: Aggregation, Bifurcation */ ++ int pcie30_phymode; ++ struct regmap *phy_grf; ++ struct regmap *pipe_grf; ++ struct reset_control *p30phy; ++ struct phy *phy; ++ struct clk_bulk_data *clks; ++ int num_clks; ++ int num_lanes; ++ u32 lanes[4]; ++}; ++ ++struct rockchip_p3phy_ops { ++ int (*phy_init)(struct rockchip_p3phy_priv *priv); ++}; ++ ++static int rockchip_p3phy_set_mode(struct phy *phy, enum phy_mode mode, int submode) ++{ ++ struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy); ++ ++ /* Actually We don't care EP/RC mode, but just record it */ ++ switch (submode) { ++ case PHY_MODE_PCIE_RC: ++ priv->mode = PHY_MODE_PCIE_RC; ++ break; ++ case PHY_MODE_PCIE_EP: ++ priv->mode = PHY_MODE_PCIE_EP; ++ break; ++ default: ++ dev_err(&phy->dev, "%s, invalid mode\n", __func__); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int rockchip_p3phy_rk3568_init(struct rockchip_p3phy_priv *priv) ++{ ++ struct phy *phy = priv->phy; ++ bool bifurcation = false; ++ int ret, i; ++ u32 reg; ++ ++ /* Deassert PCIe PMA output clamp mode */ ++ regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON9, GRF_PCIE30PHY_DA_OCM); ++ ++ for (i = 0; i < priv->num_lanes; i++) { ++ dev_info(&phy->dev, "lane number %d, val %d\n", i, priv->lanes[i]); ++ if (priv->lanes[i] > 1) ++ bifurcation = true; ++ } ++ ++ /* Set bifurcation if needed, and it doesn't care RC/EP */ ++ if (bifurcation) { ++ dev_info(&phy->dev, "bifurcation enabled\n"); ++ regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON6, ++ GRF_PCIE30PHY_WR_EN | RK3568_BIFURCATION_LANE_0_1); ++ regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON1, ++ GRF_PCIE30PHY_DA_OCM); ++ } else { ++ dev_dbg(&phy->dev, "bifurcation disabled\n"); ++ regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON6, ++ GRF_PCIE30PHY_WR_EN & ~RK3568_BIFURCATION_LANE_0_1); ++ } ++ ++ reset_control_deassert(priv->p30phy); ++ ++ ret = regmap_read_poll_timeout(priv->phy_grf, ++ GRF_PCIE30PHY_STATUS0, ++ reg, SRAM_INIT_DONE(reg), ++ 0, 500); ++ if (ret) ++ dev_err(&priv->phy->dev, "%s: lock failed 0x%x, check input refclk and power supply\n", ++ __func__, reg); ++ return ret; ++} ++ ++static const struct rockchip_p3phy_ops rk3568_ops = { ++ .phy_init = rockchip_p3phy_rk3568_init, ++}; ++ ++static int rockchip_p3phy_rk3588_init(struct rockchip_p3phy_priv *priv) ++{ ++ u32 reg = 0; ++ u8 mode = 0; ++ int i, ret; ++ ++ /* Deassert PCIe PMA output clamp mode */ ++ regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0, BIT(8) | BIT(24)); ++ ++ /* Set bifurcation if needed */ ++ for (i = 0; i < priv->num_lanes; i++) { ++ if (!priv->lanes[i]) ++ mode |= (BIT(i) << 3); ++ ++ if (priv->lanes[i] > 1) ++ mode |= (BIT(i) >> 1); ++ } ++ ++ if (!mode) ++ reg = RK3588_LANE_AGGREGATION; ++ else { ++ if (mode & (BIT(0) | BIT(1))) ++ reg |= RK3588_BIFURCATION_LANE_0_1; ++ ++ if (mode & (BIT(2) | BIT(3))) ++ reg |= RK3588_BIFURCATION_LANE_2_3; ++ } ++ ++ regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0, (0x7<<16) | reg); ++ ++ /* Set pcie1ln_sel in PHP_GRF_PCIESEL_CON */ ++ if (!IS_ERR(priv->pipe_grf)) { ++ reg = (mode & (BIT(6) | BIT(7))) >> 6; ++ if (reg) ++ regmap_write(priv->pipe_grf, PHP_GRF_PCIESEL_CON, ++ (reg << 16) | reg); ++ } ++ ++ reset_control_deassert(priv->p30phy); ++ ++ ret = regmap_read_poll_timeout(priv->phy_grf, ++ RK3588_PCIE3PHY_GRF_PHY0_STATUS1, ++ reg, RK3588_SRAM_INIT_DONE(reg), ++ 0, 500); ++ ret |= regmap_read_poll_timeout(priv->phy_grf, ++ RK3588_PCIE3PHY_GRF_PHY1_STATUS1, ++ reg, RK3588_SRAM_INIT_DONE(reg), ++ 0, 500); ++ if (ret) ++ dev_err(&priv->phy->dev, "lock failed 0x%x, check input refclk and power supply\n", ++ reg); ++ return ret; ++} ++ ++static const struct rockchip_p3phy_ops rk3588_ops = { ++ .phy_init = rockchip_p3phy_rk3588_init, ++}; ++ ++static int rochchip_p3phy_init(struct phy *phy) ++{ ++ struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy); ++ int ret; ++ ++ ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks); ++ if (ret) { ++ dev_err(&priv->phy->dev, "failed to enable PCIe bulk clks %d\n", ret); ++ return ret; ++ } ++ ++ reset_control_assert(priv->p30phy); ++ udelay(1); ++ ++ if (priv->ops->phy_init) { ++ ret = priv->ops->phy_init(priv); ++ if (ret) ++ clk_bulk_disable_unprepare(priv->num_clks, priv->clks); ++ } ++ ++ return ret; ++} ++ ++static int rochchip_p3phy_exit(struct phy *phy) ++{ ++ struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy); ++ ++ clk_bulk_disable_unprepare(priv->num_clks, priv->clks); ++ reset_control_assert(priv->p30phy); ++ return 0; ++} ++ ++static const struct phy_ops rochchip_p3phy_ops = { ++ .init = rochchip_p3phy_init, ++ .exit = rochchip_p3phy_exit, ++ .set_mode = rockchip_p3phy_set_mode, ++ .owner = THIS_MODULE, ++}; ++ ++static int rockchip_p3phy_probe(struct platform_device *pdev) ++{ ++ struct phy_provider *phy_provider; ++ struct device *dev = &pdev->dev; ++ struct rockchip_p3phy_priv *priv; ++ struct device_node *np = dev->of_node; ++ struct resource *res; ++ int ret; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ priv->mmio = devm_ioremap_resource(dev, res); ++ if (IS_ERR(priv->mmio)) { ++ ret = PTR_ERR(priv->mmio); ++ return ret; ++ } ++ ++ priv->ops = of_device_get_match_data(&pdev->dev); ++ if (!priv->ops) { ++ dev_err(dev, "no of match data provided\n"); ++ return -EINVAL; ++ } ++ ++ priv->phy_grf = syscon_regmap_lookup_by_phandle(np, "rockchip,phy-grf"); ++ if (IS_ERR(priv->phy_grf)) { ++ dev_err(dev, "failed to find rockchip,phy_grf regmap\n"); ++ return PTR_ERR(priv->phy_grf); ++ } ++ ++ priv->pipe_grf = syscon_regmap_lookup_by_phandle(dev->of_node, ++ "rockchip,pipe-grf"); ++ if (IS_ERR(priv->pipe_grf)) ++ dev_info(dev, "failed to find rockchip,pipe_grf regmap\n"); ++ ++ priv->num_lanes = of_property_read_variable_u32_array(dev->of_node, "data-lanes", ++ priv->lanes, 2, ++ ARRAY_SIZE(priv->lanes)); ++ ++ /* if no data-lanes assume aggregation */ ++ if (priv->num_lanes == -EINVAL) { ++ dev_dbg(dev, "no data-lanes property found\n"); ++ priv->num_lanes = 1; ++ priv->lanes[0] = 1; ++ } else if (priv->num_lanes < 0) { ++ dev_err(dev, "failed to read data-lanes property %d\n", priv->num_lanes); ++ return priv->num_lanes; ++ } ++ ++ priv->phy = devm_phy_create(dev, NULL, &rochchip_p3phy_ops); ++ if (IS_ERR(priv->phy)) { ++ dev_err(dev, "failed to create combphy\n"); ++ return PTR_ERR(priv->phy); ++ } ++ ++ priv->p30phy = devm_reset_control_get_optional_exclusive(dev, "phy"); ++ if (IS_ERR(priv->p30phy)) { ++ return dev_err_probe(dev, PTR_ERR(priv->p30phy), ++ "failed to get phy reset control\n"); ++ } ++ if (!priv->p30phy) ++ dev_info(dev, "no phy reset control specified\n"); ++ ++ priv->num_clks = devm_clk_bulk_get_all(dev, &priv->clks); ++ if (priv->num_clks < 1) ++ return -ENODEV; ++ ++ dev_set_drvdata(dev, priv); ++ phy_set_drvdata(priv->phy, priv); ++ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); ++ return PTR_ERR_OR_ZERO(phy_provider); ++} ++ ++static const struct of_device_id rockchip_p3phy_of_match[] = { ++ { .compatible = "rockchip,rk3568-pcie3-phy", .data = &rk3568_ops }, ++ { .compatible = "rockchip,rk3588-pcie3-phy", .data = &rk3588_ops }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, rockchip_p3phy_of_match); ++ ++static struct platform_driver rockchip_p3phy_driver = { ++ .probe = rockchip_p3phy_probe, ++ .driver = { ++ .name = "rockchip-snps-pcie3-phy", ++ .of_match_table = rockchip_p3phy_of_match, ++ }, ++}; ++module_platform_driver(rockchip_p3phy_driver); ++MODULE_DESCRIPTION("Rockchip Synopsys PCIe 3.0 PHY driver"); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/include/linux/phy/pcie.h +@@ -0,0 +1,12 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (c) 2022 Rockchip Electronics Co., Ltd. ++ */ ++#ifndef __PHY_PCIE_H ++#define __PHY_PCIE_H ++ ++#define PHY_MODE_PCIE_RC 20 ++#define PHY_MODE_PCIE_EP 21 ++#define PHY_MODE_PCIE_BIFURCATION 22 ++ ++#endif diff --git a/root/target/linux/rockchip/patches-5.4/071-v6.1-arm64-dts-rockchip-Add-PCIe-v3-nodes-to-rk3568.patch b/root/target/linux/rockchip/patches-5.4/071-v6.1-arm64-dts-rockchip-Add-PCIe-v3-nodes-to-rk3568.patch new file mode 100644 index 00000000..670c3772 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/071-v6.1-arm64-dts-rockchip-Add-PCIe-v3-nodes-to-rk3568.patch @@ -0,0 +1,146 @@ +From faedfa5b40f095d09040c3a040e2f8dee4a36b4b Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Thu, 25 Aug 2022 21:38:35 +0200 +Subject: [PATCH] arm64: dts: rockchip: Add PCIe v3 nodes to rk3568 + +Add nodes to rk356x devicetree to support PCIe v3. + +Signed-off-by: Peter Geis +Signed-off-by: Frank Wunderlich +Link: https://lore.kernel.org/r/20220825193836.54262-5-linux@fw-web.de +Signed-off-by: Heiko Stuebner +--- + arch/arm64/boot/dts/rockchip/rk3568.dtsi | 122 +++++++++++++++++++++++ + 1 file changed, 122 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3568.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3568.dtsi +@@ -42,6 +42,128 @@ + reg = <0x0 0xfe190200 0x0 0x20>; + }; + ++ pcie30_phy_grf: syscon@fdcb8000 { ++ compatible = "rockchip,rk3568-pcie3-phy-grf", "syscon"; ++ reg = <0x0 0xfdcb8000 0x0 0x10000>; ++ }; ++ ++ pcie30phy: phy@fe8c0000 { ++ compatible = "rockchip,rk3568-pcie3-phy"; ++ reg = <0x0 0xfe8c0000 0x0 0x20000>; ++ #phy-cells = <0>; ++ clocks = <&pmucru CLK_PCIE30PHY_REF_M>, <&pmucru CLK_PCIE30PHY_REF_N>, ++ <&cru PCLK_PCIE30PHY>; ++ clock-names = "refclk_m", "refclk_n", "pclk"; ++ resets = <&cru SRST_PCIE30PHY>; ++ reset-names = "phy"; ++ rockchip,phy-grf = <&pcie30_phy_grf>; ++ status = "disabled"; ++ }; ++ ++ pcie3x1: pcie@fe270000 { ++ compatible = "rockchip,rk3568-pcie"; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ bus-range = <0x0 0xf>; ++ clocks = <&cru ACLK_PCIE30X1_MST>, <&cru ACLK_PCIE30X1_SLV>, ++ <&cru ACLK_PCIE30X1_DBI>, <&cru PCLK_PCIE30X1>, ++ <&cru CLK_PCIE30X1_AUX_NDFT>; ++ clock-names = "aclk_mst", "aclk_slv", ++ "aclk_dbi", "pclk", "aux"; ++ device_type = "pci"; ++ interrupts = , ++ , ++ , ++ , ++ ; ++ interrupt-names = "sys", "pmc", "msg", "legacy", "err"; ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 7>; ++ interrupt-map = <0 0 0 1 &pcie3x1_intc 0>, ++ <0 0 0 2 &pcie3x1_intc 1>, ++ <0 0 0 3 &pcie3x1_intc 2>, ++ <0 0 0 4 &pcie3x1_intc 3>; ++ linux,pci-domain = <1>; ++ num-ib-windows = <6>; ++ num-ob-windows = <2>; ++ max-link-speed = <3>; ++ msi-map = <0x0 &gic 0x1000 0x1000>; ++ num-lanes = <1>; ++ phys = <&pcie30phy>; ++ phy-names = "pcie-phy"; ++ power-domains = <&power RK3568_PD_PIPE>; ++ reg = <0x3 0xc0400000 0x0 0x00400000>, ++ <0x0 0xfe270000 0x0 0x00010000>, ++ <0x3 0x7f000000 0x0 0x01000000>; ++ ranges = <0x01000000 0x0 0x3ef00000 0x3 0x7ef00000 0x0 0x00100000>, ++ <0x02000000 0x0 0x00000000 0x3 0x40000000 0x0 0x3ef00000>; ++ reg-names = "dbi", "apb", "config"; ++ resets = <&cru SRST_PCIE30X1_POWERUP>; ++ reset-names = "pipe"; ++ /* bifurcation; lane1 when using 1+1 */ ++ status = "disabled"; ++ ++ pcie3x1_intc: legacy-interrupt-controller { ++ interrupt-controller; ++ #address-cells = <0>; ++ #interrupt-cells = <1>; ++ interrupt-parent = <&gic>; ++ interrupts = ; ++ }; ++ }; ++ ++ pcie3x2: pcie@fe280000 { ++ compatible = "rockchip,rk3568-pcie"; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ bus-range = <0x0 0xf>; ++ clocks = <&cru ACLK_PCIE30X2_MST>, <&cru ACLK_PCIE30X2_SLV>, ++ <&cru ACLK_PCIE30X2_DBI>, <&cru PCLK_PCIE30X2>, ++ <&cru CLK_PCIE30X2_AUX_NDFT>; ++ clock-names = "aclk_mst", "aclk_slv", ++ "aclk_dbi", "pclk", "aux"; ++ device_type = "pci"; ++ interrupts = , ++ , ++ , ++ , ++ ; ++ interrupt-names = "sys", "pmc", "msg", "legacy", "err"; ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 7>; ++ interrupt-map = <0 0 0 1 &pcie3x2_intc 0>, ++ <0 0 0 2 &pcie3x2_intc 1>, ++ <0 0 0 3 &pcie3x2_intc 2>, ++ <0 0 0 4 &pcie3x2_intc 3>; ++ linux,pci-domain = <2>; ++ num-ib-windows = <6>; ++ num-ob-windows = <2>; ++ max-link-speed = <3>; ++ msi-map = <0x0 &gic 0x2000 0x1000>; ++ num-lanes = <2>; ++ phys = <&pcie30phy>; ++ phy-names = "pcie-phy"; ++ power-domains = <&power RK3568_PD_PIPE>; ++ reg = <0x3 0xc0800000 0x0 0x00400000>, ++ <0x0 0xfe280000 0x0 0x00010000>, ++ <0x3 0xbf000000 0x0 0x01000000>; ++ ranges = <0x01000000 0x0 0x3ef00000 0x3 0xbef00000 0x0 0x00100000>, ++ <0x02000000 0x0 0x00000000 0x3 0x80000000 0x0 0x3ef00000>; ++ reg-names = "dbi", "apb", "config"; ++ resets = <&cru SRST_PCIE30X2_POWERUP>; ++ reset-names = "pipe"; ++ /* bifurcation; lane0 when using 1+1 */ ++ status = "disabled"; ++ ++ pcie3x2_intc: legacy-interrupt-controller { ++ interrupt-controller; ++ #address-cells = <0>; ++ #interrupt-cells = <1>; ++ interrupt-parent = <&gic>; ++ interrupts = ; ++ }; ++ }; ++ + gmac0: ethernet@fe2a0000 { + compatible = "rockchip,rk3568-gmac", "snps,dwmac-4.20a"; + reg = <0x0 0xfe2a0000 0x0 0x10000>; diff --git a/root/target/linux/rockchip/patches-5.15/103-arm64-rockchip-add-OF-node-for-USB-eth-on-NanoPi-R2S.patch b/root/target/linux/rockchip/patches-5.4/103-arm64-rockchip-add-OF-node-for-USB-eth-on-NanoPi-R2S.patch similarity index 78% rename from root/target/linux/rockchip/patches-5.15/103-arm64-rockchip-add-OF-node-for-USB-eth-on-NanoPi-R2S.patch rename to root/target/linux/rockchip/patches-5.4/103-arm64-rockchip-add-OF-node-for-USB-eth-on-NanoPi-R2S.patch index 6f323dc2..f8f15b9c 100644 --- a/root/target/linux/rockchip/patches-5.15/103-arm64-rockchip-add-OF-node-for-USB-eth-on-NanoPi-R2S.patch +++ b/root/target/linux/rockchip/patches-5.4/103-arm64-rockchip-add-OF-node-for-USB-eth-on-NanoPi-R2S.patch @@ -10,14 +10,19 @@ register to match the blink behavior of the other port on the device. Signed-off-by: David Bauer --- arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts | 7 +++++++ - 1 file changed, 1 insertions(+) + 1 file changed, 7 insertions(+) --- a/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts +++ b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts -@@ -404,6 +404,7 @@ - rtl8153: device@2 { - compatible = "usbbda,8153"; - reg = <2>; +@@ -401,4 +401,11 @@ + &usbdrd_dwc3 { + dr_mode = "host"; + status = "okay"; ++ ++ usb_eth: usb-eth@2 { ++ compatible = "realtek,rtl8153"; ++ reg = <2>; ++ + realtek,led-data = <0x87>; - }; ++ }; }; diff --git a/root/target/linux/rockchip/patches-5.4/105-mmc-core-set-initial-signal-voltage-on-power-off.patch b/root/target/linux/rockchip/patches-5.4/105-mmc-core-set-initial-signal-voltage-on-power-off.patch new file mode 100644 index 00000000..d4628990 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/105-mmc-core-set-initial-signal-voltage-on-power-off.patch @@ -0,0 +1,35 @@ +From 0d329112c709d6cfedf0fffb19f0cc6b19043f6b Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 20 Feb 2019 07:38:34 +0000 +Subject: [PATCH] mmc: core: set initial signal voltage on power off + +Some boards have SD card connectors where the power rail cannot be switched +off by the driver. If the card has not been power cycled, it may still be +using 1.8V signaling after a warm re-boot. Bootroms expecting 3.3V signaling +will fail to boot from a UHS card that continue to use 1.8V signaling. + +Set initial signal voltage in mmc_power_off() to allow re-boot to function. + +This fixes re-boot with UHS cards on Asus Tinker Board (Rockchip RK3288), +same issue have been seen on some Rockchip RK3399 boards. + +I am sending this as a RFC because I have no insights into SD/MMC subsystem, +this change fix a re-boot issue on my boards and does not break emmc/sdio. +Is this an acceptable workaround? Any advice is appreciated. + +Signed-off-by: Jonas Karlman +--- + drivers/mmc/core/core.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/mmc/core/core.c ++++ b/drivers/mmc/core/core.c +@@ -1371,6 +1371,8 @@ void mmc_power_off(struct mmc_host *host + + mmc_pwrseq_power_off(host); + ++ mmc_set_initial_signal_voltage(host); ++ + host->ios.clock = 0; + host->ios.vdd = 0; + diff --git a/root/target/linux/rockchip/patches-5.4/106-arm64-rockchip-add-OF-node-for-pcie-eth-on-NanoPi-R4S.patch b/root/target/linux/rockchip/patches-5.4/106-arm64-rockchip-add-OF-node-for-pcie-eth-on-NanoPi-R4S.patch new file mode 100644 index 00000000..67465759 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/106-arm64-rockchip-add-OF-node-for-pcie-eth-on-NanoPi-R4S.patch @@ -0,0 +1,22 @@ +--- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts +@@ -96,6 +96,19 @@ + max-link-speed = <1>; + num-lanes = <1>; + vpcie3v3-supply = <&vcc3v3_sys>; ++ ++ pcie@0 { ++ reg = <0x00000000 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ ++ pcie-eth@0,0 { ++ compatible = "pci10ec,8168"; ++ reg = <0x000000 0 0 0 0>; ++ ++ realtek,led-data = <0x870>; ++ }; ++ }; + }; + + &pinctrl { diff --git a/root/target/linux/rockchip/patches-5.15/105-nanopi-r4s-sd-signalling.patch b/root/target/linux/rockchip/patches-5.4/107-nanopi-r4s-sd-signalling.patch similarity index 97% rename from root/target/linux/rockchip/patches-5.15/105-nanopi-r4s-sd-signalling.patch rename to root/target/linux/rockchip/patches-5.4/107-nanopi-r4s-sd-signalling.patch index a04c14b7..f4f77835 100644 --- a/root/target/linux/rockchip/patches-5.15/105-nanopi-r4s-sd-signalling.patch +++ b/root/target/linux/rockchip/patches-5.4/107-nanopi-r4s-sd-signalling.patch @@ -12,7 +12,7 @@ Signed-off-by: David Bauer --- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts -@@ -121,6 +121,11 @@ +@@ -145,6 +145,11 @@ status = "disabled"; }; diff --git a/root/target/linux/rockchip/patches-5.4/201-rockchip-rk3328-add-i2c0-controller-for-nanopi-r2s.patch b/root/target/linux/rockchip/patches-5.4/201-rockchip-rk3328-add-i2c0-controller-for-nanopi-r2s.patch new file mode 100644 index 00000000..28798047 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/201-rockchip-rk3328-add-i2c0-controller-for-nanopi-r2s.patch @@ -0,0 +1,22 @@ +From 3b7eb946b1d640d684a921e53e1e50985ab7eb89 Mon Sep 17 00:00:00 2001 +From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> +Date: Tue, 4 Aug 2020 20:17:53 +0800 +Subject: [PATCH] rockchip: rk3328: add i2c0 controller for nanopi r2s + +--- + arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts | 4 ++++ + 1 files changed, 4 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts +@@ -165,6 +165,10 @@ + }; + }; + ++&i2c0 { ++ status = "okay"; ++}; ++ + &i2c1 { + status = "okay"; + diff --git a/root/target/linux/rockchip/patches-5.4/202-rockchip-rk3328-Add-support-for-OrangePi-R1-Plus.patch b/root/target/linux/rockchip/patches-5.4/202-rockchip-rk3328-Add-support-for-OrangePi-R1-Plus.patch new file mode 100644 index 00000000..de9d9bee --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/202-rockchip-rk3328-Add-support-for-OrangePi-R1-Plus.patch @@ -0,0 +1,52 @@ +--- a/arch/arm64/boot/dts/rockchip/Makefile ++++ b/arch/arm64/boot/dts/rockchip/Makefile +@@ -2,6 +2,7 @@ + dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-evb.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-evb.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-r2s.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-orangepi-r1-plus.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-rock64.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-roc-cc.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-evb-act8846.dtb +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus.dts +@@ -0,0 +1,39 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++#include "rk3328-nanopi-r2s.dts" ++ ++/ { ++ model = "Xunlong Orange Pi R1 Plus"; ++ compatible = "xunlong,orangepi-r1-plus", "rockchip,rk3328"; ++}; ++ ++&lan_led { ++ label = "orangepi-r1-plus:green:lan"; ++}; ++ ++&spi0 { ++ max-freq = <48000000>; ++ status = "okay"; ++ ++ flash@0 { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <10000000>; ++ }; ++}; ++ ++&sys_led { ++ gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; ++ label = "orangepi-r1-plus:red:sys"; ++}; ++ ++&sys_led_pin { ++ rockchip,pins = <3 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>; ++}; ++ ++&uart1 { ++ status = "okay"; ++}; ++ ++&wan_led { ++ label = "orangepi-r1-plus:green:wan"; ++}; diff --git a/root/target/linux/rockchip/patches-5.4/203-rockchip-rk3328-Add-support-for-OrangePi-R1-Plus-LTS.patch b/root/target/linux/rockchip/patches-5.4/203-rockchip-rk3328-Add-support-for-OrangePi-R1-Plus-LTS.patch new file mode 100644 index 00000000..56c40c3c --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/203-rockchip-rk3328-Add-support-for-OrangePi-R1-Plus-LTS.patch @@ -0,0 +1,79 @@ +--- a/arch/arm64/boot/dts/rockchip/Makefile ++++ b/arch/arm64/boot/dts/rockchip/Makefile +@@ -3,6 +3,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-evb. + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-evb.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-r2s.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-orangepi-r1-plus.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-orangepi-r1-plus-lts.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-rock64.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-roc-cc.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-evb-act8846.dtb +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus-lts.dts +@@ -0,0 +1,66 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2016 Xunlong Software. Co., Ltd. ++ * (http://www.orangepi.org) ++ * ++ * Copyright (c) 2021 Tianling Shen ++ */ ++ ++#include "rk3328-orangepi-r1-plus.dts" ++ ++/ { ++ model = "Xunlong Orange Pi R1 Plus LTS"; ++ compatible = "xunlong,orangepi-r1-plus-lts", "rockchip,rk3328"; ++}; ++ ++&dmc_opp_table { ++ opp-798000000 { ++ status = "disabled"; ++ }; ++ opp-840000000 { ++ status = "disabled"; ++ }; ++ opp-924000000 { ++ status = "disabled"; ++ }; ++ opp-1056000000 { ++ status = "disabled"; ++ }; ++}; ++ ++&gmac2io { ++ phy-handle = <&yt8531c>; ++ tx_delay = <0x19>; ++ rx_delay = <0x05>; ++ ++ mdio { ++ /delete-node/ ethernet-phy@1; ++ ++ yt8531c: ethernet-phy@0 { ++ compatible = "ethernet-phy-id4f51.e91b", ++ "ethernet-phy-ieee802.3-c22"; ++ reg = <0>; ++ pinctrl-0 = <ð_phy_reset_pin>; ++ pinctrl-names = "default"; ++ reset-assert-us = <15000>; ++ reset-deassert-us = <50000>; ++ reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; ++ ++&lan_led { ++ label = "orangepi-r1-plus-lts:green:lan"; ++}; ++ ++&sys_led { ++ label = "orangepi-r1-plus-lts:red:sys"; ++}; ++ ++&usb_eth { ++ realtek,led-data = <0x78>; ++}; ++ ++&wan_led { ++ label = "orangepi-r1-plus-lts:green:wan"; ++}; diff --git a/root/target/linux/rockchip/patches-5.4/204-rockchip-rk3328-Add-support-for-FriendlyARM-NanoPi-R.patch b/root/target/linux/rockchip/patches-5.4/204-rockchip-rk3328-Add-support-for-FriendlyARM-NanoPi-R.patch new file mode 100644 index 00000000..96b43087 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/204-rockchip-rk3328-Add-support-for-FriendlyARM-NanoPi-R.patch @@ -0,0 +1,64 @@ +--- a/arch/arm64/boot/dts/rockchip/Makefile ++++ b/arch/arm64/boot/dts/rockchip/Makefile +@@ -1,6 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-evb.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-evb.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-r2c.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-r2s.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-orangepi-r1-plus.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-orangepi-r1-plus-lts.dtb +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2c.dts +@@ -0,0 +1,51 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2021 FriendlyElec Computer Tech. Co., Ltd. ++ * (http://www.friendlyarm.com) ++ * ++ * Copyright (c) 2021 Tianling Shen ++ */ ++ ++/dts-v1/; ++ ++#include "rk3328-nanopi-r2s.dts" ++ ++/ { ++ model = "FriendlyElec NanoPi R2C"; ++ compatible = "friendlyarm,nanopi-r2c", "rockchip,rk3328"; ++}; ++ ++&gmac2io { ++ phy-handle = <&yt8521s>; ++ ++ mdio { ++ /delete-node/ ethernet-phy@1; ++ ++ yt8521s: ethernet-phy@3 { ++ compatible = "ethernet-phy-id0000.011a", ++ "ethernet-phy-ieee802.3-c22"; ++ reg = <3>; ++ pinctrl-0 = <ð_phy_reset_pin>; ++ pinctrl-names = "default"; ++ reset-assert-us = <10000>; ++ reset-deassert-us = <50000>; ++ reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; ++ ++&lan_led { ++ label = "nanopi-r2c:green:lan"; ++}; ++ ++&sys_led { ++ label = "nanopi-r2c:red:sys"; ++}; ++ ++&usb_eth { ++ realtek,led-data = <0x78>; ++}; ++ ++&wan_led { ++ label = "nanopi-r2c:green:wan"; ++}; diff --git a/root/target/linux/rockchip/patches-5.4/205-rockchip-rk3328-add-support-for-FriendlyARM-NanoPi-Neo3.patch b/root/target/linux/rockchip/patches-5.4/205-rockchip-rk3328-add-support-for-FriendlyARM-NanoPi-Neo3.patch new file mode 100644 index 00000000..06a8f8ed --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/205-rockchip-rk3328-add-support-for-FriendlyARM-NanoPi-Neo3.patch @@ -0,0 +1,444 @@ +From 0f989817a4c1d2c3d196d550ff05cda98bc91324 Mon Sep 17 00:00:00 2001 +From: Julian Pidancet +Date: Sun, 23 Jan 2022 16:34:08 +0100 +Subject: [PATCH v2] rockchip: rk3328: add support for FriendlyARM NanoPi NEO3 + +This patch adds support for FriendlyARM NanoPi NEO3 + +Soc: RockChip RK3328 +RAM: 1GB/2GB DDR4 +LAN: 10/100/1000M Ethernet with unique MAC +USB Host: 1x USB3.0 Type A and 2x USB2.0 on 2.54mm pin header +MicroSD: x 1 for system boot and storage +LED: Power LED x 1, System LED x 1 +Key: User Button x 1 +Fan: 2 Pin JST ZH 1.5mm Connector for 5V Fan +GPIO: 26 pin-header, include I2C, UART, SPI, I2S, GPIO +Power: 5V/1A, via Type-C or GPIO + +Signed-off-by: Julian Pidancet +--- + +This is another shot at previous work submitted by Marty Jones + (https://lore.kernel.org/linux-arm-kernel/20201228152836.02795e09.mj8263788@gmail.com/), +which is now a year old. + +v2: Following up on Robin Murphy's comments, the NEO3 DTS is now +standalone and no longer includes the nanopi R2S one. The lan_led and +wan_len nodes have been removed, and the sys_led node has been renamed +to status_led in accordance with the board schematics. + + arch/arm64/boot/dts/rockchip/Makefile | 1 + + .../boot/dts/rockchip/rk3328-nanopi-neo3.dts | 396 ++++++++++++++++++ + 2 files changed, 397 insertions(+) + create mode 100644 arch/arm64/boot/dts/rockchip/rk3328-nanopi-neo3.dts + +--- a/arch/arm64/boot/dts/rockchip/Makefile ++++ b/arch/arm64/boot/dts/rockchip/Makefile +@@ -3,6 +3,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-evb. + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-evb.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-r2c.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-r2s.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-neo3.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-orangepi-r1-plus.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-orangepi-r1-plus-lts.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-rock64.dtb +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-neo3.dts +@@ -0,0 +1,396 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2020 David Bauer ++ * Copyright (c) 2022 Julian Pidancet ++ */ ++ ++/dts-v1/; ++ ++#include ++#include ++#include "rk3328.dtsi" ++ ++/ { ++ model = "FriendlyElec NanoPi NEO3"; ++ compatible = "friendlyarm,nanopi-neo3", "rockchip,rk3328"; ++ ++ aliases { ++ led-boot = &status_led; ++ led-failsafe = &status_led; ++ led-running = &status_led; ++ led-upgrade = &status_led; ++ }; ++ ++ chosen { ++ stdout-path = "serial2:1500000n8"; ++ }; ++ ++ gmac_clk: gmac-clock { ++ compatible = "fixed-clock"; ++ clock-frequency = <125000000>; ++ clock-output-names = "gmac_clkin"; ++ #clock-cells = <0>; ++ }; ++ ++ keys { ++ compatible = "gpio-keys"; ++ pinctrl-0 = <&reset_button_pin>; ++ pinctrl-names = "default"; ++ ++ reset { ++ label = "reset"; ++ gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_LOW>; ++ linux,code = ; ++ debounce-interval = <50>; ++ }; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ pinctrl-0 = <&status_led_pin>; ++ pinctrl-names = "default"; ++ ++ status_led: led-0 { ++ gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; ++ label = "nanopi-neo3:green:status"; ++ }; ++ }; ++ ++ vcc_io_sdio: sdmmcio-regulator { ++ compatible = "regulator-gpio"; ++ enable-active-high; ++ gpios = <&gpio1 RK_PD4 GPIO_ACTIVE_HIGH>; ++ pinctrl-0 = <&sdio_vcc_pin>; ++ pinctrl-names = "default"; ++ regulator-name = "vcc_io_sdio"; ++ regulator-always-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-settling-time-us = <5000>; ++ regulator-type = "voltage"; ++ startup-delay-us = <2000>; ++ states = <1800000 0x1>, ++ <3300000 0x0>; ++ vin-supply = <&vcc_io_33>; ++ }; ++ ++ vcc_sd: sdmmc-regulator { ++ compatible = "regulator-fixed"; ++ gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>; ++ pinctrl-0 = <&sdmmc0m1_gpio>; ++ pinctrl-names = "default"; ++ regulator-name = "vcc_sd"; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc_io_33>; ++ }; ++ ++ vdd_5v: vdd-5v { ++ compatible = "regulator-fixed"; ++ regulator-name = "vdd_5v"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ }; ++ ++ vcc_rtl8153: vcc-rtl8153-regulator { ++ compatible = "regulator-fixed"; ++ gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rtl8153_en_drv>; ++ regulator-always-on; ++ regulator-name = "vcc_rtl8153"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ enable-active-high; ++ }; ++}; ++ ++&cpu0 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu2 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu3 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&display_subsystem { ++ status = "disabled"; ++}; ++ ++&gmac2io { ++ assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>; ++ assigned-clock-parents = <&gmac_clk>, <&gmac_clk>; ++ clock_in_out = "input"; ++ phy-handle = <&rtl8211e>; ++ phy-mode = "rgmii"; ++ phy-supply = <&vcc_io_33>; ++ pinctrl-0 = <&rgmiim1_pins>; ++ pinctrl-names = "default"; ++ rx_delay = <0x18>; ++ snps,aal; ++ tx_delay = <0x24>; ++ status = "okay"; ++ ++ mdio { ++ compatible = "snps,dwmac-mdio"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ rtl8211e: ethernet-phy@1 { ++ reg = <1>; ++ pinctrl-0 = <ð_phy_reset_pin>; ++ pinctrl-names = "default"; ++ reset-assert-us = <10000>; ++ reset-deassert-us = <50000>; ++ reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; ++ ++&i2c1 { ++ status = "okay"; ++ ++ rk805: pmic@18 { ++ compatible = "rockchip,rk805"; ++ reg = <0x18>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <24 IRQ_TYPE_LEVEL_LOW>; ++ #clock-cells = <1>; ++ clock-output-names = "xin32k", "rk805-clkout2"; ++ gpio-controller; ++ #gpio-cells = <2>; ++ pinctrl-0 = <&pmic_int_l>; ++ pinctrl-names = "default"; ++ rockchip,system-power-controller; ++ wakeup-source; ++ ++ vcc1-supply = <&vdd_5v>; ++ vcc2-supply = <&vdd_5v>; ++ vcc3-supply = <&vdd_5v>; ++ vcc4-supply = <&vdd_5v>; ++ vcc5-supply = <&vcc_io_33>; ++ vcc6-supply = <&vdd_5v>; ++ ++ regulators { ++ vdd_log: DCDC_REG1 { ++ regulator-name = "vdd_log"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1450000>; ++ regulator-ramp-delay = <12500>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1000000>; ++ }; ++ }; ++ ++ vdd_arm: DCDC_REG2 { ++ regulator-name = "vdd_arm"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1450000>; ++ regulator-ramp-delay = <12500>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <950000>; ++ }; ++ }; ++ ++ vcc_ddr: DCDC_REG3 { ++ regulator-name = "vcc_ddr"; ++ regulator-always-on; ++ regulator-boot-on; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc_io_33: DCDC_REG4 { ++ regulator-name = "vcc_io_33"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vcc_18: LDO_REG1 { ++ regulator-name = "vcc_18"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcc18_emmc: LDO_REG2 { ++ regulator-name = "vcc18_emmc"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vdd_10: LDO_REG3 { ++ regulator-name = "vdd_10"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1000000>; ++ regulator-max-microvolt = <1000000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1000000>; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&io_domains { ++ pmuio-supply = <&vcc_io_33>; ++ vccio1-supply = <&vcc_io_33>; ++ vccio2-supply = <&vcc18_emmc>; ++ vccio3-supply = <&vcc_io_sdio>; ++ vccio4-supply = <&vcc_18>; ++ vccio5-supply = <&vcc_io_33>; ++ vccio6-supply = <&vcc_io_33>; ++ status = "okay"; ++}; ++ ++&pinctrl { ++ button { ++ reset_button_pin: reset-button-pin { ++ rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ ethernet-phy { ++ eth_phy_reset_pin: eth-phy-reset-pin { ++ rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>; ++ }; ++ }; ++ ++ leds { ++ status_led_pin: status-led-pin { ++ rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ pmic { ++ pmic_int_l: pmic-int-l { ++ rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ sd { ++ sdio_vcc_pin: sdio-vcc-pin { ++ rockchip,pins = <1 RK_PD4 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ usb { ++ rtl8153_en_drv: rtl8153-en-drv { ++ rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++}; ++ ++&pwm2 { ++ status = "okay"; ++}; ++ ++&sdmmc { ++ bus-width = <4>; ++ cap-sd-highspeed; ++ disable-wp; ++ pinctrl-0 = <&sdmmc0_clk>, <&sdmmc0_cmd>, <&sdmmc0_dectn>, <&sdmmc0_bus4>; ++ pinctrl-names = "default"; ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ sd-uhs-sdr104; ++ vmmc-supply = <&vcc_sd>; ++ vqmmc-supply = <&vcc_io_sdio>; ++ status = "okay"; ++}; ++ ++&tsadc { ++ rockchip,hw-tshut-mode = <0>; ++ rockchip,hw-tshut-polarity = <0>; ++ status = "okay"; ++}; ++ ++&u2phy { ++ status = "okay"; ++}; ++ ++&u2phy_host { ++ status = "okay"; ++}; ++ ++&u2phy_otg { ++ status = "okay"; ++}; ++ ++&uart2 { ++ status = "okay"; ++}; ++ ++&usb20_otg { ++ status = "okay"; ++ dr_mode = "host"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usbdrd3 { ++ status = "okay"; ++}; ++ ++&usbdrd_dwc3 { ++ dr_mode = "host"; ++ status = "okay"; ++ ++ usb-eth@2 { ++ compatible = "realtek,rtl8153"; ++ reg = <2>; ++ ++ realtek,led-data = <0x87>; ++ }; ++}; diff --git a/root/target/linux/rockchip/patches-5.4/206-rockchip-rk3399-add-support-for-Rongpin-King3399.patch b/root/target/linux/rockchip/patches-5.4/206-rockchip-rk3399-add-support-for-Rongpin-King3399.patch new file mode 100644 index 00000000..448065fd --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/206-rockchip-rk3399-add-support-for-Rongpin-King3399.patch @@ -0,0 +1,7 @@ +--- a/arch/arm64/boot/dts/rockchip/Makefile ++++ b/arch/arm64/boot/dts/rockchip/Makefile +@@ -39,3 +39,4 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-ro + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-rockpro64.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-sapphire.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-sapphire-excavator.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-king3399.dtb diff --git a/root/target/linux/rockchip/patches-5.4/210-rockchip-rk356x-add-support-for-new-boards.patch b/root/target/linux/rockchip/patches-5.4/210-rockchip-rk356x-add-support-for-new-boards.patch new file mode 100644 index 00000000..5ba7ca0a --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/210-rockchip-rk356x-add-support-for-new-boards.patch @@ -0,0 +1,13 @@ +--- a/arch/arm64/boot/dts/rockchip/Makefile ++++ b/arch/arm64/boot/dts/rockchip/Makefile +@@ -59,2 +59,10 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-sa + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-sapphire-excavator.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-king3399.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-rock-pi-e25.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-mrkaio-m68s.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-nanopi-r5s.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-opc-h68k.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-rock-3a.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-roc-pc.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-r66s.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-r68s.dtb diff --git a/root/target/linux/rockchip/patches-5.4/600-net-phy-Add-driver-for-Motorcomm-YT85xx-PHYs.patch b/root/target/linux/rockchip/patches-5.4/600-net-phy-Add-driver-for-Motorcomm-YT85xx-PHYs.patch new file mode 100644 index 00000000..db903b2a --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/600-net-phy-Add-driver-for-Motorcomm-YT85xx-PHYs.patch @@ -0,0 +1,39 @@ +From 5d6862cc5eac1679d7a4ef388f7c9bbc70e76770 Mon Sep 17 00:00:00 2001 +From: hmz007 +Date: Mon, 5 Jul 2021 17:03:00 +0800 +Subject: [PATCH] net: phy: Add driver for Motorcomm YT85xx PHYs + +Signed-off-by: hmz007 +--- + drivers/net/phy/Kconfig | 5 + + drivers/net/phy/Makefile | 1 + + drivers/net/phy/motorcomm.c | 346 ++++++++++++++++++++++++++++++++++ + include/linux/motorcomm_phy.h | 68 +++++++ + 4 files changed, 420 insertions(+) + create mode 100644 drivers/net/phy/motorcomm.c + create mode 100644 include/linux/motorcomm_phy.h + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -519,6 +519,11 @@ config MICROSEMI_PHY + ---help--- + Currently supports VSC8514, VSC8530, VSC8531, VSC8540 and VSC8541 PHYs + ++config MOTORCOMM_PHY ++ tristate "Motorcomm PHYs" ++ ---help--- ++ Supports the YT8010, YT8510, YT8511, YT8512 PHYs. ++ + config NATIONAL_PHY + tristate "National Semiconductor PHYs" + ---help--- +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -98,6 +98,7 @@ obj-$(CONFIG_MICREL_PHY) += micrel.o + obj-$(CONFIG_MICROCHIP_PHY) += microchip.o + obj-$(CONFIG_MICROCHIP_T1_PHY) += microchip_t1.o + obj-$(CONFIG_MICROSEMI_PHY) += mscc.o ++obj-$(CONFIG_MOTORCOMM_PHY) += motorcomm.o + obj-$(CONFIG_NATIONAL_PHY) += national.o + obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o + obj-$(CONFIG_QSEMI_PHY) += qsemi.o diff --git a/root/target/linux/rockchip/patches-5.4/801-char-add-support-for-rockchip-hardware-random-number.patch b/root/target/linux/rockchip/patches-5.4/801-char-add-support-for-rockchip-hardware-random-number.patch new file mode 100644 index 00000000..85f14e61 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/801-char-add-support-for-rockchip-hardware-random-number.patch @@ -0,0 +1,45 @@ +From e5b5361651940ff5c0c1784dfd0130abec7ab535 Mon Sep 17 00:00:00 2001 +From: wevsty +Date: Mon, 24 Aug 2020 02:27:11 +0800 +Subject: [PATCH] char: add support for rockchip hardware random number + generator + +This patch provides hardware random number generator support for all rockchip SOC. + +rockchip-rng.c from https://github.com/rockchip-linux/kernel/blob/develop-4.4/drivers/char/hw_random/rockchip-rng.c + +Signed-off-by: wevsty +--- + +--- a/drivers/char/hw_random/Kconfig ++++ b/drivers/char/hw_random/Kconfig +@@ -345,6 +345,19 @@ config HW_RANDOM_STM32 + + If unsure, say N. + ++config HW_RANDOM_ROCKCHIP ++ tristate "Rockchip Random Number Generator support" ++ depends on ARCH_ROCKCHIP ++ default HW_RANDOM ++ help ++ This driver provides kernel-side support for the Random Number ++ Generator hardware found on Rockchip cpus. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called rockchip-rng. ++ ++ If unsure, say Y. ++ + config HW_RANDOM_PIC32 + tristate "Microchip PIC32 Random Number Generator support" + depends on HW_RANDOM && MACH_PIC32 +--- a/drivers/char/hw_random/Makefile ++++ b/drivers/char/hw_random/Makefile +@@ -32,6 +32,7 @@ obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += + obj-$(CONFIG_HW_RANDOM_ST) += st-rng.o + obj-$(CONFIG_HW_RANDOM_XGENE) += xgene-rng.o + obj-$(CONFIG_HW_RANDOM_STM32) += stm32-rng.o ++obj-$(CONFIG_HW_RANDOM_ROCKCHIP) += rockchip-rng.o + obj-$(CONFIG_HW_RANDOM_PIC32) += pic32-rng.o + obj-$(CONFIG_HW_RANDOM_MESON) += meson-rng.o + obj-$(CONFIG_HW_RANDOM_CAVIUM) += cavium-rng.o cavium-rng-vf.o diff --git a/root/target/linux/rockchip/patches-5.4/802-arm64-dts-rockchip-add-hardware-random-number-genera.patch b/root/target/linux/rockchip/patches-5.4/802-arm64-dts-rockchip-add-hardware-random-number-genera.patch new file mode 100644 index 00000000..7157acd2 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/802-arm64-dts-rockchip-add-hardware-random-number-genera.patch @@ -0,0 +1,69 @@ +From e5b5361651940ff5c0c1784dfd0130abec7ab535 Mon Sep 17 00:00:00 2001 +From: wevsty +Date: Mon, 24 Aug 2020 02:27:11 +0800 +Subject: [PATCH] arm64: dts: rockchip: add hardware random number generator + for RK3328 and RK3399 + +Adding Hardware Random Number Generator Resources to the RK3328 and RK3399. + +Signed-off-by: wevsty +--- + +--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +@@ -279,6 +279,17 @@ + status = "disabled"; + }; + ++ rng: rng@ff060000 { ++ compatible = "rockchip,cryptov1-rng"; ++ reg = <0x0 0xff060000 0x0 0x4000>; ++ ++ clocks = <&cru SCLK_CRYPTO>, <&cru HCLK_CRYPTO_SLV>; ++ clock-names = "clk_crypto", "hclk_crypto"; ++ assigned-clocks = <&cru SCLK_CRYPTO>, <&cru HCLK_CRYPTO_SLV>; ++ assigned-clock-rates = <150000000>, <100000000>; ++ status = "disabled"; ++ }; ++ + grf: syscon@ff100000 { + compatible = "rockchip,rk3328-grf", "syscon", "simple-mfd"; + reg = <0x0 0xff100000 0x0 0x1000>; +--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +@@ -1937,6 +1937,16 @@ + }; + }; + ++ rng: rng@ff8b8000 { ++ compatible = "rockchip,cryptov1-rng"; ++ reg = <0x0 0xff8b8000 0x0 0x1000>; ++ clocks = <&cru SCLK_CRYPTO1>, <&cru HCLK_S_CRYPTO1>; ++ clock-names = "clk_crypto", "hclk_crypto"; ++ assigned-clocks = <&cru SCLK_CRYPTO1>, <&cru HCLK_S_CRYPTO1>; ++ assigned-clock-rates = <150000000>, <100000000>; ++ status = "okay"; ++ }; ++ + gpu: gpu@ff9a0000 { + compatible = "rockchip,rk3399-mali", "arm,mali-t860"; + reg = <0x0 0xff9a0000 0x0 0x10000>; +--- a/arch/arm64/boot/dts/rockchip/rk3568.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3568.dtsi +@@ -211,6 +211,16 @@ + }; + }; + ++ rng: rng@fe388000 { ++ compatible = "rockchip,cryptov2-rng"; ++ reg = <0x0 0xfe388000 0x0 0x2000>; ++ clocks = <&cru CLK_TRNG_NS>, <&cru HCLK_TRNG_NS>; ++ clock-names = "clk_trng", "hclk_trng"; ++ resets = <&cru SRST_TRNG_NS>; ++ reset-names = "reset"; ++ status = "disabled"; ++ }; ++ + combphy0: phy@fe820000 { + compatible = "rockchip,rk3568-naneng-combphy"; + reg = <0x0 0xfe820000 0x0 0x100>; diff --git a/root/target/linux/rockchip/patches-5.4/803-PM-devfreq-rockchip-add-devfreq-driver-for-rk3328-dmc.patch b/root/target/linux/rockchip/patches-5.4/803-PM-devfreq-rockchip-add-devfreq-driver-for-rk3328-dmc.patch new file mode 100644 index 00000000..8c4233f1 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/803-PM-devfreq-rockchip-add-devfreq-driver-for-rk3328-dmc.patch @@ -0,0 +1,44 @@ +From fcd9629c05f373771e85920e1c1d0ab252617878 Mon Sep 17 00:00:00 2001 +From: hmz007 +Date: Tue, 19 Nov 2019 13:53:25 +0800 +Subject: [PATCH] PM / devfreq: rockchip: add devfreq driver for rk3328 dmc + +Signed-off-by: hmz007 +--- + drivers/devfreq/Kconfig | 18 +- + drivers/devfreq/Makefile | 1 + + drivers/devfreq/rk3328_dmc.c | 846 +++++++++++++++++++++++++++++++++++ + 3 files changed, 862 insertions(+), 3 deletions(-) + create mode 100644 drivers/devfreq/rk3328_dmc.c + +--- a/drivers/devfreq/Kconfig ++++ b/drivers/devfreq/Kconfig +@@ -116,6 +116,18 @@ config ARM_TEGRA20_DEVFREQ + It reads Memory Controller counters and adjusts the operating + frequencies and voltages with OPP support. + ++config ARM_RK3328_DMC_DEVFREQ ++ tristate "ARM RK3328 DMC DEVFREQ Driver" ++ depends on ARCH_ROCKCHIP ++ select DEVFREQ_EVENT_ROCKCHIP_DFI ++ select DEVFREQ_GOV_SIMPLE_ONDEMAND ++ select PM_DEVFREQ_EVENT ++ select PM_OPP ++ help ++ This adds the DEVFREQ driver for the RK3328 DMC(Dynamic Memory Controller). ++ It sets the frequency for the memory controller and reads the usage counts ++ from hardware. ++ + config ARM_RK3399_DMC_DEVFREQ + tristate "ARM RK3399 DMC DEVFREQ Driver" + depends on (ARCH_ROCKCHIP && HAVE_ARM_SMCCC) || \ +--- a/drivers/devfreq/Makefile ++++ b/drivers/devfreq/Makefile +@@ -9,6 +9,7 @@ obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += gov + + # DEVFREQ Drivers + obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o ++obj-$(CONFIG_ARM_RK3328_DMC_DEVFREQ) += rk3328_dmc.o + obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o + obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o + obj-$(CONFIG_ARM_TEGRA20_DEVFREQ) += tegra20-devfreq.o diff --git a/root/target/linux/rockchip/patches-5.4/804-clk-rockchip-support-setting-ddr-clock-via-SIP-Version-2-.patch b/root/target/linux/rockchip/patches-5.4/804-clk-rockchip-support-setting-ddr-clock-via-SIP-Version-2-.patch new file mode 100644 index 00000000..430a4fd5 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/804-clk-rockchip-support-setting-ddr-clock-via-SIP-Version-2-.patch @@ -0,0 +1,210 @@ +From ce6d3614888e6358466f0e84e248177a6bca5258 Mon Sep 17 00:00:00 2001 +From: Tang Yun ping +Date: Thu, 4 May 2017 20:49:58 +0800 +Subject: [PATCH] clk: rockchip: support setting ddr clock via SIP Version 2 + APIs + +commit 764e893ee82321938fc6f4349e9e7caf06a04410 rockchip. + +Signed-off-by: Tang Yun ping +Signed-off-by: hmz007 +--- + drivers/clk/rockchip/clk-ddr.c | 130 ++++++++++++++++++++++++++++ + drivers/clk/rockchip/clk-rk3328.c | 7 +- + drivers/clk/rockchip/clk.h | 3 +- + include/soc/rockchip/rockchip_sip.h | 11 +++ + 4 files changed, 147 insertions(+), 4 deletions(-) + +--- a/drivers/clk/rockchip/clk-ddr.c ++++ b/drivers/clk/rockchip/clk-ddr.c +@@ -87,6 +87,133 @@ static const struct clk_ops rockchip_ddr + .get_parent = rockchip_ddrclk_get_parent, + }; + ++/* See v4.4/include/dt-bindings/display/rk_fb.h */ ++#define SCREEN_NULL 0 ++#define SCREEN_HDMI 6 ++ ++static inline int rk_drm_get_lcdc_type(void) ++{ ++ return SCREEN_NULL; ++} ++ ++struct share_params { ++ u32 hz; ++ u32 lcdc_type; ++ u32 vop; ++ u32 vop_dclk_mode; ++ u32 sr_idle_en; ++ u32 addr_mcu_el3; ++ /* ++ * 1: need to wait flag1 ++ * 0: never wait flag1 ++ */ ++ u32 wait_flag1; ++ /* ++ * 1: need to wait flag1 ++ * 0: never wait flag1 ++ */ ++ u32 wait_flag0; ++ u32 complt_hwirq; ++ /* if need, add parameter after */ ++}; ++ ++struct rockchip_ddrclk_data { ++ u32 inited_flag; ++ void __iomem *share_memory; ++}; ++ ++static struct rockchip_ddrclk_data ddr_data; ++ ++static void rockchip_ddrclk_data_init(void) ++{ ++ struct arm_smccc_res res; ++ ++ arm_smccc_smc(ROCKCHIP_SIP_SHARE_MEM, ++ 1, SHARE_PAGE_TYPE_DDR, 0, ++ 0, 0, 0, 0, &res); ++ ++ if (!res.a0) { ++ ddr_data.share_memory = (void __iomem *)ioremap(res.a1, 1<<12); ++ ddr_data.inited_flag = 1; ++ } ++} ++ ++static int rockchip_ddrclk_sip_set_rate_v2(struct clk_hw *hw, ++ unsigned long drate, ++ unsigned long prate) ++{ ++ struct share_params *p; ++ struct arm_smccc_res res; ++ ++ if (!ddr_data.inited_flag) ++ rockchip_ddrclk_data_init(); ++ ++ p = (struct share_params *)ddr_data.share_memory; ++ ++ p->hz = drate; ++ p->lcdc_type = rk_drm_get_lcdc_type(); ++ p->wait_flag1 = 1; ++ p->wait_flag0 = 1; ++ ++ arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, ++ SHARE_PAGE_TYPE_DDR, 0, ++ ROCKCHIP_SIP_CONFIG_DRAM_SET_RATE, ++ 0, 0, 0, 0, &res); ++ ++ if ((int)res.a1 == -6) { ++ pr_err("%s: timeout, drate = %lumhz\n", __func__, drate/1000000); ++ /* TODO: rockchip_dmcfreq_wait_complete(); */ ++ } ++ ++ return res.a0; ++} ++ ++static unsigned long rockchip_ddrclk_sip_recalc_rate_v2 ++ (struct clk_hw *hw, unsigned long parent_rate) ++{ ++ struct arm_smccc_res res; ++ ++ arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, ++ SHARE_PAGE_TYPE_DDR, 0, ++ ROCKCHIP_SIP_CONFIG_DRAM_GET_RATE, ++ 0, 0, 0, 0, &res); ++ if (!res.a0) ++ return res.a1; ++ else ++ return 0; ++} ++ ++static long rockchip_ddrclk_sip_round_rate_v2(struct clk_hw *hw, ++ unsigned long rate, ++ unsigned long *prate) ++{ ++ struct share_params *p; ++ struct arm_smccc_res res; ++ ++ if (!ddr_data.inited_flag) ++ rockchip_ddrclk_data_init(); ++ ++ p = (struct share_params *)ddr_data.share_memory; ++ ++ p->hz = rate; ++ ++ arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, ++ SHARE_PAGE_TYPE_DDR, 0, ++ ROCKCHIP_SIP_CONFIG_DRAM_ROUND_RATE, ++ 0, 0, 0, 0, &res); ++ if (!res.a0) ++ return res.a1; ++ else ++ return 0; ++} ++ ++static const struct clk_ops rockchip_ddrclk_sip_ops_v2 = { ++ .recalc_rate = rockchip_ddrclk_sip_recalc_rate_v2, ++ .set_rate = rockchip_ddrclk_sip_set_rate_v2, ++ .round_rate = rockchip_ddrclk_sip_round_rate_v2, ++ .get_parent = rockchip_ddrclk_get_parent, ++}; ++ + struct clk *rockchip_clk_register_ddrclk(const char *name, int flags, + const char *const *parent_names, + u8 num_parents, int mux_offset, +@@ -114,6 +241,9 @@ struct clk *rockchip_clk_register_ddrclk + case ROCKCHIP_DDRCLK_SIP: + init.ops = &rockchip_ddrclk_sip_ops; + break; ++ case ROCKCHIP_DDRCLK_SIP_V2: ++ init.ops = &rockchip_ddrclk_sip_ops_v2; ++ break; + default: + pr_err("%s: unsupported ddrclk type %d\n", __func__, ddr_flag); + kfree(ddrclk); +--- a/drivers/clk/rockchip/clk-rk3328.c ++++ b/drivers/clk/rockchip/clk-rk3328.c +@@ -314,9 +314,10 @@ static struct rockchip_clk_branch rk3328 + RK3328_CLKGATE_CON(14), 1, GFLAGS), + + /* PD_DDR */ +- COMPOSITE(0, "clk_ddr", mux_ddrphy_p, CLK_IGNORE_UNUSED, +- RK3328_CLKSEL_CON(3), 8, 2, MFLAGS, 0, 3, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, +- RK3328_CLKGATE_CON(0), 4, GFLAGS), ++ COMPOSITE_DDRCLK(SCLK_DDRCLK, "sclk_ddrc", mux_ddrphy_p, 0, ++ RK3328_CLKSEL_CON(3), 8, 2, 0, 3, ++ ROCKCHIP_DDRCLK_SIP_V2), ++ + GATE(0, "clk_ddrmsch", "clk_ddr", CLK_IGNORE_UNUSED, + RK3328_CLKGATE_CON(18), 6, GFLAGS), + GATE(0, "clk_ddrupctl", "clk_ddr", CLK_IGNORE_UNUSED, +--- a/drivers/clk/rockchip/clk.h ++++ b/drivers/clk/rockchip/clk.h +@@ -362,7 +362,8 @@ struct clk *rockchip_clk_register_mmc(co + * DDRCLK flags, including method of setting the rate + * ROCKCHIP_DDRCLK_SIP: use SIP call to bl31 to change ddrclk rate. + */ +-#define ROCKCHIP_DDRCLK_SIP BIT(0) ++#define ROCKCHIP_DDRCLK_SIP 0x01 ++#define ROCKCHIP_DDRCLK_SIP_V2 0x03 + + struct clk *rockchip_clk_register_ddrclk(const char *name, int flags, + const char *const *parent_names, +--- a/include/soc/rockchip/rockchip_sip.h ++++ b/include/soc/rockchip/rockchip_sip.h +@@ -16,5 +16,16 @@ + #define ROCKCHIP_SIP_CONFIG_DRAM_CLR_IRQ 0x06 + #define ROCKCHIP_SIP_CONFIG_DRAM_SET_PARAM 0x07 + #define ROCKCHIP_SIP_CONFIG_DRAM_SET_ODT_PD 0x08 ++#define ROCKCHIP_SIP_CONFIG_DRAM_GET_VERSION 0x08 ++ ++#define ROCKCHIP_SIP_SHARE_MEM 0x82000009 ++ ++/* Share mem page types */ ++typedef enum { ++ SHARE_PAGE_TYPE_INVALID = 0, ++ SHARE_PAGE_TYPE_UARTDBG, ++ SHARE_PAGE_TYPE_DDR, ++ SHARE_PAGE_TYPE_MAX, ++} share_page_type_t; + + #endif diff --git a/root/target/linux/rockchip/patches-5.4/805-PM-devfreq-rockchip-dfi-add-more-soc-support.patch b/root/target/linux/rockchip/patches-5.4/805-PM-devfreq-rockchip-dfi-add-more-soc-support.patch new file mode 100644 index 00000000..dee96e82 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/805-PM-devfreq-rockchip-dfi-add-more-soc-support.patch @@ -0,0 +1,663 @@ +From 4db93c6dad0c71750b86163df2fdb21c35f00d9a Mon Sep 17 00:00:00 2001 +From: hmz007 +Date: Tue, 19 Nov 2019 12:49:48 +0800 +Subject: [PATCH] PM / devfreq: rockchip-dfi: add more soc support + +Signed-off-by: hmz007 +--- + drivers/devfreq/event/rockchip-dfi.c | 554 ++++++++++++++++++++++++--- + 1 file changed, 505 insertions(+), 49 deletions(-) + +--- a/drivers/devfreq/event/rockchip-dfi.c ++++ b/drivers/devfreq/event/rockchip-dfi.c +@@ -18,25 +18,66 @@ + #include + #include + +-#include +- +-#define RK3399_DMC_NUM_CH 2 ++#define PX30_PMUGRF_OS_REG2 0x208 + ++#define RK3128_GRF_SOC_CON0 0x140 ++#define RK3128_GRF_OS_REG1 0x1cc ++#define RK3128_GRF_DFI_WRNUM 0x220 ++#define RK3128_GRF_DFI_RDNUM 0x224 ++#define RK3128_GRF_DFI_TIMERVAL 0x22c ++#define RK3128_DDR_MONITOR_EN ((1 << (16 + 6)) + (1 << 6)) ++#define RK3128_DDR_MONITOR_DISB ((1 << (16 + 6)) + (0 << 6)) ++ ++#define RK3288_PMU_SYS_REG2 0x9c ++#define RK3288_GRF_SOC_CON4 0x254 ++#define RK3288_GRF_SOC_STATUS(n) (0x280 + (n) * 4) ++#define RK3288_DFI_EN (0x30003 << 14) ++#define RK3288_DFI_DIS (0x30000 << 14) ++#define RK3288_LPDDR_SEL (0x10001 << 13) ++#define RK3288_DDR3_SEL (0x10000 << 13) ++ ++#define RK3328_GRF_OS_REG2 0x5d0 ++ ++#define RK3368_GRF_DDRC0_CON0 0x600 ++#define RK3368_GRF_SOC_STATUS5 0x494 ++#define RK3368_GRF_SOC_STATUS6 0x498 ++#define RK3368_GRF_SOC_STATUS8 0x4a0 ++#define RK3368_GRF_SOC_STATUS9 0x4a4 ++#define RK3368_GRF_SOC_STATUS10 0x4a8 ++#define RK3368_DFI_EN (0x30003 << 5) ++#define RK3368_DFI_DIS (0x30000 << 5) ++ ++#define MAX_DMC_NUM_CH 2 ++#define READ_DRAMTYPE_INFO(n) (((n) >> 13) & 0x7) ++#define READ_CH_INFO(n) (((n) >> 28) & 0x3) + /* DDRMON_CTRL */ +-#define DDRMON_CTRL 0x04 +-#define CLR_DDRMON_CTRL (0x1f0000 << 0) +-#define LPDDR4_EN (0x10001 << 4) +-#define HARDWARE_EN (0x10001 << 3) +-#define LPDDR3_EN (0x10001 << 2) +-#define SOFTWARE_EN (0x10001 << 1) +-#define SOFTWARE_DIS (0x10000 << 1) +-#define TIME_CNT_EN (0x10001 << 0) ++#define DDRMON_CTRL 0x04 ++#define CLR_DDRMON_CTRL (0x3f0000 << 0) ++#define DDR4_EN (0x10001 << 5) ++#define LPDDR4_EN (0x10001 << 4) ++#define HARDWARE_EN (0x10001 << 3) ++#define LPDDR2_3_EN (0x10001 << 2) ++#define SOFTWARE_EN (0x10001 << 1) ++#define SOFTWARE_DIS (0x10000 << 1) ++#define TIME_CNT_EN (0x10001 << 0) + + #define DDRMON_CH0_COUNT_NUM 0x28 + #define DDRMON_CH0_DFI_ACCESS_NUM 0x2c + #define DDRMON_CH1_COUNT_NUM 0x3c + #define DDRMON_CH1_DFI_ACCESS_NUM 0x40 + ++/* pmu grf */ ++#define PMUGRF_OS_REG2 0x308 ++ ++enum { ++ DDR4 = 0, ++ DDR3 = 3, ++ LPDDR2 = 5, ++ LPDDR3 = 6, ++ LPDDR4 = 7, ++ UNUSED = 0xFF ++}; ++ + struct dmc_usage { + u32 access; + u32 total; +@@ -50,33 +91,261 @@ struct dmc_usage { + struct rockchip_dfi { + struct devfreq_event_dev *edev; + struct devfreq_event_desc *desc; +- struct dmc_usage ch_usage[RK3399_DMC_NUM_CH]; ++ struct dmc_usage ch_usage[MAX_DMC_NUM_CH]; + struct device *dev; + void __iomem *regs; + struct regmap *regmap_pmu; ++ struct regmap *regmap_grf; ++ struct regmap *regmap_pmugrf; + struct clk *clk; ++ u32 dram_type; ++ /* ++ * available mask, 1: available, 0: not available ++ * each bit represent a channel ++ */ ++ u32 ch_msk; ++}; ++ ++static void rk3128_dfi_start_hardware_counter(struct devfreq_event_dev *edev) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ ++ regmap_write(info->regmap_grf, ++ RK3128_GRF_SOC_CON0, ++ RK3128_DDR_MONITOR_EN); ++} ++ ++static void rk3128_dfi_stop_hardware_counter(struct devfreq_event_dev *edev) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ ++ regmap_write(info->regmap_grf, ++ RK3128_GRF_SOC_CON0, ++ RK3128_DDR_MONITOR_DISB); ++} ++ ++static int rk3128_dfi_disable(struct devfreq_event_dev *edev) ++{ ++ rk3128_dfi_stop_hardware_counter(edev); ++ ++ return 0; ++} ++ ++static int rk3128_dfi_enable(struct devfreq_event_dev *edev) ++{ ++ rk3128_dfi_start_hardware_counter(edev); ++ ++ return 0; ++} ++ ++static int rk3128_dfi_set_event(struct devfreq_event_dev *edev) ++{ ++ return 0; ++} ++ ++static int rk3128_dfi_get_event(struct devfreq_event_dev *edev, ++ struct devfreq_event_data *edata) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ unsigned long flags; ++ u32 dfi_wr, dfi_rd, dfi_timer; ++ ++ local_irq_save(flags); ++ ++ rk3128_dfi_stop_hardware_counter(edev); ++ ++ regmap_read(info->regmap_grf, RK3128_GRF_DFI_WRNUM, &dfi_wr); ++ regmap_read(info->regmap_grf, RK3128_GRF_DFI_RDNUM, &dfi_rd); ++ regmap_read(info->regmap_grf, RK3128_GRF_DFI_TIMERVAL, &dfi_timer); ++ ++ edata->load_count = (dfi_wr + dfi_rd) * 4; ++ edata->total_count = dfi_timer; ++ ++ rk3128_dfi_start_hardware_counter(edev); ++ ++ local_irq_restore(flags); ++ ++ return 0; ++} ++ ++static const struct devfreq_event_ops rk3128_dfi_ops = { ++ .disable = rk3128_dfi_disable, ++ .enable = rk3128_dfi_enable, ++ .get_event = rk3128_dfi_get_event, ++ .set_event = rk3128_dfi_set_event, ++}; ++ ++static void rk3288_dfi_start_hardware_counter(struct devfreq_event_dev *edev) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ ++ regmap_write(info->regmap_grf, RK3288_GRF_SOC_CON4, RK3288_DFI_EN); ++} ++ ++static void rk3288_dfi_stop_hardware_counter(struct devfreq_event_dev *edev) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ ++ regmap_write(info->regmap_grf, RK3288_GRF_SOC_CON4, RK3288_DFI_DIS); ++} ++ ++static int rk3288_dfi_disable(struct devfreq_event_dev *edev) ++{ ++ rk3288_dfi_stop_hardware_counter(edev); ++ ++ return 0; ++} ++ ++static int rk3288_dfi_enable(struct devfreq_event_dev *edev) ++{ ++ rk3288_dfi_start_hardware_counter(edev); ++ ++ return 0; ++} ++ ++static int rk3288_dfi_set_event(struct devfreq_event_dev *edev) ++{ ++ return 0; ++} ++ ++static int rk3288_dfi_get_busier_ch(struct devfreq_event_dev *edev) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ u32 tmp, max = 0; ++ u32 i, busier_ch = 0; ++ u32 rd_count, wr_count, total_count; ++ ++ rk3288_dfi_stop_hardware_counter(edev); ++ ++ /* Find out which channel is busier */ ++ for (i = 0; i < MAX_DMC_NUM_CH; i++) { ++ if (!(info->ch_msk & BIT(i))) ++ continue; ++ regmap_read(info->regmap_grf, ++ RK3288_GRF_SOC_STATUS(11 + i * 4), &wr_count); ++ regmap_read(info->regmap_grf, ++ RK3288_GRF_SOC_STATUS(12 + i * 4), &rd_count); ++ regmap_read(info->regmap_grf, ++ RK3288_GRF_SOC_STATUS(14 + i * 4), &total_count); ++ info->ch_usage[i].access = (wr_count + rd_count) * 4; ++ info->ch_usage[i].total = total_count; ++ tmp = info->ch_usage[i].access; ++ if (tmp > max) { ++ busier_ch = i; ++ max = tmp; ++ } ++ } ++ rk3288_dfi_start_hardware_counter(edev); ++ ++ return busier_ch; ++} ++ ++static int rk3288_dfi_get_event(struct devfreq_event_dev *edev, ++ struct devfreq_event_data *edata) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ int busier_ch; ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ busier_ch = rk3288_dfi_get_busier_ch(edev); ++ local_irq_restore(flags); ++ ++ edata->load_count = info->ch_usage[busier_ch].access; ++ edata->total_count = info->ch_usage[busier_ch].total; ++ ++ return 0; ++} ++ ++static const struct devfreq_event_ops rk3288_dfi_ops = { ++ .disable = rk3288_dfi_disable, ++ .enable = rk3288_dfi_enable, ++ .get_event = rk3288_dfi_get_event, ++ .set_event = rk3288_dfi_set_event, ++}; ++ ++static void rk3368_dfi_start_hardware_counter(struct devfreq_event_dev *edev) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ ++ regmap_write(info->regmap_grf, RK3368_GRF_DDRC0_CON0, RK3368_DFI_EN); ++} ++ ++static void rk3368_dfi_stop_hardware_counter(struct devfreq_event_dev *edev) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ ++ regmap_write(info->regmap_grf, RK3368_GRF_DDRC0_CON0, RK3368_DFI_DIS); ++} ++ ++static int rk3368_dfi_disable(struct devfreq_event_dev *edev) ++{ ++ rk3368_dfi_stop_hardware_counter(edev); ++ ++ return 0; ++} ++ ++static int rk3368_dfi_enable(struct devfreq_event_dev *edev) ++{ ++ rk3368_dfi_start_hardware_counter(edev); ++ ++ return 0; ++} ++ ++static int rk3368_dfi_set_event(struct devfreq_event_dev *edev) ++{ ++ return 0; ++} ++ ++static int rk3368_dfi_get_event(struct devfreq_event_dev *edev, ++ struct devfreq_event_data *edata) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ unsigned long flags; ++ u32 dfi0_wr, dfi0_rd, dfi1_wr, dfi1_rd, dfi_timer; ++ ++ local_irq_save(flags); ++ ++ rk3368_dfi_stop_hardware_counter(edev); ++ ++ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS5, &dfi0_wr); ++ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS6, &dfi0_rd); ++ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS9, &dfi1_wr); ++ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS10, &dfi1_rd); ++ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS8, &dfi_timer); ++ ++ edata->load_count = (dfi0_wr + dfi0_rd + dfi1_wr + dfi1_rd) * 2; ++ edata->total_count = dfi_timer; ++ ++ rk3368_dfi_start_hardware_counter(edev); ++ ++ local_irq_restore(flags); ++ ++ return 0; ++} ++ ++static const struct devfreq_event_ops rk3368_dfi_ops = { ++ .disable = rk3368_dfi_disable, ++ .enable = rk3368_dfi_enable, ++ .get_event = rk3368_dfi_get_event, ++ .set_event = rk3368_dfi_set_event, + }; + + static void rockchip_dfi_start_hardware_counter(struct devfreq_event_dev *edev) + { + struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); + void __iomem *dfi_regs = info->regs; +- u32 val; +- u32 ddr_type; +- +- /* get ddr type */ +- regmap_read(info->regmap_pmu, RK3399_PMUGRF_OS_REG2, &val); +- ddr_type = (val >> RK3399_PMUGRF_DDRTYPE_SHIFT) & +- RK3399_PMUGRF_DDRTYPE_MASK; + + /* clear DDRMON_CTRL setting */ + writel_relaxed(CLR_DDRMON_CTRL, dfi_regs + DDRMON_CTRL); + + /* set ddr type to dfi */ +- if (ddr_type == RK3399_PMUGRF_DDRTYPE_LPDDR3) +- writel_relaxed(LPDDR3_EN, dfi_regs + DDRMON_CTRL); +- else if (ddr_type == RK3399_PMUGRF_DDRTYPE_LPDDR4) ++ if (info->dram_type == LPDDR3 || info->dram_type == LPDDR2) ++ writel_relaxed(LPDDR2_3_EN, dfi_regs + DDRMON_CTRL); ++ else if (info->dram_type == LPDDR4) + writel_relaxed(LPDDR4_EN, dfi_regs + DDRMON_CTRL); ++ else if (info->dram_type == DDR4) ++ writel_relaxed(DDR4_EN, dfi_regs + DDRMON_CTRL); + + /* enable count, use software mode */ + writel_relaxed(SOFTWARE_EN, dfi_regs + DDRMON_CTRL); +@@ -100,12 +369,22 @@ static int rockchip_dfi_get_busier_ch(st + rockchip_dfi_stop_hardware_counter(edev); + + /* Find out which channel is busier */ +- for (i = 0; i < RK3399_DMC_NUM_CH; i++) { +- info->ch_usage[i].access = readl_relaxed(dfi_regs + +- DDRMON_CH0_DFI_ACCESS_NUM + i * 20) * 4; ++ for (i = 0; i < MAX_DMC_NUM_CH; i++) { ++ if (!(info->ch_msk & BIT(i))) ++ continue; ++ + info->ch_usage[i].total = readl_relaxed(dfi_regs + + DDRMON_CH0_COUNT_NUM + i * 20); +- tmp = info->ch_usage[i].access; ++ ++ /* LPDDR4 BL = 16,other DDR type BL = 8 */ ++ tmp = readl_relaxed(dfi_regs + ++ DDRMON_CH0_DFI_ACCESS_NUM + i * 20); ++ if (info->dram_type == LPDDR4) ++ tmp *= 8; ++ else ++ tmp *= 4; ++ info->ch_usage[i].access = tmp; ++ + if (tmp > max) { + busier_ch = i; + max = tmp; +@@ -121,7 +400,8 @@ static int rockchip_dfi_disable(struct d + struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); + + rockchip_dfi_stop_hardware_counter(edev); +- clk_disable_unprepare(info->clk); ++ if (info->clk) ++ clk_disable_unprepare(info->clk); + + return 0; + } +@@ -131,10 +411,13 @@ static int rockchip_dfi_enable(struct de + struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); + int ret; + +- ret = clk_prepare_enable(info->clk); +- if (ret) { +- dev_err(&edev->dev, "failed to enable dfi clk: %d\n", ret); +- return ret; ++ if (info->clk) { ++ ret = clk_prepare_enable(info->clk); ++ if (ret) { ++ dev_err(&edev->dev, "failed to enable dfi clk: %d\n", ++ ret); ++ return ret; ++ } + } + + rockchip_dfi_start_hardware_counter(edev); +@@ -151,8 +434,11 @@ static int rockchip_dfi_get_event(struct + { + struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); + int busier_ch; ++ unsigned long flags; + ++ local_irq_save(flags); + busier_ch = rockchip_dfi_get_busier_ch(edev); ++ local_irq_restore(flags); + + edata->load_count = info->ch_usage[busier_ch].access; + edata->total_count = info->ch_usage[busier_ch].total; +@@ -167,23 +453,117 @@ static const struct devfreq_event_ops ro + .set_event = rockchip_dfi_set_event, + }; + +-static const struct of_device_id rockchip_dfi_id_match[] = { +- { .compatible = "rockchip,rk3399-dfi" }, +- { }, +-}; +-MODULE_DEVICE_TABLE(of, rockchip_dfi_id_match); ++static __init int px30_dfi_init(struct platform_device *pdev, ++ struct rockchip_dfi *data, ++ struct devfreq_event_desc *desc) ++{ ++ struct device_node *np = pdev->dev.of_node, *node; ++ struct resource *res; ++ u32 val; + +-static int rockchip_dfi_probe(struct platform_device *pdev) ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ data->regs = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(data->regs)) ++ return PTR_ERR(data->regs); ++ ++ node = of_parse_phandle(np, "rockchip,pmugrf", 0); ++ if (node) { ++ data->regmap_pmugrf = syscon_node_to_regmap(node); ++ if (IS_ERR(data->regmap_pmugrf)) ++ return PTR_ERR(data->regmap_pmugrf); ++ } ++ ++ regmap_read(data->regmap_pmugrf, PX30_PMUGRF_OS_REG2, &val); ++ data->dram_type = READ_DRAMTYPE_INFO(val); ++ data->ch_msk = 1; ++ data->clk = NULL; ++ ++ desc->ops = &rockchip_dfi_ops; ++ ++ return 0; ++} ++ ++static __init int rk3128_dfi_init(struct platform_device *pdev, ++ struct rockchip_dfi *data, ++ struct devfreq_event_desc *desc) ++{ ++ struct device_node *np = pdev->dev.of_node, *node; ++ ++ node = of_parse_phandle(np, "rockchip,grf", 0); ++ if (node) { ++ data->regmap_grf = syscon_node_to_regmap(node); ++ if (IS_ERR(data->regmap_grf)) ++ return PTR_ERR(data->regmap_grf); ++ } ++ ++ desc->ops = &rk3128_dfi_ops; ++ ++ return 0; ++} ++ ++static __init int rk3288_dfi_init(struct platform_device *pdev, ++ struct rockchip_dfi *data, ++ struct devfreq_event_desc *desc) ++{ ++ struct device_node *np = pdev->dev.of_node, *node; ++ u32 val; ++ ++ node = of_parse_phandle(np, "rockchip,pmu", 0); ++ if (node) { ++ data->regmap_pmu = syscon_node_to_regmap(node); ++ if (IS_ERR(data->regmap_pmu)) ++ return PTR_ERR(data->regmap_pmu); ++ } ++ ++ node = of_parse_phandle(np, "rockchip,grf", 0); ++ if (node) { ++ data->regmap_grf = syscon_node_to_regmap(node); ++ if (IS_ERR(data->regmap_grf)) ++ return PTR_ERR(data->regmap_grf); ++ } ++ ++ regmap_read(data->regmap_pmu, RK3288_PMU_SYS_REG2, &val); ++ data->dram_type = READ_DRAMTYPE_INFO(val); ++ data->ch_msk = READ_CH_INFO(val); ++ ++ if (data->dram_type == DDR3) ++ regmap_write(data->regmap_grf, RK3288_GRF_SOC_CON4, ++ RK3288_DDR3_SEL); ++ else ++ regmap_write(data->regmap_grf, RK3288_GRF_SOC_CON4, ++ RK3288_LPDDR_SEL); ++ ++ desc->ops = &rk3288_dfi_ops; ++ ++ return 0; ++} ++ ++static __init int rk3368_dfi_init(struct platform_device *pdev, ++ struct rockchip_dfi *data, ++ struct devfreq_event_desc *desc) ++{ ++ struct device *dev = &pdev->dev; ++ ++ if (!dev->parent || !dev->parent->of_node) ++ return -EINVAL; ++ ++ data->regmap_grf = syscon_node_to_regmap(dev->parent->of_node); ++ if (IS_ERR(data->regmap_grf)) ++ return PTR_ERR(data->regmap_grf); ++ ++ desc->ops = &rk3368_dfi_ops; ++ ++ return 0; ++} ++ ++static __init int rockchip_dfi_init(struct platform_device *pdev, ++ struct rockchip_dfi *data, ++ struct devfreq_event_desc *desc) + { + struct device *dev = &pdev->dev; +- struct rockchip_dfi *data; + struct resource *res; +- struct devfreq_event_desc *desc; + struct device_node *np = pdev->dev.of_node, *node; +- +- data = devm_kzalloc(dev, sizeof(struct rockchip_dfi), GFP_KERNEL); +- if (!data) +- return -ENOMEM; ++ u32 val; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + data->regs = devm_ioremap_resource(&pdev->dev, res); +@@ -203,21 +583,97 @@ static int rockchip_dfi_probe(struct pla + if (IS_ERR(data->regmap_pmu)) + return PTR_ERR(data->regmap_pmu); + } +- data->dev = dev; ++ ++ regmap_read(data->regmap_pmu, PMUGRF_OS_REG2, &val); ++ data->dram_type = READ_DRAMTYPE_INFO(val); ++ data->ch_msk = READ_CH_INFO(val); ++ ++ desc->ops = &rockchip_dfi_ops; ++ ++ return 0; ++} ++ ++static __init int rk3328_dfi_init(struct platform_device *pdev, ++ struct rockchip_dfi *data, ++ struct devfreq_event_desc *desc) ++{ ++ struct device_node *np = pdev->dev.of_node, *node; ++ struct resource *res; ++ u32 val; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ data->regs = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(data->regs)) ++ return PTR_ERR(data->regs); ++ ++ node = of_parse_phandle(np, "rockchip,grf", 0); ++ if (node) { ++ data->regmap_grf = syscon_node_to_regmap(node); ++ if (IS_ERR(data->regmap_grf)) ++ return PTR_ERR(data->regmap_grf); ++ } ++ ++ regmap_read(data->regmap_grf, RK3328_GRF_OS_REG2, &val); ++ data->dram_type = READ_DRAMTYPE_INFO(val); ++ data->ch_msk = 1; ++ data->clk = NULL; ++ ++ desc->ops = &rockchip_dfi_ops; ++ ++ return 0; ++} ++ ++static const struct of_device_id rockchip_dfi_id_match[] = { ++ { .compatible = "rockchip,px30-dfi", .data = px30_dfi_init }, ++ { .compatible = "rockchip,rk1808-dfi", .data = px30_dfi_init }, ++ { .compatible = "rockchip,rk3128-dfi", .data = rk3128_dfi_init }, ++ { .compatible = "rockchip,rk3288-dfi", .data = rk3288_dfi_init }, ++ { .compatible = "rockchip,rk3328-dfi", .data = rk3328_dfi_init }, ++ { .compatible = "rockchip,rk3368-dfi", .data = rk3368_dfi_init }, ++ { .compatible = "rockchip,rk3399-dfi", .data = rockchip_dfi_init }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, rockchip_dfi_id_match); ++ ++static int rockchip_dfi_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct rockchip_dfi *data; ++ struct devfreq_event_desc *desc; ++ struct device_node *np = pdev->dev.of_node; ++ const struct of_device_id *match; ++ int (*init)(struct platform_device *pdev, struct rockchip_dfi *data, ++ struct devfreq_event_desc *desc); ++ ++ data = devm_kzalloc(dev, sizeof(struct rockchip_dfi), GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; + + desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL); + if (!desc) + return -ENOMEM; + +- desc->ops = &rockchip_dfi_ops; ++ match = of_match_node(rockchip_dfi_id_match, pdev->dev.of_node); ++ if (match) { ++ init = match->data; ++ if (init) { ++ if (init(pdev, data, desc)) ++ return -EINVAL; ++ } else { ++ return 0; ++ } ++ } else { ++ return 0; ++ } ++ + desc->driver_data = data; + desc->name = np->name; + data->desc = desc; ++ data->dev = dev; + +- data->edev = devm_devfreq_event_add_edev(&pdev->dev, desc); ++ data->edev = devm_devfreq_event_add_edev(dev, desc); + if (IS_ERR(data->edev)) { +- dev_err(&pdev->dev, +- "failed to add devfreq-event device\n"); ++ dev_err(dev, "failed to add devfreq-event device\n"); + return PTR_ERR(data->edev); + } + diff --git a/root/target/linux/rockchip/patches-5.4/806-arm64-dts-rockchip-rk3328-add-dfi-node.patch b/root/target/linux/rockchip/patches-5.4/806-arm64-dts-rockchip-rk3328-add-dfi-node.patch new file mode 100644 index 00000000..e9b79b6f --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/806-arm64-dts-rockchip-rk3328-add-dfi-node.patch @@ -0,0 +1,27 @@ +From f9ae6e992d3d9e80357fee7d65ba0fe2dd37ae1f Mon Sep 17 00:00:00 2001 +From: hmz007 +Date: Tue, 19 Nov 2019 14:21:51 +0800 +Subject: [PATCH] arm64: dts: rockchip: rk3328: add dfi node + +Signed-off-by: hmz007 +[adjusted commit title] +Signed-off-by: Tianling Shen +--- + arch/arm64/boot/dts/rockchip/rk3328.dtsi | 7 +++++++ + +--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +@@ -993,6 +993,13 @@ + }; + }; + ++ dfi: dfi@ff790000 { ++ reg = <0x00 0xff790000 0x00 0x400>; ++ compatible = "rockchip,rk3328-dfi"; ++ rockchip,grf = <&grf>; ++ status = "disabled"; ++ }; ++ + gic: interrupt-controller@ff811000 { + compatible = "arm,gic-400"; + #interrupt-cells = <3>; diff --git a/root/target/linux/rockchip/patches-5.4/807-arm64-dts-nanopi-r2s-add-rk3328-dmc-relate-node.patch b/root/target/linux/rockchip/patches-5.4/807-arm64-dts-nanopi-r2s-add-rk3328-dmc-relate-node.patch new file mode 100644 index 00000000..091e2959 --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/807-arm64-dts-nanopi-r2s-add-rk3328-dmc-relate-node.patch @@ -0,0 +1,126 @@ +From f9ae6e992d3d9e80357fee7d65ba0fe2dd37ae1f Mon Sep 17 00:00:00 2001 +From: hmz007 +Date: Tue, 19 Nov 2019 14:21:51 +0800 +Subject: [PATCH] arm64: dts: nanopi-r2: add rk3328-dmc relate node + +Signed-off-by: hmz007 +--- + .../rockchip/rk3328-dram-default-timing.dtsi | 311 ++++++++++++++++++ + .../dts/rockchip/rk3328-nanopi-r2-common.dtsi | 85 ++++- + include/dt-bindings/clock/rockchip-ddr.h | 63 ++++ + include/dt-bindings/memory/rk3328-dram.h | 159 +++++++++ + 4 files changed, 617 insertions(+), 1 deletion(-) + create mode 100644 arch/arm64/boot/dts/rockchip/rk3328-dram-default-timing.dtsi + create mode 100644 include/dt-bindings/clock/rockchip-ddr.h + create mode 100644 include/dt-bindings/memory/rk3328-dram.h + +--- a/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts +@@ -7,6 +7,7 @@ + + #include + #include ++#include "rk3328-dram-default-timing.dtsi" + #include "rk3328.dtsi" + + / { +@@ -115,6 +116,72 @@ + regulator-max-microvolt = <5000000>; + enable-active-high; + }; ++ ++ dmc: dmc { ++ compatible = "rockchip,rk3328-dmc"; ++ devfreq-events = <&dfi>; ++ center-supply = <&vdd_log>; ++ clocks = <&cru SCLK_DDRCLK>; ++ clock-names = "dmc_clk"; ++ operating-points-v2 = <&dmc_opp_table>; ++ ddr_timing = <&ddr_timing>; ++ upthreshold = <40>; ++ downdifferential = <20>; ++ auto-min-freq = <786000>; ++ auto-freq-en = <0>; ++ #cooling-cells = <2>; ++ status = "okay"; ++ ++ ddr_power_model: ddr_power_model { ++ compatible = "ddr_power_model"; ++ dynamic-power-coefficient = <120>; ++ static-power-coefficient = <200>; ++ ts = <32000 4700 (-80) 2>; ++ thermal-zone = "soc-thermal"; ++ }; ++ }; ++ ++ dmc_opp_table: dmc-opp-table { ++ compatible = "operating-points-v2"; ++ ++ rockchip,leakage-voltage-sel = < ++ 1 10 0 ++ 11 254 1 ++ >; ++ nvmem-cells = <&logic_leakage>; ++ nvmem-cell-names = "ddr_leakage"; ++ ++ opp-786000000 { ++ opp-hz = /bits/ 64 <786000000>; ++ opp-microvolt = <1075000>; ++ opp-microvolt-L0 = <1075000>; ++ opp-microvolt-L1 = <1050000>; ++ }; ++ opp-798000000 { ++ opp-hz = /bits/ 64 <798000000>; ++ opp-microvolt = <1075000>; ++ opp-microvolt-L0 = <1075000>; ++ opp-microvolt-L1 = <1050000>; ++ }; ++ opp-840000000 { ++ opp-hz = /bits/ 64 <840000000>; ++ opp-microvolt = <1075000>; ++ opp-microvolt-L0 = <1075000>; ++ opp-microvolt-L1 = <1050000>; ++ }; ++ opp-924000000 { ++ opp-hz = /bits/ 64 <924000000>; ++ opp-microvolt = <1100000>; ++ opp-microvolt-L0 = <1100000>; ++ opp-microvolt-L1 = <1075000>; ++ }; ++ opp-1056000000 { ++ opp-hz = /bits/ 64 <1056000000>; ++ opp-microvolt = <1175000>; ++ opp-microvolt-L0 = <1175000>; ++ opp-microvolt-L1 = <1150000>; ++ }; ++ }; + }; + + &cpu0 { +@@ -133,6 +200,10 @@ + cpu-supply = <&vdd_arm>; + }; + ++&dfi { ++ status = "okay"; ++}; ++ + &gmac2io { + assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>; + assigned-clock-parents = <&gmac_clk>, <&gmac_clk>; +@@ -198,6 +269,7 @@ + regulator-name = "vdd_log"; + regulator-always-on; + regulator-boot-on; ++ regulator-init-microvolt = <1075000>; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1450000>; + regulator-ramp-delay = <12500>; +@@ -212,6 +284,7 @@ + regulator-name = "vdd_arm"; + regulator-always-on; + regulator-boot-on; ++ regulator-init-microvolt = <1225000>; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1450000>; + regulator-ramp-delay = <12500>; diff --git a/root/target/linux/rockchip/patches-5.4/991-arm64-dts-rockchip-add-more-cpu-operating-points-for.patch b/root/target/linux/rockchip/patches-5.4/991-arm64-dts-rockchip-add-more-cpu-operating-points-for.patch new file mode 100644 index 00000000..818ee4ce --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/991-arm64-dts-rockchip-add-more-cpu-operating-points-for.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Leonidas P. Papadakos +Date: Fri, 1 Mar 2019 21:55:53 +0200 +Subject: [PATCH v2] arm64: dts: rockchip: add more cpu operating points for + RK3328 + +This allows for greater max frequency on rk3328 boards, +increasing performance. + +It has been included in Armbian (a linux distibution for ARM boards) +for a while now without any reported issues + +https://github.com/armbian/build/blob/master/patch/kernel/rockchip64-default/enable-1392mhz-opp.patch +https://github.com/armbian/build/blob/master/patch/kernel/rockchip64-default/enable-1512mhz-opp.patch + +Signed-off-by: Leonidas P. Papadakos +--- + arch/arm64/boot/dts/rockchip/rk3328.dtsi | 15 +++++++++++++++ + 1 files changed, 15 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +@@ -140,6 +140,21 @@ + opp-microvolt = <1300000>; + clock-latency-ns = <40000>; + }; ++ opp-1392000000 { ++ opp-hz = /bits/ 64 <1392000000>; ++ opp-microvolt = <1350000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1512000000 { ++ opp-hz = /bits/ 64 <1512000000>; ++ opp-microvolt = <1400000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1608000000 { ++ opp-hz = /bits/ 64 <1608000000>; ++ opp-microvolt = <1450000>; ++ clock-latency-ns = <40000>; ++ }; + }; + + amba { diff --git a/root/target/linux/rockchip/patches-5.4/992-rockchip-rk3399-overclock-to-2.2-1.8-GHz.patch b/root/target/linux/rockchip/patches-5.4/992-rockchip-rk3399-overclock-to-2.2-1.8-GHz.patch new file mode 100644 index 00000000..12cb932d --- /dev/null +++ b/root/target/linux/rockchip/patches-5.4/992-rockchip-rk3399-overclock-to-2.2-1.8-GHz.patch @@ -0,0 +1,46 @@ +From 04202df5cb497b1934c95211cf43784ef62245a4 Mon Sep 17 00:00:00 2001 +From: Tianling Shen +Date: Mon, 18 Oct 2021 12:47:30 +0800 +Subject: [PATCH] rockchip: rk3399: overclock to 2.2/1.8 GHz + +It's stable enough to overclock cpu frequency to 2.2/1.8 GHz, +and for better performance. + +Co-development-by: gzelvis +Signed-off-by: Tianling Shen +--- + arch/arm64/boot/dts/rockchip/rk3399-opp.dtsi | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3399-opp.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-opp.dtsi +@@ -33,6 +33,14 @@ + opp-hz = /bits/ 64 <1416000000>; + opp-microvolt = <1125000>; + }; ++ opp06 { ++ opp-hz = /bits/ 64 <1608000000>; ++ opp-microvolt = <1225000>; ++ }; ++ opp07 { ++ opp-hz = /bits/ 64 <1800000000>; ++ opp-microvolt = <1275000>; ++ }; + }; + + cluster1_opp: opp-table1 { +@@ -72,6 +80,14 @@ + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <1200000>; + }; ++ opp08 { ++ opp-hz = /bits/ 64 <2016000000>; ++ opp-microvolt = <1250000>; ++ }; ++ opp09 { ++ opp-hz = /bits/ 64 <2208000000>; ++ opp-microvolt = <1325000>; ++ }; + }; + + gpu_opp_table: opp-table2 { From c7c730337a298f0bd703bc3d8a0f70c1e87e72cf Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 18 Nov 2022 18:12:09 +0100 Subject: [PATCH 044/102] Update 5.15 kernel config --- root/target/linux/generic/config-5.15 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/root/target/linux/generic/config-5.15 b/root/target/linux/generic/config-5.15 index a3303d5b..737c20bf 100644 --- a/root/target/linux/generic/config-5.15 +++ b/root/target/linux/generic/config-5.15 @@ -328,6 +328,7 @@ CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8 # CONFIG_ARM64_ERRATUM_1508412 is not set # CONFIG_ARM64_ERRATUM_1530923 is not set # CONFIG_ARM64_ERRATUM_1542419 is not set +# CONFIG_ARM64_ERRATUM_1742098 is not set # CONFIG_ARM64_ERRATUM_819472 is not set # CONFIG_ARM64_ERRATUM_824069 is not set # CONFIG_ARM64_ERRATUM_826319 is not set @@ -411,6 +412,7 @@ CONFIG_ARM_MODULE_PLTS=y # CONFIG_ARM_PSCI_CHECKER is not set # CONFIG_ARM_PSCI_CPUIDLE is not set # CONFIG_ARM_PTDUMP_DEBUGFS is not set +# CONFIG_ARM_RK3328_DMC_DEVFREQ is not set # CONFIG_ARM_SBSA_WATCHDOG is not set # CONFIG_ARM_SCPI_PROTOCOL is not set # CONFIG_ARM_SDE_INTERFACE is not set @@ -2383,6 +2385,7 @@ CONFIG_HW_PERF_EVENTS=y # CONFIG_HW_RANDOM_PPC4XX is not set # CONFIG_HW_RANDOM_TIMERIOMEM is not set CONFIG_HW_RANDOM_TPM=y +# CONFIG_HW_RANDOM_ROCKCHIP is not set # CONFIG_HW_RANDOM_VIA is not set # CONFIG_HW_RANDOM_VIRTIO is not set # CONFIG_HW_RANDOM_XIPHERA is not set From 7f1d15191bcdf231680e2a83eed5727f0d9578d4 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 18 Nov 2022 18:12:31 +0100 Subject: [PATCH 045/102] Add R5S config --- config-r4s | 2 +- config-r5s | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 config-r5s diff --git a/config-r4s b/config-r4s index 5d235497..ccb2af0b 100644 --- a/config-r4s +++ b/config-r4s @@ -2,7 +2,7 @@ CONFIG_TARGET_rockchip=y CONFIG_TARGET_rockchip_armv8=y CONFIG_TARGET_rockchip_armv8_DEVICE_friendlyarm_nanopi-r4s=y CONFIG_PACKAGE_kmod-6lowpan=y -CONFIG_KERNEL_ARM_MODULE_PLTS=y +CONFIG_KERNEL_ARM64_MODULE_PLTS=y CONFIG_KERNEL_TCP_CONG_BBR2=y CONFIG_CRYPTO_HW=y CONFIG_ARM64_CRYPTO=y diff --git a/config-r5s b/config-r5s new file mode 100644 index 00000000..46514267 --- /dev/null +++ b/config-r5s @@ -0,0 +1,13 @@ +CONFIG_TARGET_rockchip=y +CONFIG_TARGET_rockchip_armv8=y +CONFIG_TARGET_rockchip_armv8_DEVICE_friendlyarm_nanopi-r5s=y +CONFIG_PACKAGE_kmod-6lowpan=y +CONFIG_KERNEL_ARM64_MODULE_PLTS=y +CONFIG_KERNEL_TCP_CONG_BBR2=y +CONFIG_CRYPTO_HW=y +CONFIG_ARM64_CRYPTO=y +CONFIG_CRYPTO_SHA1_ARM_CE=y +CONFIG_CRYPTO_SHA2_ARM_CE=y +CONFIG_CRYPTO_GHASH_ARM_CE=y +CONFIG_CRYPTO_AES_ARM=y +CONFIG_CRYPTO_AES_ARM_CE=y From 3d0fb489fd439bf953a1c7eb1d2a8a6c759d5732 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 18 Nov 2022 18:12:48 +0100 Subject: [PATCH 046/102] Fix r2s config --- config-r2s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config-r2s b/config-r2s index 292f4db5..78171435 100644 --- a/config-r2s +++ b/config-r2s @@ -2,7 +2,7 @@ CONFIG_TARGET_rockchip=y CONFIG_TARGET_rockchip_armv8=y CONFIG_TARGET_rockchip_armv8_DEVICE_friendlyarm_nanopi-r2s=y CONFIG_PACKAGE_kmod-6lowpan=y -CONFIG_KERNEL_ARM_MODULE_PLTS=y +CONFIG_KERNEL_ARM64_MODULE_PLTS=y CONFIG_KERNEL_TCP_CONG_BBR2=y CONFIG_CRYPTO_HW=y CONFIG_ARM64_CRYPTO=y From 87b90117aa23457c1268f2bd7d692db332229c2d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 18 Nov 2022 20:56:33 +0100 Subject: [PATCH 047/102] Update rockchip 5.15 kernel --- root/target/linux/rockchip/armv8/config-5.15 | 1 + 1 file changed, 1 insertion(+) diff --git a/root/target/linux/rockchip/armv8/config-5.15 b/root/target/linux/rockchip/armv8/config-5.15 index 85299456..d6430824 100644 --- a/root/target/linux/rockchip/armv8/config-5.15 +++ b/root/target/linux/rockchip/armv8/config-5.15 @@ -70,6 +70,7 @@ CONFIG_ARM_PSCI_CPUIDLE_DOMAIN=y CONFIG_ARM_PSCI_FW=y CONFIG_ARM_RK3328_DMC_DEVFREQ=y # CONFIG_ARM_RK3399_DMC_DEVFREQ is not set +# CONFIG_ARM_SCMI_CPUFREQ is not set CONFIG_ARM_SCMI_PROTOCOL=y CONFIG_ARM_SCPI_CPUFREQ=y CONFIG_ARM_SCPI_POWER_DOMAIN=y From 348ec04da01cc2a373457f9de5c3f60c597bb8eb Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 20 Nov 2022 08:05:27 +0100 Subject: [PATCH 048/102] Update rockchip 5.15 kernel config --- root/target/linux/rockchip/armv8/config-5.15 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/root/target/linux/rockchip/armv8/config-5.15 b/root/target/linux/rockchip/armv8/config-5.15 index d6430824..3183926f 100644 --- a/root/target/linux/rockchip/armv8/config-5.15 +++ b/root/target/linux/rockchip/armv8/config-5.15 @@ -71,7 +71,8 @@ CONFIG_ARM_PSCI_FW=y CONFIG_ARM_RK3328_DMC_DEVFREQ=y # CONFIG_ARM_RK3399_DMC_DEVFREQ is not set # CONFIG_ARM_SCMI_CPUFREQ is not set -CONFIG_ARM_SCMI_PROTOCOL=y +# CONFIG_ARM_SCMI_PROTOCOL is not set +# CONFIG_ARM_SCMI_TRANSPORT_MAILBOX is not set CONFIG_ARM_SCPI_CPUFREQ=y CONFIG_ARM_SCPI_POWER_DOMAIN=y CONFIG_ARM_SCPI_PROTOCOL=y From 403e257a341e5e09e3eb86262b11f2314572cc06 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 20 Nov 2022 16:42:49 +0100 Subject: [PATCH 049/102] Update 5.15 config --- root/target/linux/rockchip/armv8/config-5.15 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/root/target/linux/rockchip/armv8/config-5.15 b/root/target/linux/rockchip/armv8/config-5.15 index 3183926f..e69c9f6b 100644 --- a/root/target/linux/rockchip/armv8/config-5.15 +++ b/root/target/linux/rockchip/armv8/config-5.15 @@ -176,6 +176,7 @@ CONFIG_CRYPTO_CRC32C=y CONFIG_CRYPTO_CRCT10DIF=y CONFIG_CRYPTO_CRCT10DIF_ARM64_CE=y CONFIG_CRYPTO_CRYPTD=y +# CONFIG_CRYPTO_DEV_ROCKCHIP is not set CONFIG_CRYPTO_GHASH_ARM64_CE=y CONFIG_CRYPTO_GF128MUL=y CONFIG_CRYPTO_LIB_SHA256=y @@ -209,6 +210,7 @@ CONFIG_DMA_REMAP=y # CONFIG_DMA_RESTRICTED_POOL is not set CONFIG_DMA_SHARED_BUFFER=y CONFIG_DNOTIFY=y +# CONFIG_DRM_ROCKCHIP is not set CONFIG_DTC=y CONFIG_DT_IDLE_STATES=y CONFIG_DUMMY_CONSOLE=y @@ -312,6 +314,7 @@ CONFIG_INPUT_KEYBOARD=y CONFIG_INPUT_LEDS=y CONFIG_INPUT_MATRIXKMAP=y # CONFIG_INPUT_MISC is not set +# CONFIG_INPUT_RK805_PWRKEY is not set CONFIG_IOMMU_API=y # CONFIG_IOMMU_DEBUGFS is not set # CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set @@ -557,6 +560,7 @@ CONFIG_ROCKCHIP_MBOX=y # CONFIG_ROCKCHIP_OTP is not set CONFIG_ROCKCHIP_PHY=y CONFIG_ROCKCHIP_PM_DOMAINS=y +# CONFIG_ROCKCHIP_SARADC is not set CONFIG_ROCKCHIP_THERMAL=y CONFIG_ROCKCHIP_TIMER=y CONFIG_RODATA_FULL_DEFAULT_ENABLED=y From 064a17e169ba7343fc0039dfd875dd71862bbec2 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Tue, 22 Nov 2022 14:10:17 +0800 Subject: [PATCH 050/102] fix --- ...onntrack-events-support-multiple-registrant.patch | 2 +- ...t-patch-linux-kernel-to-support-shortcut-fe.patch | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/root/target/linux/generic/hack-5.4/952-net-conntrack-events-support-multiple-registrant.patch b/root/target/linux/generic/hack-5.4/952-net-conntrack-events-support-multiple-registrant.patch index c7634495..e01728fc 100755 --- a/root/target/linux/generic/hack-5.4/952-net-conntrack-events-support-multiple-registrant.patch +++ b/root/target/linux/generic/hack-5.4/952-net-conntrack-events-support-multiple-registrant.patch @@ -98,7 +98,7 @@ Signed-off-by: Zhi Chen #if defined(CONFIG_NF_CONNTRACK_LABELS) --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig -@@ -136,6 +136,14 @@ config NF_CONNTRACK_EVENTS +@@ -135,6 +135,14 @@ config NF_CONNTRACK_EVENTS If unsure, say `N'. diff --git a/root/target/linux/generic/hack-5.4/953-net-patch-linux-kernel-to-support-shortcut-fe.patch b/root/target/linux/generic/hack-5.4/953-net-patch-linux-kernel-to-support-shortcut-fe.patch index 57b40292..a25ed559 100755 --- a/root/target/linux/generic/hack-5.4/953-net-patch-linux-kernel-to-support-shortcut-fe.patch +++ b/root/target/linux/generic/hack-5.4/953-net-patch-linux-kernel-to-support-shortcut-fe.patch @@ -12,9 +12,9 @@ struct list_head *br_ip_list); --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h -@@ -826,6 +826,10 @@ struct sk_buff { +@@ -827,6 +827,10 @@ struct sk_buff { #endif - __u8 gro_skip:1; + __u8 scm_io_uring:1; +#ifdef CONFIG_SHORTCUT_FE + __u8 fast_forwarded:1; @@ -99,7 +99,7 @@ #ifdef CONFIG_ETHERNET_PACKET_MANGLE if (!dev->eth_mangle_tx || (skb = dev->eth_mangle_tx(dev, skb)) != NULL) -@@ -4714,6 +4722,11 @@ void netdev_rx_handler_unregister(struct +@@ -4715,6 +4723,11 @@ void netdev_rx_handler_unregister(struct } EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister); @@ -111,7 +111,7 @@ /* * Limit the use of PFMEMALLOC reserves to those protocols that implement * the special handling of PFMEMALLOC skbs. -@@ -4764,6 +4777,10 @@ static int __netif_receive_skb_core(stru +@@ -4765,6 +4778,10 @@ static int __netif_receive_skb_core(stru int ret = NET_RX_DROP; __be16 type; @@ -119,10 +119,10 @@ + int (*fast_recv)(struct sk_buff *skb); +#endif + - net_timestamp_check(!netdev_tstamp_prequeue, skb); + net_timestamp_check(!READ_ONCE(netdev_tstamp_prequeue), skb); trace_netif_receive_skb(skb); -@@ -4803,6 +4820,16 @@ another_round: +@@ -4804,6 +4821,16 @@ another_round: goto out; } From 766555f9945bcc241045c66e4a63c8c60ed162a6 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Tue, 22 Nov 2022 14:19:14 +0800 Subject: [PATCH 051/102] fix x --- ...ter-export-udp_get_timeouts-function.patch | 34 + ...lter-connmark-introduce-set-dscpmark.patch | 212 +++++++ .../hack-5.4/647-netfilter-flow-acct.patch | 70 +++ .../650-netfilter-add-xt_OFFLOAD-target.patch | 589 ++++++++++++++++++ 4 files changed, 905 insertions(+) create mode 100644 root/target/linux/generic/hack-5.4/601-netfilter-export-udp_get_timeouts-function.patch create mode 100644 root/target/linux/generic/hack-5.4/645-netfilter-connmark-introduce-set-dscpmark.patch create mode 100644 root/target/linux/generic/hack-5.4/647-netfilter-flow-acct.patch create mode 100644 root/target/linux/generic/hack-5.4/650-netfilter-add-xt_OFFLOAD-target.patch diff --git a/root/target/linux/generic/hack-5.4/601-netfilter-export-udp_get_timeouts-function.patch b/root/target/linux/generic/hack-5.4/601-netfilter-export-udp_get_timeouts-function.patch new file mode 100644 index 00000000..ef3fba22 --- /dev/null +++ b/root/target/linux/generic/hack-5.4/601-netfilter-export-udp_get_timeouts-function.patch @@ -0,0 +1,34 @@ +From ba041eb8000e4a8f556ca641335894f7e7429dbb Mon Sep 17 00:00:00 2001 +From: Ailick <277498654@qq.com> +Date: Sat, 21 Aug 2021 17:12:22 +0800 +Subject: [PATCH] net: patch linux kernel to support shortcut-fe-cm + +--- + nf_conntrack_proto_udp.c | 3 ++- + nf_conntrack_timeout.h | 2 + + 1 file changed, 2 insertion(+) + +--- a/include/net/netfilter/nf_conntrack_timeout.h ++++ b/include/net/netfilter/nf_conntrack_timeout.h +@@ -124,4 +124,6 @@ extern struct nf_ct_timeout *(*nf_ct_tim + extern void (*nf_ct_timeout_put_hook)(struct nf_ct_timeout *timeout); + #endif + ++extern unsigned int *udp_get_timeouts(struct net *net); ++ + #endif /* _NF_CONNTRACK_TIMEOUT_H */ +--- a/net/netfilter/nf_conntrack_proto_udp.c ++++ b/net/netfilter/nf_conntrack_proto_udp.c +@@ -29,10 +29,11 @@ static const unsigned int udp_timeouts[U + [UDP_CT_REPLIED] = 120*HZ, + }; + +-static unsigned int *udp_get_timeouts(struct net *net) ++unsigned int *udp_get_timeouts(struct net *net) + { + return nf_udp_pernet(net)->timeouts; + } ++EXPORT_SYMBOL(udp_get_timeouts); + + static void udp_error_log(const struct sk_buff *skb, + const struct nf_hook_state *state, diff --git a/root/target/linux/generic/hack-5.4/645-netfilter-connmark-introduce-set-dscpmark.patch b/root/target/linux/generic/hack-5.4/645-netfilter-connmark-introduce-set-dscpmark.patch new file mode 100644 index 00000000..2d3fe01a --- /dev/null +++ b/root/target/linux/generic/hack-5.4/645-netfilter-connmark-introduce-set-dscpmark.patch @@ -0,0 +1,212 @@ +From eda40b8c8c82e0f2789d6bc8bf63846dce2e8f32 Mon Sep 17 00:00:00 2001 +From: Kevin Darbyshire-Bryant +Date: Sat, 23 Mar 2019 09:29:49 +0000 +Subject: [PATCH] netfilter: connmark: introduce set-dscpmark + +set-dscpmark is a method of storing the DSCP of an ip packet into +conntrack mark. In combination with a suitable tc filter action +(act_ctinfo) DSCP values are able to be stored in the mark on egress and +restored on ingress across links that otherwise alter or bleach DSCP. + +This is useful for qdiscs such as CAKE which are able to shape according +to policies based on DSCP. + +Ingress classification is traditionally a challenging task since +iptables rules haven't yet run and tc filter/eBPF programs are pre-NAT +lookups, hence are unable to see internal IPv4 addresses as used on the +typical home masquerading gateway. + +x_tables CONNMARK set-dscpmark target solves the problem of storing the +DSCP to the conntrack mark in a way suitable for the new act_ctinfo tc +action to restore. + +The set-dscpmark option accepts 2 parameters, a 32bit 'dscpmask' and a +32bit 'statemask'. The dscp mask must be 6 contiguous bits and +represents the area where the DSCP will be stored in the connmark. The +state mask is a minimum 1 bit length mask that must not overlap with the +dscpmask. It represents a flag which is set when the DSCP has been +stored in the conntrack mark. This is useful to implement a 'one shot' +iptables based classification where the 'complicated' iptables rules are +only run once to classify the connection on initial (egress) packet and +subsequent packets are all marked/restored with the same DSCP. A state +mask of zero disables the setting of a status bit/s. + +example syntax with a suitably modified iptables user space application: + +iptables -A QOS_MARK_eth0 -t mangle -j CONNMARK --set-dscpmark 0xfc000000/0x01000000 + +Would store the DSCP in the top 6 bits of the 32bit mark field, and use +the LSB of the top byte as the 'DSCP has been stored' marker. + +|----0xFC----conntrack mark----000000---| +| Bits 31-26 | bit 25 | bit24 |~~~ Bit 0| +| DSCP | unused | flag |unused | +|-----------------------0x01---000000---| + ^ ^ + | | + ---| Conditional flag + | set this when dscp +|-ip diffserv-| stored in mark +| 6 bits | +|-------------| + +an identically configured tc action to restore looks like: + +tc filter show dev eth0 ingress +filter parent ffff: protocol all pref 10 u32 chain 0 +filter parent ffff: protocol all pref 10 u32 chain 0 fh 800: ht divisor 1 +filter parent ffff: protocol all pref 10 u32 chain 0 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1: not_in_hw + match 00000000/00000000 at 0 + action order 1: ctinfo zone 0 pipe + index 2 ref 1 bind 1 dscp 0xfc000000/0x1000000 + + action order 2: mirred (Egress Redirect to device ifb4eth0) stolen + index 1 ref 1 bind 1 + +|----0xFC----conntrack mark----000000---| +| Bits 31-26 | bit 25 | bit24 |~~~ Bit 0| +| DSCP | unused | flag |unused | +|-----------------------0x01---000000---| + | | + | | + ---| Conditional flag + v only restore if set +|-ip diffserv-| +| 6 bits | +|-------------| + +Signed-off-by: Kevin Darbyshire-Bryant +--- + include/uapi/linux/netfilter/xt_connmark.h | 10 ++++ + net/netfilter/xt_connmark.c | 55 ++++++++++++++++++---- + 2 files changed, 57 insertions(+), 8 deletions(-) + +--- a/include/uapi/linux/netfilter/xt_connmark.h ++++ b/include/uapi/linux/netfilter/xt_connmark.h +@@ -20,6 +20,11 @@ enum { + }; + + enum { ++ XT_CONNMARK_VALUE = (1 << 0), ++ XT_CONNMARK_DSCP = (1 << 1) ++}; ++ ++enum { + D_SHIFT_LEFT = 0, + D_SHIFT_RIGHT, + }; +@@ -34,6 +39,11 @@ struct xt_connmark_tginfo2 { + __u8 shift_dir, shift_bits, mode; + }; + ++struct xt_connmark_tginfo3 { ++ __u32 ctmark, ctmask, nfmask; ++ __u8 shift_dir, shift_bits, mode, func; ++}; ++ + struct xt_connmark_mtinfo1 { + __u32 mark, mask; + __u8 invert; +--- a/net/netfilter/xt_connmark.c ++++ b/net/netfilter/xt_connmark.c +@@ -24,12 +24,13 @@ MODULE_ALIAS("ipt_connmark"); + MODULE_ALIAS("ip6t_connmark"); + + static unsigned int +-connmark_tg_shift(struct sk_buff *skb, const struct xt_connmark_tginfo2 *info) ++connmark_tg_shift(struct sk_buff *skb, const struct xt_connmark_tginfo3 *info) + { + enum ip_conntrack_info ctinfo; + u_int32_t new_targetmark; + struct nf_conn *ct; + u_int32_t newmark; ++ u_int8_t dscp; + + ct = nf_ct_get(skb, &ctinfo); + if (ct == NULL) +@@ -37,12 +38,24 @@ connmark_tg_shift(struct sk_buff *skb, c + + switch (info->mode) { + case XT_CONNMARK_SET: +- newmark = (ct->mark & ~info->ctmask) ^ info->ctmark; +- if (info->shift_dir == D_SHIFT_RIGHT) +- newmark >>= info->shift_bits; +- else +- newmark <<= info->shift_bits; ++ newmark = ct->mark; ++ if (info->func & XT_CONNMARK_VALUE) { ++ newmark = (newmark & ~info->ctmask) ^ info->ctmark; ++ if (info->shift_dir == D_SHIFT_RIGHT) ++ newmark >>= info->shift_bits; ++ else ++ newmark <<= info->shift_bits; ++ } else if (info->func & XT_CONNMARK_DSCP) { ++ if (skb->protocol == htons(ETH_P_IP)) ++ dscp = ipv4_get_dsfield(ip_hdr(skb)) >> 2; ++ else if (skb->protocol == htons(ETH_P_IPV6)) ++ dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> 2; ++ else /* protocol doesn't have diffserv */ ++ break; + ++ newmark = (newmark & ~info->ctmark) | ++ (info->ctmask | (dscp << info->shift_bits)); ++ } + if (ct->mark != newmark) { + ct->mark = newmark; + nf_conntrack_event_cache(IPCT_MARK, ct); +@@ -81,20 +94,36 @@ static unsigned int + connmark_tg(struct sk_buff *skb, const struct xt_action_param *par) + { + const struct xt_connmark_tginfo1 *info = par->targinfo; +- const struct xt_connmark_tginfo2 info2 = { ++ const struct xt_connmark_tginfo3 info3 = { + .ctmark = info->ctmark, + .ctmask = info->ctmask, + .nfmask = info->nfmask, + .mode = info->mode, ++ .func = XT_CONNMARK_VALUE + }; + +- return connmark_tg_shift(skb, &info2); ++ return connmark_tg_shift(skb, &info3); + } + + static unsigned int + connmark_tg_v2(struct sk_buff *skb, const struct xt_action_param *par) + { + const struct xt_connmark_tginfo2 *info = par->targinfo; ++ const struct xt_connmark_tginfo3 info3 = { ++ .ctmark = info->ctmark, ++ .ctmask = info->ctmask, ++ .nfmask = info->nfmask, ++ .mode = info->mode, ++ .func = XT_CONNMARK_VALUE ++ }; ++ ++ return connmark_tg_shift(skb, &info3); ++} ++ ++static unsigned int ++connmark_tg_v3(struct sk_buff *skb, const struct xt_action_param *par) ++{ ++ const struct xt_connmark_tginfo3 *info = par->targinfo; + + return connmark_tg_shift(skb, info); + } +@@ -165,6 +194,16 @@ static struct xt_target connmark_tg_reg[ + .targetsize = sizeof(struct xt_connmark_tginfo2), + .destroy = connmark_tg_destroy, + .me = THIS_MODULE, ++ }, ++ { ++ .name = "CONNMARK", ++ .revision = 3, ++ .family = NFPROTO_UNSPEC, ++ .checkentry = connmark_tg_check, ++ .target = connmark_tg_v3, ++ .targetsize = sizeof(struct xt_connmark_tginfo3), ++ .destroy = connmark_tg_destroy, ++ .me = THIS_MODULE, + } + }; + diff --git a/root/target/linux/generic/hack-5.4/647-netfilter-flow-acct.patch b/root/target/linux/generic/hack-5.4/647-netfilter-flow-acct.patch new file mode 100644 index 00000000..9f7ca615 --- /dev/null +++ b/root/target/linux/generic/hack-5.4/647-netfilter-flow-acct.patch @@ -0,0 +1,70 @@ +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -163,6 +163,8 @@ struct nf_flow_table_hw { + int nf_flow_table_hw_register(const struct nf_flow_table_hw *offload); + void nf_flow_table_hw_unregister(const struct nf_flow_table_hw *offload); + ++void nf_flow_table_acct(struct flow_offload *flow, struct sk_buff *skb, int dir); ++ + extern struct work_struct nf_flow_offload_hw_work; + + #define MODULE_ALIAS_NF_FLOWTABLE(family) \ +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + + struct flow_offload_entry { + struct flow_offload flow; +@@ -177,6 +178,22 @@ void flow_offload_free(struct flow_offlo + } + EXPORT_SYMBOL_GPL(flow_offload_free); + ++void nf_flow_table_acct(struct flow_offload *flow, struct sk_buff *skb, int dir) ++{ ++ struct flow_offload_entry *entry; ++ struct nf_conn_acct *acct; ++ ++ entry = container_of(flow, struct flow_offload_entry, flow); ++ acct = nf_conn_acct_find(entry->ct); ++ if (acct) { ++ struct nf_conn_counter *counter = acct->counter; ++ ++ atomic64_inc(&counter[dir].packets); ++ atomic64_add(skb->len, &counter[dir].bytes); ++ } ++} ++EXPORT_SYMBOL_GPL(nf_flow_table_acct); ++ + static u32 flow_offload_hash(const void *data, u32 len, u32 seed) + { + const struct flow_offload_tuple *tuple = data; +--- a/net/netfilter/nf_flow_table_ip.c ++++ b/net/netfilter/nf_flow_table_ip.c +@@ -12,6 +12,7 @@ + #include + #include + #include ++ + /* For layer 4 checksum field offset. */ + #include + #include +@@ -288,6 +289,7 @@ nf_flow_offload_ip_hook(void *priv, stru + skb->dev = outdev; + nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr); + skb_dst_set_noref(skb, &rt->dst); ++ nf_flow_table_acct(flow, skb, dir); + neigh_xmit(NEIGH_ARP_TABLE, outdev, &nexthop, skb); + + return NF_STOLEN; +@@ -518,6 +520,7 @@ nf_flow_offload_ipv6_hook(void *priv, st + skb->dev = outdev; + nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6); + skb_dst_set_noref(skb, &rt->dst); ++ nf_flow_table_acct(flow, skb, dir); + neigh_xmit(NEIGH_ND_TABLE, outdev, nexthop, skb); + + return NF_STOLEN; diff --git a/root/target/linux/generic/hack-5.4/650-netfilter-add-xt_OFFLOAD-target.patch b/root/target/linux/generic/hack-5.4/650-netfilter-add-xt_OFFLOAD-target.patch new file mode 100644 index 00000000..8d9fec06 --- /dev/null +++ b/root/target/linux/generic/hack-5.4/650-netfilter-add-xt_OFFLOAD-target.patch @@ -0,0 +1,589 @@ +From: Felix Fietkau +Date: Tue, 20 Feb 2018 15:56:02 +0100 +Subject: [PATCH] netfilter: add xt_OFFLOAD target + +Signed-off-by: Felix Fietkau +--- + create mode 100644 net/netfilter/xt_OFFLOAD.c + +--- a/net/ipv4/netfilter/Kconfig ++++ b/net/ipv4/netfilter/Kconfig +@@ -56,8 +56,6 @@ config NF_TABLES_ARP + help + This option enables the ARP support for nf_tables. + +-endif # NF_TABLES +- + config NF_FLOW_TABLE_IPV4 + tristate "Netfilter flow table IPv4 module" + depends on NF_FLOW_TABLE +@@ -66,6 +64,8 @@ config NF_FLOW_TABLE_IPV4 + + To compile it as a module, choose M here. + ++endif # NF_TABLES ++ + config NF_DUP_IPV4 + tristate "Netfilter IPv4 packet duplication to alternate destination" + depends on !NF_CONNTRACK || NF_CONNTRACK +--- a/net/ipv6/netfilter/Kconfig ++++ b/net/ipv6/netfilter/Kconfig +@@ -45,7 +45,6 @@ config NFT_FIB_IPV6 + multicast or blackhole. + + endif # NF_TABLES_IPV6 +-endif # NF_TABLES + + config NF_FLOW_TABLE_IPV6 + tristate "Netfilter flow table IPv6 module" +@@ -55,6 +54,8 @@ config NF_FLOW_TABLE_IPV6 + + To compile it as a module, choose M here. + ++endif # NF_TABLES ++ + config NF_DUP_IPV6 + tristate "Netfilter IPv6 packet duplication to alternate destination" + depends on !NF_CONNTRACK || NF_CONNTRACK +--- a/net/netfilter/Kconfig ++++ b/net/netfilter/Kconfig +@@ -689,8 +689,6 @@ config NFT_FIB_NETDEV + + endif # NF_TABLES_NETDEV + +-endif # NF_TABLES +- + config NF_FLOW_TABLE_INET + tristate "Netfilter flow table mixed IPv4/IPv6 module" + depends on NF_FLOW_TABLE +@@ -699,11 +697,12 @@ config NF_FLOW_TABLE_INET + + To compile it as a module, choose M here. + ++endif # NF_TABLES ++ + config NF_FLOW_TABLE + tristate "Netfilter flow table module" + depends on NETFILTER_INGRESS + depends on NF_CONNTRACK +- depends on NF_TABLES + help + This option adds the flow table core infrastructure. + +@@ -992,6 +991,15 @@ config NETFILTER_XT_TARGET_NOTRACK + depends on NETFILTER_ADVANCED + select NETFILTER_XT_TARGET_CT + ++config NETFILTER_XT_TARGET_FLOWOFFLOAD ++ tristate '"FLOWOFFLOAD" target support' ++ depends on NF_FLOW_TABLE ++ depends on NETFILTER_INGRESS ++ help ++ This option adds a `FLOWOFFLOAD' target, which uses the nf_flow_offload ++ module to speed up processing of packets by bypassing the usual ++ netfilter chains ++ + config NETFILTER_XT_TARGET_RATEEST + tristate '"RATEEST" target support' + depends on NETFILTER_ADVANCED +--- a/net/netfilter/Makefile ++++ b/net/netfilter/Makefile +@@ -141,6 +141,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIF + obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o + obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o + obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o ++obj-$(CONFIG_NETFILTER_XT_TARGET_FLOWOFFLOAD) += xt_FLOWOFFLOAD.o + obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o + obj-$(CONFIG_NETFILTER_XT_TARGET_HMARK) += xt_HMARK.o + obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o +--- /dev/null ++++ b/net/netfilter/xt_FLOWOFFLOAD.c +@@ -0,0 +1,427 @@ ++/* ++ * Copyright (C) 2018 Felix Fietkau ++ * ++ * 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. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static struct nf_flowtable nf_flowtable; ++static HLIST_HEAD(hooks); ++static DEFINE_SPINLOCK(hooks_lock); ++static struct delayed_work hook_work; ++ ++struct xt_flowoffload_hook { ++ struct hlist_node list; ++ struct nf_hook_ops ops; ++ struct net *net; ++ bool registered; ++ bool used; ++}; ++ ++static unsigned int ++xt_flowoffload_net_hook(void *priv, struct sk_buff *skb, ++ const struct nf_hook_state *state) ++{ ++ switch (skb->protocol) { ++ case htons(ETH_P_IP): ++ return nf_flow_offload_ip_hook(priv, skb, state); ++ case htons(ETH_P_IPV6): ++ return nf_flow_offload_ipv6_hook(priv, skb, state); ++ } ++ ++ return NF_ACCEPT; ++} ++ ++int nf_flow_table_iterate(struct nf_flowtable *flow_table, ++ void (*iter)(struct flow_offload *flow, void *data), ++ void *data); ++ ++static int ++xt_flowoffload_create_hook(struct net_device *dev) ++{ ++ struct xt_flowoffload_hook *hook; ++ struct nf_hook_ops *ops; ++ ++ hook = kzalloc(sizeof(*hook), GFP_ATOMIC); ++ if (!hook) ++ return -ENOMEM; ++ ++ ops = &hook->ops; ++ ops->pf = NFPROTO_NETDEV; ++ ops->hooknum = NF_NETDEV_INGRESS; ++ ops->priority = 10; ++ ops->priv = &nf_flowtable; ++ ops->hook = xt_flowoffload_net_hook; ++ ops->dev = dev; ++ ++ hlist_add_head(&hook->list, &hooks); ++ mod_delayed_work(system_power_efficient_wq, &hook_work, 0); ++ ++ return 0; ++} ++ ++static struct xt_flowoffload_hook * ++flow_offload_lookup_hook(struct net_device *dev) ++{ ++ struct xt_flowoffload_hook *hook; ++ ++ hlist_for_each_entry(hook, &hooks, list) { ++ if (hook->ops.dev == dev) ++ return hook; ++ } ++ ++ return NULL; ++} ++ ++static void ++xt_flowoffload_check_device(struct net_device *dev) ++{ ++ struct xt_flowoffload_hook *hook; ++ ++ spin_lock_bh(&hooks_lock); ++ hook = flow_offload_lookup_hook(dev); ++ if (hook) ++ hook->used = true; ++ else ++ xt_flowoffload_create_hook(dev); ++ spin_unlock_bh(&hooks_lock); ++} ++ ++static void ++xt_flowoffload_register_hooks(void) ++{ ++ struct xt_flowoffload_hook *hook; ++ ++restart: ++ hlist_for_each_entry(hook, &hooks, list) { ++ if (hook->registered) ++ continue; ++ ++ hook->registered = true; ++ hook->net = dev_net(hook->ops.dev); ++ spin_unlock_bh(&hooks_lock); ++ nf_register_net_hook(hook->net, &hook->ops); ++ spin_lock_bh(&hooks_lock); ++ goto restart; ++ } ++ ++} ++ ++static void ++xt_flowoffload_cleanup_hooks(void) ++{ ++ struct xt_flowoffload_hook *hook; ++ ++restart: ++ hlist_for_each_entry(hook, &hooks, list) { ++ if (hook->used || !hook->registered) ++ continue; ++ ++ hlist_del(&hook->list); ++ spin_unlock_bh(&hooks_lock); ++ nf_unregister_net_hook(hook->net, &hook->ops); ++ kfree(hook); ++ spin_lock_bh(&hooks_lock); ++ goto restart; ++ } ++ ++} ++ ++static void ++xt_flowoffload_check_hook(struct flow_offload *flow, void *data) ++{ ++ struct flow_offload_tuple *tuple = &flow->tuplehash[0].tuple; ++ struct xt_flowoffload_hook *hook; ++ bool *found = data; ++ struct rtable *rt = (struct rtable *)tuple->dst_cache; ++ ++ spin_lock_bh(&hooks_lock); ++ hlist_for_each_entry(hook, &hooks, list) { ++ if (hook->ops.dev->ifindex != tuple->iifidx && ++ hook->ops.dev->ifindex != rt->dst.dev->ifindex) ++ continue; ++ ++ hook->used = true; ++ *found = true; ++ } ++ spin_unlock_bh(&hooks_lock); ++} ++ ++static void ++xt_flowoffload_hook_work(struct work_struct *work) ++{ ++ struct xt_flowoffload_hook *hook; ++ bool found = false; ++ int err; ++ ++ spin_lock_bh(&hooks_lock); ++ xt_flowoffload_register_hooks(); ++ hlist_for_each_entry(hook, &hooks, list) ++ hook->used = false; ++ spin_unlock_bh(&hooks_lock); ++ ++ err = nf_flow_table_iterate(&nf_flowtable, xt_flowoffload_check_hook, ++ &found); ++ if (err && err != -EAGAIN) ++ goto out; ++ ++ spin_lock_bh(&hooks_lock); ++ xt_flowoffload_cleanup_hooks(); ++ spin_unlock_bh(&hooks_lock); ++ ++out: ++ if (found) ++ queue_delayed_work(system_power_efficient_wq, &hook_work, HZ); ++} ++ ++static bool ++xt_flowoffload_skip(struct sk_buff *skb, int family) ++{ ++ if (skb_sec_path(skb)) ++ return true; ++ ++ if (family == NFPROTO_IPV4) { ++ const struct ip_options *opt = &(IPCB(skb)->opt); ++ ++ if (unlikely(opt->optlen)) ++ return true; ++ } ++ ++ return false; ++} ++ ++static struct dst_entry * ++xt_flowoffload_dst(const struct nf_conn *ct, enum ip_conntrack_dir dir, ++ const struct xt_action_param *par, int ifindex) ++{ ++ struct dst_entry *dst = NULL; ++ struct flowi fl; ++ ++ memset(&fl, 0, sizeof(fl)); ++ switch (xt_family(par)) { ++ case NFPROTO_IPV4: ++ fl.u.ip4.daddr = ct->tuplehash[dir].tuple.src.u3.ip; ++ fl.u.ip4.flowi4_oif = ifindex; ++ break; ++ case NFPROTO_IPV6: ++ fl.u.ip6.saddr = ct->tuplehash[dir].tuple.dst.u3.in6; ++ fl.u.ip6.daddr = ct->tuplehash[dir].tuple.src.u3.in6; ++ fl.u.ip6.flowi6_oif = ifindex; ++ break; ++ } ++ ++ nf_route(xt_net(par), &dst, &fl, false, xt_family(par)); ++ ++ return dst; ++} ++ ++static int ++xt_flowoffload_route(struct sk_buff *skb, const struct nf_conn *ct, ++ const struct xt_action_param *par, ++ struct nf_flow_route *route, enum ip_conntrack_dir dir) ++{ ++ struct dst_entry *this_dst, *other_dst; ++ ++ this_dst = xt_flowoffload_dst(ct, !dir, par, xt_out(par)->ifindex); ++ other_dst = xt_flowoffload_dst(ct, dir, par, xt_in(par)->ifindex); ++ ++ route->tuple[dir].dst = this_dst; ++ route->tuple[!dir].dst = other_dst; ++ ++ if (!this_dst || !other_dst) ++ return -ENOENT; ++ ++ if (dst_xfrm(this_dst) || dst_xfrm(other_dst)) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static unsigned int ++flowoffload_tg(struct sk_buff *skb, const struct xt_action_param *par) ++{ ++ const struct xt_flowoffload_target_info *info = par->targinfo; ++ struct tcphdr _tcph, *tcph = NULL; ++ enum ip_conntrack_info ctinfo; ++ enum ip_conntrack_dir dir; ++ struct nf_flow_route route; ++ struct flow_offload *flow = NULL; ++ struct nf_conn *ct; ++ struct net *net; ++ ++ if (xt_flowoffload_skip(skb, xt_family(par))) ++ return XT_CONTINUE; ++ ++ ct = nf_ct_get(skb, &ctinfo); ++ if (ct == NULL) ++ return XT_CONTINUE; ++ ++ switch (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum) { ++ case IPPROTO_TCP: ++ if (ct->proto.tcp.state != TCP_CONNTRACK_ESTABLISHED) ++ return XT_CONTINUE; ++ ++ tcph = skb_header_pointer(skb, par->thoff, ++ sizeof(_tcph), &_tcph); ++ if (unlikely(!tcph || tcph->fin || tcph->rst)) ++ return XT_CONTINUE; ++ break; ++ case IPPROTO_UDP: ++ break; ++ default: ++ return XT_CONTINUE; ++ } ++ ++ if (nf_ct_ext_exist(ct, NF_CT_EXT_HELPER) || ++ ct->status & IPS_SEQ_ADJUST) ++ return XT_CONTINUE; ++ ++ if (!nf_ct_is_confirmed(ct)) ++ return XT_CONTINUE; ++ ++ if (!xt_in(par) || !xt_out(par)) ++ return XT_CONTINUE; ++ ++ if (test_and_set_bit(IPS_OFFLOAD_BIT, &ct->status)) ++ return XT_CONTINUE; ++ ++ dir = CTINFO2DIR(ctinfo); ++ ++ if (xt_flowoffload_route(skb, ct, par, &route, dir) == 0) ++ flow = flow_offload_alloc(ct, &route); ++ ++ dst_release(route.tuple[dir].dst); ++ dst_release(route.tuple[!dir].dst); ++ ++ if (!flow) ++ goto err_flow_route; ++ ++ if (tcph) { ++ ct->proto.tcp.seen[0].flags |= IP_CT_TCP_FLAG_BE_LIBERAL; ++ ct->proto.tcp.seen[1].flags |= IP_CT_TCP_FLAG_BE_LIBERAL; ++ } ++ ++ if (flow_offload_add(&nf_flowtable, flow) < 0) ++ goto err_flow_add; ++ ++ xt_flowoffload_check_device(xt_in(par)); ++ xt_flowoffload_check_device(xt_out(par)); ++ ++ net = read_pnet(&nf_flowtable.ft_net); ++ if (!net) ++ write_pnet(&nf_flowtable.ft_net, xt_net(par)); ++ ++ if (info->flags & XT_FLOWOFFLOAD_HW) ++ nf_flow_offload_hw_add(xt_net(par), flow, ct); ++ ++ return XT_CONTINUE; ++ ++err_flow_add: ++ flow_offload_free(flow); ++err_flow_route: ++ clear_bit(IPS_OFFLOAD_BIT, &ct->status); ++ return XT_CONTINUE; ++} ++ ++ ++static int flowoffload_chk(const struct xt_tgchk_param *par) ++{ ++ struct xt_flowoffload_target_info *info = par->targinfo; ++ ++ if (info->flags & ~XT_FLOWOFFLOAD_MASK) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static struct xt_target offload_tg_reg __read_mostly = { ++ .family = NFPROTO_UNSPEC, ++ .name = "FLOWOFFLOAD", ++ .revision = 0, ++ .targetsize = sizeof(struct xt_flowoffload_target_info), ++ .usersize = sizeof(struct xt_flowoffload_target_info), ++ .checkentry = flowoffload_chk, ++ .target = flowoffload_tg, ++ .me = THIS_MODULE, ++}; ++ ++static int xt_flowoffload_table_init(struct nf_flowtable *table) ++{ ++ table->flags = NF_FLOWTABLE_F_HW; ++ nf_flow_table_init(table); ++ return 0; ++} ++ ++static void xt_flowoffload_table_cleanup(struct nf_flowtable *table) ++{ ++ nf_flow_table_free(table); ++} ++ ++static int flow_offload_netdev_event(struct notifier_block *this, ++ unsigned long event, void *ptr) ++{ ++ struct xt_flowoffload_hook *hook = NULL; ++ struct net_device *dev = netdev_notifier_info_to_dev(ptr); ++ ++ if (event != NETDEV_UNREGISTER) ++ return NOTIFY_DONE; ++ ++ spin_lock_bh(&hooks_lock); ++ hook = flow_offload_lookup_hook(dev); ++ if (hook) { ++ hlist_del(&hook->list); ++ } ++ spin_unlock_bh(&hooks_lock); ++ if (hook) { ++ nf_unregister_net_hook(hook->net, &hook->ops); ++ kfree(hook); ++ } ++ ++ nf_flow_table_cleanup(dev); ++ ++ return NOTIFY_DONE; ++} ++ ++static struct notifier_block flow_offload_netdev_notifier = { ++ .notifier_call = flow_offload_netdev_event, ++}; ++ ++static int __init xt_flowoffload_tg_init(void) ++{ ++ int ret; ++ ++ register_netdevice_notifier(&flow_offload_netdev_notifier); ++ ++ INIT_DELAYED_WORK(&hook_work, xt_flowoffload_hook_work); ++ ++ ret = xt_flowoffload_table_init(&nf_flowtable); ++ if (ret) ++ return ret; ++ ++ ret = xt_register_target(&offload_tg_reg); ++ if (ret) ++ xt_flowoffload_table_cleanup(&nf_flowtable); ++ ++ return ret; ++} ++ ++static void __exit xt_flowoffload_tg_exit(void) ++{ ++ xt_unregister_target(&offload_tg_reg); ++ xt_flowoffload_table_cleanup(&nf_flowtable); ++ unregister_netdevice_notifier(&flow_offload_netdev_notifier); ++} ++ ++MODULE_LICENSE("GPL"); ++module_init(xt_flowoffload_tg_init); ++module_exit(xt_flowoffload_tg_exit); +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -7,7 +7,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -351,8 +350,7 @@ flow_offload_lookup(struct nf_flowtable + } + EXPORT_SYMBOL_GPL(flow_offload_lookup); + +-static int +-nf_flow_table_iterate(struct nf_flowtable *flow_table, ++int nf_flow_table_iterate(struct nf_flowtable *flow_table, + void (*iter)(struct flow_offload *flow, void *data), + void *data) + { +@@ -385,6 +383,7 @@ nf_flow_table_iterate(struct nf_flowtabl + + return err; + } ++EXPORT_SYMBOL_GPL(nf_flow_table_iterate); + + static void nf_flow_offload_gc_step(struct flow_offload *flow, void *data) + { +--- /dev/null ++++ b/include/uapi/linux/netfilter/xt_FLOWOFFLOAD.h +@@ -0,0 +1,17 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++#ifndef _XT_FLOWOFFLOAD_H ++#define _XT_FLOWOFFLOAD_H ++ ++#include ++ ++enum { ++ XT_FLOWOFFLOAD_HW = 1 << 0, ++ ++ XT_FLOWOFFLOAD_MASK = XT_FLOWOFFLOAD_HW ++}; ++ ++struct xt_flowoffload_target_info { ++ __u32 flags; ++}; ++ ++#endif /* _XT_FLOWOFFLOAD_H */ +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -133,6 +133,10 @@ static inline void flow_offload_dead(str + flow->flags |= FLOW_OFFLOAD_DYING; + } + ++int nf_flow_table_iterate(struct nf_flowtable *flow_table, ++ void (*iter)(struct flow_offload *flow, void *data), ++ void *data); ++ + int nf_flow_snat_port(const struct flow_offload *flow, + struct sk_buff *skb, unsigned int thoff, + u8 protocol, enum flow_offload_tuple_dir dir); From e5abee8abb5ec8ac9248ecac8f5f7cf247e84208 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Tue, 22 Nov 2022 15:33:32 +0800 Subject: [PATCH 052/102] fix --- ...filter-export-udp_get_timeouts-function.patch | 16 ++++++++++++---- .../hack-5.4/647-netfilter-flow-acct.patch | 8 ++++---- .../650-netfilter-add-xt_OFFLOAD-target.patch | 12 ++++++------ ...rack-events-support-multiple-registrant.patch | 2 +- ...tch-linux-kernel-to-support-shortcut-fe.patch | 12 ++++++------ 5 files changed, 29 insertions(+), 21 deletions(-) diff --git a/root/target/linux/generic/hack-5.4/601-netfilter-export-udp_get_timeouts-function.patch b/root/target/linux/generic/hack-5.4/601-netfilter-export-udp_get_timeouts-function.patch index ef3fba22..3c28843a 100644 --- a/root/target/linux/generic/hack-5.4/601-netfilter-export-udp_get_timeouts-function.patch +++ b/root/target/linux/generic/hack-5.4/601-netfilter-export-udp_get_timeouts-function.patch @@ -8,18 +8,23 @@ Subject: [PATCH] net: patch linux kernel to support shortcut-fe-cm nf_conntrack_timeout.h | 2 + 1 file changed, 2 insertion(+) +diff --git a/include/net/netfilter/nf_conntrack_timeout.h b/include/net/netfilter/nf_conntrack_timeout.h +index 6dd7239..e1f6d69 100644 --- a/include/net/netfilter/nf_conntrack_timeout.h +++ b/include/net/netfilter/nf_conntrack_timeout.h -@@ -124,4 +124,6 @@ extern struct nf_ct_timeout *(*nf_ct_tim +@@ -123,5 +123,7 @@ static inline void nf_ct_destroy_timeout(struct nf_conn *ct) + extern struct nf_ct_timeout *(*nf_ct_timeout_find_get_hook)(struct net *net, const char *name); extern void (*nf_ct_timeout_put_hook)(struct nf_ct_timeout *timeout); #endif - -+extern unsigned int *udp_get_timeouts(struct net *net); + ++extern unsigned int *udp_get_timeouts(struct net *net); + #endif /* _NF_CONNTRACK_TIMEOUT_H */ +diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c +index 7365b43..2238d55 100644 --- a/net/netfilter/nf_conntrack_proto_udp.c +++ b/net/netfilter/nf_conntrack_proto_udp.c -@@ -29,10 +29,11 @@ static const unsigned int udp_timeouts[U +@@ -29,10 +29,11 @@ static const unsigned int udp_timeouts[UDP_CT_MAX] = { [UDP_CT_REPLIED] = 120*HZ, }; @@ -32,3 +37,6 @@ Subject: [PATCH] net: patch linux kernel to support shortcut-fe-cm static void udp_error_log(const struct sk_buff *skb, const struct nf_hook_state *state, +-- +2.17.1 + diff --git a/root/target/linux/generic/hack-5.4/647-netfilter-flow-acct.patch b/root/target/linux/generic/hack-5.4/647-netfilter-flow-acct.patch index 9f7ca615..f9480d59 100644 --- a/root/target/linux/generic/hack-5.4/647-netfilter-flow-acct.patch +++ b/root/target/linux/generic/hack-5.4/647-netfilter-flow-acct.patch @@ -1,6 +1,6 @@ --- a/include/net/netfilter/nf_flow_table.h +++ b/include/net/netfilter/nf_flow_table.h -@@ -163,6 +163,8 @@ struct nf_flow_table_hw { +@@ -160,6 +160,8 @@ struct nf_flow_table_hw { int nf_flow_table_hw_register(const struct nf_flow_table_hw *offload); void nf_flow_table_hw_unregister(const struct nf_flow_table_hw *offload); @@ -19,7 +19,7 @@ struct flow_offload_entry { struct flow_offload flow; -@@ -177,6 +178,22 @@ void flow_offload_free(struct flow_offlo +@@ -164,6 +165,22 @@ void flow_offload_free(struct flow_offlo } EXPORT_SYMBOL_GPL(flow_offload_free); @@ -52,7 +52,7 @@ /* For layer 4 checksum field offset. */ #include #include -@@ -288,6 +289,7 @@ nf_flow_offload_ip_hook(void *priv, stru +@@ -296,6 +297,7 @@ nf_flow_offload_ip_hook(void *priv, stru skb->dev = outdev; nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr); skb_dst_set_noref(skb, &rt->dst); @@ -60,7 +60,7 @@ neigh_xmit(NEIGH_ARP_TABLE, outdev, &nexthop, skb); return NF_STOLEN; -@@ -518,6 +520,7 @@ nf_flow_offload_ipv6_hook(void *priv, st +@@ -526,6 +528,7 @@ nf_flow_offload_ipv6_hook(void *priv, st skb->dev = outdev; nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6); skb_dst_set_noref(skb, &rt->dst); diff --git a/root/target/linux/generic/hack-5.4/650-netfilter-add-xt_OFFLOAD-target.patch b/root/target/linux/generic/hack-5.4/650-netfilter-add-xt_OFFLOAD-target.patch index 8d9fec06..d584cb5c 100644 --- a/root/target/linux/generic/hack-5.4/650-netfilter-add-xt_OFFLOAD-target.patch +++ b/root/target/linux/generic/hack-5.4/650-netfilter-add-xt_OFFLOAD-target.patch @@ -47,7 +47,7 @@ Signed-off-by: Felix Fietkau depends on !NF_CONNTRACK || NF_CONNTRACK --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig -@@ -689,8 +689,6 @@ config NFT_FIB_NETDEV +@@ -690,8 +690,6 @@ config NFT_FIB_NETDEV endif # NF_TABLES_NETDEV @@ -56,7 +56,7 @@ Signed-off-by: Felix Fietkau config NF_FLOW_TABLE_INET tristate "Netfilter flow table mixed IPv4/IPv6 module" depends on NF_FLOW_TABLE -@@ -699,11 +697,12 @@ config NF_FLOW_TABLE_INET +@@ -700,11 +698,12 @@ config NF_FLOW_TABLE_INET To compile it as a module, choose M here. @@ -70,7 +70,7 @@ Signed-off-by: Felix Fietkau help This option adds the flow table core infrastructure. -@@ -992,6 +991,15 @@ config NETFILTER_XT_TARGET_NOTRACK +@@ -993,6 +992,15 @@ config NETFILTER_XT_TARGET_NOTRACK depends on NETFILTER_ADVANCED select NETFILTER_XT_TARGET_CT @@ -536,7 +536,7 @@ Signed-off-by: Felix Fietkau #include #include #include -@@ -351,8 +350,7 @@ flow_offload_lookup(struct nf_flowtable +@@ -338,8 +337,7 @@ flow_offload_lookup(struct nf_flowtable } EXPORT_SYMBOL_GPL(flow_offload_lookup); @@ -546,7 +546,7 @@ Signed-off-by: Felix Fietkau void (*iter)(struct flow_offload *flow, void *data), void *data) { -@@ -385,6 +383,7 @@ nf_flow_table_iterate(struct nf_flowtabl +@@ -372,6 +370,7 @@ nf_flow_table_iterate(struct nf_flowtabl return err; } @@ -576,7 +576,7 @@ Signed-off-by: Felix Fietkau +#endif /* _XT_FLOWOFFLOAD_H */ --- a/include/net/netfilter/nf_flow_table.h +++ b/include/net/netfilter/nf_flow_table.h -@@ -133,6 +133,10 @@ static inline void flow_offload_dead(str +@@ -130,6 +130,10 @@ static inline void flow_offload_dead(str flow->flags |= FLOW_OFFLOAD_DYING; } diff --git a/root/target/linux/generic/hack-5.4/952-net-conntrack-events-support-multiple-registrant.patch b/root/target/linux/generic/hack-5.4/952-net-conntrack-events-support-multiple-registrant.patch index e01728fc..c7634495 100755 --- a/root/target/linux/generic/hack-5.4/952-net-conntrack-events-support-multiple-registrant.patch +++ b/root/target/linux/generic/hack-5.4/952-net-conntrack-events-support-multiple-registrant.patch @@ -98,7 +98,7 @@ Signed-off-by: Zhi Chen #if defined(CONFIG_NF_CONNTRACK_LABELS) --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig -@@ -135,6 +135,14 @@ config NF_CONNTRACK_EVENTS +@@ -136,6 +136,14 @@ config NF_CONNTRACK_EVENTS If unsure, say `N'. diff --git a/root/target/linux/generic/hack-5.4/953-net-patch-linux-kernel-to-support-shortcut-fe.patch b/root/target/linux/generic/hack-5.4/953-net-patch-linux-kernel-to-support-shortcut-fe.patch index a25ed559..57b40292 100755 --- a/root/target/linux/generic/hack-5.4/953-net-patch-linux-kernel-to-support-shortcut-fe.patch +++ b/root/target/linux/generic/hack-5.4/953-net-patch-linux-kernel-to-support-shortcut-fe.patch @@ -12,9 +12,9 @@ struct list_head *br_ip_list); --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h -@@ -827,6 +827,10 @@ struct sk_buff { +@@ -826,6 +826,10 @@ struct sk_buff { #endif - __u8 scm_io_uring:1; + __u8 gro_skip:1; +#ifdef CONFIG_SHORTCUT_FE + __u8 fast_forwarded:1; @@ -99,7 +99,7 @@ #ifdef CONFIG_ETHERNET_PACKET_MANGLE if (!dev->eth_mangle_tx || (skb = dev->eth_mangle_tx(dev, skb)) != NULL) -@@ -4715,6 +4723,11 @@ void netdev_rx_handler_unregister(struct +@@ -4714,6 +4722,11 @@ void netdev_rx_handler_unregister(struct } EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister); @@ -111,7 +111,7 @@ /* * Limit the use of PFMEMALLOC reserves to those protocols that implement * the special handling of PFMEMALLOC skbs. -@@ -4765,6 +4778,10 @@ static int __netif_receive_skb_core(stru +@@ -4764,6 +4777,10 @@ static int __netif_receive_skb_core(stru int ret = NET_RX_DROP; __be16 type; @@ -119,10 +119,10 @@ + int (*fast_recv)(struct sk_buff *skb); +#endif + - net_timestamp_check(!READ_ONCE(netdev_tstamp_prequeue), skb); + net_timestamp_check(!netdev_tstamp_prequeue, skb); trace_netif_receive_skb(skb); -@@ -4804,6 +4821,16 @@ another_round: +@@ -4803,6 +4820,16 @@ another_round: goto out; } From 2822d42d1b84c99a4ec8cd118405a3b2bfb1e675 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Tue, 22 Nov 2022 21:37:36 +0800 Subject: [PATCH 053/102] addqca --- .../qca/firmware/nss-firmware/Makefile | 70 + root/package/qca/nss/nss-ifb/Makefile | 49 + root/package/qca/nss/nss-ifb/README.md | 45 + root/package/qca/nss/nss-ifb/src/Makefile | 3 + root/package/qca/nss/nss-ifb/src/nss_ifb.c | 304 ++++ root/package/qca/nss/qca-nss-cfi/Makefile | 99 ++ .../patches/0001-compile-only-cryptoapi.patch | 30 + .../patches/0002-wip-support-5.4.patch | 78 + .../0003-Convert-ablkcipher-to-skcipher.patch | 707 +++++++++ .../qca/nss/qca-nss-clients-64/Makefile | 97 ++ .../qca-nss-clients-64/files/qca-nss-ipsec | 214 +++ .../files/qca-nss-mirred.init | 28 + .../files/qca-nss-ovpn.init | 69 + root/package/qca/nss/qca-nss-clients/Makefile | 469 ++++++ .../nss/qca-nss-clients/files/qca-nss-ipsec | 92 ++ .../qca-nss-clients/files/qca-nss-mirred.init | 28 + .../qca-nss-clients/files/qca-nss-ovpn.init | 69 + .../100-kernel-5.4-support-qdisc.patch | 1145 +++++++++++++++ .../patches/101-kernel-5.4-support-gre.patch | 106 ++ .../102-kernel-5.4-support-ipsec.patch | 29 + .../patches/103-kernel-5.4-support-dtls.patch | 11 + .../patches/104-kernel-5.4-support-l2tp.patch | 64 + .../patches/200-qdisc-fix-compile-error.patch | 14 + .../202-vlanmgr-fix-compile-error.patch | 48 + root/package/qca/nss/qca-nss-crypto/Makefile | 74 + .../patches/100-kernel-5.4-support.patch | 42 + .../200-fix-NULL-pointer-exception.patch | 57 + root/package/qca/nss/qca-nss-dp/Makefile | 62 + ...port-newer-kernels-time-stamping-API.patch | 44 + ...-phy-mode-code-compatible-with-newer.patch | 48 + ...03-Drop-_nocache-variants-of-ioremap.patch | 48 + .../0004-EDMA-Fix-NAPI-packet-counting.patch | 31 + ...-Use-NAPI_POLL_WEIGHT-as-NAPI-weight.patch | 41 + .../0006-NSS-DP-fix-of_get_mac_address.patch | 50 + ...07-NSS-DP-implement-ethernet-IOCTL-s.patch | 29 + ...dev-remove-the-transaction-structure.patch | 48 + ...09-switchdev-use-new-switchdev-flags.patch | 54 + .../0010-switchdev-fix-FDB-roaming.patch | 110 ++ ...fusing-printing-of-registered-netdev.patch | 31 + root/package/qca/nss/qca-nss-drv-64/Makefile | 121 ++ .../nss/qca-nss-drv-64/files/qca-nss-drv.conf | 6 + .../qca-nss-drv-64/files/qca-nss-drv.debug | 26 + .../qca-nss-drv-64/files/qca-nss-drv.hotplug | 70 + .../nss/qca-nss-drv-64/files/qca-nss-drv.init | 50 + .../qca-nss-drv-64/files/qca-nss-drv.sysctl | 4 + ...ore-add-5.10-kernel-to-version-check.patch | 25 + ...replace-ioremap_nocache-with-ioremap.patch | 164 +++ ...0003-DMA-Fix-NULL-pointer-exceptions.patch | 49 + ...-nss-drv-add-support-for-kernel-5.15.patch | 73 + ...dard-skb_skip_tc_classify-instead-of.patch | 29 + ...hack-support-for-mismatched-firmware.patch | 344 +++++ root/package/qca/nss/qca-nss-drv/Makefile | 125 ++ .../files/nss-firmware/LICENSE.TXT | 45 + .../qca-nss-drv/files/nss-firmware/NOTICE.TXT | 217 +++ .../qca-nss-drv/files/nss-firmware/README.md | 10 + .../files/nss-firmware/qca-nss0-retail.bin | Bin 0 -> 536324 bytes .../files/nss-firmware/qca-nss1-retail.bin | Bin 0 -> 218224 bytes .../nss/qca-nss-drv/files/qca-nss-drv.conf | 6 + .../nss/qca-nss-drv/files/qca-nss-drv.debug | 26 + .../nss/qca-nss-drv/files/qca-nss-drv.hotplug | 70 + .../nss/qca-nss-drv/files/qca-nss-drv.init | 50 + .../nss/qca-nss-drv/files/qca-nss-drv.sysctl | 4 + .../patches/100-kernel-5.4-support.patch | 107 ++ ...ol-fab-scaling-from-package-Makefile.patch | 38 + .../200-fix-NULL-pointer-exception.patch | 11 + ...1-Fix-Kernel-Panic-dma-with-NULL-dev.patch | 82 ++ .../400-Exported-set-nexthop-function.patch | 47 + root/package/qca/nss/qca-nss-ecm-64/Makefile | 96 ++ .../qca/nss/qca-nss-ecm-64/files/ecm_dump.sh | 95 ++ .../nss/qca-nss-ecm-64/files/on-demand-down | 6 + .../qca-nss-ecm-64/files/qca-nss-ecm.defaults | 28 + .../qca-nss-ecm-64/files/qca-nss-ecm.firewall | 18 + .../nss/qca-nss-ecm-64/files/qca-nss-ecm.init | 137 ++ .../qca-nss-ecm-64/files/qca-nss-ecm.sysctl | 2 + .../nss/qca-nss-ecm-64/files/qca-nss-ecm.uci | 2 + ...de-componentize-the-module-even-more.patch | 335 +++++ .../patches/002-kernel-5.10-support.patch | 831 +++++++++++ .../003-rework-nfct-notification.patch | 25 + .../patches/004-More-compile-fixes.patch | 58 + .../patches/005-resolve-high-load.patch | 61 + ...terface-switch-to-kernel_recvmsg-api.patch | 40 + ...ide-rework-notifier-changes-for-5.15.patch | 72 + ...se-of-static-be_liberal-and-no_windo.patch | 156 ++ ...tagram-drop-static-for-EXPORT_SYMBOL.patch | 55 + ...dp_get_timeouts-and-use-standard-ups.patch | 74 + ...-ecm-fix-a-memcpy-overflow-in-ecm_db.patch | 67 + root/package/qca/nss/qca-nss-ecm/Makefile | 278 ++++ .../qca/nss/qca-nss-ecm/files/ecm_dump.sh | 95 ++ .../qca/nss/qca-nss-ecm/files/on-demand-down | 6 + .../qca-nss-ecm/files/qca-nss-ecm.defaults | 28 + .../qca-nss-ecm/files/qca-nss-ecm.firewall | 18 + .../nss/qca-nss-ecm/files/qca-nss-ecm.init | 133 ++ .../nss/qca-nss-ecm/files/qca-nss-ecm.sysctl | 2 + .../qca/nss/qca-nss-ecm/files/qca-nss-ecm.uci | 2 + .../patches/001-Drop_SFE_from_ecm.patch | 12 + .../patches/100-kernel-5.4-support.patch | 1276 +++++++++++++++++ .../101-Fix_Kern_Panic_on_UDP_CONNTRACK.patch | 60 + .../patches/200-resolve-high-load.patch | 44 + .../203-rework-nfct-notification.patch | 20 + ...heck-TCP_UDP-conntrack-state-earlier.patch | 236 +++ ...ix-NSS-stats-request-roll-over-issue.patch | 52 + ...01-Fix-for-ref-leak-during-multicast.patch | 112 ++ ...neighbour-solicitation-send-function.patch | 33 + ...e-leak-during-multicast_PPPoE-bridge.patch | 260 ++++ ...-global-accelerated-count-under-lock.patch | 59 + ...x-IPv6-neighbor-solicitation-request.patch | 83 ++ ...tation-fix-with-zero-gateway-address.patch | 63 + ...-port-when-bridge-hairpin-is-enabled.patch | 126 ++ root/package/qca/nss/qca-nss-gmac/Makefile | 47 + .../patches/100-kernel-5.4-support.patch | 279 ++++ .../patches/101-nss-gmac-test-ptr.patch | 25 + ...-work-around-interface-close-warning.patch | 15 + root/package/qca/qca-mcs/Makefile | 54 + root/package/qca/qca-rfs/Makefile | 51 + root/package/qca/qca-rfs/files/qrfs.init | 27 + .../patches/100-add-kernel-5.4-support.patch | 57 + .../200-rework-nfct-notification.patch | 20 + root/package/qca/qca-ssdk-shell/Makefile | 48 + root/package/qca/qca-ssdk/Makefile | 125 ++ root/package/qca/qca-ssdk/files/qca-ssdk | 206 +++ ...001-SSDK-config-add-kernel-5.10-5.15.patch | 60 + ...replace-ioremap_nocache-with-ioremap.patch | 102 ++ ...use-of_mdio_find_bus-to-get-MDIO-bus.patch | 40 + .../patches/0005-add-kernel-5.4-support.patch | 108 ++ .../0006-fix-mdio-probe-on-ipq806x.patch | 11 + ...0007-SSDK-dts-fix-of_get_mac_address.patch | 42 + .../0008-add-aquantia-phy-id-113CB0.patch | 37 + ...09-qca8081-convert-to-5.11-IRQ-model.patch | 83 ++ ...mpilation-error-for-parse_uci_option.patch | 27 + 129 files changed, 13056 insertions(+) create mode 100644 root/package/qca/firmware/nss-firmware/Makefile create mode 100644 root/package/qca/nss/nss-ifb/Makefile create mode 100644 root/package/qca/nss/nss-ifb/README.md create mode 100644 root/package/qca/nss/nss-ifb/src/Makefile create mode 100644 root/package/qca/nss/nss-ifb/src/nss_ifb.c create mode 100644 root/package/qca/nss/qca-nss-cfi/Makefile create mode 100644 root/package/qca/nss/qca-nss-cfi/patches/0001-compile-only-cryptoapi.patch create mode 100644 root/package/qca/nss/qca-nss-cfi/patches/0002-wip-support-5.4.patch create mode 100644 root/package/qca/nss/qca-nss-cfi/patches/0003-Convert-ablkcipher-to-skcipher.patch create mode 100644 root/package/qca/nss/qca-nss-clients-64/Makefile create mode 100644 root/package/qca/nss/qca-nss-clients-64/files/qca-nss-ipsec create mode 100644 root/package/qca/nss/qca-nss-clients-64/files/qca-nss-mirred.init create mode 100644 root/package/qca/nss/qca-nss-clients-64/files/qca-nss-ovpn.init create mode 100644 root/package/qca/nss/qca-nss-clients/Makefile create mode 100644 root/package/qca/nss/qca-nss-clients/files/qca-nss-ipsec create mode 100644 root/package/qca/nss/qca-nss-clients/files/qca-nss-mirred.init create mode 100644 root/package/qca/nss/qca-nss-clients/files/qca-nss-ovpn.init create mode 100644 root/package/qca/nss/qca-nss-clients/patches/100-kernel-5.4-support-qdisc.patch create mode 100644 root/package/qca/nss/qca-nss-clients/patches/101-kernel-5.4-support-gre.patch create mode 100644 root/package/qca/nss/qca-nss-clients/patches/102-kernel-5.4-support-ipsec.patch create mode 100644 root/package/qca/nss/qca-nss-clients/patches/103-kernel-5.4-support-dtls.patch create mode 100644 root/package/qca/nss/qca-nss-clients/patches/104-kernel-5.4-support-l2tp.patch create mode 100644 root/package/qca/nss/qca-nss-clients/patches/200-qdisc-fix-compile-error.patch create mode 100644 root/package/qca/nss/qca-nss-clients/patches/202-vlanmgr-fix-compile-error.patch create mode 100644 root/package/qca/nss/qca-nss-crypto/Makefile create mode 100644 root/package/qca/nss/qca-nss-crypto/patches/100-kernel-5.4-support.patch create mode 100644 root/package/qca/nss/qca-nss-crypto/patches/200-fix-NULL-pointer-exception.patch create mode 100644 root/package/qca/nss/qca-nss-dp/Makefile create mode 100644 root/package/qca/nss/qca-nss-dp/patches/0001-edma_tx_rx-support-newer-kernels-time-stamping-API.patch create mode 100644 root/package/qca/nss/qca-nss-dp/patches/0002-nss_dp_main-make-phy-mode-code-compatible-with-newer.patch create mode 100644 root/package/qca/nss/qca-nss-dp/patches/0003-Drop-_nocache-variants-of-ioremap.patch create mode 100644 root/package/qca/nss/qca-nss-dp/patches/0004-EDMA-Fix-NAPI-packet-counting.patch create mode 100644 root/package/qca/nss/qca-nss-dp/patches/0005-EDMA-Use-NAPI_POLL_WEIGHT-as-NAPI-weight.patch create mode 100644 root/package/qca/nss/qca-nss-dp/patches/0006-NSS-DP-fix-of_get_mac_address.patch create mode 100644 root/package/qca/nss/qca-nss-dp/patches/0007-NSS-DP-implement-ethernet-IOCTL-s.patch create mode 100644 root/package/qca/nss/qca-nss-dp/patches/0008-switchdev-remove-the-transaction-structure.patch create mode 100644 root/package/qca/nss/qca-nss-dp/patches/0009-switchdev-use-new-switchdev-flags.patch create mode 100644 root/package/qca/nss/qca-nss-dp/patches/0010-switchdev-fix-FDB-roaming.patch create mode 100644 root/package/qca/nss/qca-nss-dp/patches/0011-treewide-fix-confusing-printing-of-registered-netdev.patch create mode 100644 root/package/qca/nss/qca-nss-drv-64/Makefile create mode 100644 root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.conf create mode 100644 root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.debug create mode 100644 root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.hotplug create mode 100644 root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.init create mode 100644 root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.sysctl create mode 100644 root/package/qca/nss/qca-nss-drv-64/patches/0001-core-add-5.10-kernel-to-version-check.patch create mode 100644 root/package/qca/nss/qca-nss-drv-64/patches/0002-nss-drv-replace-ioremap_nocache-with-ioremap.patch create mode 100644 root/package/qca/nss/qca-nss-drv-64/patches/0003-DMA-Fix-NULL-pointer-exceptions.patch create mode 100644 root/package/qca/nss/qca-nss-drv-64/patches/0005-nss-drv-add-support-for-kernel-5.15.patch create mode 100644 root/package/qca/nss/qca-nss-drv-64/patches/0005-nss-drv-use-standard-skb_skip_tc_classify-instead-of.patch create mode 100644 root/package/qca/nss/qca-nss-drv-64/patches/0999-treewide-hack-support-for-mismatched-firmware.patch create mode 100644 root/package/qca/nss/qca-nss-drv/Makefile create mode 100644 root/package/qca/nss/qca-nss-drv/files/nss-firmware/LICENSE.TXT create mode 100644 root/package/qca/nss/qca-nss-drv/files/nss-firmware/NOTICE.TXT create mode 100644 root/package/qca/nss/qca-nss-drv/files/nss-firmware/README.md create mode 100644 root/package/qca/nss/qca-nss-drv/files/nss-firmware/qca-nss0-retail.bin create mode 100644 root/package/qca/nss/qca-nss-drv/files/nss-firmware/qca-nss1-retail.bin create mode 100644 root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.conf create mode 100644 root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.debug create mode 100644 root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.hotplug create mode 100644 root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.init create mode 100644 root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.sysctl create mode 100644 root/package/qca/nss/qca-nss-drv/patches/100-kernel-5.4-support.patch create mode 100644 root/package/qca/nss/qca-nss-drv/patches/101-nss-drv-Control-fab-scaling-from-package-Makefile.patch create mode 100644 root/package/qca/nss/qca-nss-drv/patches/200-fix-NULL-pointer-exception.patch create mode 100644 root/package/qca/nss/qca-nss-drv/patches/201-Fix-Kernel-Panic-dma-with-NULL-dev.patch create mode 100644 root/package/qca/nss/qca-nss-drv/patches/400-Exported-set-nexthop-function.patch create mode 100644 root/package/qca/nss/qca-nss-ecm-64/Makefile create mode 100644 root/package/qca/nss/qca-nss-ecm-64/files/ecm_dump.sh create mode 100644 root/package/qca/nss/qca-nss-ecm-64/files/on-demand-down create mode 100644 root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.defaults create mode 100644 root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.firewall create mode 100644 root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.init create mode 100644 root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.sysctl create mode 100644 root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.uci create mode 100644 root/package/qca/nss/qca-nss-ecm-64/patches/001-treewide-componentize-the-module-even-more.patch create mode 100644 root/package/qca/nss/qca-nss-ecm-64/patches/002-kernel-5.10-support.patch create mode 100644 root/package/qca/nss/qca-nss-ecm-64/patches/003-rework-nfct-notification.patch create mode 100644 root/package/qca/nss/qca-nss-ecm-64/patches/004-More-compile-fixes.patch create mode 100644 root/package/qca/nss/qca-nss-ecm-64/patches/005-resolve-high-load.patch create mode 100644 root/package/qca/nss/qca-nss-ecm-64/patches/006-ecm_interface-switch-to-kernel_recvmsg-api.patch create mode 100644 root/package/qca/nss/qca-nss-ecm-64/patches/007-treewide-rework-notifier-changes-for-5.15.patch create mode 100644 root/package/qca/nss/qca-nss-ecm-64/patches/008-frontends-drop-use-of-static-be_liberal-and-no_windo.patch create mode 100644 root/package/qca/nss/qca-nss-ecm-64/patches/009-ecm_tracker_datagram-drop-static-for-EXPORT_SYMBOL.patch create mode 100644 root/package/qca/nss/qca-nss-ecm-64/patches/010-frontends-drop-udp_get_timeouts-and-use-standard-ups.patch create mode 100644 root/package/qca/nss/qca-nss-ecm-64/patches/901-qca-nss-ecm-fix-a-memcpy-overflow-in-ecm_db.patch create mode 100644 root/package/qca/nss/qca-nss-ecm/Makefile create mode 100644 root/package/qca/nss/qca-nss-ecm/files/ecm_dump.sh create mode 100644 root/package/qca/nss/qca-nss-ecm/files/on-demand-down create mode 100644 root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.defaults create mode 100644 root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.firewall create mode 100644 root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.init create mode 100644 root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.sysctl create mode 100644 root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.uci create mode 100644 root/package/qca/nss/qca-nss-ecm/patches/001-Drop_SFE_from_ecm.patch create mode 100644 root/package/qca/nss/qca-nss-ecm/patches/100-kernel-5.4-support.patch create mode 100644 root/package/qca/nss/qca-nss-ecm/patches/101-Fix_Kern_Panic_on_UDP_CONNTRACK.patch create mode 100644 root/package/qca/nss/qca-nss-ecm/patches/200-resolve-high-load.patch create mode 100644 root/package/qca/nss/qca-nss-ecm/patches/203-rework-nfct-notification.patch create mode 100644 root/package/qca/nss/qca-nss-ecm/patches/400-Check-TCP_UDP-conntrack-state-earlier.patch create mode 100644 root/package/qca/nss/qca-nss-ecm/patches/401-Fix-NSS-stats-request-roll-over-issue.patch create mode 100644 root/package/qca/nss/qca-nss-ecm/patches/401-Fix-for-ref-leak-during-multicast.patch create mode 100644 root/package/qca/nss/qca-nss-ecm/patches/401-Fix-neighbour-solicitation-send-function.patch create mode 100644 root/package/qca/nss/qca-nss-ecm/patches/402-Reference-leak-during-multicast_PPPoE-bridge.patch create mode 100644 root/package/qca/nss/qca-nss-ecm/patches/403-Access-global-accelerated-count-under-lock.patch create mode 100644 root/package/qca/nss/qca-nss-ecm/patches/403-Fix-IPv6-neighbor-solicitation-request.patch create mode 100644 root/package/qca/nss/qca-nss-ecm/patches/404-IPv6-solicitation-fix-with-zero-gateway-address.patch create mode 100644 root/package/qca/nss/qca-nss-ecm/patches/405-Allow-egress-on-same-port-when-bridge-hairpin-is-enabled.patch create mode 100644 root/package/qca/nss/qca-nss-gmac/Makefile create mode 100644 root/package/qca/nss/qca-nss-gmac/patches/100-kernel-5.4-support.patch create mode 100644 root/package/qca/nss/qca-nss-gmac/patches/101-nss-gmac-test-ptr.patch create mode 100644 root/package/qca/nss/qca-nss-gmac/patches/200-work-around-interface-close-warning.patch create mode 100644 root/package/qca/qca-mcs/Makefile create mode 100644 root/package/qca/qca-rfs/Makefile create mode 100644 root/package/qca/qca-rfs/files/qrfs.init create mode 100644 root/package/qca/qca-rfs/patches/100-add-kernel-5.4-support.patch create mode 100644 root/package/qca/qca-rfs/patches/200-rework-nfct-notification.patch create mode 100644 root/package/qca/qca-ssdk-shell/Makefile create mode 100644 root/package/qca/qca-ssdk/Makefile create mode 100644 root/package/qca/qca-ssdk/files/qca-ssdk create mode 100644 root/package/qca/qca-ssdk/patches/0001-SSDK-config-add-kernel-5.10-5.15.patch create mode 100644 root/package/qca/qca-ssdk/patches/0002-SSDK-replace-ioremap_nocache-with-ioremap.patch create mode 100644 root/package/qca/qca-ssdk/patches/0004-platform-use-of_mdio_find_bus-to-get-MDIO-bus.patch create mode 100644 root/package/qca/qca-ssdk/patches/0005-add-kernel-5.4-support.patch create mode 100644 root/package/qca/qca-ssdk/patches/0006-fix-mdio-probe-on-ipq806x.patch create mode 100644 root/package/qca/qca-ssdk/patches/0007-SSDK-dts-fix-of_get_mac_address.patch create mode 100644 root/package/qca/qca-ssdk/patches/0008-add-aquantia-phy-id-113CB0.patch create mode 100644 root/package/qca/qca-ssdk/patches/0009-qca8081-convert-to-5.11-IRQ-model.patch create mode 100644 root/package/qca/qca-ssdk/patches/0012-include-fix-compilation-error-for-parse_uci_option.patch diff --git a/root/package/qca/firmware/nss-firmware/Makefile b/root/package/qca/firmware/nss-firmware/Makefile new file mode 100644 index 00000000..6ea4a57c --- /dev/null +++ b/root/package/qca/firmware/nss-firmware/Makefile @@ -0,0 +1,70 @@ +# +# Copyright (C) 2021 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=nss-firmware +PKG_SOURCE_DATE:=2021-03-12 +PKG_SOURCE_VERSION:=73f378d6be21a9c20a69b77000dbb54a537006a9 +PKG_MIRROR_HASH:=0c21afe29002754edf2983bc9e8543dddd722e75bd12e961e300e99a310d1f62 +PKG_RELEASE:=$(AUTORELEASE) + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/quic/qca-sdk-nss-fw.git + +PKG_LICENSE_FILES:=LICENSE.md + +PKG_MAINTAINER:=Robert Marko + +include $(INCLUDE_DIR)/package.mk + +VERSION_PATH=$(PKG_BUILD_DIR)/QCA_Networking_2020.SPF_11.3/CS + +define Package/nss-firmware-default + SECTION:=firmware + CATEGORY:=Firmware + URL:=$(PKG_SOURCE_URL) + DEPENDS:=@(TARGET_ipq807x||TARGET_ipq60xx) +endef + +define Package/nss-firmware-ipq6018 +$(Package/nss-firmware-default) + TITLE:=NSS firmware for IPQ6018 devices + NSS_ARCHIVE:=$(VERSION_PATH)/IPQ6018.ATH.11.3/BIN-NSS.CP.11.3-9-R.tar.bz2 +endef + +define Package/nss-firmware-ipq8074 +$(Package/nss-firmware-default) + TITLE:=NSS firmware for IPQ8074 devices + NSS_ARCHIVE:=$(VERSION_PATH)/IPQ8074.ATH.11.3/BIN-NSS.HK.11.3-9-R.tar.bz2 +endef + +define Build/Compile + +endef + +define Package/nss-firmware-ipq6018/install + $(TAR) -C $(PKG_BUILD_DIR) -xf $(NSS_ARCHIVE) + $(INSTALL_DIR) $(1)/lib/firmware/ + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/BIN-NSS.CP.11.3-9-R/retail_router0.bin \ + $(1)/lib/firmware/qca-nss0-retail.bin +endef + +define Package/nss-firmware-ipq8074/install + $(TAR) -C $(PKG_BUILD_DIR) -xf $(NSS_ARCHIVE) + $(INSTALL_DIR) $(1)/lib/firmware/ + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/BIN-NSS.HK.11.3-9-R/retail_router0.bin \ + $(1)/lib/firmware/qca-nss0-retail.bin + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/BIN-NSS.HK.11.3-9-R/retail_router1.bin \ + $(1)/lib/firmware/qca-nss1-retail.bin +endef + +$(eval $(call BuildPackage,nss-firmware-ipq6018)) +$(eval $(call BuildPackage,nss-firmware-ipq8074)) diff --git a/root/package/qca/nss/nss-ifb/Makefile b/root/package/qca/nss/nss-ifb/Makefile new file mode 100644 index 00000000..6b7f0b48 --- /dev/null +++ b/root/package/qca/nss/nss-ifb/Makefile @@ -0,0 +1,49 @@ +# +# Copyright (C) 2008-2012 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=nss-ifb +PKG_RELEASE:=1 + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/nss-ifb + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + TITLE:=NSS IFB Interface + DEPENDS:=+kmod-qca-nss-drv @LINUX_5_4 + FILES:=$(PKG_BUILD_DIR)/nss-ifb.ko + KCONFIG:= +endef + +define KernelPackage/nss-ifb/description + Kernel module to register a NSS aware IFB interface. +endef + +EXTRA_KCONFIG:= \ + CONFIG_NET_CLS=y + +EXTRA_CFLAGS:= \ + -I$(STAGING_DIR)/usr/include/qca-nss-drv + +MAKE_OPTS:= \ + $(KERNEL_MAKE_FLAGS) \ + M="$(PKG_BUILD_DIR)" \ + EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ + $(EXTRA_KCONFIG) + +define Build/Compile + $(MAKE) -C "$(LINUX_DIR)" \ + $(MAKE_OPTS) \ + modules +endef + +$(eval $(call KernelPackage,nss-ifb)) + diff --git a/root/package/qca/nss/nss-ifb/README.md b/root/package/qca/nss/nss-ifb/README.md new file mode 100644 index 00000000..a0af7a5e --- /dev/null +++ b/root/package/qca/nss/nss-ifb/README.md @@ -0,0 +1,45 @@ +NSS Physical Interface Ingress Driver +===================================== + +This driver redirect NSS physical interface (namely GMACs) ingress traffic to itself +and sends it back to the Linux network stack (as the source GMACs packets) as it's +egress traffic. + +This allows the NSS QDISC drivers to manage the egress traffic of this driver's +NSS virtual interface. + +This driver will create a single network interface named 'nssifb'. The default +source interface is defined as 'eth0'. It can be changed using the following module +parameter path: + +/sys/module/nss-ifb/parameter/nss_src_dev + +To change the source NSS physical interface to 'eth1', use the following command: + +printf eth1 > /sys/module/nss-ifb/parameter/nss_src_dev + +You need to change the source interface first before bringing up the 'nssifb' +interface. Changing it after the interface is up will have no effect. You need +to bring down the interface and bring it back up to have the changes take effect. + +CPU load imposed on the Krait CPUs appears negligible with this driver intercepting +the physical interface's ingress traffic. Full line speed of the GMAC interface +could still be achieved. + +The commands below shows an example to shape ingress traffic to 500 Mbps and egress +to 200 Mbps for the 'eth0' interface. + +# Load the module if it's not loaded +modprobe nss-ifb + +# Bring up the nssifb interface to active ingress redirect +ip link set up nssifb + +# Shape ingress traffic to 500 Mbit with chained NSSFQ_CODEL +tc qdisc add dev nssifb root handle 1: nsstbl rate 500Mbit burst 1Mb +tc qdisc add dev nssifb parent 1: handle 10: nssfq_codel limit 10240 flows 1024 quantum 1514 target 5ms interval 100ms set_default + +# Shape egress traffic to 200 Mbit with chained NSSFQ_CODEL +tc qdisc add dev eth0 root handle 1: nsstbl rate 200Mbit burst 1Mb +tc qdisc add dev eth0 parent 1: handle 10: nssfq_codel limit 10240 flows 1024 quantum 1514 target 5ms interval 100ms set_default + diff --git a/root/package/qca/nss/nss-ifb/src/Makefile b/root/package/qca/nss/nss-ifb/src/Makefile new file mode 100644 index 00000000..332b9b4e --- /dev/null +++ b/root/package/qca/nss/nss-ifb/src/Makefile @@ -0,0 +1,3 @@ +obj-m += nss-ifb.o + +nss-ifb-objs := nss_ifb.o diff --git a/root/package/qca/nss/nss-ifb/src/nss_ifb.c b/root/package/qca/nss/nss-ifb/src/nss_ifb.c new file mode 100644 index 00000000..18c017fe --- /dev/null +++ b/root/package/qca/nss/nss-ifb/src/nss_ifb.c @@ -0,0 +1,304 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +/* + * This driver is adapted from the Linux /drivers/net/ifb.c file. + * + * Redirect QCA NSS physical interface ingress traffic to this driver's + * virtual interface. This will allow ingress traffic shaping using the + * QCA NSS shaper. + */ + +#include + +#define TX_Q_LIMIT 32 + +struct nss_ifb_dev_private { + struct nss_virt_if_handle *nssctx; + struct net_device *nss_src_dev; + uint32_t nss_src_if_num; + char nss_src_dev_name[32]; +}; + +char nss_dev_name_array[32] = "eth0"; +char *nss_dev_name = nss_dev_name_array; +module_param(nss_dev_name, charp, 0644); +MODULE_PARM_DESC(nss_dev_name, "NSS physical interface source device name"); + +/* + * Virtual interface egress packet callback. + * + * We send it back to the Linux network stack. + */ +static void nss_ifb_data_cb(struct net_device *netdev, struct sk_buff *skb, struct napi_struct *napi) +{ + struct nss_ifb_dev_private *dp = netdev_priv(netdev); + + skb->protocol = eth_type_trans(skb, dp->nss_src_dev); + skb->ip_summed = CHECKSUM_UNNECESSARY; + + napi_gro_receive(napi, skb); +} + +/* + * Virtual interface ingress packet callback. + * + * We just send it back to the NSS firmware to let the shaper work on it. + */ +static void nss_ifb_xmit_cb(struct net_device *netdev, struct sk_buff *skb) +{ + struct nss_ifb_dev_private *dp = netdev_priv(netdev); + int ret; + + ret = nss_virt_if_tx_buf(dp->nssctx, skb); + if (unlikely(ret)) { + pr_warn("Failed [%d] to send skb [len: %d, protocol: 0x%X] to NSS!\n", + ret, skb->len, ntohs(skb->protocol)); + } +} + +static void nss_ifb_stats64(struct net_device *dev, + struct rtnl_link_stats64 *stats) +{ + +} + +static int nss_ifb_dev_init(struct net_device *dev) +{ + struct nss_ifb_dev_private *dp = netdev_priv(dev); + + dp->nssctx = nss_virt_if_create_sync_nexthop(dev, NSS_ETH_RX_INTERFACE, NSS_ETH_RX_INTERFACE); + if (!dp->nssctx) { + dp->nssctx = NULL; + pr_warn("Could not create a NSS virtual interface for dev [%s]\n", + dev->name); + + return -ENODEV; + } + pr_info("Created a NSS virtual interface for dev [%s]\n", dev->name); + + nss_virt_if_register(dp->nssctx, nss_ifb_data_cb, dev); + pr_info("NSS IFB data callback registered\n"); + + nss_virt_if_xmit_callback_register(dp->nssctx, nss_ifb_xmit_cb); + pr_info("NSS IFB transmit callback registered\n"); + + return 0; +} + +static void nss_ifb_dev_uninit(struct net_device *dev) +{ + struct nss_ifb_dev_private *dp = netdev_priv(dev); + int ret; + + nss_virt_if_xmit_callback_unregister(dp->nssctx); + pr_info("NSS IFB transmit callback unregistered\n"); + + ret = nss_virt_if_destroy_sync(dp->nssctx); + if (ret == NSS_TX_SUCCESS) { + pr_info("NSS virtual interface destroyed for dev [%s]\n", dev->name); + } + else { + pr_warn("Unable to destroy NSS virtual interface for dev [%s], error[%d]\n", + dev->name, ret); + } + dp->nssctx = NULL; +} + +static netdev_tx_t nss_ifb_xmit(struct sk_buff *skb, struct net_device *dev) +{ + return NETDEV_TX_OK; +} + +static int nss_ifb_close(struct net_device *dev) +{ + struct nss_ifb_dev_private *dp = netdev_priv(dev); + struct nss_ctx_instance *nss_ctx; + struct net_device *src_dev; + uint32_t src_if_num; + int ret; + + nss_ctx = dp->nssctx->nss_ctx; + src_dev = dp->nss_src_dev; + src_if_num = dp->nss_src_if_num; + + ret = nss_phys_if_set_nexthop(nss_ctx, src_if_num, NSS_ETH_RX_INTERFACE); + if (ret != NSS_TX_SUCCESS) { + pr_warn("%p: Failed to reset next hop for net device [%s].\n", + nss_ctx, src_dev->name); + } + else { + pr_info("%p: Reset nexthop successful for net device [%s].\n", + nss_ctx, src_dev->name); + } + + dev_put(src_dev); + dp->nss_src_dev = NULL; + dp->nss_src_if_num = -1; + + return 0; +} + +static int nss_ifb_open(struct net_device *dev) +{ + struct nss_ifb_dev_private *dp = netdev_priv(dev); + struct net_device *src_dev; + uint32_t src_if_num; + uint32_t nh_if_num; + nss_tx_status_t nss_tx_status; + struct nss_ctx_instance *nss_ctx; + + nss_ctx = dp->nssctx->nss_ctx; + nh_if_num = dp->nssctx->if_num_n2h; + + strcpy(dp->nss_src_dev_name, nss_dev_name); + + src_dev = dev_get_by_name(&init_net, dp->nss_src_dev_name); + if (!src_dev) { + pr_warn("%p: Cannot find the net device [%s]\n", + nss_ctx, dp->nss_src_dev_name); + + return -ENODEV; + } + pr_info("%p: Found net device [%s]\n", nss_ctx, dp->nss_src_dev_name); + + src_if_num = nss_cmn_get_interface_number_by_dev(src_dev); + if (src_if_num < 0) { + pr_warn("%p: Invalid interface number:%d\n", nss_ctx, src_if_num); + dev_put(src_dev); + + return -ENODEV; + } + pr_info("%p: Net device [%s] has NSS intf_num [%d]\n", + nss_ctx, dp->nss_src_dev_name, src_if_num); + + nss_tx_status = nss_phys_if_set_nexthop(nss_ctx, src_if_num, nh_if_num); + if (nss_tx_status != NSS_TX_SUCCESS) { + pr_warn("%p: Sending message failed, cannot change nexthop for [%s]\n", + nss_ctx, dp->nss_src_dev_name); + } + else { + pr_info("Nexthop successfully set for [%s] to [%s]\n", + dp->nss_src_dev_name, dev->name); + } + + dp->nss_src_dev = src_dev; + dp->nss_src_if_num = src_if_num; + + return 0; +} + +static const struct net_device_ops nss_ifb_netdev_ops = { + .ndo_open = nss_ifb_open, + .ndo_stop = nss_ifb_close, + .ndo_get_stats64 = nss_ifb_stats64, + .ndo_start_xmit = nss_ifb_xmit, + .ndo_validate_addr = eth_validate_addr, + .ndo_init = nss_ifb_dev_init, + .ndo_uninit = nss_ifb_dev_uninit, +}; + +#define IFB_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | NETIF_F_FRAGLIST | \ + NETIF_F_TSO_ECN | NETIF_F_TSO | NETIF_F_TSO6 | \ + NETIF_F_GSO_ENCAP_ALL | \ + NETIF_F_HIGHDMA | NETIF_F_HW_VLAN_CTAG_TX | \ + NETIF_F_HW_VLAN_STAG_TX) + +static void nss_ifb_dev_free(struct net_device *dev) +{ + +} + +static void nss_ifb_setup(struct net_device *dev) +{ + /* Initialize the device structure. */ + dev->netdev_ops = &nss_ifb_netdev_ops; + + /* Fill in device structure with ethernet-generic values. */ + ether_setup(dev); + dev->tx_queue_len = TX_Q_LIMIT; + + dev->features |= IFB_FEATURES; + dev->hw_features |= dev->features; + dev->hw_enc_features |= dev->features; + dev->vlan_features |= IFB_FEATURES & ~(NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_HW_VLAN_STAG_TX); + + dev->flags |= IFF_NOARP; + dev->flags &= ~IFF_MULTICAST; + dev->priv_flags &= ~IFF_TX_SKB_SHARING; + netif_keep_dst(dev); + eth_hw_addr_random(dev); + dev->needs_free_netdev = true; + dev->priv_destructor = nss_ifb_dev_free; + + dev->min_mtu = 0; + dev->max_mtu = 0; +} + +static int nss_ifb_validate(struct nlattr *tb[], struct nlattr *data[], + struct netlink_ext_ack *extack) +{ + if (tb[IFLA_ADDRESS]) { + if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) + return -EINVAL; + if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) + return -EADDRNOTAVAIL; + } + return 0; +} + +static struct rtnl_link_ops nss_ifb_link_ops __read_mostly = { + .kind = "nss_ifb", + .priv_size = sizeof(struct nss_ifb_dev_private), + .setup = nss_ifb_setup, + .validate = nss_ifb_validate, +}; + +static int __init nss_ifb_init_module(void) +{ + struct net_device *dev; + int err; + + down_write(&pernet_ops_rwsem); + rtnl_lock(); + err = __rtnl_link_register(&nss_ifb_link_ops); + if (err < 0) + goto out; + + dev = alloc_netdev(sizeof(struct nss_ifb_dev_private), "nssifb", + NET_NAME_UNKNOWN, nss_ifb_setup); + + if (dev) { + dev->rtnl_link_ops = &nss_ifb_link_ops; + err = register_netdevice(dev); + } + else { + err = -ENOMEM; + } + + if (err) + __rtnl_link_unregister(&nss_ifb_link_ops); + +out: + rtnl_unlock(); + up_write(&pernet_ops_rwsem); + + if (!err) + pr_info("NSS IFB module loaded.\n"); + else + pr_warn("Failed to load NSS IFB module.\n"); + + return err; +} + +static void __exit nss_ifb_cleanup_module(void) +{ + rtnl_link_unregister(&nss_ifb_link_ops); + + pr_info("NSS IFB module unloaded.\n"); +} + +module_init(nss_ifb_init_module); +module_exit(nss_ifb_cleanup_module); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_RTNL_LINK("nss_ifb"); diff --git a/root/package/qca/nss/qca-nss-cfi/Makefile b/root/package/qca/nss/qca-nss-cfi/Makefile new file mode 100644 index 00000000..570b45cf --- /dev/null +++ b/root/package/qca/nss/qca-nss-cfi/Makefile @@ -0,0 +1,99 @@ +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=qca-nss-cfi +PKG_RELEASE:=2 + +PKG_SOURCE_URL:=https://source.codeaurora.org/quic/qsdk/oss/lklm/nss-cfi +PKG_SOURCE_PROTO:=git +PKG_SOURCE_VERSION:=8035a8ddefdcc8a2f06c96b2a82618ca6ce6406d +PKG_MIRROR_HASH:=23316395d1346994d069eb41ef73a5505853687f8beab14f83545b3a05e52429 + +include $(INCLUDE_DIR)/package.mk + +ifeq ($(CONFIG_TARGET_ipq),y) +subtarget:=$(SUBTARGET) +else +subtarget:=$(CONFIG_TARGET_BOARD) +endif + +# v1.0 is for Akronite +# v2.0 is for Hawkeye/Cypress/Maple +ifneq (, $(findstring $(subtarget), "ipq807x" "ipq807x_64" "ipq60xx" "ipq60xx_64")) + CFI_OCF_DIR:=ocf/v2.0 + CFI_CRYPTOAPI_DIR:=cryptoapi/v2.0 +else + CFI_CRYPTOAPI_DIR:=cryptoapi/v1.1 + CFI_OCF_DIR:=ocf/v1.0 + CFI_IPSEC_DIR:=ipsec/v1.0 +endif + +define KernelPackage/qca-nss-cfi-cryptoapi + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + DEPENDS:=@TARGET_ipq806x||TARGET_ipq_ipq806x||TARGET_ipq_ipq807x||TARGET_ipq_ipq807x_64||TARGET_ipq807x||TARGET_ipq807x_64||TARGET_ipq_ipq60xx||TARGET_ipq_ipq60xx_64 \ + +kmod-qca-nss-crypto +kmod-crypto-authenc @LINUX_5_4 + TITLE:=Kernel driver for NSS cfi + FILES:=$(PKG_BUILD_DIR)/$(CFI_CRYPTOAPI_DIR)/qca-nss-cfi-cryptoapi.ko + AUTOLOAD:=$(call AutoLoad,59,qca-nss-cfi-cryptoapi) +endef + +# OCF should be dropped +# define KernelPackage/qca-nss-cfi-ocf +# SECTION:=kernel +# CATEGORY:=Kernel modules +# SUBMENU:=Network Devices +# DEPENDS:=@TARGET_ipq806x||TARGET_ipq_ipq806x||TARGET_ipq_ipq807x||TARGET_ipq_ipq807x_64||TARGET_ipq807x||TARGET_ipq807x_64||TARGET_ipq_ipq60xx||TARGET_ipq_ipq60xx_64 \ +# +kmod-qca-nss-crypto +PACKAGE_kmod-crypto-ocf:kmod-crypto-ocf @!LINUX_3_18 +# TITLE:=Kernel driver for NSS cfi +# FILES:=$(PKG_BUILD_DIR)/$(CFI_OCF_DIR)/qca-nss-cfi-ocf.ko + +# ifdef CFI_IPSEC_DIR +# FILES+=$(PKG_BUILD_DIR)/$(CFI_IPSEC_DIR)/qca-nss-ipsec.ko +# AUTOLOAD:=$(call AutoLoad,61,qca-nss-cfi-ocf qca-nss-ipsec) +# else +# AUTOLOAD:=$(call AutoLoad,61,qca-nss-cfi-ocf) +# endif +# endef + +define Build/InstallDev/qca-nss-cfi + $(INSTALL_DIR) $(1)/usr/include/qca-nss-cfi + $(CP) $(PKG_BUILD_DIR)/$(CFI_CRYPTOAPI_DIR)/../exports/* $(1)/usr/include/qca-nss-cfi + $(CP) $(PKG_BUILD_DIR)/include/* $(1)/usr/include/qca-nss-cfi +endef + +define Build/InstallDev + $(call Build/InstallDev/qca-nss-cfi,$(1)) +endef + +define KernelPackage/qca-nss-cfi/Description +This package contains a NSS cfi driver for QCA chipset +endef + +EXTRA_CFLAGS+= \ + -DCONFIG_NSS_DEBUG_LEVEL=4 \ + -I$(LINUX_DIR)/crypto/ocf \ + -I$(STAGING_DIR)/usr/include/qca-nss-crypto \ + -I$(STAGING_DIR)/usr/include/crypto \ + -I$(STAGING_DIR)/usr/include/qca-nss-drv + +ifneq (, $(findstring $(subtarget), "ipq807x" "ipq807x_64" "ipq60xx" "ipq60xx_64")) +EXTRA_CFLAGS+= -I$(STAGING_DIR)/usr/include/qca-nss-clients +endif + +define Build/Compile + $(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \ + $(KERNEL_MAKE_FLAGS) \ + $(PKG_MAKE_FLAGS) \ + M="$(PKG_BUILD_DIR)" \ + EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ + CFI_CRYPTOAPI_DIR=$(CFI_CRYPTOAPI_DIR) \ + CFI_OCF_DIR=$(CFI_OCF_DIR) \ + CFI_IPSEC_DIR=$(CFI_IPSEC_DIR) \ + SoC=$(subtarget) \ + modules +endef + +$(eval $(call KernelPackage,qca-nss-cfi-cryptoapi)) +#$(eval $(call KernelPackage,qca-nss-cfi-ocf)) diff --git a/root/package/qca/nss/qca-nss-cfi/patches/0001-compile-only-cryptoapi.patch b/root/package/qca/nss/qca-nss-cfi/patches/0001-compile-only-cryptoapi.patch new file mode 100644 index 00000000..00968f5f --- /dev/null +++ b/root/package/qca/nss/qca-nss-cfi/patches/0001-compile-only-cryptoapi.patch @@ -0,0 +1,30 @@ +From a8a573c5ce83bdddca9a60c62161638a5fd906d4 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Sat, 13 Jun 2020 12:57:14 +0200 +Subject: [PATCH 1/3] compile only cryptoapi + +--- + Makefile | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/Makefile b/Makefile +index c42adca..36a9d3f 100644 +--- a/Makefile ++++ b/Makefile +@@ -4,9 +4,9 @@ + + export BUILD_ID = \"Build Id: $(shell date +'%m/%d/%y, %H:%M:%S')\" + +-obj-m += $(CFI_OCF_DIR)/ ++# obj-m += $(CFI_OCF_DIR)/ + obj-m += $(CFI_CRYPTOAPI_DIR)/ + +-ifeq ($(SoC),$(filter $(SoC),ipq806x)) +-obj-m += $(CFI_IPSEC_DIR)/ +-endif ++# ifeq ($(SoC),$(filter $(SoC),ipq806x)) ++# obj-m += $(CFI_IPSEC_DIR)/ ++# endif +-- +2.27.0.rc0 + diff --git a/root/package/qca/nss/qca-nss-cfi/patches/0002-wip-support-5.4.patch b/root/package/qca/nss/qca-nss-cfi/patches/0002-wip-support-5.4.patch new file mode 100644 index 00000000..d68fc939 --- /dev/null +++ b/root/package/qca/nss/qca-nss-cfi/patches/0002-wip-support-5.4.patch @@ -0,0 +1,78 @@ +From 202f57bae49947a04301ac8ac9bdc00f28f09355 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Sat, 13 Jun 2020 12:58:26 +0200 +Subject: [PATCH 2/3] wip: support 5.4 + +--- + cryptoapi/v1.1/nss_cryptoapi.c | 1 - + cryptoapi/v1.1/nss_cryptoapi_ablk.c | 12 ++++++------ + cryptoapi/v1.1/nss_cryptoapi_aead.c | 2 +- + 3 files changed, 7 insertions(+), 8 deletions(-) + +diff --git a/cryptoapi/v1.1/nss_cryptoapi.c b/cryptoapi/v1.1/nss_cryptoapi.c +index d1a7313..a10590e 100644 +--- a/cryptoapi/v1.1/nss_cryptoapi.c ++++ b/cryptoapi/v1.1/nss_cryptoapi.c +@@ -231,7 +231,6 @@ static struct crypto_alg cryptoapi_ablkcipher_algs[] = { + .cra_u = { + .ablkcipher = { + .ivsize = CTR_RFC3686_IV_SIZE, +- .geniv = "seqiv", + .min_keysize = AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, + .max_keysize = AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, + .setkey = nss_cryptoapi_ablk_aes_setkey, +diff --git a/cryptoapi/v1.1/nss_cryptoapi_ablk.c b/cryptoapi/v1.1/nss_cryptoapi_ablk.c +index 223591c..9b6c65e 100644 +--- a/cryptoapi/v1.1/nss_cryptoapi_ablk.c ++++ b/cryptoapi/v1.1/nss_cryptoapi_ablk.c +@@ -108,7 +108,7 @@ EXPORT_SYMBOL(nss_cryptoapi_skcipher_ctx2session); + int nss_cryptoapi_ablkcipher_init(struct crypto_tfm *tfm) + { + struct nss_cryptoapi_ctx *ctx = crypto_tfm_ctx(tfm); +- struct crypto_ablkcipher *sw_tfm; ++ struct crypto_cipher *sw_tfm; + + nss_cfi_assert(ctx); + +@@ -122,20 +122,20 @@ int nss_cryptoapi_ablkcipher_init(struct crypto_tfm *tfm) + + nss_cryptoapi_set_magic(ctx); + +- if (!(crypto_tfm_alg_flags(tfm) & CRYPTO_ALG_NEED_FALLBACK)) ++ if (!(crypto_tfm_alg_type(tfm) & CRYPTO_ALG_NEED_FALLBACK)) + return 0; + + /* Alloc fallback transform for future use */ +- sw_tfm = crypto_alloc_ablkcipher(crypto_tfm_alg_name(tfm), 0, CRYPTO_ALG_ASYNC | +- CRYPTO_ALG_NEED_FALLBACK); ++ sw_tfm = crypto_alloc_cipher(crypto_tfm_alg_name(tfm), 0, CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_NEED_FALLBACK); + if (IS_ERR(sw_tfm)) { + nss_cfi_err("unable to alloc software crypto for %s\n", crypto_tfm_alg_name(tfm)); + return -EINVAL; + } + + /* set this tfm reqsize same to fallback tfm */ +- tfm->crt_ablkcipher.reqsize = crypto_ablkcipher_reqsize(sw_tfm); +- ctx->sw_tfm = crypto_ablkcipher_tfm(sw_tfm); ++ tfm->crt_ablkcipher.reqsize = sizeof(struct nss_cryptoapi_ctx); ++ ctx->sw_tfm = crypto_cipher_tfm(sw_tfm); + + return 0; + } +diff --git a/cryptoapi/v1.1/nss_cryptoapi_aead.c b/cryptoapi/v1.1/nss_cryptoapi_aead.c +index 527936b..53e4bed 100644 +--- a/cryptoapi/v1.1/nss_cryptoapi_aead.c ++++ b/cryptoapi/v1.1/nss_cryptoapi_aead.c +@@ -103,7 +103,7 @@ int nss_cryptoapi_aead_init(struct crypto_aead *aead) + + nss_cryptoapi_set_magic(ctx); + +- if (!(crypto_tfm_alg_flags(tfm) & CRYPTO_ALG_NEED_FALLBACK)) ++ if (!(crypto_tfm_alg_type(tfm) & CRYPTO_ALG_NEED_FALLBACK)) + return 0; + + /* Alloc fallback transform for future use */ +-- +2.27.0.rc0 + diff --git a/root/package/qca/nss/qca-nss-cfi/patches/0003-Convert-ablkcipher-to-skcipher.patch b/root/package/qca/nss/qca-nss-cfi/patches/0003-Convert-ablkcipher-to-skcipher.patch new file mode 100644 index 00000000..b4520a3d --- /dev/null +++ b/root/package/qca/nss/qca-nss-cfi/patches/0003-Convert-ablkcipher-to-skcipher.patch @@ -0,0 +1,707 @@ +From e3a53a6d11b2c1770545a2820a58c117799bcb70 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Tue, 16 Jun 2020 18:12:34 +0200 +Subject: [PATCH 3/3] Convert ablkcipher to skcipher + +--- + cryptoapi/v1.1/nss_cryptoapi.c | 149 +++++++++++-------------- + cryptoapi/v1.1/nss_cryptoapi_ablk.c | 136 +++++++++++----------- + cryptoapi/v1.1/nss_cryptoapi_debugfs.c | 1 + + cryptoapi/v1.1/nss_cryptoapi_private.h | 16 +-- + 4 files changed, 145 insertions(+), 157 deletions(-) + +diff --git a/cryptoapi/v1.1/nss_cryptoapi.c b/cryptoapi/v1.1/nss_cryptoapi.c +index a10590e..3a835dc 100644 +--- a/cryptoapi/v1.1/nss_cryptoapi.c ++++ b/cryptoapi/v1.1/nss_cryptoapi.c +@@ -66,7 +66,7 @@ struct aead_alg cryptoapi_aead_algs[] = { + .cra_name = "echainiv(authenc(hmac(sha1),cbc(aes)))", + .cra_driver_name = "nss-hmac-sha1-cbc-aes", + .cra_priority = 10000, +- .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_NEED_FALLBACK, ++ .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_KERN_DRIVER_ONLY, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct nss_cryptoapi_ctx), + .cra_alignmask = 0, +@@ -87,7 +87,7 @@ struct aead_alg cryptoapi_aead_algs[] = { + .cra_name = "seqiv(authenc(hmac(sha1),rfc3686(ctr(aes))))", + .cra_driver_name = "nss-hmac-sha1-rfc3686-ctr-aes", + .cra_priority = 10000, +- .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_NEED_FALLBACK, ++ .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_KERN_DRIVER_ONLY, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct nss_cryptoapi_ctx), + .cra_alignmask = 0, +@@ -108,7 +108,7 @@ struct aead_alg cryptoapi_aead_algs[] = { + .cra_name = "echainiv(authenc(hmac(sha1),cbc(des3_ede)))", + .cra_driver_name = "nss-hmac-sha1-cbc-3des", + .cra_priority = 300, +- .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NOSUPP_SG, ++ .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_KERN_DRIVER_ONLY, + .cra_blocksize = DES3_EDE_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct nss_cryptoapi_ctx), + .cra_alignmask = 0, +@@ -129,7 +129,7 @@ struct aead_alg cryptoapi_aead_algs[] = { + .cra_name = "echainiv(authenc(hmac(sha256),cbc(aes)))", + .cra_driver_name = "nss-hmac-sha256-cbc-aes", + .cra_priority = 10000, +- .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_NEED_FALLBACK, ++ .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_KERN_DRIVER_ONLY, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct nss_cryptoapi_ctx), + .cra_alignmask = 0, +@@ -150,7 +150,7 @@ struct aead_alg cryptoapi_aead_algs[] = { + .cra_name = "seqiv(authenc(hmac(sha256),rfc3686(ctr(aes))))", + .cra_driver_name = "nss-hmac-sha256-rfc3686-ctr-aes", + .cra_priority = 10000, +- .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_NEED_FALLBACK, ++ .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_KERN_DRIVER_ONLY, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct nss_cryptoapi_ctx), + .cra_alignmask = 0, +@@ -171,7 +171,7 @@ struct aead_alg cryptoapi_aead_algs[] = { + .cra_name = "echainiv(authenc(hmac(sha256),cbc(des3_ede)))", + .cra_driver_name = "nss-hmac-sha256-cbc-3des", + .cra_priority = 300, +- .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NOSUPP_SG, ++ .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_KERN_DRIVER_ONLY, + .cra_blocksize = DES3_EDE_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct nss_cryptoapi_ctx), + .cra_alignmask = 0, +@@ -192,75 +192,66 @@ struct aead_alg cryptoapi_aead_algs[] = { + /* + * ABLK cipher algorithms + */ +-static struct crypto_alg cryptoapi_ablkcipher_algs[] = { ++static struct skcipher_alg cryptoapi_skcipher_algs[] = { + { +- .cra_name = "cbc(aes)", +- .cra_driver_name = "nss-cbc-aes", +- .cra_priority = 10000, +- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, +- .cra_blocksize = AES_BLOCK_SIZE, +- .cra_ctxsize = sizeof(struct nss_cryptoapi_ctx), +- .cra_alignmask = 0, +- .cra_type = &crypto_ablkcipher_type, +- .cra_module = THIS_MODULE, +- .cra_init = nss_cryptoapi_ablkcipher_init, +- .cra_exit = nss_cryptoapi_ablkcipher_exit, +- .cra_u = { +- .ablkcipher = { +- .ivsize = AES_BLOCK_SIZE, +- .min_keysize = AES_MIN_KEY_SIZE, +- .max_keysize = AES_MAX_KEY_SIZE, +- .setkey = nss_cryptoapi_ablk_aes_setkey, +- .encrypt = nss_cryptoapi_ablk_aes_encrypt, +- .decrypt = nss_cryptoapi_ablk_aes_decrypt, +- }, ++ .base = { ++ .cra_name = "cbc(aes)", ++ .cra_driver_name = "nss-cbc-aes", ++ .cra_priority = 10000, ++ .cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_KERN_DRIVER_ONLY, ++ .cra_blocksize = AES_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct nss_cryptoapi_ctx), ++ .cra_alignmask = 0, ++ .cra_module = THIS_MODULE, + }, ++ .init = nss_cryptoapi_skcipher_init, ++ .exit = nss_cryptoapi_skcipher_exit, ++ .ivsize = AES_BLOCK_SIZE, ++ .min_keysize = AES_MIN_KEY_SIZE, ++ .max_keysize = AES_MAX_KEY_SIZE, ++ .setkey = nss_cryptoapi_ablk_aes_setkey, ++ .encrypt = nss_cryptoapi_ablk_aes_encrypt, ++ .decrypt = nss_cryptoapi_ablk_aes_decrypt, + }, + { +- .cra_name = "rfc3686(ctr(aes))", +- .cra_driver_name = "nss-rfc3686-ctr-aes", +- .cra_priority = 30000, +- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, +- .cra_blocksize = AES_BLOCK_SIZE, +- .cra_ctxsize = sizeof(struct nss_cryptoapi_ctx), +- .cra_alignmask = 0, +- .cra_type = &crypto_ablkcipher_type, +- .cra_module = THIS_MODULE, +- .cra_init = nss_cryptoapi_ablkcipher_init, +- .cra_exit = nss_cryptoapi_ablkcipher_exit, +- .cra_u = { +- .ablkcipher = { +- .ivsize = CTR_RFC3686_IV_SIZE, +- .min_keysize = AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, +- .max_keysize = AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, +- .setkey = nss_cryptoapi_ablk_aes_setkey, +- .encrypt = nss_cryptoapi_ablk_aes_encrypt, +- .decrypt = nss_cryptoapi_ablk_aes_decrypt, +- }, ++ .base = { ++ .cra_name = "rfc3686(ctr(aes))", ++ .cra_driver_name = "nss-rfc3686-ctr-aes", ++ .cra_priority = 30000, ++ .cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_KERN_DRIVER_ONLY, ++ .cra_blocksize = AES_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct nss_cryptoapi_ctx), ++ .cra_alignmask = 0, ++ .cra_module = THIS_MODULE, + }, ++ .init = nss_cryptoapi_skcipher_init, ++ .exit = nss_cryptoapi_skcipher_exit, ++ .ivsize = CTR_RFC3686_IV_SIZE, ++ .min_keysize = AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, ++ .max_keysize = AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, ++ .setkey = nss_cryptoapi_ablk_aes_setkey, ++ .encrypt = nss_cryptoapi_ablk_aes_encrypt, ++ .decrypt = nss_cryptoapi_ablk_aes_decrypt, + }, + { +- .cra_name = "cbc(des3_ede)", +- .cra_driver_name = "nss-cbc-3des", +- .cra_priority = 1000, +- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_ASYNC, +- .cra_blocksize = DES3_EDE_BLOCK_SIZE, +- .cra_ctxsize = sizeof(struct nss_cryptoapi_ctx), +- .cra_alignmask = 0, +- .cra_type = &crypto_ablkcipher_type, +- .cra_module = THIS_MODULE, +- .cra_init = nss_cryptoapi_ablkcipher_init, +- .cra_exit = nss_cryptoapi_ablkcipher_exit, +- .cra_u = { +- .ablkcipher = { +- .ivsize = DES3_EDE_BLOCK_SIZE, +- .min_keysize = DES3_EDE_KEY_SIZE, +- .max_keysize = DES3_EDE_KEY_SIZE, +- .setkey = nss_cryptoapi_3des_cbc_setkey, +- .encrypt = nss_cryptoapi_3des_cbc_encrypt, +- .decrypt = nss_cryptoapi_3des_cbc_decrypt, +- }, ++ .base = { ++ .cra_name = "cbc(des3_ede)", ++ .cra_driver_name = "nss-cbc-3des", ++ .cra_priority = 1000, ++ .cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY, ++ .cra_blocksize = DES3_EDE_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct nss_cryptoapi_ctx), ++ .cra_alignmask = 0, ++ .cra_module = THIS_MODULE, + }, ++ .init = nss_cryptoapi_skcipher_init, ++ .exit = nss_cryptoapi_skcipher_exit, ++ .ivsize = DES3_EDE_BLOCK_SIZE, ++ .min_keysize = DES3_EDE_KEY_SIZE, ++ .max_keysize = DES3_EDE_KEY_SIZE, ++ .setkey = nss_cryptoapi_3des_cbc_setkey, ++ .encrypt = nss_cryptoapi_3des_cbc_encrypt, ++ .decrypt = nss_cryptoapi_3des_cbc_decrypt, + }, + }; + +@@ -277,14 +268,14 @@ static nss_crypto_user_ctx_t nss_cryptoapi_register(nss_crypto_handle_t crypto) + + sc->crypto = crypto; + +- for (i = 0; i < ARRAY_SIZE(cryptoapi_ablkcipher_algs); i++) { +- rc = crypto_register_alg(&cryptoapi_ablkcipher_algs[i]); ++ for (i = 0; i < ARRAY_SIZE(cryptoapi_skcipher_algs); i++) { ++ rc = crypto_register_skcipher(&cryptoapi_skcipher_algs[i]); + if (rc) { +- nss_cfi_trace("Ablk registration failed, algo: %s\n", cryptoapi_ablkcipher_algs[i].cra_name); +- cryptoapi_ablkcipher_algs[i].cra_flags = 0; ++ nss_cfi_trace("Ablk registration failed, algo: %s\n", cryptoapi_skcipher_algs[i].base.cra_name); ++ cryptoapi_skcipher_algs[i].base.cra_flags = 0; + continue; + } +- nss_cfi_info("Ablk registration succeeded, algo: %s\n", cryptoapi_ablkcipher_algs[i].cra_name); ++ nss_cfi_info("Ablk registration succeeded, algo: %s\n", cryptoapi_skcipher_algs[i].base.cra_name); + } + + for (i = 0; i < ARRAY_SIZE(cryptoapi_aead_algs); i++) { +@@ -317,7 +308,7 @@ static nss_crypto_user_ctx_t nss_cryptoapi_register(nss_crypto_handle_t crypto) + static void nss_cryptoapi_unregister(nss_crypto_user_ctx_t cfi) + { + struct nss_cryptoapi *sc = &gbl_ctx; +- int i, ret = 0; ++ int i; + + nss_cfi_info("unregister nss_cryptoapi\n"); + +@@ -326,16 +317,12 @@ static void nss_cryptoapi_unregister(nss_crypto_user_ctx_t cfi) + */ + atomic_set(&gbl_ctx.registered, 0); + +- for (i = 0; i < ARRAY_SIZE(cryptoapi_ablkcipher_algs); i++) { +- if (!cryptoapi_ablkcipher_algs[i].cra_flags) { +- continue; +- } +- ret = crypto_unregister_alg(&cryptoapi_ablkcipher_algs[i]); +- if (ret) { +- nss_cfi_err("Ablk unregister failed, algo: %s\n", cryptoapi_ablkcipher_algs[i].cra_name); ++ for (i = 0; i < ARRAY_SIZE(cryptoapi_skcipher_algs); i++) { ++ if (!cryptoapi_skcipher_algs[i].base.cra_flags) { + continue; + } +- nss_cfi_info("Ablk unregister succeeded, algo: %s\n", cryptoapi_ablkcipher_algs[i].cra_name); ++ crypto_unregister_skcipher(&cryptoapi_skcipher_algs[i]); ++ nss_cfi_info("Ablk unregister succeeded, algo: %s\n", cryptoapi_skcipher_algs[i].base.cra_name); + } + + for (i = 0; i < ARRAY_SIZE(cryptoapi_aead_algs); i++) { +diff --git a/cryptoapi/v1.1/nss_cryptoapi_ablk.c b/cryptoapi/v1.1/nss_cryptoapi_ablk.c +index 9b6c65e..913e9cc 100644 +--- a/cryptoapi/v1.1/nss_cryptoapi_ablk.c ++++ b/cryptoapi/v1.1/nss_cryptoapi_ablk.c +@@ -102,12 +102,12 @@ int nss_cryptoapi_skcipher_ctx2session(struct crypto_skcipher *sk, uint32_t *sid + EXPORT_SYMBOL(nss_cryptoapi_skcipher_ctx2session); + + /* +- * nss_cryptoapi_ablkcipher_init() +- * Cryptoapi ablkcipher init function. ++ * nss_cryptoapi_skcipher_init() ++ * Cryptoapi skcipher init function. + */ +-int nss_cryptoapi_ablkcipher_init(struct crypto_tfm *tfm) ++int nss_cryptoapi_skcipher_init(struct crypto_skcipher *tfm) + { +- struct nss_cryptoapi_ctx *ctx = crypto_tfm_ctx(tfm); ++ struct nss_cryptoapi_ctx *ctx = crypto_skcipher_ctx(tfm); + struct crypto_cipher *sw_tfm; + + nss_cfi_assert(ctx); +@@ -122,31 +122,31 @@ int nss_cryptoapi_ablkcipher_init(struct crypto_tfm *tfm) + + nss_cryptoapi_set_magic(ctx); + +- if (!(crypto_tfm_alg_type(tfm) & CRYPTO_ALG_NEED_FALLBACK)) ++ if (!(crypto_tfm_alg_type(&tfm->base) & CRYPTO_ALG_NEED_FALLBACK)) + return 0; + + /* Alloc fallback transform for future use */ +- sw_tfm = crypto_alloc_cipher(crypto_tfm_alg_name(tfm), 0, CRYPTO_ALG_ASYNC | ++ sw_tfm = crypto_alloc_cipher(crypto_tfm_alg_name(&tfm->base), 0, CRYPTO_ALG_ASYNC | + CRYPTO_ALG_NEED_FALLBACK); + if (IS_ERR(sw_tfm)) { +- nss_cfi_err("unable to alloc software crypto for %s\n", crypto_tfm_alg_name(tfm)); ++ nss_cfi_err("unable to alloc software crypto for %s\n", crypto_tfm_alg_name(&tfm->base)); + return -EINVAL; + } + + /* set this tfm reqsize same to fallback tfm */ +- tfm->crt_ablkcipher.reqsize = sizeof(struct nss_cryptoapi_ctx); ++ crypto_skcipher_set_reqsize(tfm, sizeof(struct nss_cryptoapi_ctx)); + ctx->sw_tfm = crypto_cipher_tfm(sw_tfm); + + return 0; + } + + /* +- * nss_cryptoapi_ablkcipher_exit() +- * Cryptoapi ablkcipher exit function. ++ * nss_cryptoapi_skcipher_exit() ++ * Cryptoapi skcipher exit function. + */ +-void nss_cryptoapi_ablkcipher_exit(struct crypto_tfm *tfm) ++void nss_cryptoapi_skcipher_exit(struct crypto_skcipher *tfm) + { +- struct nss_cryptoapi_ctx *ctx = crypto_tfm_ctx(tfm); ++ struct nss_cryptoapi_ctx *ctx = crypto_skcipher_ctx(tfm); + struct nss_cryptoapi *sc = &gbl_ctx; + nss_crypto_status_t status; + +@@ -158,7 +158,7 @@ void nss_cryptoapi_ablkcipher_exit(struct crypto_tfm *tfm) + } + + if (ctx->sw_tfm) { +- crypto_free_ablkcipher(__crypto_ablkcipher_cast(ctx->sw_tfm)); ++ crypto_free_skcipher(__crypto_skcipher_cast(ctx->sw_tfm)); + ctx->sw_tfm = NULL; + } + +@@ -183,9 +183,9 @@ void nss_cryptoapi_ablkcipher_exit(struct crypto_tfm *tfm) + * nss_cryptoapi_ablk_aes_setkey() + * Cryptoapi setkey routine for aes. + */ +-int nss_cryptoapi_ablk_aes_setkey(struct crypto_ablkcipher *cipher, const u8 *key, unsigned int keylen) ++int nss_cryptoapi_ablk_aes_setkey(struct crypto_skcipher *cipher, const u8 *key, unsigned int keylen) + { +- struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher); ++ struct crypto_tfm *tfm = crypto_skcipher_tfm(cipher); + struct nss_cryptoapi_ctx *ctx = crypto_tfm_ctx(tfm); + struct nss_cryptoapi *sc = &gbl_ctx; + struct nss_crypto_key cip; +@@ -255,10 +255,10 @@ int nss_cryptoapi_ablk_aes_setkey(struct crypto_ablkcipher *cipher, const u8 *ke + + /* set flag to fallback tfm */ + crypto_tfm_clear_flags(ctx->sw_tfm, CRYPTO_TFM_REQ_MASK); +- crypto_tfm_set_flags(ctx->sw_tfm, crypto_ablkcipher_get_flags(cipher) & CRYPTO_TFM_REQ_MASK); ++ crypto_tfm_set_flags(ctx->sw_tfm, crypto_skcipher_get_flags(cipher) & CRYPTO_TFM_REQ_MASK); + + /* Set key to the fallback tfm */ +- ret = crypto_ablkcipher_setkey(__crypto_ablkcipher_cast(ctx->sw_tfm), key, keylen); ++ ret = crypto_skcipher_setkey(__crypto_skcipher_cast(ctx->sw_tfm), key, keylen); + if (ret) { + nss_cfi_err("Failed to set key to the sw crypto"); + +@@ -266,7 +266,7 @@ int nss_cryptoapi_ablk_aes_setkey(struct crypto_ablkcipher *cipher, const u8 *ke + * Set back the fallback tfm flag to the original flag one after + * doing setkey + */ +- crypto_ablkcipher_set_flags(cipher, crypto_tfm_get_flags(ctx->sw_tfm)); ++ crypto_skcipher_set_flags(cipher, crypto_tfm_get_flags(ctx->sw_tfm)); + } + return ret; + default: +@@ -289,23 +289,23 @@ int nss_cryptoapi_ablk_aes_setkey(struct crypto_ablkcipher *cipher, const u8 *ke + return 0; + + fail: +- crypto_ablkcipher_set_flags(cipher, flag); ++ crypto_skcipher_set_flags(cipher, flag); + return -EINVAL; + } + + /* +- * nss_cryptoapi_ablkcipher_done() ++ * nss_cryptoapi_skcipher_done() + * Cipher operation completion callback function + */ +-void nss_cryptoapi_ablkcipher_done(struct nss_crypto_buf *buf) ++void nss_cryptoapi_skcipher_done(struct nss_crypto_buf *buf) + { + struct nss_cryptoapi_ctx *ctx; +- struct ablkcipher_request *req; ++ struct skcipher_request *req; + int err = 0; + + nss_cfi_assert(buf); + +- req = (struct ablkcipher_request *)nss_crypto_get_cb_ctx(buf); ++ req = (struct skcipher_request *)nss_crypto_get_cb_ctx(buf); + + /* + * check cryptoapi context magic number. +@@ -319,7 +319,7 @@ void nss_cryptoapi_ablkcipher_done(struct nss_crypto_buf *buf) + nss_crypto_buf_free(gbl_ctx.crypto, buf); + + nss_cfi_dbg("after transformation\n"); +- nss_cfi_dbg_data(sg_virt(req->dst), req->nbytes, ' '); ++ nss_cfi_dbg_data(sg_virt(req->dst), req->cryptlen, ' '); + + /* + * Passing always pass in case of encrypt. +@@ -337,7 +337,7 @@ void nss_cryptoapi_ablkcipher_done(struct nss_crypto_buf *buf) + * Cryptoapi: obtain sg to virtual address mapping. + * Check for multiple sg in src and dst + */ +-int nss_cryptoapi_ablk_checkaddr(struct ablkcipher_request *req) ++int nss_cryptoapi_ablk_checkaddr(struct skcipher_request *req) + { + /* + * Currently only single sg is supported +@@ -356,7 +356,7 @@ int nss_cryptoapi_ablk_checkaddr(struct ablkcipher_request *req) + /* + * If the size of data is more than 65K reject transformation + */ +- if (req->nbytes > NSS_CRYPTOAPI_MAX_DATA_LEN) { ++ if (req->cryptlen > NSS_CRYPTOAPI_MAX_DATA_LEN) { + nss_cfi_err("Buffer length exceeded limit\n"); + return -EINVAL; + } +@@ -368,10 +368,10 @@ int nss_cryptoapi_ablk_checkaddr(struct ablkcipher_request *req) + * nss_cryptoapi_ablk_transform() + * Crytoapi common routine for encryption and decryption operations. + */ +-struct nss_crypto_buf *nss_cryptoapi_ablk_transform(struct ablkcipher_request *req, struct nss_cryptoapi_ablk_info *info) ++struct nss_crypto_buf *nss_cryptoapi_ablk_transform(struct skcipher_request *req, struct nss_cryptoapi_ablk_info *info) + { +- struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(req); +- struct nss_cryptoapi_ctx *ctx = crypto_ablkcipher_ctx(cipher); ++ struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(req); ++ struct nss_cryptoapi_ctx *ctx = crypto_skcipher_ctx(cipher); + struct nss_crypto_buf *buf; + struct nss_cryptoapi *sc = &gbl_ctx; + nss_crypto_status_t status; +@@ -382,7 +382,7 @@ struct nss_crypto_buf *nss_cryptoapi_ablk_transform(struct ablkcipher_request *r + nss_cfi_assert(ctx); + + nss_cfi_dbg("src_vaddr: 0x%p, dst_vaddr: 0x%p, iv: 0x%p\n", +- sg_virt(req->src), sg_virt(req->dst), req->info); ++ sg_virt(req->src), sg_virt(req->dst), req->iv); + + info->params->cipher_skip = 0; + info->params->auth_skip = 0; +@@ -419,19 +419,19 @@ struct nss_crypto_buf *nss_cryptoapi_ablk_transform(struct ablkcipher_request *r + /* + * Get IV location and memcpy the IV + */ +- iv_size = crypto_ablkcipher_ivsize(cipher); ++ iv_size = crypto_skcipher_ivsize(cipher); + iv_addr = nss_crypto_get_ivaddr(buf); + + switch (ctx->cip_alg) { + case NSS_CRYPTO_CIPHER_AES_CBC: + case NSS_CRYPTO_CIPHER_DES: +- memcpy(iv_addr, req->info, iv_size); ++ memcpy(iv_addr, req->iv, iv_size); + break; + + case NSS_CRYPTO_CIPHER_AES_CTR: + ((uint32_t *)iv_addr)[0] = ctx->ctx_iv[0]; +- ((uint32_t *)iv_addr)[1] = ((uint32_t *)req->info)[0]; +- ((uint32_t *)iv_addr)[2] = ((uint32_t *)req->info)[1]; ++ ((uint32_t *)iv_addr)[1] = ((uint32_t *)req->iv)[0]; ++ ((uint32_t *)iv_addr)[2] = ((uint32_t *)req->iv)[1]; + ((uint32_t *)iv_addr)[3] = ctx->ctx_iv[3]; + break; + +@@ -446,7 +446,7 @@ struct nss_crypto_buf *nss_cryptoapi_ablk_transform(struct ablkcipher_request *r + /* + * Fill Cipher and Auth len + */ +- cipher_len = req->nbytes; ++ cipher_len = req->cryptlen; + auth_len = 0; + + nss_crypto_set_data(buf, sg_virt(req->src), sg_virt(req->dst), cipher_len); +@@ -463,12 +463,12 @@ struct nss_crypto_buf *nss_cryptoapi_ablk_transform(struct ablkcipher_request *r + } + + /* +- * nss_cryptoapi_ablkcipher_fallback() +- * Cryptoapi fallback for ablkcipher algorithm. ++ * nss_cryptoapi_skcipher_fallback() ++ * Cryptoapi fallback for skcipher algorithm. + */ +-int nss_cryptoapi_ablkcipher_fallback(struct nss_cryptoapi_ctx *ctx, struct ablkcipher_request *req, int type) ++int nss_cryptoapi_skcipher_fallback(struct nss_cryptoapi_ctx *ctx, struct skcipher_request *req, int type) + { +- struct crypto_ablkcipher *orig_tfm = crypto_ablkcipher_reqtfm(req); ++ struct crypto_skcipher *orig_tfm = crypto_skcipher_reqtfm(req); + int err; + + if (!ctx->sw_tfm) { +@@ -476,16 +476,16 @@ int nss_cryptoapi_ablkcipher_fallback(struct nss_cryptoapi_ctx *ctx, struct ablk + } + + /* Set new fallback tfm to the request */ +- ablkcipher_request_set_tfm(req, __crypto_ablkcipher_cast(ctx->sw_tfm)); ++ skcipher_request_set_tfm(req, __crypto_skcipher_cast(ctx->sw_tfm)); + + ctx->queued++; + + switch (type) { + case NSS_CRYPTOAPI_ENCRYPT: +- err = crypto_ablkcipher_encrypt(req); ++ err = crypto_skcipher_encrypt(req); + break; + case NSS_CRYPTOAPI_DECRYPT: +- err = crypto_ablkcipher_decrypt(req); ++ err = crypto_skcipher_decrypt(req); + break; + default: + err = -EINVAL; +@@ -495,7 +495,7 @@ int nss_cryptoapi_ablkcipher_fallback(struct nss_cryptoapi_ctx *ctx, struct ablk + ctx->completed++; + + /* Set original tfm to the request */ +- ablkcipher_request_set_tfm(req, orig_tfm); ++ skcipher_request_set_tfm(req, orig_tfm); + + return err; + } +@@ -504,13 +504,13 @@ int nss_cryptoapi_ablkcipher_fallback(struct nss_cryptoapi_ctx *ctx, struct ablk + * nss_cryptoapi_ablk_aes_encrypt() + * Crytoapi encrypt for aes(aes-cbc/rfc3686-aes-ctr) algorithms. + */ +-int nss_cryptoapi_ablk_aes_encrypt(struct ablkcipher_request *req) ++int nss_cryptoapi_ablk_aes_encrypt(struct skcipher_request *req) + { + struct nss_crypto_params params = { .req_type = NSS_CRYPTO_REQ_TYPE_ENCRYPT }; +- struct nss_cryptoapi_ablk_info info = {.cb_fn = nss_cryptoapi_ablkcipher_done, ++ struct nss_cryptoapi_ablk_info info = {.cb_fn = nss_cryptoapi_skcipher_done, + .params = ¶ms}; +- struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(req); +- struct nss_cryptoapi_ctx *ctx = crypto_ablkcipher_ctx(cipher); ++ struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(req); ++ struct nss_cryptoapi_ctx *ctx = crypto_skcipher_ctx(cipher); + struct nss_cryptoapi *sc = &gbl_ctx; + struct nss_crypto_buf *buf; + +@@ -520,7 +520,7 @@ int nss_cryptoapi_ablk_aes_encrypt(struct ablkcipher_request *req) + nss_cryptoapi_verify_magic(ctx); + + if (ctx->fallback_req) +- return nss_cryptoapi_ablkcipher_fallback(ctx, req, NSS_CRYPTOAPI_ENCRYPT); ++ return nss_cryptoapi_skcipher_fallback(ctx, req, NSS_CRYPTOAPI_ENCRYPT); + + /* + * Check if previous call to setkey couldn't allocate session with core crypto. +@@ -539,9 +539,9 @@ int nss_cryptoapi_ablk_aes_encrypt(struct ablkcipher_request *req) + * According to RFC3686, AES-CTR algo need not be padded if the + * plaintext or ciphertext is unaligned to block size boundary. + */ +- if (nss_cryptoapi_check_unalign(req->nbytes, AES_BLOCK_SIZE) && (ctx->cip_alg != NSS_CRYPTO_CIPHER_AES_CTR)) { ++ if (nss_cryptoapi_check_unalign(req->cryptlen, AES_BLOCK_SIZE) && (ctx->cip_alg != NSS_CRYPTO_CIPHER_AES_CTR)) { + nss_cfi_err("Invalid cipher len - Not aligned to algo blocksize\n"); +- crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_BLOCK_LEN); ++ crypto_skcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_BLOCK_LEN); + return -EINVAL; + } + +@@ -571,13 +571,13 @@ int nss_cryptoapi_ablk_aes_encrypt(struct ablkcipher_request *req) + * nss_cryptoapi_ablk_aes_decrypt() + * Crytoapi decrypt for aes(aes-cbc/rfc3686-aes-ctr) algorithms. + */ +-int nss_cryptoapi_ablk_aes_decrypt(struct ablkcipher_request *req) ++int nss_cryptoapi_ablk_aes_decrypt(struct skcipher_request *req) + { + struct nss_crypto_params params = { .req_type = NSS_CRYPTO_REQ_TYPE_DECRYPT }; +- struct nss_cryptoapi_ablk_info info = {.cb_fn = nss_cryptoapi_ablkcipher_done, ++ struct nss_cryptoapi_ablk_info info = {.cb_fn = nss_cryptoapi_skcipher_done, + .params = ¶ms}; +- struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(req); +- struct nss_cryptoapi_ctx *ctx = crypto_ablkcipher_ctx(cipher); ++ struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(req); ++ struct nss_cryptoapi_ctx *ctx = crypto_skcipher_ctx(cipher); + struct nss_cryptoapi *sc = &gbl_ctx; + struct nss_crypto_buf *buf; + +@@ -587,7 +587,7 @@ int nss_cryptoapi_ablk_aes_decrypt(struct ablkcipher_request *req) + nss_cryptoapi_verify_magic(ctx); + + if (ctx->fallback_req) +- return nss_cryptoapi_ablkcipher_fallback(ctx, req, NSS_CRYPTOAPI_DECRYPT); ++ return nss_cryptoapi_skcipher_fallback(ctx, req, NSS_CRYPTOAPI_DECRYPT); + + /* + * Check if previous call to setkey couldn't allocate session with core crypto. +@@ -606,9 +606,9 @@ int nss_cryptoapi_ablk_aes_decrypt(struct ablkcipher_request *req) + * According to RFC3686, AES-CTR algo need not be padded if the + * plaintext or ciphertext is unaligned to block size boundary. + */ +- if (nss_cryptoapi_check_unalign(req->nbytes, AES_BLOCK_SIZE) && (ctx->cip_alg != NSS_CRYPTO_CIPHER_AES_CTR)) { ++ if (nss_cryptoapi_check_unalign(req->cryptlen, AES_BLOCK_SIZE) && (ctx->cip_alg != NSS_CRYPTO_CIPHER_AES_CTR)) { + nss_cfi_err("Invalid cipher len - Not aligned to algo blocksize\n"); +- crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_BLOCK_LEN); ++ crypto_skcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_BLOCK_LEN); + return -EINVAL; + } + +@@ -638,9 +638,9 @@ int nss_cryptoapi_ablk_aes_decrypt(struct ablkcipher_request *req) + * nss_cryptoapi_3des_cbc_setkey() + * Cryptoapi DES3 CBC setkey function. + */ +-int nss_cryptoapi_3des_cbc_setkey(struct crypto_ablkcipher *cipher, const u8 *key, unsigned int keylen) ++int nss_cryptoapi_3des_cbc_setkey(struct crypto_skcipher *cipher, const u8 *key, unsigned int keylen) + { +- struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher); ++ struct crypto_tfm *tfm = crypto_skcipher_tfm(cipher); + struct nss_cryptoapi_ctx *ctx = crypto_tfm_ctx(tfm); + struct nss_cryptoapi *sc = &gbl_ctx; + struct nss_crypto_key cip = { .algo = NSS_CRYPTO_CIPHER_DES }; +@@ -693,7 +693,7 @@ int nss_cryptoapi_3des_cbc_setkey(struct crypto_ablkcipher *cipher, const u8 *ke + return 0; + + fail: +- crypto_ablkcipher_set_flags(cipher, flag); ++ crypto_skcipher_set_flags(cipher, flag); + return -EINVAL; + } + +@@ -701,7 +701,7 @@ fail: + * nss_cryptoapi_3des_cbc_encrypt() + * Cryptoapi DES3 CBC encrypt function. + */ +-int nss_cryptoapi_3des_cbc_encrypt(struct ablkcipher_request *req) ++int nss_cryptoapi_3des_cbc_encrypt(struct skcipher_request *req) + { + struct nss_cryptoapi *sc = &gbl_ctx; + struct nss_cryptoapi_ctx *ctx = crypto_tfm_ctx(req->base.tfm); +@@ -727,14 +727,14 @@ int nss_cryptoapi_3des_cbc_encrypt(struct ablkcipher_request *req) + return -EINVAL; + } + +- if (nss_cryptoapi_check_unalign(req->nbytes, DES3_EDE_BLOCK_SIZE)) { ++ if (nss_cryptoapi_check_unalign(req->cryptlen, DES3_EDE_BLOCK_SIZE)) { + nss_cfi_err("Invalid cipher len - Not aligned to algo blocksize\n"); +- crypto_ablkcipher_set_flags(crypto_ablkcipher_reqtfm(req), CRYPTO_TFM_RES_BAD_BLOCK_LEN); ++ crypto_skcipher_set_flags(crypto_skcipher_reqtfm(req), CRYPTO_TFM_RES_BAD_BLOCK_LEN); + return -EINVAL; + } + + info.params = ¶ms; +- info.cb_fn = nss_cryptoapi_ablkcipher_done; ++ info.cb_fn = nss_cryptoapi_skcipher_done; + + buf = nss_cryptoapi_ablk_transform(req, &info); + if (!buf) { +@@ -762,7 +762,7 @@ int nss_cryptoapi_3des_cbc_encrypt(struct ablkcipher_request *req) + * nss_cryptoapi_3des_cbc_decrypt() + * Cryptoapi DES3 CBC decrypt function. + */ +-int nss_cryptoapi_3des_cbc_decrypt(struct ablkcipher_request *req) ++int nss_cryptoapi_3des_cbc_decrypt(struct skcipher_request *req) + { + struct nss_cryptoapi *sc = &gbl_ctx; + struct nss_cryptoapi_ctx *ctx = crypto_tfm_ctx(req->base.tfm); +@@ -788,14 +788,14 @@ int nss_cryptoapi_3des_cbc_decrypt(struct ablkcipher_request *req) + return -EINVAL; + } + +- if (nss_cryptoapi_check_unalign(req->nbytes, DES3_EDE_BLOCK_SIZE)) { ++ if (nss_cryptoapi_check_unalign(req->cryptlen, DES3_EDE_BLOCK_SIZE)) { + nss_cfi_err("Invalid cipher len - Not aligned to algo blocksize\n"); +- crypto_ablkcipher_set_flags(crypto_ablkcipher_reqtfm(req), CRYPTO_TFM_RES_BAD_BLOCK_LEN); ++ crypto_skcipher_set_flags(crypto_skcipher_reqtfm(req), CRYPTO_TFM_RES_BAD_BLOCK_LEN); + return -EINVAL; + } + + info.params = ¶ms; +- info.cb_fn = nss_cryptoapi_ablkcipher_done; ++ info.cb_fn = nss_cryptoapi_skcipher_done; + + buf = nss_cryptoapi_ablk_transform(req, &info); + if (!buf) { +diff --git a/cryptoapi/v1.1/nss_cryptoapi_debugfs.c b/cryptoapi/v1.1/nss_cryptoapi_debugfs.c +index dff774c..cf4bc70 100644 +--- a/cryptoapi/v1.1/nss_cryptoapi_debugfs.c ++++ b/cryptoapi/v1.1/nss_cryptoapi_debugfs.c +@@ -55,6 +55,7 @@ + */ + void nss_cryptoapi_debugfs_add_stats(struct dentry *parent, struct nss_cryptoapi_ctx *session_ctx) + { ++ pr_info("add stats"); + debugfs_create_u64("queued", S_IRUGO, parent, &session_ctx->queued); + debugfs_create_u64("completed", S_IRUGO, parent, &session_ctx->completed); + debugfs_create_u64("queue_failed", S_IRUGO, parent, &session_ctx->queue_failed); +diff --git a/cryptoapi/v1.1/nss_cryptoapi_private.h b/cryptoapi/v1.1/nss_cryptoapi_private.h +index 5feb9e3..70c6714 100644 +--- a/cryptoapi/v1.1/nss_cryptoapi_private.h ++++ b/cryptoapi/v1.1/nss_cryptoapi_private.h +@@ -141,16 +141,16 @@ int nss_cryptoapi_sha256_3des_encrypt(struct aead_request *req); + int nss_cryptoapi_sha256_3des_decrypt(struct aead_request *req); + + /* ABLKCIPHER */ +-int nss_cryptoapi_ablkcipher_init(struct crypto_tfm *tfm); +-void nss_cryptoapi_ablkcipher_exit(struct crypto_tfm *tfm); +-int nss_cryptoapi_ablk_aes_setkey(struct crypto_ablkcipher *cipher, const u8 *key, unsigned int len); +-int nss_cryptoapi_3des_cbc_setkey(struct crypto_ablkcipher *cipher, const u8 *key, unsigned int len); ++int nss_cryptoapi_skcipher_init(struct crypto_skcipher *tfm); ++void nss_cryptoapi_skcipher_exit(struct crypto_skcipher *tfm); ++int nss_cryptoapi_ablk_aes_setkey(struct crypto_skcipher *cipher, const u8 *key, unsigned int len); ++int nss_cryptoapi_3des_cbc_setkey(struct crypto_skcipher *cipher, const u8 *key, unsigned int len); + +-int nss_cryptoapi_ablk_aes_encrypt(struct ablkcipher_request *req); +-int nss_cryptoapi_ablk_aes_decrypt(struct ablkcipher_request *req); ++int nss_cryptoapi_ablk_aes_encrypt(struct skcipher_request *req); ++int nss_cryptoapi_ablk_aes_decrypt(struct skcipher_request *req); + +-int nss_cryptoapi_3des_cbc_encrypt(struct ablkcipher_request *req); +-int nss_cryptoapi_3des_cbc_decrypt(struct ablkcipher_request *req); ++int nss_cryptoapi_3des_cbc_encrypt(struct skcipher_request *req); ++int nss_cryptoapi_3des_cbc_decrypt(struct skcipher_request *req); + + #endif /* __NSS_CRYPTOAPI_PRIVATE_H */ + +-- +2.27.0.rc0 + diff --git a/root/package/qca/nss/qca-nss-clients-64/Makefile b/root/package/qca/nss/qca-nss-clients-64/Makefile new file mode 100644 index 00000000..15316687 --- /dev/null +++ b/root/package/qca/nss/qca-nss-clients-64/Makefile @@ -0,0 +1,97 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=qca-nss-clients-64 +PKG_RELEASE:=$(AUTORELEASE) + +PKG_SOURCE_URL:=https://source.codeaurora.org/quic/cc-qrdk/oss/lklm/nss-clients +PKG_SOURCE_PROTO:=git +PKG_SOURCE_DATE:=2021-04-29 +PKG_SOURCE_VERSION:=b93c72c1b72c591c2ddc2f0b24f0e2b457720118 +PKG_MIRROR_HASH:=fbfba64a364b095ea7c9a24cd7af96b63ab0bc29c179e1628c675aa223c0d063 + +include $(INCLUDE_DIR)/kernel.mk +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/qca-nss-drv-pppoe-64 + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + TITLE:=Kernel driver for NSS (connection manager) - PPPoE + DEPENDS:=@(TARGET_ipq60xx||TARGET_ipq807x) +kmod-qca-nss-drv-64 +kmod-ppp +kmod-pppoe + FILES:=$(PKG_BUILD_DIR)/pppoe/qca-nss-pppoe.ko + AUTOLOAD:=$(call AutoLoad,51,qca-nss-pppoe) +endef + +define KernelPackage/qca-nss-drv-pppoe-64/Description +Kernel modules for NSS connection manager - Support for PPPoE +endef + +define KernelPackage/qca-nss-drv-bridge-mgr-64 + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + TITLE:=Kernel driver for NSS bridge manager + DEPENDS:=@(LINUX_5_10||LINUX_5_15) @(TARGET_ipq60xx||TARGET_ipq807x) +kmod-qca-nss-drv-64 +kmod-qca-nss-drv-vlan-mgr-64 + FILES:=$(PKG_BUILD_DIR)/bridge/qca-nss-bridge-mgr.ko + AUTOLOAD:=$(call AutoLoad,51,qca-nss-bridge-mgr) +endef + +define KernelPackage/qca-nss-drv-bridge-mgr-64/Description +Kernel modules for NSS bridge manager +endef + +define KernelPackage/qca-nss-drv-vlan-mgr-64 + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + TITLE:=Kernel driver for NSS vlan manager + DEPENDS:=@(LINUX_5_10||LINUX_5_15) @(TARGET_ipq60xx||TARGET_ipq807x) +kmod-qca-nss-drv-64 + FILES:=$(PKG_BUILD_DIR)/vlan/qca-nss-vlan.ko + AUTOLOAD:=$(call AutoLoad,51,qca-nss-vlan) +endef + +define KernelPackage/qca-nss-drv-vlan-mgr-64/Description +Kernel modules for NSS vlan manager +endef + +EXTRA_CFLAGS+= \ + -I$(STAGING_DIR)/usr/include/qca-nss-drv \ + -I$(STAGING_DIR)/usr/include/qca-nss-crypto \ + -I$(STAGING_DIR)/usr/include/qca-nss-cfi \ + -I$(STAGING_DIR)/usr/include/qca-nss-gmac \ + -I$(STAGING_DIR)/usr/include/qca-ssdk \ + -I$(STAGING_DIR)/usr/include/qca-ssdk/fal \ + -I$(STAGING_DIR)/usr/include/nat46 + +ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-pppoe-64),) +NSS_CLIENTS_MAKE_OPTS+=pppoe=y +endif + +ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-bridge-mgr-64),) +NSS_CLIENTS_MAKE_OPTS+=bridge-mgr=y +endif + +ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-vlan-mgr-64),) +NSS_CLIENTS_MAKE_OPTS+=vlan-mgr=y +endif + +ifeq ($(CONFIG_TARGET_BOARD), "ipq807x") + SOC="ipq807x_64" +else ifeq ($(CONFIG_TARGET_BOARD), "ipq60xx") + SOC="ipq60xx_64" +endif + +define Build/Compile + $(MAKE) -C "$(LINUX_DIR)" $(strip $(NSS_CLIENTS_MAKE_OPTS)) \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + ARCH="$(LINUX_KARCH)" \ + M="$(PKG_BUILD_DIR)" \ + EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ + SoC=$(SOC) \ + $(KERNEL_MAKE_FLAGS) \ + modules +endef + +$(eval $(call KernelPackage,qca-nss-drv-pppoe-64)) +$(eval $(call KernelPackage,qca-nss-drv-bridge-mgr-64)) +$(eval $(call KernelPackage,qca-nss-drv-vlan-mgr-64)) diff --git a/root/package/qca/nss/qca-nss-clients-64/files/qca-nss-ipsec b/root/package/qca/nss/qca-nss-clients-64/files/qca-nss-ipsec new file mode 100644 index 00000000..5f682c8e --- /dev/null +++ b/root/package/qca/nss/qca-nss-clients-64/files/qca-nss-ipsec @@ -0,0 +1,214 @@ +#!/bin/sh /etc/rc.common +# +# Copyright (c) 2018-2019, 2021 The Linux Foundation. All rights reserved. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +NSS_IPSEC_LOG_FILE=/tmp/.nss_ipsec_log +NSS_IPSEC_LOG_STR_ECM="ECM_Loaded" +NSS_IPSEC_OL_FILE=/tmp/qca_nss_ipsec_ol + +ecm_load () { + if [ ! -d /sys/module/ecm ]; then + /etc/init.d/qca-nss-ecm start + if [ -d /sys/module/ecm ]; then + echo ${NSS_IPSEC_LOG_STR_ECM} >> ${NSS_IPSEC_LOG_FILE} + fi + fi +} + +ecm_unload () { + if [ -f /tmp/.nss_ipsec_log ]; then + str=`grep ${NSS_IPSEC_LOG_STR_ECM} ${NSS_IPSEC_LOG_FILE}` + if [[ $str == ${NSS_IPSEC_LOG_STR_ECM} ]]; then + /etc/init.d/qca-nss-ecm stop + `sed 's/${NSS_IPSEC_LOG_STR_ECM}/ /g' $NSS_IPSEC_LOG_FILE > $NSS_IPSEC_LOG_FILE` + fi + fi +} + +ecm_disable() { + + if [ ! -d /sys/module/ecm ]; then + return; + fi + + echo 1 > /sys/kernel/debug/ecm/front_end_ipv4_stop + echo 1 > /sys/kernel/debug/ecm/front_end_ipv6_stop + echo 1 > /sys/kernel/debug/ecm/ecm_db/defunct_all + sleep 2 +} + +ecm_enable() { + if [ ! -d /sys/module/ecm ]; then + return; + fi + + echo 0 > /sys/kernel/debug/ecm/ecm_db/defunct_all + echo 0 > /sys/kernel/debug/ecm/front_end_ipv4_stop + echo 0 > /sys/kernel/debug/ecm/front_end_ipv6_stop +} + +kernel_version_check_5_4() { + major_ver=$(uname -r | awk -F '.' '{print $1}') + minor_ver=$(uname -r | awk -F '.' '{print $2}') + if [ $major_ver -lt 5 ] || ([ $major_ver -eq 5 ] && [ $minor_ver -lt 4 ] ) ; then + return 1 + else + return 0 + fi +} + +start_klips() { + if kernel_version_check_5_4 + then + echo "Kernel 5.4 doesn't support klips stack." + return $? + fi + + touch $NSS_IPSEC_OL_FILE + ecm_load + + local kernel_version=$(uname -r) + + insmod /lib/modules/${kernel_version}/qca-nss-ipsec-klips.ko + if [ "$?" -gt 0 ]; then + echo "Failed to load plugin. Please start ecm if not done already" + ecm_enable + rm $NSS_IPSEC_OL_FILE + return + fi + + /etc/init.d/ipsec start + sleep 2 + ipsec eroute + + ecm_enable +} + +stop_klips() { + if kernel_version_check_5_4 + then + echo "Kernel 5.4 doesn't support klips stack." + return $? + fi + + ecm_disable + + /etc/init.d/ipsec stop + rmmod qca-nss-ipsec-klips + rm $NSS_IPSEC_OL_FILE + + ecm_unload +} + +start_xfrm() { + touch $NSS_IPSEC_OL_FILE + ecm_load + + local kernel_version=$(uname -r) + + # load all NETKEY modules first. + for mod in xfrm_ipcomp ipcomp xfrm6_tunnel ipcomp6 xfrm6_mode_tunnel xfrm6_mode_beet xfrm6_mode_ro \ + xfrm6_mode_transport xfrm4_mode_transport xfrm4_mode_tunnel \ + xfrm4_tunnel xfrm4_mode_beet esp4 esp6 ah4 ah6 af_key + do + insmod $mod 2> /dev/null + done + + # Now load the xfrm plugin + insmod /lib/modules/${kernel_version}/qca-nss-ipsec-xfrm.ko + if [ "$?" -gt 0 ]; then + echo "Failed to load plugin. Please start ecm if not done already" + ecm_enable + rm $NSS_IPSEC_OL_FILE + return + fi + + /etc/init.d/ipsec start + sleep 2 + + ecm_enable +} + +stop_xfrm() { + ecm_disable + + #Shutdown Pluto first. Then only plugin can be removed. + plutopid=/var/run/pluto/pluto.pid + if [ -f $plutopid ]; then + pid=`cat $plutopid` + if [ ! -z "$pid" ]; then + ipsec whack --shutdown | grep -v "002"; + if [ -s $plutopid ]; then + echo "Attempt to shut Pluto down failed! Trying kill:" + kill $pid; + sleep 5; + fi + fi + rm -rf $plutopid + fi + ip xfrm state flush; + ip xfrm policy flush; + sleep 2 + + #Now we can remove the plugin + retries=5 + while [ -d /sys/module/qca_nss_ipsec_xfrm ] + do + rmmod qca-nss-ipsec-xfrm + if [ "$?" -eq 0 ]; then + rm $NSS_IPSEC_OL_FILE + break + fi + + if [ ${retries} -eq 0 ]; then + echo "Failed to unload qca-nss-ipsec-xfrm plugin!" + exit + fi + + echo "XFRM plugin unload failed; retrying ${retries} times" + sleep 1 + retries=`expr ${retries} - 1` + done + + /etc/init.d/ipsec stop + ecm_unload +} + +start() { + local protostack=`uci -q get ipsec.setup.protostack` + if [ "$protostack" = "klips" ]; then + start_klips + return $? + fi + + start_xfrm + return $? +} + +stop() { + local protostack=`uci -q get ipsec.setup.protostack` + if [ "$protostack" = "klips" ]; then + stop_klips + return $? + fi + + stop_xfrm + return $? +} + +restart() { + stop + start +} diff --git a/root/package/qca/nss/qca-nss-clients-64/files/qca-nss-mirred.init b/root/package/qca/nss/qca-nss-clients-64/files/qca-nss-mirred.init new file mode 100644 index 00000000..1f931f09 --- /dev/null +++ b/root/package/qca/nss/qca-nss-clients-64/files/qca-nss-mirred.init @@ -0,0 +1,28 @@ +#!/bin/sh /etc/rc.common + +########################################################################### +# Copyright (c) 2019, The Linux Foundation. All rights reserved. +# Permission to use, copy, modify, and/or distribute this software for +# any purpose with or without fee is hereby granted, provided that the +# above copyright notice and this permission notice appear in all copies. +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +########################################################################### + +restart() { + rmmod act_nssmirred.ko + insmod act_nssmirred.ko +} + +start() { + insmod act_nssmirred.ko +} + +stop() { + rmmod act_nssmirred.ko +} diff --git a/root/package/qca/nss/qca-nss-clients-64/files/qca-nss-ovpn.init b/root/package/qca/nss/qca-nss-clients-64/files/qca-nss-ovpn.init new file mode 100644 index 00000000..622e295e --- /dev/null +++ b/root/package/qca/nss/qca-nss-clients-64/files/qca-nss-ovpn.init @@ -0,0 +1,69 @@ +#!/bin/sh /etc/rc.common + +########################################################################### +# Copyright (c) 2019, The Linux Foundation. All rights reserved. +# Permission to use, copy, modify, and/or distribute this software for +# any purpose with or without fee is hereby granted, provided that the +# above copyright notice and this permission notice appear in all copies. +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +########################################################################### + +ecm_disable() { + if [ ! -d /sys/module/ecm ]; then + return + fi + + echo 1 > /sys/kernel/debug/ecm/front_end_ipv4_stop + echo 1 > /sys/kernel/debug/ecm/front_end_ipv6_stop + echo 1 > /sys/kernel/debug/ecm/ecm_db/defunct_all + sleep 2 +} + +ecm_enable() { + if [ ! -d /sys/module/ecm ]; then + return + fi + + echo 0 > /sys/kernel/debug/ecm/ecm_db/defunct_all + echo 0 > /sys/kernel/debug/ecm/front_end_ipv4_stop + echo 0 > /sys/kernel/debug/ecm/front_end_ipv6_stop +} + +restart() { + ecm_disable + + /etc/init.d/openvpn stop + rmmod qca-nss-ovpn-link + rmmod qca-nss-ovpn-mgr + + insmod qca-nss-ovpn-mgr + insmod qca-nss-ovpn-link + + if [ "$?" -gt 0 ]; then + echo "Failed to load plugin. Please start ecm if not done already" + ecm_enable + return + fi + + ecm_enable +} + +start() { + restart +} + +stop() { + ecm_disable + + /etc/init.d/openvpn stop + rmmod qca-nss-ovpn-link + rmmod qca-nss-ovpn-mgr + + ecm_enable +} diff --git a/root/package/qca/nss/qca-nss-clients/Makefile b/root/package/qca/nss/qca-nss-clients/Makefile new file mode 100644 index 00000000..e782cf81 --- /dev/null +++ b/root/package/qca/nss/qca-nss-clients/Makefile @@ -0,0 +1,469 @@ +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=qca-nss-clients +PKG_RELEASE:=2 + +PKG_SOURCE_URL:=https://source.codeaurora.org/quic/qsdk/oss/lklm/nss-clients +PKG_SOURCE_PROTO:=git +PKG_SOURCE_VERSION:=740d0102c518cd49f30c5580982b218b480006b1 +PKG_MIRROR_HASH:=2f427d01dba69b1b89d3a081daf08b36fb345d55b9c9462eb358e5b071e2a171 + +include $(INCLUDE_DIR)/package.mk + +# Keep default as ipq806x for branches that does not have subtarget framework +ifeq ($(CONFIG_TARGET_ipq),y) +subtarget:=$(SUBTARGET) +else +subtarget:=$(CONFIG_TARGET_BOARD) +endif + +ifneq (, $(findstring $(subtarget), "ipq807x" "ipq807x_64" "ipq60xx" "ipq60xx_64")) +# DTLS Manager v2.0 for Hawkeye/Cypress + DTLSMGR_DIR:=v2.0 +# IPsec Manager v2.0 for Hawkeye/Cypress + IPSECMGR_DIR:=v2.0 +# KLIPS plugin + IPSECMGR_KLIPS:= $(PKG_BUILD_DIR)/ipsecmgr/$(IPSECMGR_DIR)/plugins/klips/qca-nss-ipsec-klips.ko +else +# DTLS Manager v1.0 for Akronite. + DTLSMGR_DIR:=v1.0 +# IPsec Manager v1.0 for Akronite. + IPSECMGR_DIR:=v1.0 +# KLIPS plugin not needed + IPSECMGR_KLIPS:= +endif + +define KernelPackage/qca-nss-drv-tun6rd + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + TITLE:=Kernel driver for NSS (connection manager) - tun6rd + DEPENDS:=+kmod-qca-nss-drv +kmod-sit +6rd @!LINUX_3_18 + FILES:=$(PKG_BUILD_DIR)/qca-nss-tun6rd.ko + AUTOLOAD:=$(call AutoLoad,60,qca-nss-tun6rd) +endef + +define KernelPackage/qca-nss-drv-tun6rd/Description +Kernel modules for NSS connection manager - Support for 6rd tunnel +endef + +define KernelPackage/qca-nss-drv-dtlsmgr + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + TITLE:=Kernel driver for NSS (connection manager) - dtlsmgr + DEPENDS:=+kmod-qca-nss-drv +kmod-qca-nss-cfi-cryptoapi @!LINUX_3_18 + FILES:=$(PKG_BUILD_DIR)/dtls/$(DTLSMGR_DIR)/qca-nss-dtlsmgr.ko +endef + +define KernelPackage/qca-nss-drv-dtls/Description +Kernel modules for NSS connection manager - Support for DTLS sessions +endef + +define KernelPackage/qca-nss-drv-l2tpv2 + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + TITLE:=Kernel driver for NSS (connection manager) - l2tp + DEPENDS:=+kmod-qca-nss-drv +kmod-ppp +kmod-l2tp @!LINUX_3_18 + FILES:=$(PKG_BUILD_DIR)/l2tp/l2tpv2/qca-nss-l2tpv2.ko + KCONFIG:=CONFIG_L2TP=y + AUTOLOAD:=$(call AutoLoad,51,qca-nss-l2tpv2) +endef + +define KernelPackage/qca-nss-drv-l2tpv2/Description +Kernel modules for NSS connection manager - Support for l2tp tunnel +endef + +define KernelPackage/qca-nss-drv-pptp + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + TITLE:=Kernel driver for NSS (connection manager) - PPTP + DEPENDS:=+kmod-qca-nss-drv +kmod-pptp @!LINUX_3_18 + FILES:=$(PKG_BUILD_DIR)/pptp/qca-nss-pptp.ko + AUTOLOAD:=$(call AutoLoad,51,qca-nss-pptp) +endef + +define KernelPackage/qca-nss-drv-pptp/Description +Kernel modules for NSS connection manager - Support for PPTP tunnel +endef + +define KernelPackage/qca-nss-drv-pppoe + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + TITLE:=Kernel driver for NSS (connection manager) - PPPoE + DEPENDS:=+kmod-qca-nss-drv +kmod-pppoe @!LINUX_3_18 \ + +!(TARGET_ipq_ipq807x_QSDK_256||TARGET_ipq_ipq60xx_QSDK_256):kmod-bonding + FILES:=$(PKG_BUILD_DIR)/pppoe/qca-nss-pppoe.ko + AUTOLOAD:=$(call AutoLoad,51,qca-nss-pppoe) +endef + +define KernelPackage/qca-nss-drv-pppoe/Description +Kernel modules for NSS connection manager - Support for PPPoE +endef + +define KernelPackage/qca-nss-drv-map-t + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + TITLE:=Kernel driver for NSS (connection manager) - MAP-T + DEPENDS:=+kmod-qca-nss-drv +kmod-nat46 @!LINUX_3_18 + FILES:=$(PKG_BUILD_DIR)/map/map-t/qca-nss-map-t.ko + AUTOLOAD:=$(call AutoLoad,51,qca-nss-map-t) +endef + +define KernelPackage/qca-nss-drv-map-t/Description +Kernel modules for NSS connection manager - Support for MAP-T +endef + +define KernelPackage/qca-nss-drv-gre + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + TITLE:=Kernel driver for NSS (connection manager) - GRE + DEPENDS:=@TARGET_ipq_ipq806x||TARGET_ipq806x||TARGET_ipq_ipq807x||TARGET_ipq_ipq807x_64||TARGET_ipq807x||TARGET_ipq807x_64||TARGET_ipq_ipq60xx||TARGET_ipq_ipq60xx_64||TARGET_ipq_ipq50xx||TARGET_ipq_ipq50xx_64 \ + +kmod-qca-nss-drv @!LINUX_3_18 +kmod-gre6 + FILES:=$(PKG_BUILD_DIR)/gre/qca-nss-gre.ko $(PKG_BUILD_DIR)/gre/test/qca-nss-gre-test.ko + AUTOLOAD:=$(call AutoLoad,51,qca-nss-gre) +endef + +define KernelPackage/qca-nss-drv-gre/Description +Kernel modules for NSS connection manager - Support for GRE +endef + +define KernelPackage/qca-nss-drv-tunipip6 + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + TITLE:=Kernel driver for NSS (connection manager) - DS-lite and ipip6 Tunnel + DEPENDS:=+kmod-qca-nss-drv +kmod-iptunnel6 +kmod-ip6-tunnel @!LINUX_3_18 + FILES:=$(PKG_BUILD_DIR)/qca-nss-tunipip6.ko + AUTOLOAD:=$(call AutoLoad,60,qca-nss-tunipip6) +endef + +define KernelPackage/qca-nss-drv-tunipip6/Description +Kernel modules for NSS connection manager +Add support for DS-lite and ipip6 tunnel +endef + +define KernelPackage/qca-nss-drv-profile + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + DEPENDS:=+kmod-qca-nss-drv @!LINUX_3_18 + TITLE:=Profiler for QCA NSS driver (IPQ806x) + FILES:=$(PKG_BUILD_DIR)/profiler/qca-nss-profile-drv.ko +endef + +define KernelPackage/qca-nss-drv-profile/Description +This package contains a NSS driver profiler for QCA chipset +endef + +define KernelPackage/qca-nss-drv-ipsecmgr + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + TITLE:=Kernel driver for NSS (ipsec manager) - ipsecmgr + DEPENDS:=@TARGET_ipq806x||TARGET_ipq_ipq806x||TARGET_ipq_ipq807x||TARGET_ipq_ipq807x_64||TARGET_ipq807x||TARGET_ipq807x_64||TARGET_ipq_ipq60xx||TARGET_ipq_ipq60xx_64 \ + +kmod-qca-nss-drv +kmod-qca-nss-ecm-standard +kmod-qca-nss-cfi-cryptoapi @!LINUX_3_18 +ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-l2tpv2),) + DEPENDS+=+kmod-qca-nss-drv-l2tpv2 +endif + FILES:=$(PKG_BUILD_DIR)/ipsecmgr/$(IPSECMGR_DIR)/qca-nss-ipsecmgr.ko $(IPSECMGR_KLIPS) + AUTOLOAD:=$(call AutoLoad,60,qca-nss-ipsecmgr) +endef + +define KernelPackage/qca-nss-drv-ipsecmgr/Description +Kernel module for NSS IPsec offload manager +endef + +define KernelPackage/qca-nss-drv-capwapmgr + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + DEPENDS:=+kmod-qca-nss-drv +kmod-qca-nss-drv-dtlsmgr @!LINUX_3_18 + TITLE:=NSS CAPWAP Manager for QCA NSS driver (IPQ806x) + FILES:=$(PKG_BUILD_DIR)/capwapmgr/qca-nss-capwapmgr.ko +endef + +define KernelPackage/qca-nss-drv-capwapmgr/Description +This package contains a NSS CAPWAP Manager +endef + +define KernelPackage/qca-nss-drv-bridge-mgr + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + TITLE:=Kernel driver for NSS bridge manager + DEPENDS:=@TARGET_ipq_ipq807x||TARGET_ipq_ipq807x_64||TARGET_ipq807x||TARGET_ipq807x_64||TARGET_ipq_ipq60xx||TARGET_ipq_ipq60xx_64 \ + +TARGET_ipq_ipq807x:kmod-qca-nss-drv-vlan-mgr \ + +TARGET_ipq_ipq807x_64:kmod-qca-nss-drv-vlan-mgr \ + +TARGET_ipq807x:kmod-qca-nss-drv-vlan-mgr \ + +TARGET_ipq807x_64:kmod-qca-nss-drv-vlan-mgr \ + +TARGET_ipq_ipq60xx:kmod-qca-nss-drv-vlan-mgr \ + +TARGET_ipq_ipq60xx_64:kmod-qca-nss-drv-vlan-mgr @!LINUX_3_18 \ + +!(TARGET_ipq_ipq807x_QSDK_256||TARGET_ipq_ipq60xx_QSDK_256):kmod-bonding + FILES:=$(PKG_BUILD_DIR)/bridge/qca-nss-bridge-mgr.ko + AUTOLOAD:=$(call AutoLoad,51,qca-nss-bridge-mgr) +endef + +define KernelPackage/qca-nss-drv-bridge-mgr/Description +Kernel modules for NSS bridge manager +endef + +define KernelPackage/qca-nss-drv-vlan-mgr + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + TITLE:=Kernel driver for NSS vlan manager + DEPENDS:=@TARGET_ipq806x||TARGET_ipq807x +kmod-qca-nss-drv @!LINUX_3_18 \ + +!(TARGET_ipq_ipq807x_QSDK_256||TARGET_ipq_ipq60xx_QSDK_256):kmod-bonding + FILES:=$(PKG_BUILD_DIR)/vlan/qca-nss-vlan.ko + AUTOLOAD:=$(call AutoLoad,51,qca-nss-vlan) +endef + +define KernelPackage/qca-nss-drv-vlan-mgr/Description +Kernel modules for NSS vlan manager +endef + +define KernelPackage/qca-nss-drv-qdisc + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Support + TITLE:=Qdisc for configuring shapers in NSS + DEPENDS:=+kmod-qca-nss-drv @!LINUX_3_18 + FILES:=$(PKG_BUILD_DIR)/nss_qdisc/qca-nss-qdisc.ko + KCONFIG:=CONFIG_NET_CLS_ACT=y + AUTOLOAD:=$(call AutoLoad,58,qca-nss-qdisc) +endef + +define KernelPackage/qca-nss-drv-qdisc/Description +Linux qdisc that aids in configuring shapers in the NSS +endef + +define KernelPackage/qca-nss-drv-lag-mgr + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + TITLE:=Kernel driver for NSS LAG manager + DEPENDS:=+kmod-qca-nss-drv @!LINUX_3_18 \ + +TARGET_ipq_ipq807x:kmod-qca-nss-drv-vlan-mgr \ + +TARGET_ipq_ipq807x_64:kmod-qca-nss-drv-vlan-mgr @!LINUX_3_18 \ + +TARGET_ipq807x:kmod-qca-nss-drv-vlan-mgr \ + +TARGET_ipq807x_64:kmod-qca-nss-drv-vlan-mgr @!LINUX_3_18 \ + +TARGET_ipq_ipq60xx:kmod-qca-nss-drv-vlan-mgr @!LINUX_3_18 \ + +TARGET_ipq_ipq60xx_64:kmod-qca-nss-drv-vlan-mgr @!LINUX_3_18 \ + +kmod-bonding + FILES:=$(PKG_BUILD_DIR)/lag/qca-nss-lag-mgr.ko + AUTOLOAD:=$(call AutoLoad,51,qca-nss-lag-mgr) +endef + +define KernelPackage/qca-nss-drv-lag-mgr/Description +Kernel modules for NSS LAG manager +endef + +define KernelPackage/qca-nss-drv-netlink + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + DEPENDS:=@TARGET_ipq807x||TARGET_ipq_ipq807x||TARGET_ipq807x_64||TARGET_ipq_ipq807x_64||TARGET_ipq_ipq60xx||TARGET_ipq_ipq60xx_64||TARGET_ipq_ipq50xx||TARGET_ipq_ipq50xx_64 \ + +kmod-qca-nss-drv @!LINUX_3_18 \ + +PACKAGE_kmod-qca-nss-drv-ipsecmgr:kmod-qca-nss-drv-ipsecmgr \ + +PACKAGE_kmod-qca-nss-drv-dtlsmgr:kmod-qca-nss-drv-dtlsmgr \ + +PACKAGE_kmod-qca-nss-drv-capwapmgr:kmod-qca-nss-drv-capwapmgr @!LINUX_3_18 + TITLE:=NSS NETLINK Manager for QCA NSS driver + FILES:=$(PKG_BUILD_DIR)/netlink/qca-nss-netlink.ko +endef + +define KernelPackage/qca-nss-drv-netlink/Description +Kernel module for NSS netlink manager +endef + +define KernelPackage/qca-nss-drv-ovpn-mgr + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + TITLE:=Kernel driver for NSS OpenVPN manager + DEPENDS:=+kmod-qca-nss-drv +kmod-qca-nss-cfi-cryptoapi +kmod-tun +kmod-ipt-conntrack @!LINUX_3_18 \ + @TARGET_ipq_ipq807x||TARGET_ipq_ipq807x_64||TARGET_ipq_ipq60xx||TARGET_ipq_ipq60xx_64 + FILES:=$(PKG_BUILD_DIR)/openvpn/src/qca-nss-ovpn-mgr.ko +endef + +define KernelPackage/qca-nss-drv-ovpn-mgr/Description +Kernel module for NSS OpenVPN manager +endef + +define KernelPackage/qca-nss-drv-ovpn-link + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + TITLE:=Kernel driver for interfacing NSS OpenVPN manager with ECM + DEPENDS:=+kmod-qca-nss-drv-ovpn-mgr +@PACKAGE_kmod-qca-nss-ecm-premium @!LINUX_3_18 \ + @TARGET_ipq_ipq807x||TARGET_ipq_ipq807x_64||TARGET_ipq_ipq60xx||TARGET_ipq_ipq60xx_64 + FILES:=$(PKG_BUILD_DIR)/openvpn/plugins/qca-nss-ovpn-link.ko +endef + +define KernelPackage/qca-nss-drv-ovpn-link/Description +This module registers with ECM and communicates with NSS OpenVPN manager for supporting OpenVPN offload. +endef + +define KernelPackage/qca-nss-drv-pvxlanmgr + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + DEPENDS:=+kmod-qca-nss-drv @!LINUX_3_18 + TITLE:=NSS PVXLAN Manager for QCA NSS driver + FILES:=$(PKG_BUILD_DIR)/pvxlanmgr/qca-nss-pvxlanmgr.ko +endef + +define KernelPackage/qca-nss-drv-pvxlanmgr/Description +Kernel module for managing NSS PVxLAN +endef + +define Build/InstallDev/qca-nss-clients + $(INSTALL_DIR) $(1)/usr/include/qca-nss-clients + $(CP) $(PKG_BUILD_DIR)/netlink/include/* $(1)/usr/include/qca-nss-clients/ + $(CP) $(PKG_BUILD_DIR)/exports/* $(1)/usr/include/qca-nss-clients/ +endef + +define Build/InstallDev + $(call Build/InstallDev/qca-nss-clients,$(1)) +endef + +define KernelPackage/qca-nss-drv-ovpn-mgr/install + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/qca-nss-ovpn.init $(1)/etc/init.d/qca-nss-ovpn +endef + +define KernelPackage/qca-nss-drv-ipsecmgr/install + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/qca-nss-ipsec $(1)/etc/init.d/qca-nss-ipsec +endef + + +EXTRA_CFLAGS+= \ + -I$(STAGING_DIR)/usr/include/qca-nss-drv \ + -I$(STAGING_DIR)/usr/include/qca-nss-crypto \ + -I$(STAGING_DIR)/usr/include/qca-nss-cfi \ + -I$(STAGING_DIR)/usr/include/qca-nss-gmac \ + -I$(STAGING_DIR)/usr/include/qca-nss-ecm \ + -I$(STAGING_DIR)/usr/include/qca-ssdk \ + -I$(STAGING_DIR)/usr/include/qca-ssdk/fal \ + -I$(STAGING_DIR)/usr/include/nat46 + +# Build individual packages if selected +ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-profile),) +MAKE_OPTS+=profile=y +endif + +ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-capwapmgr),) +MAKE_OPTS+=capwapmgr=y +EXTRA_CFLAGS += -DNSS_CAPWAPMGR_ONE_NETDEV +endif + +ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-tun6rd),) +MAKE_OPTS+=tun6rd=m +endif + +ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-dtlsmgr),) +MAKE_OPTS+=dtlsmgr=y +endif + +ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-l2tpv2),) +MAKE_OPTS+=l2tpv2=y +EXTRA_CFLAGS += -DNSS_L2TPV2_ENABLED +endif + +ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-pptp),) +MAKE_OPTS+=pptp=y +endif + +ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-map-t),) +MAKE_OPTS+=map-t=y +endif + +ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-tunipip6),) +MAKE_OPTS+=tunipip6=m +endif + +ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-qdisc),) +MAKE_OPTS+=qdisc=y +endif + +ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-ipsecmgr),) +EXTRA_CFLAGS+= -I$(PKG_BUILD_DIR)/exports \ + -I$(STAGING_DIR)/usr/include/qca-nss-ecm +MAKE_OPTS+=ipsecmgr=y +endif + +ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-bridge-mgr),) +MAKE_OPTS+=bridge-mgr=y +endif + +ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-vlan-mgr),) +MAKE_OPTS+=vlan-mgr=y +endif + +ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-lag-mgr),) +MAKE_OPTS+=lag-mgr=y +endif + +ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-gre),) +EXTRA_CFLAGS+= -I$(PKG_BUILD_DIR)/exports +MAKE_OPTS+=gre=y +endif + +ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-pppoe),) +MAKE_OPTS+=pppoe=y +endif + +ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-netlink),) +MAKE_OPTS+=netlink=y +endif + +ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-ovpn-mgr),) +MAKE_OPTS+=ovpn-mgr=y +endif + +ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-ovpn-link),) +MAKE_OPTS+=ovpn-link=y +endif + +ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-pvxlanmgr),) +MAKE_OPTS+=pvxlanmgr=y +endif + +define Build/Compile + $(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" $(strip $(MAKE_OPTS)) \ + $(KERNEL_MAKE_FLAGS) \ + $(PKG_MAKE_FLAGS) \ + M="$(PKG_BUILD_DIR)" \ + EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ + SoC="$(subtarget)" \ + DTLSMGR_DIR="$(DTLSMGR_DIR)" \ + IPSECMGR_DIR="$(IPSECMGR_DIR)" \ + modules +endef + +$(eval $(call KernelPackage,qca-nss-drv-profile)) +$(eval $(call KernelPackage,qca-nss-drv-capwapmgr)) +$(eval $(call KernelPackage,qca-nss-drv-tun6rd)) +$(eval $(call KernelPackage,qca-nss-drv-dtlsmgr)) +$(eval $(call KernelPackage,qca-nss-drv-l2tpv2)) +$(eval $(call KernelPackage,qca-nss-drv-pptp)) +$(eval $(call KernelPackage,qca-nss-drv-pppoe)) +$(eval $(call KernelPackage,qca-nss-drv-map-t)) +$(eval $(call KernelPackage,qca-nss-drv-tunipip6)) +$(eval $(call KernelPackage,qca-nss-drv-qdisc)) +$(eval $(call KernelPackage,qca-nss-drv-netlink)) +$(eval $(call KernelPackage,qca-nss-drv-ipsecmgr)) +$(eval $(call KernelPackage,qca-nss-drv-bridge-mgr)) +$(eval $(call KernelPackage,qca-nss-drv-vlan-mgr)) +$(eval $(call KernelPackage,qca-nss-drv-lag-mgr)) +$(eval $(call KernelPackage,qca-nss-drv-gre)) +$(eval $(call KernelPackage,qca-nss-drv-ovpn-mgr)) +$(eval $(call KernelPackage,qca-nss-drv-ovpn-link)) +$(eval $(call KernelPackage,qca-nss-drv-pvxlanmgr)) diff --git a/root/package/qca/nss/qca-nss-clients/files/qca-nss-ipsec b/root/package/qca/nss/qca-nss-clients/files/qca-nss-ipsec new file mode 100644 index 00000000..bb202e8e --- /dev/null +++ b/root/package/qca/nss/qca-nss-clients/files/qca-nss-ipsec @@ -0,0 +1,92 @@ +#!/bin/sh /etc/rc.common +# +# Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +NSS_IPSEC_LOG_FILE=/tmp/.nss_ipsec_log +NSS_IPSEC_LOG_STR_ECM="ECM_Loaded" + +ecm_load () { + if [ ! -d /sys/module/ecm ]; then + /etc/init.d/qca-nss-ecm start + if [ -d /sys/module/ecm ]; then + echo ${NSS_IPSEC_LOG_STR_ECM} >> ${NSS_IPSEC_LOG_FILE} + fi + fi +} + +ecm_unload () { + if [ -f /tmp/.nss_ipsec_log ]; then + str=`grep ${NSS_IPSEC_LOG_STR_ECM} ${NSS_IPSEC_LOG_FILE}` + if [[ $str == ${NSS_IPSEC_LOG_STR_ECM} ]]; then + /etc/init.d/qca-nss-ecm stop + `sed 's/${NSS_IPSEC_LOG_STR_ECM}/ /g' $NSS_IPSEC_LOG_FILE > $NSS_IPSEC_LOG_FILE` + fi + fi +} + +ecm_disable() { + + if [ ! -d /sys/module/ecm ]; then + return; + fi + + echo 1 > /sys/kernel/debug/ecm/front_end_ipv4_stop + echo 1 > /sys/kernel/debug/ecm/front_end_ipv6_stop + echo 1 > /sys/kernel/debug/ecm/ecm_db/defunct_all + sleep 2 +} + +ecm_enable() { + if [ ! -d /sys/module/ecm ]; then + return; + fi + + echo 0 > /sys/kernel/debug/ecm/ecm_db/defunct_all + echo 0 > /sys/kernel/debug/ecm/front_end_ipv4_stop + echo 0 > /sys/kernel/debug/ecm/front_end_ipv6_stop +} + +start() { + ecm_load + + local kernel_version=$(uname -r) + + insmod /lib/modules/${kernel_version}/qca-nss-ipsec-klips.ko + if [ "$?" -gt 0 ]; then + echo "Failed to load plugin. Please start ecm if not done already" + ecm_enable + return + fi + + /etc/init.d/ipsec start + sleep 2 + ipsec eroute + + ecm_enable +} + +stop() { + ecm_disable + + /etc/init.d/ipsec stop + rmmod qca-nss-ipsec-klips + + ecm_unload +} + +restart() { + stop + start +} diff --git a/root/package/qca/nss/qca-nss-clients/files/qca-nss-mirred.init b/root/package/qca/nss/qca-nss-clients/files/qca-nss-mirred.init new file mode 100644 index 00000000..1f931f09 --- /dev/null +++ b/root/package/qca/nss/qca-nss-clients/files/qca-nss-mirred.init @@ -0,0 +1,28 @@ +#!/bin/sh /etc/rc.common + +########################################################################### +# Copyright (c) 2019, The Linux Foundation. All rights reserved. +# Permission to use, copy, modify, and/or distribute this software for +# any purpose with or without fee is hereby granted, provided that the +# above copyright notice and this permission notice appear in all copies. +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +########################################################################### + +restart() { + rmmod act_nssmirred.ko + insmod act_nssmirred.ko +} + +start() { + insmod act_nssmirred.ko +} + +stop() { + rmmod act_nssmirred.ko +} diff --git a/root/package/qca/nss/qca-nss-clients/files/qca-nss-ovpn.init b/root/package/qca/nss/qca-nss-clients/files/qca-nss-ovpn.init new file mode 100644 index 00000000..622e295e --- /dev/null +++ b/root/package/qca/nss/qca-nss-clients/files/qca-nss-ovpn.init @@ -0,0 +1,69 @@ +#!/bin/sh /etc/rc.common + +########################################################################### +# Copyright (c) 2019, The Linux Foundation. All rights reserved. +# Permission to use, copy, modify, and/or distribute this software for +# any purpose with or without fee is hereby granted, provided that the +# above copyright notice and this permission notice appear in all copies. +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +########################################################################### + +ecm_disable() { + if [ ! -d /sys/module/ecm ]; then + return + fi + + echo 1 > /sys/kernel/debug/ecm/front_end_ipv4_stop + echo 1 > /sys/kernel/debug/ecm/front_end_ipv6_stop + echo 1 > /sys/kernel/debug/ecm/ecm_db/defunct_all + sleep 2 +} + +ecm_enable() { + if [ ! -d /sys/module/ecm ]; then + return + fi + + echo 0 > /sys/kernel/debug/ecm/ecm_db/defunct_all + echo 0 > /sys/kernel/debug/ecm/front_end_ipv4_stop + echo 0 > /sys/kernel/debug/ecm/front_end_ipv6_stop +} + +restart() { + ecm_disable + + /etc/init.d/openvpn stop + rmmod qca-nss-ovpn-link + rmmod qca-nss-ovpn-mgr + + insmod qca-nss-ovpn-mgr + insmod qca-nss-ovpn-link + + if [ "$?" -gt 0 ]; then + echo "Failed to load plugin. Please start ecm if not done already" + ecm_enable + return + fi + + ecm_enable +} + +start() { + restart +} + +stop() { + ecm_disable + + /etc/init.d/openvpn stop + rmmod qca-nss-ovpn-link + rmmod qca-nss-ovpn-mgr + + ecm_enable +} diff --git a/root/package/qca/nss/qca-nss-clients/patches/100-kernel-5.4-support-qdisc.patch b/root/package/qca/nss/qca-nss-clients/patches/100-kernel-5.4-support-qdisc.patch new file mode 100644 index 00000000..0ec8d766 --- /dev/null +++ b/root/package/qca/nss/qca-nss-clients/patches/100-kernel-5.4-support-qdisc.patch @@ -0,0 +1,1145 @@ +--- a/nss_qdisc/nss_qdisc.h ++++ b/nss_qdisc/nss_qdisc.h +@@ -338,7 +340,7 @@ extern void nss_qdisc_destroy(struct nss + * Initializes a shaper in NSS, based on the position of this qdisc (child or root) + * and if its a normal interface or a bridge interface. + */ +-extern int nss_qdisc_init(struct Qdisc *sch, struct nss_qdisc *nq, nss_shaper_node_type_t type, uint32_t classid, uint32_t accel_mode); ++extern int nss_qdisc_init(struct Qdisc *sch, struct netlink_ext_ack *extack, struct nss_qdisc *nq, nss_shaper_node_type_t type, uint32_t classid, uint32_t accel_mode); + + /* + * nss_qdisc_start_basic_stats_polling() +--- a/nss_qdisc/nss_bf.c ++++ b/nss_qdisc/nss_bf.c +@@ -69,7 +69,7 @@ static inline struct nss_bf_class_data * + * Configures a new class. + */ + static int nss_bf_change_class(struct Qdisc *sch, u32 classid, u32 parentid, +- struct nlattr **tca, unsigned long *arg) ++ struct nlattr **tca, unsigned long *arg, struct netlink_ext_ack *extack) + { + struct nss_bf_sched_data *q = qdisc_priv(sch); + struct nss_bf_class_data *cl = (struct nss_bf_class_data *)*arg; +@@ -121,7 +121,7 @@ static int nss_bf_change_class(struct Qd + * that is registered to Linux. Therefore we initialize the NSSBF_GROUP shaper + * here. + */ +- if (nss_qdisc_init(sch, &cl->nq, NSS_SHAPER_NODE_TYPE_BF_GROUP, classid, accel_mode) < 0) { ++ if (nss_qdisc_init(sch, extack, &cl->nq, NSS_SHAPER_NODE_TYPE_BF_GROUP, classid, accel_mode) < 0) { + nss_qdisc_error("Nss init for class %u failed\n", classid); + kfree(cl); + return -EINVAL; +@@ -260,7 +260,7 @@ static void nss_bf_destroy_class(struct + /* + * And now we destroy the child. + */ +- qdisc_destroy(cl->qdisc); ++ qdisc_put(cl->qdisc); + + /* + * Stop the stats polling timer and free class +@@ -325,7 +325,7 @@ static int nss_bf_delete_class(struct Qd + * Replaces the qdisc attached to the provided class. + */ + static int nss_bf_graft_class(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, +- struct Qdisc **old) ++ struct Qdisc **old, struct netlink_ext_ack *extack) + { + struct nss_bf_sched_data *q = qdisc_priv(sch); + struct nss_bf_class_data *cl = (struct nss_bf_class_data *)arg; +@@ -432,24 +432,6 @@ static unsigned long nss_bf_get_class(st + } + + /* +- * nss_bf_put_class() +- * Reduces reference count for this class. +- */ +-static void nss_bf_put_class(struct Qdisc *sch, unsigned long arg) +-{ +- struct nss_bf_class_data *cl = (struct nss_bf_class_data *)arg; +- nss_qdisc_info("bf put class for %p\n", cl); +- +- /* +- * We are safe to destroy the qdisc if the reference count +- * goes down to 0. +- */ +- if (atomic_sub_return(1, &cl->nq.refcnt) == 0) { +- nss_bf_destroy_class(sch, cl); +- } +-} +- +-/* + * nss_bf_dump_class() + * Dumps all configurable parameters pertaining to this class. + */ +@@ -538,7 +520,7 @@ static void nss_bf_walk(struct Qdisc *sc + * nss_bf_change_qdisc() + * Can be used to configure a nssbf qdisc. + */ +-static int nss_bf_change_qdisc(struct Qdisc *sch, struct nlattr *opt) ++static int nss_bf_change_qdisc(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) + { + struct nss_bf_sched_data *q = qdisc_priv(sch); + struct tc_nssbf_qopt *qopt; +@@ -684,7 +666,7 @@ static void nss_bf_destroy_qdisc(struct + * nss_bf_init_qdisc() + * Initializes the nssbf qdisc. + */ +-static int nss_bf_init_qdisc(struct Qdisc *sch, struct nlattr *opt) ++static int nss_bf_init_qdisc(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) + { + struct nss_bf_sched_data *q = qdisc_priv(sch); + struct tc_nssbf_qopt *qopt; +@@ -720,7 +702,7 @@ static int nss_bf_init_qdisc(struct Qdis + /* + * Initialize the NSSBF shaper in NSS + */ +- if (nss_qdisc_init(sch, &q->nq, NSS_SHAPER_NODE_TYPE_BF, 0, accel_mode) < 0) { ++ if (nss_qdisc_init(sch, extack, &q->nq, NSS_SHAPER_NODE_TYPE_BF, 0, accel_mode) < 0) { + return -EINVAL; + } + +@@ -729,7 +711,7 @@ static int nss_bf_init_qdisc(struct Qdis + /* + * Tune nss_bf parameters. + */ +- if (nss_bf_change_qdisc(sch, opt) < 0) { ++ if (nss_bf_change_qdisc(sch, opt, NULL) < 0) { + nss_qdisc_destroy(&q->nq); + return -EINVAL; + } +@@ -772,7 +754,7 @@ nla_put_failure: + * nss_bf_enqueue() + * Enqueues a skb to nssbf qdisc. + */ +-static int nss_bf_enqueue(struct sk_buff *skb, struct Qdisc *sch) ++static int nss_bf_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free) + { + return nss_qdisc_enqueue(skb, sch); + } +@@ -787,18 +769,6 @@ static struct sk_buff *nss_bf_dequeue(st + } + + /* +- * nss_bf_drop() +- * Drops a single skb from linux queue, if not empty. +- * +- * Does not drop packets that are queued in the NSS. +- */ +-static unsigned int nss_bf_drop(struct Qdisc *sch) +-{ +- printk("In bf drop\n"); +- return nss_qdisc_drop(sch); +-} +- +-/* + * Registration structure for nssbf class + */ + const struct Qdisc_class_ops nss_bf_class_ops = { +@@ -807,9 +777,8 @@ const struct Qdisc_class_ops nss_bf_clas + .graft = nss_bf_graft_class, + .leaf = nss_bf_leaf_class, + .qlen_notify = nss_bf_qlen_notify, +- .get = nss_bf_get_class, +- .put = nss_bf_put_class, ++ .find = nss_bf_get_class, + .dump = nss_bf_dump_class, + .dump_stats = nss_bf_dump_class_stats, + .walk = nss_bf_walk + }; +@@ -830,7 +798,6 @@ struct Qdisc_ops nss_bf_qdisc_ops __read + .enqueue = nss_bf_enqueue, + .dequeue = nss_bf_dequeue, + .peek = qdisc_peek_dequeued, +- .drop = nss_bf_drop, + .cl_ops = &nss_bf_class_ops, + .priv_size = sizeof(struct nss_bf_sched_data), + .owner = THIS_MODULE +--- a/nss_qdisc/nss_blackhole.c ++++ b/nss_qdisc/nss_blackhole.c +@@ -35,7 +35,7 @@ static struct nla_policy nss_blackhole_p + * nss_blackhole_enqueue() + * Enqueue API for nss blackhole qdisc. + */ +-static int nss_blackhole_enqueue(struct sk_buff *skb, struct Qdisc *sch) ++static int nss_blackhole_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free) + { + return nss_qdisc_enqueue(skb, sch); + } +@@ -50,18 +50,6 @@ static struct sk_buff *nss_blackhole_deq + } + + /* +- * nss_blackhole_drop() +- * The following function drops a packet from HLOS queue. +- * +- * Note, this does not drop packets from queues in the NSS. We do not support that. +- */ +-static unsigned int nss_blackhole_drop(struct Qdisc *sch) +-{ +- nss_qdisc_info("qdisc %x dropping\n", sch->handle); +- return nss_qdisc_drop(sch); +-} +- +-/* + * nss_blackhole_reset() + * Resets the nss blackhole qdisc. + */ +@@ -92,7 +80,7 @@ static void nss_blackhole_destroy(struct + * nss_blackhole_change() + * Function call used to configure the parameters of the nss blackhole qdisc. + */ +-static int nss_blackhole_change(struct Qdisc *sch, struct nlattr *opt) ++static int nss_blackhole_change(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) + { + struct nss_blackhole_sched_data *q; + struct tc_nssblackhole_qopt *qopt; +@@ -154,7 +142,7 @@ static int nss_blackhole_change(struct Q + * nss_blackhole_init() + * Initializes a nss blackhole qdisc. + */ +-static int nss_blackhole_init(struct Qdisc *sch, struct nlattr *opt) ++static int nss_blackhole_init(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) + { + struct nss_qdisc *nq = qdisc_priv(sch); + struct tc_nssblackhole_qopt *qopt; +@@ -176,12 +164,12 @@ static int nss_blackhole_init(struct Qdi + nss_qdisc_info("qdisc %x initializing\n", sch->handle); + nss_blackhole_reset(sch); + +- if (nss_qdisc_init(sch, nq, NSS_SHAPER_NODE_TYPE_FIFO, 0, accel_mode) < 0) { ++ if (nss_qdisc_init(sch, extack, nq, NSS_SHAPER_NODE_TYPE_FIFO, 0, accel_mode) < 0) { + return -EINVAL; + } + + nss_qdisc_info("qdisc %x initialized with parent %x\n", sch->handle, sch->parent); +- if (nss_blackhole_change(sch, opt) < 0) { ++ if (nss_blackhole_change(sch, opt, NULL) < 0) { + nss_qdisc_destroy(nq); + return -EINVAL; + } +@@ -251,7 +239,6 @@ struct Qdisc_ops nss_blackhole_qdisc_ops + .enqueue = nss_blackhole_enqueue, + .dequeue = nss_blackhole_dequeue, + .peek = nss_blackhole_peek, +- .drop = nss_blackhole_drop, + .init = nss_blackhole_init, + .reset = nss_blackhole_reset, + .destroy = nss_blackhole_destroy, +--- a/nss_qdisc/nss_codel.c ++++ b/nss_qdisc/nss_codel.c +@@ -76,7 +76,7 @@ static struct nla_policy nss_codel_polic + * nss_codel_enqueue() + * Enqueue a packet into nss_codel queue in NSS firmware (bounce). + */ +-static int nss_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch) ++static int nss_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free) + { + return nss_qdisc_enqueue(skb, sch); + } +@@ -91,17 +91,6 @@ static struct sk_buff *nss_codel_dequeue + } + + /* +- * nss_codel_drop() +- * Drops a packet from the bounce complete queue. +- * +- * Note: this does not drop packets from the NSS queues. +- */ +-static unsigned int nss_codel_drop(struct Qdisc *sch) +-{ +- return nss_qdisc_drop(sch); +-} +- +-/* + * nss_codel_reset() + * Resets nss_codel qdisc. + */ +@@ -234,7 +223,7 @@ static int nss_codel_mem_sz_get(struct Q + * nss_codel_change() + * Used to configure the nss_codel queue in NSS firmware. + */ +-static int nss_codel_change(struct Qdisc *sch, struct nlattr *opt) ++static int nss_codel_change(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) + { + struct nss_codel_sched_data *q = qdisc_priv(sch); + struct tc_nsscodel_qopt *qopt; +@@ -381,7 +370,7 @@ fail: + * nss_codel_init() + * Initializes the nss_codel qdisc. + */ +-static int nss_codel_init(struct Qdisc *sch, struct nlattr *opt) ++static int nss_codel_init(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) + { + struct nss_qdisc *nq = qdisc_priv(sch); + struct tc_nsscodel_qopt *qopt; +@@ -404,7 +393,7 @@ static int nss_codel_init(struct Qdisc * + nss_qdisc_register_configure_callback(nq, nss_codel_configure_callback); + nss_qdisc_register_stats_callback(nq, nss_codel_stats_callback); + +- if (nss_qdisc_init(sch, nq, NSS_SHAPER_NODE_TYPE_CODEL, 0, qopt->accel_mode) < 0) { ++ if (nss_qdisc_init(sch, extack, nq, NSS_SHAPER_NODE_TYPE_CODEL, 0, qopt->accel_mode) < 0) { + return -EINVAL; + } + +@@ -412,7 +401,7 @@ static int nss_codel_init(struct Qdisc * + return -EINVAL; + } + +- if (nss_codel_change(sch, opt) < 0) { ++ if (nss_codel_change(sch, opt, NULL) < 0) { + nss_qdisc_destroy(nq); + return -EINVAL; + } +@@ -511,7 +500,6 @@ struct Qdisc_ops nss_codel_qdisc_ops __r + .enqueue = nss_codel_enqueue, + .dequeue = nss_codel_dequeue, + .peek = nss_codel_peek, +- .drop = nss_codel_drop, + .init = nss_codel_init, + .reset = nss_codel_reset, + .destroy = nss_codel_destroy, +@@ -530,7 +518,6 @@ struct Qdisc_ops nss_fq_codel_qdisc_ops + .enqueue = nss_codel_enqueue, + .dequeue = nss_codel_dequeue, + .peek = nss_codel_peek, +- .drop = nss_codel_drop, + .init = nss_codel_init, + .reset = nss_codel_reset, + .destroy = nss_codel_destroy, +--- a/nss_qdisc/nss_fifo.c ++++ b/nss_qdisc/nss_fifo.c +@@ -29,7 +29,7 @@ static struct nla_policy nss_fifo_policy + [TCA_NSSFIFO_PARMS] = { .len = sizeof(struct tc_nssfifo_qopt) }, + }; + +-static int nss_fifo_enqueue(struct sk_buff *skb, struct Qdisc *sch) ++static int nss_fifo_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free) + { + return nss_qdisc_enqueue(skb, sch); + } +@@ -39,12 +39,6 @@ static struct sk_buff *nss_fifo_dequeue( + return nss_qdisc_dequeue(sch); + } + +-static unsigned int nss_fifo_drop(struct Qdisc *sch) +-{ +- nss_qdisc_info("nss_fifo dropping"); +- return nss_qdisc_drop(sch); +-} +- + static void nss_fifo_reset(struct Qdisc *sch) + { + nss_qdisc_info("nss_fifo resetting!"); +@@ -158,7 +152,7 @@ fail: + } + #endif + +-static int nss_fifo_change(struct Qdisc *sch, struct nlattr *opt) ++static int nss_fifo_change(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) + { + struct nss_fifo_sched_data *q = qdisc_priv(sch); + struct nss_qdisc *nq = &q->nq; +@@ -208,7 +202,7 @@ static int nss_fifo_change(struct Qdisc + return 0; + } + +-static int nss_fifo_init(struct Qdisc *sch, struct nlattr *opt) ++static int nss_fifo_init(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) + { + struct nss_qdisc *nq = qdisc_priv(sch); + struct tc_nssfifo_qopt *qopt; +@@ -226,13 +220,13 @@ static int nss_fifo_init(struct Qdisc *s + return -EINVAL; + } + +- if (nss_qdisc_init(sch, nq, NSS_SHAPER_NODE_TYPE_FIFO, 0, qopt->accel_mode) < 0) { ++ if (nss_qdisc_init(sch, extack, nq, NSS_SHAPER_NODE_TYPE_FIFO, 0, qopt->accel_mode) < 0) { + nss_qdisc_warning("Fifo %x init failed", sch->handle); + return -EINVAL; + } + + nss_qdisc_info("NSS fifo initialized - handle %x parent %x\n", sch->handle, sch->parent); +- if (nss_fifo_change(sch, opt) < 0) { ++ if (nss_fifo_change(sch, opt, NULL) < 0) { + nss_qdisc_destroy(nq); + return -EINVAL; + } +@@ -290,7 +284,6 @@ struct Qdisc_ops nss_pfifo_qdisc_ops __r + .enqueue = nss_fifo_enqueue, + .dequeue = nss_fifo_dequeue, + .peek = nss_fifo_peek, +- .drop = nss_fifo_drop, + .init = nss_fifo_init, + .reset = nss_fifo_reset, + .destroy = nss_fifo_destroy, +@@ -305,7 +298,6 @@ struct Qdisc_ops nss_bfifo_qdisc_ops __r + .enqueue = nss_fifo_enqueue, + .dequeue = nss_fifo_dequeue, + .peek = nss_fifo_peek, +- .drop = nss_fifo_drop, + .init = nss_fifo_init, + .reset = nss_fifo_reset, + .destroy = nss_fifo_destroy, +--- a/nss_qdisc/nss_htb.c ++++ b/nss_qdisc/nss_htb.c +@@ -267,7 +267,7 @@ static int nss_htb_ppe_change_class(stru + * Configures a new class. + */ + static int nss_htb_change_class(struct Qdisc *sch, u32 classid, u32 parentid, +- struct nlattr **tca, unsigned long *arg) ++ struct nlattr **tca, unsigned long *arg, struct netlink_ext_ack *extack) + { + struct nss_htb_sched_data *q = qdisc_priv(sch); + struct nss_htb_class_data *cl = (struct nss_htb_class_data *)*arg; +@@ -332,7 +332,7 @@ static int nss_htb_change_class(struct Q + * here. + */ + cl->nq.parent = nq_parent; +- if (nss_qdisc_init(sch, &cl->nq, NSS_SHAPER_NODE_TYPE_HTB_GROUP, classid, accel_mode) < 0) { ++ if (nss_qdisc_init(sch, extack, &cl->nq, NSS_SHAPER_NODE_TYPE_HTB_GROUP, classid, accel_mode) < 0) { + nss_qdisc_error("nss_init for htb class %x failed\n", classid); + goto failure; + } +@@ -478,7 +478,7 @@ static void nss_htb_destroy_class(struct + /* + * And now we destroy the child. + */ +- qdisc_destroy(cl->qdisc); ++ qdisc_put(cl->qdisc); + + /* + * Stop the stats polling timer and free class +@@ -577,7 +577,8 @@ static int nss_htb_delete_class(struct Q + * nss_htb_graft_class() + * Replaces the qdisc attached to the provided class. + */ +-static int nss_htb_graft_class(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, struct Qdisc **old) ++static int nss_htb_graft_class(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, struct Qdisc **old, ++ struct netlink_ext_ack *extack) + { + struct nss_htb_class_data *cl = (struct nss_htb_class_data *)arg; + struct nss_if_msg nim_detach; +@@ -682,25 +683,6 @@ static unsigned long nss_htb_get_class(s + } + + /* +- * nss_htb_put_class() +- * Reduces reference count for this class. +- */ +-static void nss_htb_put_class(struct Qdisc *sch, unsigned long arg) +-{ +- struct nss_htb_class_data *cl = (struct nss_htb_class_data *)arg; +- nss_qdisc_trace("executing put on htb class %x in qdisc %x\n", +- cl->nq.qos_tag, sch->handle); +- +- /* +- * We are safe to destroy the qdisc if the reference count +- * goes down to 0. +- */ +- if (atomic_sub_return(1, &cl->nq.refcnt) == 0) { +- nss_htb_destroy_class(sch, cl); +- } +-} +- +-/* + * nss_htb_dump_class() + * Dumps all configurable parameters pertaining to this class. + */ +@@ -795,7 +777,7 @@ static void nss_htb_walk(struct Qdisc *s + * nss_htb_change_qdisc() + * Can be used to configure a htb qdisc. + */ +-static int nss_htb_change_qdisc(struct Qdisc *sch, struct nlattr *opt) ++static int nss_htb_change_qdisc(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) + { + struct nss_htb_sched_data *q = qdisc_priv(sch); + struct tc_nsshtb_qopt *qopt; +@@ -945,7 +927,7 @@ static void nss_htb_destroy_qdisc(struct + * nss_htb_init_qdisc() + * Initializes the htb qdisc. + */ +-static int nss_htb_init_qdisc(struct Qdisc *sch, struct nlattr *opt) ++static int nss_htb_init_qdisc(struct Qdisc *sch, struct nlattr *opt,struct netlink_ext_ack *extack) + { + struct nss_htb_sched_data *q = qdisc_priv(sch); + struct tc_nsshtb_qopt *qopt; +@@ -977,7 +959,7 @@ static int nss_htb_init_qdisc(struct Qdi + /* + * Initialize the NSSHTB shaper in NSS + */ +- if (nss_qdisc_init(sch, &q->nq, NSS_SHAPER_NODE_TYPE_HTB, 0, accel_mode) < 0) { ++ if (nss_qdisc_init(sch, extack, &q->nq, NSS_SHAPER_NODE_TYPE_HTB, 0, accel_mode) < 0) { + nss_qdisc_error("failed to initialize htb qdisc %x in nss", sch->handle); + return -EINVAL; + } +@@ -987,7 +969,7 @@ static int nss_htb_init_qdisc(struct Qdi + /* + * Tune HTB parameters + */ +- if (nss_htb_change_qdisc(sch, opt) < 0) { ++ if (nss_htb_change_qdisc(sch, opt, NULL) < 0) { + nss_qdisc_destroy(&q->nq); + return -EINVAL; + } +@@ -1032,7 +1014,7 @@ static int nss_htb_dump_qdisc(struct Qdi + * nss_htb_enqueue() + * Enqueues a skb to htb qdisc. + */ +-static int nss_htb_enqueue(struct sk_buff *skb, struct Qdisc *sch) ++static int nss_htb_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free) + { + return nss_qdisc_enqueue(skb, sch); + } +@@ -1047,18 +1029,6 @@ static struct sk_buff *nss_htb_dequeue(s + } + + /* +- * nss_htb_drop() +- * Drops a single skb from linux queue, if not empty. +- * +- * Does not drop packets that are queued in the NSS. +- */ +-static unsigned int nss_htb_drop(struct Qdisc *sch) +-{ +- nss_qdisc_trace("drop called on htb qdisc %x\n", sch->handle); +- return nss_qdisc_drop(sch); +-} +- +-/* + * Registration structure for htb class + */ + const struct Qdisc_class_ops nss_htb_class_ops = { +@@ -1067,9 +1037,8 @@ const struct Qdisc_class_ops nss_htb_cla + .graft = nss_htb_graft_class, + .leaf = nss_htb_leaf_class, + .qlen_notify = nss_htb_qlen_notify, +- .get = nss_htb_get_class, +- .put = nss_htb_put_class, ++ .find = nss_htb_get_class, + .dump = nss_htb_dump_class, + .dump_stats = nss_htb_dump_class_stats, + .walk = nss_htb_walk + }; +@@ -1090,7 +1058,6 @@ struct Qdisc_ops nss_htb_qdisc_ops __rea + .enqueue = nss_htb_enqueue, + .dequeue = nss_htb_dequeue, + .peek = qdisc_peek_dequeued, +- .drop = nss_htb_drop, + .cl_ops = &nss_htb_class_ops, + .priv_size = sizeof(struct nss_htb_sched_data), + .owner = THIS_MODULE +--- a/nss_qdisc/nss_prio.c ++++ b/nss_qdisc/nss_prio.c +@@ -37,7 +37,7 @@ static struct nla_policy nss_prio_policy + * nss_prio_enqueue() + * Enqueues a skb to nssprio qdisc. + */ +-static int nss_prio_enqueue(struct sk_buff *skb, struct Qdisc *sch) ++static int nss_prio_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free) + { + return nss_qdisc_enqueue(skb, sch); + } +@@ -52,17 +52,6 @@ static struct sk_buff *nss_prio_dequeue( + } + + /* +- * nss_prio_drop() +- * Drops a single skb from linux queue, if not empty. +- * +- * Does not drop packets that are queued in the NSS. +- */ +-static unsigned int nss_prio_drop(struct Qdisc *sch) +-{ +- return nss_qdisc_drop(sch); +-} +- +-/* + * nss_prio_peek() + * Peeks the first packet in queue for this qdisc. + */ +@@ -117,7 +106,7 @@ static void nss_prio_destroy(struct Qdis + /* + * We can now destroy it + */ +- qdisc_destroy(q->queues[i]); ++ qdisc_put(q->queues[i]); + } + + /* +@@ -157,7 +146,7 @@ static int nss_prio_get_max_bands(struct + * nss_prio_change() + * Function call to configure the nssprio parameters + */ +-static int nss_prio_change(struct Qdisc *sch, struct nlattr *opt) ++static int nss_prio_change(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) + { + struct nss_prio_sched_data *q; + struct tc_nssprio_qopt *qopt; +@@ -209,7 +198,7 @@ static int nss_prio_change(struct Qdisc + * nss_prio_init() + * Initializes the nssprio qdisc + */ +-static int nss_prio_init(struct Qdisc *sch, struct nlattr *opt) ++static int nss_prio_init(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) + { + struct nss_prio_sched_data *q = qdisc_priv(sch); + struct tc_nssprio_qopt *qopt; +@@ -230,14 +219,14 @@ static int nss_prio_init(struct Qdisc *s + accel_mode = qopt->accel_mode; + } + +- if (nss_qdisc_init(sch, &q->nq, NSS_SHAPER_NODE_TYPE_PRIO, 0, accel_mode) < 0) { ++ if (nss_qdisc_init(sch, extack, &q->nq, NSS_SHAPER_NODE_TYPE_PRIO, 0, accel_mode) < 0) { + return -EINVAL; + } + + nss_qdisc_info("Nssprio initialized - handle %x parent %x\n", + sch->handle, sch->parent); + +- if (nss_prio_change(sch, opt) < 0) { ++ if (nss_prio_change(sch, opt, NULL) < 0) { + nss_qdisc_destroy(&q->nq); + return -EINVAL; + } +@@ -280,7 +269,7 @@ nla_put_failure: + * Replaces existing child qdisc with the new qdisc that is passed. + */ + static int nss_prio_graft(struct Qdisc *sch, unsigned long arg, +- struct Qdisc *new, struct Qdisc **old) ++ struct Qdisc *new, struct Qdisc **old, struct netlink_ext_ack *extack) + { + struct nss_prio_sched_data *q = qdisc_priv(sch); + struct nss_qdisc *nq_new = qdisc_priv(new); +@@ -383,15 +372,6 @@ static unsigned long nss_prio_get(struct + } + + /* +- * nss_prio_put() +- * Unused API. +- */ +-static void nss_prio_put(struct Qdisc *sch, unsigned long arg) +-{ +- nss_qdisc_info("Inside prio put\n"); +-} +- +-/* + * nss_prio_walk() + * Walks the priority band. + */ +@@ -460,9 +440,8 @@ static int nss_prio_dump_class_stats(str + const struct Qdisc_class_ops nss_prio_class_ops = { + .graft = nss_prio_graft, + .leaf = nss_prio_leaf, +- .get = nss_prio_get, +- .put = nss_prio_put, ++ .find = nss_prio_get, + .walk = nss_prio_walk, + .dump = nss_prio_dump_class, + .dump_stats = nss_prio_dump_class_stats, + }; +@@ -481,7 +459,6 @@ struct Qdisc_ops nss_prio_qdisc_ops __re + .enqueue = nss_prio_enqueue, + .dequeue = nss_prio_dequeue, + .peek = nss_prio_peek, +- .drop = nss_prio_drop, + .init = nss_prio_init, + .reset = nss_prio_reset, + .destroy = nss_prio_destroy, +--- a/nss_qdisc/nss_qdisc.c ++++ b/nss_qdisc/nss_qdisc.c +@@ -929,7 +929,7 @@ static inline void nss_qdisc_add_to_tail + * We do not use the qdisc_enqueue_tail() API here in order + * to prevent stats from getting updated by the API. + */ +- __skb_queue_tail(&sch->q, skb); ++ __qdisc_enqueue_tail(skb, &sch->q); + + spin_unlock_bh(&nq->bounce_protection_lock); + }; +@@ -944,7 +944,7 @@ static inline void nss_qdisc_add_to_tail + * We do not use the qdisc_enqueue_tail() API here in order + * to prevent stats from getting updated by the API. + */ +- __skb_queue_tail(&sch->q, skb); ++ __qdisc_enqueue_tail(skb, &sch->q); + }; + + /* +@@ -966,7 +966,7 @@ static inline struct sk_buff *nss_qdisc_ + * We use __skb_dequeue() to ensure that + * stats don't get updated twice. + */ +- skb = __skb_dequeue(&sch->q); ++ skb = __qdisc_dequeue_head(&sch->q); + + spin_unlock_bh(&nq->bounce_protection_lock); + +@@ -983,7 +983,7 @@ static inline struct sk_buff *nss_qdisc_ + * We use __skb_dequeue() to ensure that + * stats don't get updated twice. + */ +- return __skb_dequeue(&sch->q); ++ return __qdisc_dequeue_head(&sch->q); + }; + + /* +@@ -1064,14 +1064,19 @@ struct Qdisc *nss_qdisc_replace(struct Q + void *nss_qdisc_qopt_get(struct nlattr *opt, struct nla_policy *policy, + uint32_t tca_max, uint32_t tca_params) + { +- struct nlattr *na[tca_max + 1]; ++ struct nlattr *na[8]; + int err; + ++ if (tca_max > 8) { ++ pr_warn("nss_qdisc_qopt_get(): Too many options!\n"); ++ return NULL; ++ } ++ + if (!opt) { + return NULL; + } + +- err = nla_parse_nested(na, tca_max, opt, policy); ++ err = nla_parse_nested_deprecated(na, tca_max, opt, policy, NULL); + if (err < 0) + return NULL; + +@@ -1104,10 +1109,10 @@ struct sk_buff *nss_qdisc_peek(struct Qd + struct sk_buff *skb; + + if (!nq->is_virtual) { +- skb = skb_peek(&sch->q); ++ skb = qdisc_peek_head(sch); + } else { + spin_lock_bh(&nq->bounce_protection_lock); +- skb = skb_peek(&sch->q); ++ skb = qdisc_peek_head(sch); + spin_unlock_bh(&nq->bounce_protection_lock); + } + +@@ -1122,15 +1127,16 @@ unsigned int nss_qdisc_drop(struct Qdisc + { + struct nss_qdisc *nq = qdisc_priv(sch); + unsigned int ret; ++ struct sk_buff *to_free = qdisc_peek_head(sch); + + if (!nq->is_virtual) { +- ret = __qdisc_queue_drop_head(sch, &sch->q); ++ ret = __qdisc_queue_drop_head(sch, &sch->q, &to_free); + } else { + spin_lock_bh(&nq->bounce_protection_lock); + /* + * This function is safe to call within locks + */ +- ret = __qdisc_queue_drop_head(sch, &sch->q); ++ ret = __qdisc_queue_drop_head(sch, &sch->q, &to_free); + spin_unlock_bh(&nq->bounce_protection_lock); + } + +@@ -1958,7 +1964,7 @@ void nss_qdisc_destroy(struct nss_qdisc + * Initializes a shaper in NSS, based on the position of this qdisc (child or root) + * and if its a normal interface or a bridge interface. + */ +-int nss_qdisc_init(struct Qdisc *sch, struct nss_qdisc *nq, nss_shaper_node_type_t type, uint32_t classid, uint32_t accel_mode) ++int nss_qdisc_init(struct Qdisc *sch, struct netlink_ext_ack *extack, struct nss_qdisc *nq, nss_shaper_node_type_t type, uint32_t classid, uint32_t accel_mode) + { + struct Qdisc *root; + u32 parent; +@@ -2471,6 +2481,8 @@ static void nss_qdisc_basic_stats_callba + struct gnet_stats_queue *qstats; + struct nss_shaper_node_stats_response *response; + atomic_t *refcnt; ++ refcount_t *refcnt_new; ++ bool is_refcnt_zero = false; + + if (nim->cm.response != NSS_CMN_RESPONSE_ACK) { + nss_qdisc_warning("Qdisc %p (type %d): Receive stats FAILED - " +@@ -2494,7 +2506,7 @@ static void nss_qdisc_basic_stats_callba + } else { + bstats = &qdisc->bstats; + qstats = &qdisc->qstats; +- refcnt = &qdisc->refcnt; ++ refcnt_new = &qdisc->refcnt; + qdisc->q.qlen = response->sn_stats.qlen_packets; + } + +@@ -2533,11 +2545,20 @@ static void nss_qdisc_basic_stats_callba + * All access to nq fields below do not need lock protection. They + * do not get manipulated on different thread contexts. + */ +- if (atomic_read(refcnt) == 0) { ++ if (nq->is_class) { ++ if (atomic_read(refcnt) == 0) ++ is_refcnt_zero = true; ++ } ++ else { ++ if (refcount_read(refcnt_new) == 0) ++ is_refcnt_zero = true; ++ } ++ if (is_refcnt_zero) { + atomic_sub(1, &nq->pending_stat_requests); + wake_up(&nq->wait_queue); + return; + } ++ + + /* + * Requests for stats again, after 1 sec. +@@ -2555,9 +2576,9 @@ static void nss_qdisc_basic_stats_callba + * nss_qdisc_get_stats_timer_callback() + * Invoked periodically to get updated stats + */ +-static void nss_qdisc_get_stats_timer_callback(unsigned long int data) ++static void nss_qdisc_get_stats_timer_callback(struct timer_list *arg) + { +- struct nss_qdisc *nq = (struct nss_qdisc *)data; ++ struct nss_qdisc *nq = (struct nss_qdisc *)arg->cust_data; + nss_tx_status_t rc; + struct nss_if_msg nim; + int msg_type; +@@ -2604,9 +2625,8 @@ void nss_qdisc_start_basic_stats_polling + return; + } + +- init_timer(&nq->stats_get_timer); +- nq->stats_get_timer.function = nss_qdisc_get_stats_timer_callback; +- nq->stats_get_timer.data = (unsigned long)nq; ++ timer_setup(&nq->stats_get_timer, nss_qdisc_get_stats_timer_callback, 0); ++ nq->stats_get_timer.cust_data = (unsigned long)nq; + nq->stats_get_timer.expires = jiffies + HZ; + atomic_set(&nq->pending_stat_requests, 1); + add_timer(&nq->stats_get_timer); +@@ -2650,7 +2670,7 @@ int nss_qdisc_gnet_stats_copy_basic(stru + #if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 18, 0)) + return gnet_stats_copy_basic(d, b); + #else +- return gnet_stats_copy_basic(d, NULL, b); ++ return gnet_stats_copy_basic(NULL, d, NULL, b); + #endif + } + +--- a/nss_qdisc/nss_tbl.c ++++ b/nss_qdisc/nss_tbl.c +@@ -29,7 +29,7 @@ static struct nla_policy nss_tbl_policy[ + [TCA_NSSTBL_PARMS] = { .len = sizeof(struct tc_nsstbl_qopt) }, + }; + +-static int nss_tbl_enqueue(struct sk_buff *skb, struct Qdisc *sch) ++static int nss_tbl_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free) + { + return nss_qdisc_enqueue(skb, sch); + } +@@ -39,11 +39,6 @@ static struct sk_buff *nss_tbl_dequeue(s + return nss_qdisc_dequeue(sch); + } + +-static unsigned int nss_tbl_drop(struct Qdisc *sch) +-{ +- return nss_qdisc_drop(sch); +-} +- + static struct sk_buff *nss_tbl_peek(struct Qdisc *sch) + { + return nss_qdisc_peek(sch); +@@ -77,7 +72,7 @@ static void nss_tbl_destroy(struct Qdisc + /* + * Now we can destroy our child qdisc + */ +- qdisc_destroy(q->qdisc); ++ qdisc_put(q->qdisc); + + /* + * Stop the polling of basic stats and destroy qdisc. +@@ -132,7 +127,7 @@ fail: + } + #endif + +-static int nss_tbl_change(struct Qdisc *sch, struct nlattr *opt) ++static int nss_tbl_change(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) + { + struct nss_tbl_sched_data *q = qdisc_priv(sch); + struct tc_nsstbl_qopt *qopt; +@@ -216,7 +211,7 @@ static int nss_tbl_change(struct Qdisc * + return 0; + } + +-static int nss_tbl_init(struct Qdisc *sch, struct nlattr *opt) ++static int nss_tbl_init(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) + { + struct nss_tbl_sched_data *q = qdisc_priv(sch); + struct tc_nsstbl_qopt *qopt; +@@ -232,10 +227,10 @@ static int nss_tbl_init(struct Qdisc *sc + return -EINVAL; + } + +- if (nss_qdisc_init(sch, &q->nq, NSS_SHAPER_NODE_TYPE_TBL, 0, qopt->accel_mode) < 0) ++ if (nss_qdisc_init(sch, extack, &q->nq, NSS_SHAPER_NODE_TYPE_TBL, 0, qopt->accel_mode) < 0) + return -EINVAL; + +- if (nss_tbl_change(sch, opt) < 0) { ++ if (nss_tbl_change(sch, opt, NULL) < 0) { + nss_qdisc_info("Failed to configure tbl\n"); + nss_qdisc_destroy(&q->nq); + return -EINVAL; +@@ -287,7 +282,7 @@ static int nss_tbl_dump_class(struct Qdi + } + + static int nss_tbl_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, +- struct Qdisc **old) ++ struct Qdisc **old, struct netlink_ext_ack *extack) + { + struct nss_tbl_sched_data *q = qdisc_priv(sch); + struct nss_qdisc *nq_new = (struct nss_qdisc *)qdisc_priv(new); +@@ -344,10 +339,6 @@ static unsigned long nss_tbl_get(struct + return 1; + } + +-static void nss_tbl_put(struct Qdisc *sch, unsigned long arg) +-{ +-} +- + static void nss_tbl_walk(struct Qdisc *sch, struct qdisc_walker *walker) + { + nss_qdisc_info("Nsstbl walk called"); +@@ -364,9 +355,8 @@ static void nss_tbl_walk(struct Qdisc *s + const struct Qdisc_class_ops nss_tbl_class_ops = { + .graft = nss_tbl_graft, + .leaf = nss_tbl_leaf, +- .get = nss_tbl_get, +- .put = nss_tbl_put, ++ .find = nss_tbl_get, + .walk = nss_tbl_walk, + .dump = nss_tbl_dump_class, + }; + +@@ -381,7 +370,6 @@ struct Qdisc_ops nss_tbl_qdisc_ops __rea + .enqueue = nss_tbl_enqueue, + .dequeue = nss_tbl_dequeue, + .peek = nss_tbl_peek, +- .drop = nss_tbl_drop, + .init = nss_tbl_init, + .reset = nss_tbl_reset, + .destroy = nss_tbl_destroy, +--- a/nss_qdisc/nss_wred.c ++++ b/nss_qdisc/nss_wred.c +@@ -55,7 +55,7 @@ static struct nla_policy nss_wred_policy + * nss_wred_enqueue() + * Enqueue API for nsswred qdisc + */ +-static int nss_wred_enqueue(struct sk_buff *skb, struct Qdisc *sch) ++static int nss_wred_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free) + { + return nss_qdisc_enqueue(skb, sch); + } +@@ -70,16 +70,6 @@ static struct sk_buff *nss_wred_dequeue( + } + + /* +- * nss_wred_drop() +- * Drops a packet from HLOS queue. +- */ +-static unsigned int nss_wred_drop(struct Qdisc *sch) +-{ +- nss_qdisc_info("nsswred dropping"); +- return nss_qdisc_drop(sch); +-} +- +-/* + * nss_wred_reset() + * Reset the nsswred qdisc + */ +@@ -171,7 +161,7 @@ fail: + * nss_wred_change() + * Function call to configure the nsswred parameters + */ +-static int nss_wred_change(struct Qdisc *sch, struct nlattr *opt) ++static int nss_wred_change(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) + { + struct nss_wred_sched_data *q = qdisc_priv(sch); + struct tc_nsswred_qopt *qopt; +@@ -298,7 +288,7 @@ static int nss_wred_change(struct Qdisc + * nss_wred_init() + * Init the nsswred qdisc + */ +-static int nss_wred_init(struct Qdisc *sch, struct nlattr *opt) ++static int nss_wred_init(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) + { + struct nss_qdisc *nq = qdisc_priv(sch); + struct tc_nsswred_qopt *qopt; +@@ -315,11 +305,11 @@ static int nss_wred_init(struct Qdisc *s + nss_qdisc_info("Initializing Wred - type %d\n", NSS_SHAPER_NODE_TYPE_WRED); + nss_wred_reset(sch); + +- if (nss_qdisc_init(sch, nq, NSS_SHAPER_NODE_TYPE_WRED, 0, qopt->accel_mode) < 0) ++ if (nss_qdisc_init(sch, extack, nq, NSS_SHAPER_NODE_TYPE_WRED, 0, qopt->accel_mode) < 0) + return -EINVAL; + + nss_qdisc_info("NSS wred initialized - handle %x parent %x\n", sch->handle, sch->parent); +- if (nss_wred_change(sch, opt) < 0) { ++ if (nss_wred_change(sch, opt, NULL) < 0) { + nss_qdisc_destroy(nq); + return -EINVAL; + } +@@ -405,7 +395,6 @@ struct Qdisc_ops nss_red_qdisc_ops __rea + .enqueue = nss_wred_enqueue, + .dequeue = nss_wred_dequeue, + .peek = nss_wred_peek, +- .drop = nss_wred_drop, + .init = nss_wred_init, + .reset = nss_wred_reset, + .destroy = nss_wred_destroy, +@@ -423,7 +412,6 @@ struct Qdisc_ops nss_wred_qdisc_ops __re + .enqueue = nss_wred_enqueue, + .dequeue = nss_wred_dequeue, + .peek = nss_wred_peek, +- .drop = nss_wred_drop, + .init = nss_wred_init, + .reset = nss_wred_reset, + .destroy = nss_wred_destroy, +--- a/nss_qdisc/nss_wrr.c ++++ b/nss_qdisc/nss_wrr.c +@@ -84,7 +84,7 @@ static void nss_wrr_destroy_class(struct + /* + * And now we destroy the child. + */ +- qdisc_destroy(cl->qdisc); ++ qdisc_put(cl->qdisc); + + /* + * Stop the stats polling timer and free class +@@ -219,7 +219,7 @@ static int nss_wrr_ppe_change_class(stru + #endif + + static int nss_wrr_change_class(struct Qdisc *sch, u32 classid, u32 parentid, +- struct nlattr **tca, unsigned long *arg) ++ struct nlattr **tca, unsigned long *arg, struct netlink_ext_ack *extack) + { + struct nss_wrr_sched_data *q = qdisc_priv(sch); + struct nss_wrr_class_data *cl = (struct nss_wrr_class_data *)*arg; +@@ -286,7 +286,7 @@ static int nss_wrr_change_class(struct Q + * here. + */ + cl->nq.parent = &q->nq; +- if (nss_qdisc_init(sch, &cl->nq, NSS_SHAPER_NODE_TYPE_WRR_GROUP, classid, accel_mode) < 0) { ++ if (nss_qdisc_init(sch, extack, &cl->nq, NSS_SHAPER_NODE_TYPE_WRR_GROUP, classid, accel_mode) < 0) { + nss_qdisc_error("Nss init for class %u failed\n", classid); + return -EINVAL; + } +@@ -422,7 +422,7 @@ static int nss_wrr_delete_class(struct Q + } + + static int nss_wrr_graft_class(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, +- struct Qdisc **old) ++ struct Qdisc **old, struct netlink_ext_ack *extack) + { + struct nss_wrr_sched_data *q = qdisc_priv(sch); + struct nss_wrr_class_data *cl = (struct nss_wrr_class_data *)arg; +@@ -517,20 +517,6 @@ static unsigned long nss_wrr_get_class(s + return (unsigned long)cl; + } + +-static void nss_wrr_put_class(struct Qdisc *sch, unsigned long arg) +-{ +- struct nss_wrr_class_data *cl = (struct nss_wrr_class_data *)arg; +- nss_qdisc_info("nss_wrr put class for %p\n", cl); +- +- /* +- * We are safe to destroy the qdisc if the reference count +- * goes down to 0. +- */ +- if (atomic_sub_return(1, &cl->nq.refcnt) == 0) { +- nss_wrr_destroy_class(sch, cl); +- } +-} +- + static int nss_wrr_dump_class(struct Qdisc *sch, unsigned long arg, struct sk_buff *skb, + struct tcmsg *tcm) + { +@@ -600,7 +586,7 @@ static void nss_wrr_walk(struct Qdisc *s + } + } + +-static int nss_wrr_init_qdisc(struct Qdisc *sch, struct nlattr *opt) ++static int nss_wrr_init_qdisc(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) + { + struct nss_wrr_sched_data *q = qdisc_priv(sch); + int err; +@@ -629,7 +615,7 @@ static int nss_wrr_init_qdisc(struct Qdi + /* + * Initialize the NSSWRR shaper in NSS + */ +- if (nss_qdisc_init(sch, &q->nq, NSS_SHAPER_NODE_TYPE_WRR, 0, qopt->accel_mode) < 0) { ++ if (nss_qdisc_init(sch, extack, &q->nq, NSS_SHAPER_NODE_TYPE_WRR, 0, qopt->accel_mode) < 0) { + nss_qdisc_warning("Failed init nss_wrr qdisc"); + return -EINVAL; + } +@@ -669,7 +655,7 @@ static int nss_wrr_init_qdisc(struct Qdi + return 0; + } + +-static int nss_wrr_change_qdisc(struct Qdisc *sch, struct nlattr *opt) ++static int nss_wrr_change_qdisc(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) + { + struct nss_wrr_sched_data *q; + struct tc_nsswrr_qopt *qopt; +@@ -809,7 +795,7 @@ nla_put_failure: + return -EMSGSIZE; + } + +-static int nss_wrr_enqueue(struct sk_buff *skb, struct Qdisc *sch) ++static int nss_wrr_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free) + { + return nss_qdisc_enqueue(skb, sch); + } +@@ -819,21 +805,14 @@ static struct sk_buff *nss_wrr_dequeue(s + return nss_qdisc_dequeue(sch); + } + +-static unsigned int nss_wrr_drop(struct Qdisc *sch) +-{ +- nss_qdisc_info("Nsswrr drop\n"); +- return nss_qdisc_drop(sch); +-} +- + const struct Qdisc_class_ops nss_wrr_class_ops = { + .change = nss_wrr_change_class, + .delete = nss_wrr_delete_class, + .graft = nss_wrr_graft_class, + .leaf = nss_wrr_leaf_class, + .qlen_notify = nss_wrr_qlen_notify, +- .get = nss_wrr_get_class, +- .put = nss_wrr_put_class, ++ .find = nss_wrr_get_class, + .dump = nss_wrr_dump_class, + .dump_stats = nss_wrr_dump_class_stats, + .walk = nss_bf_walk + }; +@@ -851,7 +829,6 @@ struct Qdisc_ops nss_wrr_qdisc_ops __rea + .enqueue = nss_wrr_enqueue, + .dequeue = nss_wrr_dequeue, + .peek = qdisc_peek_dequeued, +- .drop = nss_wrr_drop, + .cl_ops = &nss_wrr_class_ops, + .priv_size = sizeof(struct nss_wrr_sched_data), + .owner = THIS_MODULE +@@ -863,9 +840,8 @@ const struct Qdisc_class_ops nss_wfq_cla + .graft = nss_wrr_graft_class, + .leaf = nss_wrr_leaf_class, + .qlen_notify = nss_wrr_qlen_notify, +- .get = nss_wrr_get_class, +- .put = nss_wrr_put_class, ++ .find = nss_wrr_get_class, + .dump = nss_wrr_dump_class, + .dump_stats = nss_wrr_dump_class_stats, + .walk = nss_wrr_walk + }; +@@ -883,7 +858,6 @@ struct Qdisc_ops nss_wfq_qdisc_ops __rea + .enqueue = nss_wrr_enqueue, + .dequeue = nss_wrr_dequeue, + .peek = qdisc_peek_dequeued, +- .drop = nss_wrr_drop, + .cl_ops = &nss_wrr_class_ops, + .priv_size = sizeof(struct nss_wrr_sched_data), + .owner = THIS_MODULE diff --git a/root/package/qca/nss/qca-nss-clients/patches/101-kernel-5.4-support-gre.patch b/root/package/qca/nss/qca-nss-clients/patches/101-kernel-5.4-support-gre.patch new file mode 100644 index 00000000..705ceabe --- /dev/null +++ b/root/package/qca/nss/qca-nss-clients/patches/101-kernel-5.4-support-gre.patch @@ -0,0 +1,106 @@ +From 7c89187ab2d165ccffed627742e7cb72cce375ef Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Sun, 12 Jul 2020 22:49:30 +0200 +Subject: [PATCH] kernel-5.4-support-gre + +--- + gre/nss_connmgr_gre.c | 16 +++++++--------- + gre/nss_connmgr_gre_v6.c | 4 ++-- + 2 files changed, 9 insertions(+), 11 deletions(-) + +diff --git a/gre/nss_connmgr_gre.c b/gre/nss_connmgr_gre.c +index 52203b1..6de8f6e 100644 +--- a/gre/nss_connmgr_gre.c ++++ b/gre/nss_connmgr_gre.c +@@ -88,7 +88,7 @@ static int nss_connmgr_gre_dev_init(struct net_device *dev) + u64_stats_init(&stats->syncp); + } + +- if ((dev->priv_flags & IFF_GRE_V4_TAP) || (dev->type == ARPHRD_IPGRE)) { ++ if ((dev->priv_flags_qca_ecm & IFF_QCA_ECM_GRE_V4_TAP) || (dev->type == ARPHRD_IPGRE)) { + dev->needed_headroom = sizeof(struct iphdr) + sizeof(struct ethhdr) + MAX_WIFI_HEADROOM + append; + dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr) - append; + dev->features |= NETIF_F_NETNS_LOCAL | NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA; +@@ -169,7 +169,7 @@ fail: + * nss_connmgr_gre_dev_stats64() + * Netdev ops function to retrieve stats. + */ +-struct rtnl_link_stats64 *nss_connmgr_gre_dev_stats64(struct net_device *dev, ++void nss_connmgr_gre_dev_stats64(struct net_device *dev, + struct rtnl_link_stats64 *tot) + { + uint64_t rx_packets, rx_bytes, tx_packets, tx_bytes; +@@ -202,8 +202,6 @@ struct rtnl_link_stats64 *nss_connmgr_gre_dev_stats64(struct net_device *dev, + tot->rx_dropped = dev->stats.rx_dropped; + tot->tx_dropped = dev->stats.tx_dropped; + } +- +- return tot; + } + + /* +@@ -390,7 +388,7 @@ static int32_t nss_connmgr_gre_prepare_config_cmd(struct net_device *dev, + { + struct nss_gre_config_msg *cmsg = &req->msg.cmsg; + +- if ((dev->type == ARPHRD_ETHER) && (dev->priv_flags & IFF_GRE_V4_TAP)) { ++ if ((dev->type == ARPHRD_ETHER) && (dev->priv_flags_qca_ecm & IFF_QCA_ECM_GRE_V4_TAP)) { + cmsg->mode = NSS_GRE_MODE_TAP; + cmsg->ip_type = NSS_GRE_IP_IPV4; + if (enable_unalign) { +@@ -399,7 +397,7 @@ static int32_t nss_connmgr_gre_prepare_config_cmd(struct net_device *dev, + return nss_connmgr_gre_v4_get_config(dev, req, next_dev, hold); + } + +- if ((dev->type == ARPHRD_ETHER) && (dev->priv_flags & IFF_GRE_V6_TAP)) { ++ if ((dev->type == ARPHRD_ETHER) && (dev->priv_flags_qca_ecm & IFF_QCA_ECM_GRE_V6_TAP)) { + cmsg->mode = NSS_GRE_MODE_TAP; + cmsg->ip_type = NSS_GRE_IP_IPV6; + if (enable_unalign) { +@@ -605,7 +603,7 @@ static bool nss_connmgr_gre_is_gre(struct net_device *dev) + { + if ((dev->type == ARPHRD_IPGRE) || + (dev->type == ARPHRD_IP6GRE) || ((dev->type == ARPHRD_ETHER) && +- (dev->priv_flags & (IFF_GRE_V4_TAP | IFF_GRE_V6_TAP)))) { ++ (dev->priv_flags_qca_ecm & (IFF_QCA_ECM_GRE_V4_TAP | IFF_QCA_ECM_GRE_V6_TAP)))) { + return true; + } + +@@ -692,10 +690,10 @@ static struct net_device *__nss_connmgr_gre_create_interface(struct nss_connmgr_ + nss_connmgr_gre_tap_setup(dev); + + if (cfg->is_ipv6) { +- dev->priv_flags |= IFF_GRE_V6_TAP; ++ dev->priv_flags_qca_ecm |= IFF_QCA_ECM_GRE_V6_TAP; + ret = nss_connmgr_gre_v6_set_config(dev, cfg); + } else { +- dev->priv_flags |= IFF_GRE_V4_TAP; ++ dev->priv_flags_qca_ecm |= IFF_QCA_ECM_GRE_V4_TAP; + ret = nss_connmgr_gre_v4_set_config(dev, cfg); + } + break; +diff --git a/gre/nss_connmgr_gre_v6.c b/gre/nss_connmgr_gre_v6.c +index f9a8e58..e93c7e4 100644 +--- a/gre/nss_connmgr_gre_v6.c ++++ b/gre/nss_connmgr_gre_v6.c +@@ -46,7 +46,7 @@ static struct net_device *nss_connmgr_gre_v6_get_tx_dev(uint8_t *dest_ip) + struct net_device *dev; + + memcpy(ipv6_addr.s6_addr, dest_ip, 16); +- rt = rt6_lookup(&init_net, &ipv6_addr, NULL, 0, 0); ++ rt = rt6_lookup(&init_net, &ipv6_addr, NULL, 0, NULL, 0); + if (!rt) { + return NULL; + } +@@ -92,7 +92,7 @@ static int nss_connmgr_gre_v6_get_mac_address(uint8_t *src_ip, uint8_t *dest_ip, + * Find dest MAC address + */ + memcpy(ipv6_addr.s6_addr, dest_ip, 16); +- rt = rt6_lookup(&init_net, &ipv6_addr, NULL, 0, 0); ++ rt = rt6_lookup(&init_net, &ipv6_addr, NULL, 0, NULL, 0); + if (!rt) { + return GRE_ERR_NEIGH_LOOKUP; + } +-- +2.27.0 + diff --git a/root/package/qca/nss/qca-nss-clients/patches/102-kernel-5.4-support-ipsec.patch b/root/package/qca/nss/qca-nss-clients/patches/102-kernel-5.4-support-ipsec.patch new file mode 100644 index 00000000..de43b4d0 --- /dev/null +++ b/root/package/qca/nss/qca-nss-clients/patches/102-kernel-5.4-support-ipsec.patch @@ -0,0 +1,29 @@ +--- a/ipsecmgr/v1.0/nss_ipsecmgr.c ++++ b/ipsecmgr/v1.0/nss_ipsecmgr.c +@@ -377,7 +377,7 @@ free: + * nss_ipsecmgr_tunnel_stats() + * get tunnel statistics + */ +-static struct rtnl_link_stats64 *nss_ipsecmgr_tunnel_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) ++void nss_ipsecmgr_tunnel_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) + { + struct nss_ipsecmgr_priv *priv = netdev_priv(dev); + +@@ -389,8 +389,6 @@ static struct rtnl_link_stats64 *nss_ips + read_lock_bh(&ipsecmgr_ctx->lock); + memcpy(stats, &priv->stats, sizeof(struct rtnl_link_stats64)); + read_unlock_bh(&ipsecmgr_ctx->lock); +- +- return stats; + } + + /* +@@ -442,7 +440,7 @@ static void nss_ipsecmgr_tunnel_setup(st + dev->header_ops = NULL; + dev->netdev_ops = &nss_ipsecmgr_tunnel_ops; + +- dev->destructor = nss_ipsecmgr_tunnel_free; ++ dev->priv_destructor = nss_ipsecmgr_tunnel_free; + + /* + * get the MAC address from the ethernet device diff --git a/root/package/qca/nss/qca-nss-clients/patches/103-kernel-5.4-support-dtls.patch b/root/package/qca/nss/qca-nss-clients/patches/103-kernel-5.4-support-dtls.patch new file mode 100644 index 00000000..ae9c9147 --- /dev/null +++ b/root/package/qca/nss/qca-nss-clients/patches/103-kernel-5.4-support-dtls.patch @@ -0,0 +1,11 @@ +--- a/dtls/v1.0/nss_connmgr_dtls_netdev.c ++++ b/dtls/v1.0/nss_connmgr_dtls_netdev.c +@@ -160,7 +160,7 @@ static void nss_dtlsmgr_dev_setup(struct + dev->ethtool_ops = NULL; + dev->header_ops = NULL; + dev->netdev_ops = &nss_dtlsmgr_session_ops; +- dev->destructor = NULL; ++ dev->priv_destructor = NULL; + + memcpy(dev->dev_addr, "\xaa\xbb\xcc\xdd\xee\xff", dev->addr_len); + memset(dev->broadcast, 0xff, dev->addr_len); diff --git a/root/package/qca/nss/qca-nss-clients/patches/104-kernel-5.4-support-l2tp.patch b/root/package/qca/nss/qca-nss-clients/patches/104-kernel-5.4-support-l2tp.patch new file mode 100644 index 00000000..c637235c --- /dev/null +++ b/root/package/qca/nss/qca-nss-clients/patches/104-kernel-5.4-support-l2tp.patch @@ -0,0 +1,64 @@ +--- a/l2tp/l2tpv2/nss_connmgr_l2tpv2.h ++++ b/l2tp/l2tpv2/nss_connmgr_l2tpv2.h +@@ -30,10 +30,10 @@ + + #define L2TP_V_2 2 + +-#define tunnel_hold(tunnel) atomic_inc(&tunnel->ref_count) +-#define tunnel_put(tunnel) atomic_dec(&tunnel->ref_count) +-#define session_hold(session) atomic_inc(&session->ref_count) +-#define session_put(session) atomic_dec(&session->ref_count) ++#define tunnel_hold(tunnel) refcount_inc(&tunnel->ref_count) ++#define tunnel_put(tunnel) refcount_dec(&tunnel->ref_count) ++#define session_hold(session) refcount_inc(&session->ref_count) ++#define session_put(session) refcount_dec(&session->ref_count) + + /* + * ---------------------------------------------------------------------------------- +--- a/l2tp/l2tpv2/nss_connmgr_l2tpv2.c ++++ b/l2tp/l2tpv2/nss_connmgr_l2tpv2.c +@@ -244,7 +244,7 @@ static struct nss_connmgr_l2tpv2_session + */ + data->l2tpv2.session.session_id = session->session_id; + data->l2tpv2.session.peer_session_id = session->peer_session_id; +- data->l2tpv2.session.offset = session->offset; ++ data->l2tpv2.session.offset = 0; + data->l2tpv2.session.hdr_len = session->hdr_len; + data->l2tpv2.session.reorder_timeout = session->reorder_timeout; + data->l2tpv2.session.recv_seq = session->recv_seq; +@@ -253,7 +253,7 @@ static struct nss_connmgr_l2tpv2_session + nss_connmgr_l2tpv2_info("sess %u, peer=%u nr=%u ns=%u off=%u hdr_len=%u timeout=%x" + " recv_seq=%x send_seq=%x\n", + session->session_id, session->peer_session_id, session->nr, +- session->ns, session->offset, session->hdr_len, ++ session->ns, 0, session->hdr_len, + session->reorder_timeout, session->recv_seq, + session->send_seq); + +--- a/l2tp/l2tpv2/nss_l2tpv2_stats.c ++++ b/l2tp/l2tpv2/nss_l2tpv2_stats.c +@@ -21,6 +21,7 @@ + */ + + #include ++#include + #include + #include + #include +@@ -103,14 +104,14 @@ void nss_l2tpv2_update_dev_stats(struct + /* + * Update tunnel & session stats + */ +- tunnel = l2tp_tunnel_find(dev_net(dev), data.l2tpv2.tunnel.tunnel_id); ++ tunnel = l2tp_tunnel_get(dev_net(dev), data.l2tpv2.tunnel.tunnel_id); + if (!tunnel) { + dev_put(dev); + return; + } + tunnel_hold(tunnel); + +- session = l2tp_session_find(dev_net(dev), tunnel, data.l2tpv2.session.session_id); ++ session = l2tp_session_get(dev_net(dev), data.l2tpv2.session.session_id); + if (!session) { + tunnel_put(tunnel); + dev_put(dev); diff --git a/root/package/qca/nss/qca-nss-clients/patches/200-qdisc-fix-compile-error.patch b/root/package/qca/nss/qca-nss-clients/patches/200-qdisc-fix-compile-error.patch new file mode 100644 index 00000000..4e147489 --- /dev/null +++ b/root/package/qca/nss/qca-nss-clients/patches/200-qdisc-fix-compile-error.patch @@ -0,0 +1,14 @@ +--- a/nss_qdisc/nss_qdisc.c ++++ b/nss_qdisc/nss_qdisc.c +@@ -2708,9 +2708,11 @@ static int nss_qdisc_if_event_cb(struct + case NETDEV_BR_JOIN: + nss_qdisc_info("Reveived NETDEV_BR_JOIN on interface %s\n", + dev->name); ++ goto fall_through; + case NETDEV_BR_LEAVE: + nss_qdisc_info("Reveived NETDEV_BR_LEAVE on interface %s\n", + dev->name); ++fall_through: + br = nss_qdisc_get_dev_master(dev); + if_num = nss_cmn_get_interface_number(nss_qdisc_ctx, dev); + diff --git a/root/package/qca/nss/qca-nss-clients/patches/202-vlanmgr-fix-compile-error.patch b/root/package/qca/nss/qca-nss-clients/patches/202-vlanmgr-fix-compile-error.patch new file mode 100644 index 00000000..53af3192 --- /dev/null +++ b/root/package/qca/nss/qca-nss-clients/patches/202-vlanmgr-fix-compile-error.patch @@ -0,0 +1,48 @@ +--- a/vlan/nss_vlan_mgr.c ++++ b/vlan/nss_vlan_mgr.c +@@ -820,8 +820,10 @@ static struct nss_vlan_pvt *nss_vlan_mgr + */ + static void nss_vlan_mgr_instance_free(struct nss_vlan_pvt *v) + { ++#ifdef NSS_VLAN_MGR_PPE_SUPPORT + int32_t i; + int ret = 0; ++#endif + + spin_lock(&vlan_mgr_ctx.lock); + BUG_ON(--v->refs); +@@ -979,8 +981,11 @@ static int nss_vlan_mgr_register_event(s + int ret; + #endif + uint32_t vlan_tag; ++#ifdef NSS_VLAN_MGR_PPE_SUPPORT + struct net_device *slave; +- int32_t port, port_if; ++ int32_t port; ++#endif ++ int32_t port_if; + struct vlan_dev_priv *vlan; + struct net_device *real_dev; + bool is_bond_master = false; +@@ -1354,8 +1359,10 @@ return_with_error: + int nss_vlan_mgr_join_bridge(struct net_device *dev, uint32_t bridge_vsi) + { + struct nss_vlan_pvt *v = nss_vlan_mgr_instance_find_and_ref(dev); ++#ifdef NSS_VLAN_MGR_PPE_SUPPORT + struct net_device *real_dev; + int ret; ++#endif + + if (!v) + return 0; +@@ -1415,8 +1422,10 @@ EXPORT_SYMBOL(nss_vlan_mgr_join_bridge); + int nss_vlan_mgr_leave_bridge(struct net_device *dev, uint32_t bridge_vsi) + { + struct nss_vlan_pvt *v = nss_vlan_mgr_instance_find_and_ref(dev); ++#ifdef NSS_VLAN_MGR_PPE_SUPPORT + struct net_device *real_dev; + int ret; ++#endif + + if (!v) + return 0; diff --git a/root/package/qca/nss/qca-nss-crypto/Makefile b/root/package/qca/nss/qca-nss-crypto/Makefile new file mode 100644 index 00000000..213e2447 --- /dev/null +++ b/root/package/qca/nss/qca-nss-crypto/Makefile @@ -0,0 +1,74 @@ +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=qca-nss-crypto +PKG_RELEASE:=1 + +PKG_SOURCE_URL:=https://source.codeaurora.org/quic/qsdk/oss/lklm/nss-crypto +PKG_SOURCE_PROTO:=git +PKG_SOURCE_VERSION:=e7651c2986d30b5e8ca5ad6b9a72c47febdf3cca +PKG_MIRROR_HASH:=381ba448ccd9e0ff69fa52b3e10687b72260b7d0bf865cac10be7f159573b6c8 + +include $(INCLUDE_DIR)/package.mk + +ifeq ($(CONFIG_TARGET_ipq),y) +subtarget:=$(SUBTARGET) +else +subtarget:=$(CONFIG_TARGET_BOARD) +endif + +# v1.0 is for Akronite +# v2.0 is for Hawkeye/Cypress/Maple +ifneq (, $(findstring $(subtarget), "ipq807x" "ipq807x_64" "ipq60xx" "ipq60xx_64" "ipq50xx" "ipq50xx_64")) +NSS_CRYPTO_DIR:=v2.0 +else +NSS_CRYPTO_DIR:=v1.0 +endif + +define KernelPackage/qca-nss-crypto/Default + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + DEPENDS:=@(TARGET_ipq806x||TARGET_ipq807x||TARGET_ipq50xx||TARGET_ipq60xx) +kmod-qca-nss-drv +endef + +define KernelPackage/qca-nss-crypto + $(call KernelPackage/qca-nss-crypto/Default) + TITLE:=Kernel driver for NSS crypto driver + FILES:=$(PKG_BUILD_DIR)/$(NSS_CRYPTO_DIR)/src/qca-nss-crypto.ko \ + $(PKG_BUILD_DIR)/$(NSS_CRYPTO_DIR)/tool/qca-nss-crypto-tool.ko + AUTOLOAD:=$(call AutoLoad,52,qca-nss-crypto) +endef + +define KernelPackage/qca-nss-crypto/Description +This package contains a NSS crypto driver for QCA chipset +endef + +define Build/InstallDev/qca-nss-crypto + $(INSTALL_DIR) $(1)/usr/include/qca-nss-crypto + $(CP) $(PKG_BUILD_DIR)/$(NSS_CRYPTO_DIR)/include/* $(1)/usr/include/qca-nss-crypto +endef + +define Build/InstallDev + $(call Build/InstallDev/qca-nss-crypto,$(1)) +endef + +EXTRA_CFLAGS+= \ + -DCONFIG_NSS_DEBUG_LEVEL=4 \ + -I$(STAGING_DIR)/usr/include/qca-nss-crypto \ + -I$(STAGING_DIR)/usr/include/qca-nss-drv \ + -I$(PKG_BUILD_DIR)/$(NSS_CRYPTO_DIR)/include \ + -I$(PKG_BUILD_DIR)/$(NSS_CRYPTO_DIR)/src + +define Build/Compile + $(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \ + $(KERNEL_MAKE_FLAGS) \ + $(PKG_MAKE_FLAGS) \ + M="$(PKG_BUILD_DIR)" \ + EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ + NSS_CRYPTO_DIR=$(NSS_CRYPTO_DIR) \ + SoC="$(subtarget)" \ + modules +endef + +$(eval $(call KernelPackage,qca-nss-crypto)) diff --git a/root/package/qca/nss/qca-nss-crypto/patches/100-kernel-5.4-support.patch b/root/package/qca/nss/qca-nss-crypto/patches/100-kernel-5.4-support.patch new file mode 100644 index 00000000..b9ef6191 --- /dev/null +++ b/root/package/qca/nss/qca-nss-crypto/patches/100-kernel-5.4-support.patch @@ -0,0 +1,42 @@ +--- a/v1.0/tool/nss_crypto_bench.c ++++ b/v1.0/tool/nss_crypto_bench.c +@@ -75,8 +75,8 @@ static DECLARE_WAIT_QUEUE_HEAD(tx_comp); + static DECLARE_WAIT_QUEUE_HEAD(tx_start); + static struct task_struct *tx_thread = NULL; + +-static struct timeval init_time; +-static struct timeval comp_time; ++static struct timespec64 init_time; ++static struct timespec64 comp_time; + static spinlock_t op_lock; + static nss_crypto_handle_t crypto_hdl; + +@@ -782,7 +782,7 @@ static int crypto_bench_tx(void *arg) + crypto_bench_debug("#"); + + /* get start time */ +- do_gettimeofday(&init_time); ++ ktime_get_real_ts64(&init_time); + + /** + * Request submission +@@ -812,8 +812,8 @@ static int crypto_bench_tx(void *arg) + * Calculate time and output the Mbps + */ + +- init_usecs = (init_time.tv_sec * 1000 * 1000) + init_time.tv_usec; +- comp_usecs = (comp_time.tv_sec * 1000 * 1000) + comp_time.tv_usec; ++ init_usecs = (init_time.tv_sec * 1000 * 1000) + (init_time.tv_nsec / NSEC_PER_USEC); ++ comp_usecs = (comp_time.tv_sec * 1000 * 1000) + (comp_time.tv_nsec / NSEC_PER_USEC); + delta_usecs = comp_usecs - init_usecs; + + reqs_completed = param.num_reqs - atomic_read(&tx_reqs); +@@ -870,7 +870,7 @@ static void crypto_bench_done(struct nss + nss_crypto_buf_free(crypto_hdl, buf); + + if (atomic_dec_and_test(&tx_reqs)) { +- do_gettimeofday(&comp_time); ++ ktime_get_real_ts64(&comp_time); + + wake_up_interruptible(&tx_comp); + param.num_loops--; diff --git a/root/package/qca/nss/qca-nss-crypto/patches/200-fix-NULL-pointer-exception.patch b/root/package/qca/nss/qca-nss-crypto/patches/200-fix-NULL-pointer-exception.patch new file mode 100644 index 00000000..6bd95109 --- /dev/null +++ b/root/package/qca/nss/qca-nss-crypto/patches/200-fix-NULL-pointer-exception.patch @@ -0,0 +1,57 @@ +--- a/v1.0/src/nss_crypto_if.c ++++ b/v1.0/src/nss_crypto_if.c +@@ -370,15 +370,16 @@ void nss_crypto_transform_done(struct ne + struct nss_crypto_buf *buf = (struct nss_crypto_buf *)skb->data; + struct nss_crypto_buf_node *entry; + void *addr; ++ struct device *cdev = gbl_crypto_ctrl.eng[0].dev; + + if (likely(buf->data_in == buf->data_out)) { +- dma_unmap_single(NULL, buf->data_in, buf->data_len, DMA_BIDIRECTIONAL); ++ dma_unmap_single(cdev, buf->data_in, buf->data_len, DMA_BIDIRECTIONAL); + } else { +- dma_unmap_single(NULL, buf->data_in, buf->data_len, DMA_TO_DEVICE); +- dma_unmap_single(NULL, buf->data_out, buf->data_len, DMA_FROM_DEVICE); ++ dma_unmap_single(cdev, buf->data_in, buf->data_len, DMA_TO_DEVICE); ++ dma_unmap_single(cdev, buf->data_out, buf->data_len, DMA_FROM_DEVICE); + } + +- dma_unmap_single(NULL, buf->iv_addr, L1_CACHE_BYTES, DMA_BIDIRECTIONAL); ++ dma_unmap_single(cdev, buf->iv_addr, L1_CACHE_BYTES, DMA_BIDIRECTIONAL); + + addr = phys_to_virt(buf->iv_addr); + entry = container_of(addr, struct nss_crypto_buf_node, results); +@@ -531,6 +532,7 @@ nss_crypto_status_t nss_crypto_transform + uint32_t paddr; + void *vaddr; + size_t len; ++ struct device *cdev = gbl_crypto_ctrl.eng[0].dev; + + if (!buf->cb_fn) { + nss_crypto_warn("%p:no buffer(%p) callback present\n", crypto, buf); +@@ -544,7 +546,7 @@ nss_crypto_status_t nss_crypto_transform + */ + vaddr = (void *)buf->data_in; + len = buf->data_len; +- paddr = dma_map_single(NULL, vaddr, len, DMA_TO_DEVICE); ++ paddr = dma_map_single(cdev, vaddr, len, DMA_TO_DEVICE); + buf->data_in = paddr; + + if (vaddr == (void *)buf->data_out) { +@@ -555,14 +557,14 @@ nss_crypto_status_t nss_crypto_transform + */ + vaddr = (void *)buf->data_out; + len = buf->data_len; +- paddr = dma_map_single(NULL, vaddr, len, DMA_FROM_DEVICE); ++ paddr = dma_map_single(cdev, vaddr, len, DMA_FROM_DEVICE); + buf->data_out = paddr; + } + + /* + * We need to map the results into IV + */ +- paddr = dma_map_single(NULL, entry->results, L1_CACHE_BYTES, DMA_BIDIRECTIONAL); ++ paddr = dma_map_single(cdev, entry->results, L1_CACHE_BYTES, DMA_BIDIRECTIONAL); + buf->hash_addr = paddr; + buf->iv_addr = paddr; + diff --git a/root/package/qca/nss/qca-nss-dp/Makefile b/root/package/qca/nss/qca-nss-dp/Makefile new file mode 100644 index 00000000..8da7d314 --- /dev/null +++ b/root/package/qca/nss/qca-nss-dp/Makefile @@ -0,0 +1,62 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=qca-nss-dp +PKG_RELEASE:=$(AUTORELEASE) + +PKG_SOURCE_URL:=https://source.codeaurora.org/quic/cc-qrdk/oss/lklm/nss-dp +PKG_SOURCE_PROTO:=git +PKG_SOURCE_DATE:=2021-03-26 +PKG_SOURCE_VERSION:=e0c89348d5ad99559ce2fbe15d37b3b5bc66aa03 +PKG_MIRROR_HASH:=f369f0c3b33b5f4ad6d0a6ad6ac5495f63c9ecaf94e4e7fa345169f3e44fcf45 + +PKG_BUILD_PARALLEL:=1 + +include $(INCLUDE_DIR)/kernel.mk +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/qca-nss-dp + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + DEPENDS:=@(TARGET_ipq807x||TARGET_ipq60xx) +kmod-qca-ssdk-nohnat + TITLE:=Kernel driver for NSS data plane + FILES:=$(PKG_BUILD_DIR)/qca-nss-dp.ko + AUTOLOAD:=$(call AutoLoad,31,qca-nss-dp) +endef + +define KernelPackage/qca-nss-dp/Description +This package contains a NSS data plane driver for QCA chipset +endef + +define Build/InstallDev + mkdir -p $(1)/usr/include/qca-nss-dp + $(CP) $(PKG_BUILD_DIR)/exports/* $(1)/usr/include/qca-nss-dp/ +endef + +EXTRA_CFLAGS+= \ + -I$(STAGING_DIR)/usr/include/qca-ssdk + +NSS_DP_HAL_DIR:=$(PKG_BUILD_DIR)/hal +define Build/Configure + $(LN) $(NSS_DP_HAL_DIR)/arch/$(CONFIG_TARGET_BOARD)/nss_$(CONFIG_TARGET_BOARD).h \ + $(PKG_BUILD_DIR)/exports/nss_dp_arch.h +endef + +ifeq ($(CONFIG_TARGET_BOARD), "ipq807x") + SOC="ipq807x_64" +else ifeq ($(CONFIG_TARGET_BOARD), "ipq60xx") + SOC="ipq60xx_64" +endif + +define Build/Compile + +$(MAKE) -C "$(LINUX_DIR)" \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + ARCH="$(LINUX_KARCH)" \ + M="$(PKG_BUILD_DIR)" \ + EXTRA_CFLAGS="$(EXTRA_CFLAGS)" SoC="$(SOC)" \ + $(KERNEL_MAKE_FLAGS) \ + $(PKG_JOBS) \ + modules +endef + +$(eval $(call KernelPackage,qca-nss-dp)) diff --git a/root/package/qca/nss/qca-nss-dp/patches/0001-edma_tx_rx-support-newer-kernels-time-stamping-API.patch b/root/package/qca/nss/qca-nss-dp/patches/0001-edma_tx_rx-support-newer-kernels-time-stamping-API.patch new file mode 100644 index 00000000..15f6caa4 --- /dev/null +++ b/root/package/qca/nss/qca-nss-dp/patches/0001-edma_tx_rx-support-newer-kernels-time-stamping-API.patch @@ -0,0 +1,44 @@ +From 40979666b4371012405715ffa61ab5760fcdc6b3 Mon Sep 17 00:00:00 2001 +Message-Id: <40979666b4371012405715ffa61ab5760fcdc6b3.1620066716.git.baruch@tkos.co.il> +From: Baruch Siach +Date: Mon, 3 May 2021 20:07:36 +0300 +Subject: [PATCH 1/3] edma_tx_rx: support newer kernels time stamping API + +--- + hal/edma/edma_tx_rx.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/hal/edma/edma_tx_rx.c ++++ b/hal/edma/edma_tx_rx.c +@@ -226,10 +226,16 @@ void nss_phy_tstamp_rx_buf(__attribute__ + * set to the correct PTP class value by calling ptp_classify_raw + * in drv->rxtstamp function. + */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 6, 0)) + if (ndev && ndev->phydev && ndev->phydev->drv && + ndev->phydev->drv->rxtstamp) + if(ndev->phydev->drv->rxtstamp(ndev->phydev, skb, 0)) + return; ++#else ++ if (ndev && phy_has_rxtstamp(ndev->phydev)) ++ if (phy_rxtstamp(ndev->phydev, skb, 0)) ++ return; ++#endif + + netif_receive_skb(skb); + } +@@ -247,9 +253,14 @@ void nss_phy_tstamp_tx_buf(struct net_de + * set to the correct PTP class value by calling ptp_classify_raw + * in the drv->txtstamp function. + */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 6, 0)) + if (ndev && ndev->phydev && ndev->phydev->drv && + ndev->phydev->drv->txtstamp) + ndev->phydev->drv->txtstamp(ndev->phydev, skb, 0); ++#else ++ if (ndev && phy_has_txtstamp(ndev->phydev)) ++ phy_rxtstamp(ndev->phydev, skb, 0); ++#endif + } + EXPORT_SYMBOL(nss_phy_tstamp_tx_buf); + diff --git a/root/package/qca/nss/qca-nss-dp/patches/0002-nss_dp_main-make-phy-mode-code-compatible-with-newer.patch b/root/package/qca/nss/qca-nss-dp/patches/0002-nss_dp_main-make-phy-mode-code-compatible-with-newer.patch new file mode 100644 index 00000000..a3305dd3 --- /dev/null +++ b/root/package/qca/nss/qca-nss-dp/patches/0002-nss_dp_main-make-phy-mode-code-compatible-with-newer.patch @@ -0,0 +1,48 @@ +From cef7873a2d77df13ee702d902ed4e06b2248904b Mon Sep 17 00:00:00 2001 +Message-Id: +In-Reply-To: <40979666b4371012405715ffa61ab5760fcdc6b3.1620066716.git.baruch@tkos.co.il> +References: <40979666b4371012405715ffa61ab5760fcdc6b3.1620066716.git.baruch@tkos.co.il> +From: Baruch Siach +Date: Mon, 3 May 2021 20:17:22 +0300 +Subject: [PATCH 2/3] nss_dp_main: make phy mode code compatible with newer + kernels + +--- + include/nss_dp_dev.h | 4 ++-- + nss_dp_main.c | 4 ++++ + 2 files changed, 6 insertions(+), 2 deletions(-) + +--- a/include/nss_dp_dev.h ++++ b/include/nss_dp_dev.h +@@ -25,7 +25,7 @@ + #include + #include + #include +-#include ++#include + + #include "nss_dp_api_if.h" + #include "nss_dp_hal_if.h" +@@ -46,7 +46,7 @@ struct nss_dp_dev { + /* Phy related stuff */ + struct phy_device *phydev; /* Phy device */ + struct mii_bus *miibus; /* MII bus */ +- uint32_t phy_mii_type; /* RGMII/SGMII/QSGMII */ ++ phy_interface_t phy_mii_type; /* RGMII/SGMII/QSGMII */ + uint32_t phy_mdio_addr; /* Mdio address */ + bool link_poll; /* Link polling enable? */ + uint32_t forced_speed; /* Forced speed? */ +--- a/nss_dp_main.c ++++ b/nss_dp_main.c +@@ -463,7 +463,11 @@ static int32_t nss_dp_of_get_pdata(struc + hal_pdata->netdev = netdev; + hal_pdata->macid = dp_priv->macid; + ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 5, 0)) + dp_priv->phy_mii_type = of_get_phy_mode(np); ++#else ++ of_get_phy_mode(np, &dp_priv->phy_mii_type); ++#endif + dp_priv->link_poll = of_property_read_bool(np, "qcom,link-poll"); + if (of_property_read_u32(np, "qcom,phy-mdio-addr", + &dp_priv->phy_mdio_addr) && dp_priv->link_poll) { diff --git a/root/package/qca/nss/qca-nss-dp/patches/0003-Drop-_nocache-variants-of-ioremap.patch b/root/package/qca/nss/qca-nss-dp/patches/0003-Drop-_nocache-variants-of-ioremap.patch new file mode 100644 index 00000000..3139d349 --- /dev/null +++ b/root/package/qca/nss/qca-nss-dp/patches/0003-Drop-_nocache-variants-of-ioremap.patch @@ -0,0 +1,48 @@ +From c8c52512ff48bee578901c381a42f027e79eadf9 Mon Sep 17 00:00:00 2001 +Message-Id: +In-Reply-To: <40979666b4371012405715ffa61ab5760fcdc6b3.1620066716.git.baruch@tkos.co.il> +References: <40979666b4371012405715ffa61ab5760fcdc6b3.1620066716.git.baruch@tkos.co.il> +From: Baruch Siach +Date: Mon, 3 May 2021 20:20:29 +0300 +Subject: [PATCH 3/3] Drop _nocache variants of ioremap() + +Recent kernels removed them. +--- + hal/edma/edma_data_plane.c | 2 +- + hal/gmac_hal_ops/qcom/qcom_if.c | 2 +- + hal/gmac_hal_ops/syn/xgmac/syn_if.c | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +--- a/hal/edma/edma_data_plane.c ++++ b/hal/edma/edma_data_plane.c +@@ -797,7 +797,7 @@ int edma_init(void) + /* + * Remap register resource + */ +- edma_hw.reg_base = ioremap_nocache((edma_hw.reg_resource)->start, ++ edma_hw.reg_base = ioremap((edma_hw.reg_resource)->start, + resource_size(edma_hw.reg_resource)); + if (!edma_hw.reg_base) { + pr_warn("Unable to remap EDMA register memory.\n"); +--- a/hal/gmac_hal_ops/qcom/qcom_if.c ++++ b/hal/gmac_hal_ops/qcom/qcom_if.c +@@ -400,7 +400,7 @@ static void *qcom_init(struct gmac_hal_p + qhd->nghd.mac_id = gmacpdata->macid; + + /* Populate the mac base addresses */ +- qhd->nghd.mac_base = devm_ioremap_nocache(&dp_priv->pdev->dev, ++ qhd->nghd.mac_base = devm_ioremap(&dp_priv->pdev->dev, + res->start, resource_size(res)); + if (!qhd->nghd.mac_base) { + netdev_dbg(ndev, "ioremap fail.\n"); +--- a/hal/gmac_hal_ops/syn/xgmac/syn_if.c ++++ b/hal/gmac_hal_ops/syn/xgmac/syn_if.c +@@ -422,7 +422,7 @@ static void *syn_init(struct gmac_hal_pl + + /* Populate the mac base addresses */ + shd->nghd.mac_base = +- devm_ioremap_nocache(&dp_priv->pdev->dev, res->start, ++ devm_ioremap(&dp_priv->pdev->dev, res->start, + resource_size(res)); + if (!shd->nghd.mac_base) { + netdev_dbg(ndev, "ioremap fail.\n"); diff --git a/root/package/qca/nss/qca-nss-dp/patches/0004-EDMA-Fix-NAPI-packet-counting.patch b/root/package/qca/nss/qca-nss-dp/patches/0004-EDMA-Fix-NAPI-packet-counting.patch new file mode 100644 index 00000000..eb57fe90 --- /dev/null +++ b/root/package/qca/nss/qca-nss-dp/patches/0004-EDMA-Fix-NAPI-packet-counting.patch @@ -0,0 +1,31 @@ +From d74920e2a7c413ef40eed72f9cf287cf6fbd5fb8 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Thu, 20 May 2021 14:56:46 +0200 +Subject: [PATCH 1/2] EDMA: Fix NAPI packet counting + +There is a bug in the NAPI packet counting that will +cause NAPI over budget warnings. + +Signed-off-by: Baruch Siach +Signed-off-by: Robert Marko +--- + hal/edma/edma_tx_rx.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/hal/edma/edma_tx_rx.c ++++ b/hal/edma/edma_tx_rx.c +@@ -458,12 +458,12 @@ int edma_napi(struct napi_struct *napi, + + for (i = 0; i < ehw->txcmpl_rings; i++) { + txcmpl_ring = &ehw->txcmpl_ring[i]; +- work_done += edma_clean_tx(ehw, txcmpl_ring); ++ edma_clean_tx(ehw, txcmpl_ring); + } + + for (i = 0; i < ehw->rxfill_rings; i++) { + rxfill_ring = &ehw->rxfill_ring[i]; +- work_done += edma_alloc_rx_buffer(ehw, rxfill_ring); ++ edma_alloc_rx_buffer(ehw, rxfill_ring); + } + + /* diff --git a/root/package/qca/nss/qca-nss-dp/patches/0005-EDMA-Use-NAPI_POLL_WEIGHT-as-NAPI-weight.patch b/root/package/qca/nss/qca-nss-dp/patches/0005-EDMA-Use-NAPI_POLL_WEIGHT-as-NAPI-weight.patch new file mode 100644 index 00000000..f231c514 --- /dev/null +++ b/root/package/qca/nss/qca-nss-dp/patches/0005-EDMA-Use-NAPI_POLL_WEIGHT-as-NAPI-weight.patch @@ -0,0 +1,41 @@ +From 44a30d94abcbb10aacc21db29be212518a6b1bf7 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Thu, 20 May 2021 14:57:46 +0200 +Subject: [PATCH] EDMA: Use NAPI_POLL_WEIGHT as NAPI weight + +Currently a weight of 100 is used by the EDMA, according +to upstream max of 64 should be used and that is used for +almost any driver. + +They also introduced NAPI_POLL_WEIGHT define which equals +to 64. + +So use NAPI_POLL_WEIGHT as the weight. + +Signed-off-by: Robert Marko +--- + hal/edma/edma_data_plane.c | 2 +- + hal/edma/edma_data_plane.h | 1 - + 2 files changed, 1 insertion(+), 2 deletions(-) + +--- a/hal/edma/edma_data_plane.c ++++ b/hal/edma/edma_data_plane.c +@@ -582,7 +582,7 @@ static int edma_register_netdevice(struc + */ + if (!edma_hw.napi_added) { + netif_napi_add(netdev, &edma_hw.napi, edma_napi, +- EDMA_NAPI_WORK); ++ NAPI_POLL_WEIGHT); + /* + * Register the interrupt handlers and enable interrupts + */ +--- a/hal/edma/edma_data_plane.h ++++ b/hal/edma/edma_data_plane.h +@@ -27,7 +27,6 @@ + #define EDMA_RX_PREHDR_SIZE (sizeof(struct edma_rx_preheader)) + #define EDMA_TX_PREHDR_SIZE (sizeof(struct edma_tx_preheader)) + #define EDMA_RING_SIZE 128 +-#define EDMA_NAPI_WORK 100 + #define EDMA_START_GMACS NSS_DP_START_IFNUM + #define EDMA_MAX_GMACS NSS_DP_HAL_MAX_PORTS + #define EDMA_TX_PKT_MIN_SIZE 33 /* IPQ807x EDMA needs a minimum packet size of 33 bytes */ diff --git a/root/package/qca/nss/qca-nss-dp/patches/0006-NSS-DP-fix-of_get_mac_address.patch b/root/package/qca/nss/qca-nss-dp/patches/0006-NSS-DP-fix-of_get_mac_address.patch new file mode 100644 index 00000000..d4965716 --- /dev/null +++ b/root/package/qca/nss/qca-nss-dp/patches/0006-NSS-DP-fix-of_get_mac_address.patch @@ -0,0 +1,50 @@ +From cadeb62a42296563141d6954eec58e34ef86778d Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 13 Aug 2021 20:12:08 +0200 +Subject: [PATCH] NSS-DP: fix of_get_mac_address() + +Recently OpenWrt backported the updated of_get_mac_address() +function which returns and error code instead. + +So, patch the SSDK to use it and fix the compilation error. + +Signed-off-by: Robert Marko +--- + nss_dp_main.c | 13 ++++--------- + 1 file changed, 4 insertions(+), 9 deletions(-) + +diff --git a/nss_dp_main.c b/nss_dp_main.c +index 5580b13..28df280 100644 +--- a/nss_dp_main.c ++++ b/nss_dp_main.c +@@ -434,9 +434,10 @@ static int32_t nss_dp_of_get_pdata(struct device_node *np, + struct net_device *netdev, + struct gmac_hal_platform_data *hal_pdata) + { +- uint8_t *maddr; ++ u8 maddr[ETH_ALEN]; + struct nss_dp_dev *dp_priv; + struct resource memres_devtree = {0}; ++ int ret; + + dp_priv = netdev_priv(netdev); + +@@ -475,14 +476,8 @@ static int32_t nss_dp_of_get_pdata(struct device_node *np, + of_property_read_u32(np, "qcom,forced-speed", &dp_priv->forced_speed); + of_property_read_u32(np, "qcom,forced-duplex", &dp_priv->forced_duplex); + +- maddr = (uint8_t *)of_get_mac_address(np); +-#if (LINUX_VERSION_CODE > KERNEL_VERSION(5, 4, 0)) +- if (IS_ERR((void *)maddr)) { +- maddr = NULL; +- } +-#endif +- +- if (maddr && is_valid_ether_addr(maddr)) { ++ ret = of_get_mac_address(np, maddr); ++ if (!ret && is_valid_ether_addr(maddr)) { + ether_addr_copy(netdev->dev_addr, maddr); + } else { + random_ether_addr(netdev->dev_addr); +-- +2.31.1 diff --git a/root/package/qca/nss/qca-nss-dp/patches/0007-NSS-DP-implement-ethernet-IOCTL-s.patch b/root/package/qca/nss/qca-nss-dp/patches/0007-NSS-DP-implement-ethernet-IOCTL-s.patch new file mode 100644 index 00000000..824f1863 --- /dev/null +++ b/root/package/qca/nss/qca-nss-dp/patches/0007-NSS-DP-implement-ethernet-IOCTL-s.patch @@ -0,0 +1,29 @@ +From 5da62ba19f554bf437752a44360fb5ae9f1a7f5e Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Tue, 8 Mar 2022 10:48:32 +0100 +Subject: [PATCH] NSS-DP: implement ethernet IOCTL-s + +Since kernel 5.15 ethernet/PHY related IOCTL-s have been split from the +generic IOCTL netdev op. +So, implement the new op instead of the generic one which is considered +for private IOCTL-s only now for 5.15+. + +Signed-off-by: Robert Marko +--- + nss_dp_main.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/nss_dp_main.c ++++ b/nss_dp_main.c +@@ -532,7 +532,11 @@ static const struct net_device_ops nss_d + .ndo_set_mac_address = nss_dp_set_mac_address, + .ndo_validate_addr = eth_validate_addr, + .ndo_change_mtu = nss_dp_change_mtu, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)) + .ndo_do_ioctl = nss_dp_do_ioctl, ++#else ++ .ndo_eth_ioctl = nss_dp_do_ioctl, ++#endif + + #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0)) + .ndo_bridge_setlink = switchdev_port_bridge_setlink, diff --git a/root/package/qca/nss/qca-nss-dp/patches/0008-switchdev-remove-the-transaction-structure.patch b/root/package/qca/nss/qca-nss-dp/patches/0008-switchdev-remove-the-transaction-structure.patch new file mode 100644 index 00000000..220be961 --- /dev/null +++ b/root/package/qca/nss/qca-nss-dp/patches/0008-switchdev-remove-the-transaction-structure.patch @@ -0,0 +1,48 @@ +From c9afdcdd2642485a6476906be9da2e811090fc7a Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 18 Mar 2022 18:06:03 +0100 +Subject: [PATCH] switchdev: remove the transaction structure + +Since 5.12 there is no transaction structure anymore, so drop it for +5.12 and newer. + +Signed-off-by: Robert Marko +--- + nss_dp_switchdev.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/nss_dp_switchdev.c ++++ b/nss_dp_switchdev.c +@@ -279,13 +279,19 @@ void nss_dp_switchdev_setup(struct net_d + * Sets attributes + */ + static int nss_dp_port_attr_set(struct net_device *dev, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0)) + const struct switchdev_attr *attr, + struct switchdev_trans *trans) ++#else ++ const struct switchdev_attr *attr) ++#endif + { + struct nss_dp_dev *dp_priv = (struct nss_dp_dev *)netdev_priv(dev); + ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0)) + if (switchdev_trans_ph_prepare(trans)) + return 0; ++#endif + + switch (attr->id) { + case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: +@@ -309,8 +315,12 @@ static int nss_dp_switchdev_port_attr_se + { + int err; + ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0)) + err = nss_dp_port_attr_set(netdev, port_attr_info->attr, + port_attr_info->trans); ++#else ++ err = nss_dp_port_attr_set(netdev, port_attr_info->attr); ++#endif + + port_attr_info->handled = true; + return notifier_from_errno(err); diff --git a/root/package/qca/nss/qca-nss-dp/patches/0009-switchdev-use-new-switchdev-flags.patch b/root/package/qca/nss/qca-nss-dp/patches/0009-switchdev-use-new-switchdev-flags.patch new file mode 100644 index 00000000..5635dd96 --- /dev/null +++ b/root/package/qca/nss/qca-nss-dp/patches/0009-switchdev-use-new-switchdev-flags.patch @@ -0,0 +1,54 @@ +From f95868d54301c0f54e968ec9d978c9caa02ee425 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 18 Mar 2022 18:24:18 +0100 +Subject: [PATCH] switchdev: use new switchdev flags + +Since kernel 5.12 switched utilizes a new way of setting the flags by +using a dedicated structure with flags and mask. + +So fix using kernels 5.12 and later. + +Signed-off-by: Robert Marko +--- + include/nss_dp_dev.h | 7 +++++++ + nss_dp_switchdev.c | 2 +- + 2 files changed, 8 insertions(+), 1 deletion(-) + +--- a/include/nss_dp_dev.h ++++ b/include/nss_dp_dev.h +@@ -24,6 +24,9 @@ + #include + #include + #include ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)) ++#include ++#endif + + #include "nss_dp_api_if.h" + #include "nss_dp_hal_if.h" +@@ -126,7 +129,11 @@ struct nss_dp_dev { + /* switchdev related attributes */ + #ifdef CONFIG_NET_SWITCHDEV + u8 stp_state; /* STP state of this physical port */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0)) + unsigned long brport_flags; /* bridge port flags */ ++#else ++ struct switchdev_brport_flags brport_flags; /* bridge port flags */ ++#endif + #endif + uint32_t rx_page_mode; /* page mode for Rx processing */ + uint32_t rx_jumbo_mru; /* Jumbo mru value for Rx processing */ +--- a/nss_dp_switchdev.c ++++ b/nss_dp_switchdev.c +@@ -296,7 +296,11 @@ static int nss_dp_port_attr_set(struct n + switch (attr->id) { + case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: + dp_priv->brport_flags = attr->u.brport_flags; ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0)) + netdev_dbg(dev, "set brport_flags %lu\n", attr->u.brport_flags); ++#else ++ netdev_dbg(dev, "set brport_flags %lu\n", attr->u.brport_flags.val); ++#endif + return 0; + case SWITCHDEV_ATTR_ID_PORT_STP_STATE: + return nss_dp_stp_state_set(dp_priv, attr->u.stp_state); diff --git a/root/package/qca/nss/qca-nss-dp/patches/0010-switchdev-fix-FDB-roaming.patch b/root/package/qca/nss/qca-nss-dp/patches/0010-switchdev-fix-FDB-roaming.patch new file mode 100644 index 00000000..19395ac4 --- /dev/null +++ b/root/package/qca/nss/qca-nss-dp/patches/0010-switchdev-fix-FDB-roaming.patch @@ -0,0 +1,110 @@ +From d16102cad769f430144ca8094d928762b445e9b0 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 18 Mar 2022 22:02:01 +0100 +Subject: [PATCH] switchdev: fix FDB roaming + +Try and solve the roaming issue by trying to replicate what NSS bridge +module is doing, but by utilizing switchdev FDB notifiers instead of +adding new notifiers to the bridge code. + +We register a new non-blocking switchdev notifier and simply wait for +notification, and then process the SWITCHDEV_FDB_DEL_TO_DEVICE +notifications. + +Those tell us that a certain FDB entry should be removed, then a VSI ID +is fetched for the physical PPE port and using that VSI ID and the +notification provided MAC adress existing FDB entry gets removed. + +Signed-off-by: Robert Marko +--- + nss_dp_switchdev.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 61 insertions(+) + +--- a/nss_dp_switchdev.c ++++ b/nss_dp_switchdev.c +@@ -24,6 +24,8 @@ + #include "nss_dp_dev.h" + #include "fal/fal_stp.h" + #include "fal/fal_ctrlpkt.h" ++#include "fal/fal_fdb.h" ++#include "ref/ref_vsi.h" + + #define NSS_DP_SWITCH_ID 0 + #define NSS_DP_SW_ETHTYPE_PID 0 /* PPE ethtype profile ID for slow protocols */ +@@ -348,10 +350,64 @@ static int nss_dp_switchdev_event(struct + return NOTIFY_DONE; + } + ++static int nss_dp_switchdev_fdb_del_event(struct net_device *netdev, ++ struct switchdev_notifier_fdb_info *fdb_info) ++{ ++ struct nss_dp_dev *dp_priv = (struct nss_dp_dev *)netdev_priv(netdev); ++ fal_fdb_entry_t entry; ++ a_uint32_t vsi_id; ++ sw_error_t rv; ++ ++ netdev_dbg(netdev, "FDB DEL %pM port %d\n", fdb_info->addr, dp_priv->macid); ++ ++ rv = ppe_port_vsi_get(NSS_DP_SWITCH_ID, dp_priv->macid, &vsi_id); ++ if (rv) { ++ netdev_err(netdev, "cannot get VSI ID for port %d\n", dp_priv->macid); ++ return notifier_from_errno(rv); ++ } ++ ++ memset(&entry, 0, sizeof(entry)); ++ memcpy(&entry.addr, fdb_info->addr, ETH_ALEN); ++ entry.fid = vsi_id; ++ ++ rv = fal_fdb_entry_del_bymac(NSS_DP_SWITCH_ID, &entry); ++ if (rv) { ++ netdev_err(netdev, "FDB entry delete failed with MAC %pM and fid %d\n", ++ &entry.addr, entry.fid); ++ return notifier_from_errno(rv); ++ } ++ ++ return notifier_from_errno(rv); ++} ++ ++static int nss_dp_fdb_switchdev_event(struct notifier_block *nb, ++ unsigned long event, void *ptr) ++{ ++ struct net_device *dev = switchdev_notifier_info_to_dev(ptr); ++ ++ /* ++ * Handle switchdev event only for physical devices ++ */ ++ if (!nss_dp_is_phy_dev(dev)) { ++ return NOTIFY_DONE; ++ } ++ ++ switch (event) { ++ case SWITCHDEV_FDB_DEL_TO_DEVICE: ++ return nss_dp_switchdev_fdb_del_event(dev, ptr); ++ } ++ ++ return NOTIFY_DONE; ++} ++ + static struct notifier_block nss_dp_switchdev_notifier = { + .notifier_call = nss_dp_switchdev_event, + }; + ++static struct notifier_block nss_dp_switchdev_fdb_notifier = { ++ .notifier_call = nss_dp_fdb_switchdev_event, ++}; ++ + static bool switch_init_done; + + /* +@@ -366,6 +422,11 @@ void nss_dp_switchdev_setup(struct net_d + return; + } + ++ err = register_switchdev_notifier(&nss_dp_switchdev_fdb_notifier); ++ if (err) { ++ netdev_dbg(dev, "%px:Failed to register switchdev FDB notifier\n", dev); ++ } ++ + err = register_switchdev_blocking_notifier(&nss_dp_switchdev_notifier); + if (err) { + netdev_dbg(dev, "%px:Failed to register switchdev notifier\n", dev); diff --git a/root/package/qca/nss/qca-nss-dp/patches/0011-treewide-fix-confusing-printing-of-registered-netdev.patch b/root/package/qca/nss/qca-nss-dp/patches/0011-treewide-fix-confusing-printing-of-registered-netdev.patch new file mode 100644 index 00000000..6c3d68f7 --- /dev/null +++ b/root/package/qca/nss/qca-nss-dp/patches/0011-treewide-fix-confusing-printing-of-registered-netdev.patch @@ -0,0 +1,31 @@ +From 7e4ae2d6285095794d73d2f2ce61404f61d4e633 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Tue, 17 May 2022 15:55:36 +0200 +Subject: [PATCH 11/11] treewide: fix confusing printing of registered netdev + +Net core implementation changed and now printing the netdev name cause +confusing printing if done before register_netdev. Move the old printing +to dbg and add an additional info log right after register_netdev to +give the user some info on correct nss-dp probe. + +Signed-off-by: Ansuel Smith +--- + nss_dp_main.c | 3 +++ + 1 files changed, 3 insertions(+), 0 deletions(-) + +diff --git a/nss_dp_main.c b/nss_dp_main.c +index c0ae9d6..441c300 100644 +--- a/nss_dp_main.c ++++ b/nss_dp_main.c +@@ -875,6 +875,9 @@ static int32_t nss_dp_probe(struct platform_device *pdev) + goto phy_setup_fail; + } + ++ netdev_info(netdev, "Registered netdev %s(qcom-id:%d)\n", ++ netdev->name, port_id); ++ + dp_global_ctx.nss_dp[dp_priv->macid - 1] = dp_priv; + dp_global_ctx.slowproto_acl_bm = 0; + +-- +2.34.1 diff --git a/root/package/qca/nss/qca-nss-drv-64/Makefile b/root/package/qca/nss/qca-nss-drv-64/Makefile new file mode 100644 index 00000000..ac73475f --- /dev/null +++ b/root/package/qca/nss/qca-nss-drv-64/Makefile @@ -0,0 +1,121 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=qca-nss-drv-64 +PKG_RELEASE:=$(AUTORELEASE) + +PKG_SOURCE_URL:=https://source.codeaurora.org/quic/qsdk/oss/lklm/nss-drv +PKG_SOURCE_PROTO:=git +PKG_SOURCE_DATE:=2021-04-26 +PKG_SOURCE_VERSION:=1cf4bf81fd395f61648efeae78cdf1df60e954ff +PKG_MIRROR_HASH:=3dd84a548a530188021fd4dab54ca4e1eb9056ca77381b24f587365fc7c16f21 + +PKG_BUILD_PARALLEL:=1 + +include $(INCLUDE_DIR)/kernel.mk +include $(INCLUDE_DIR)/package.mk + +NSS_CLIENTS_DIR:=$(TOPDIR)/qca/src/qca-nss-clients + +define KernelPackage/qca-nss-drv-64 + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + DEPENDS:=@(TARGET_ipq807x||TARGET_ipq60xx) +kmod-qca-nss-dp + TITLE:=Kernel driver for NSS (core driver) + FILES:=$(PKG_BUILD_DIR)/qca-nss-drv.ko + AUTOLOAD:=$(call AutoLoad,32,qca-nss-drv) +endef + +define KernelPackage/qca-nss-drv-64/install + $(INSTALL_DIR) $(1)/lib/debug + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_DIR) $(1)/etc/sysctl.d + $(INSTALL_DIR) $(1)/etc/hotplug.d/firmware + $(INSTALL_DIR) $(1)/etc/config + + $(INSTALL_BIN) ./files/qca-nss-drv.debug $(1)/lib/debug/qca-nss-drv + $(INSTALL_BIN) ./files/qca-nss-drv.init $(1)/etc/init.d/qca-nss-drv + $(INSTALL_BIN) ./files/qca-nss-drv.sysctl $(1)/etc/sysctl.d/qca-nss-drv.conf + $(INSTALL_BIN) ./files/qca-nss-drv.hotplug $(1)/etc/hotplug.d/firmware/10-qca-nss-fw + $(INSTALL_BIN) ./files/qca-nss-drv.conf $(1)/etc/config/nss + +endef + +define KernelPackage/qca-nss-drv-64/Description +This package contains a NSS driver for QCA chipset +endef + +define Build/InstallDev + mkdir -p $(1)/usr/include/qca-nss-drv + $(CP) $(PKG_BUILD_DIR)/exports/* $(1)/usr/include/qca-nss-drv/ +endef + +EXTRA_CFLAGS+= -I$(STAGING_DIR)/usr/include/qca-nss-gmac -I$(STAGING_DIR)/usr/include/qca-nss-dp -I$(STAGING_DIR)/usr/include/qca-ssdk + +ifneq (, $(findstring $(CONFIG_TARGET_BOARD), "ipq807x" "ipq60xx")) +EXTRA_CFLAGS+= -DNSS_MEM_PROFILE_MEDIUM +LOW_MEM_PROFILE_MAKE_OPTS=y +endif + +ifeq ($(CONFIG_KERNEL_SKB_FIXED_SIZE_2K),y) +EXTRA_CFLAGS+= -DNSS_SKB_FIXED_SIZE_2K +endif + +DRV_MAKE_OPTS:= +ifeq ($(LOW_MEM_PROFILE_MAKE_OPTS),y) +DRV_MAKE_OPTS+=NSS_DRV_C2C_ENABLE=n \ + NSS_DRV_CAPWAP_ENABLE=n \ + NSS_DRV_CLMAP_ENABLE=n \ + NSS_DRV_CRYPTO_ENABLE=n \ + NSS_DRV_DTLS_ENABLE=n \ + NSS_DRV_GRE_ENABLE=n \ + NSS_DRV_GRE_REDIR_ENABLE=n \ + NSS_DRV_GRE_TUNNEL_ENABLE=n \ + NSS_DRV_IGS_ENABLE=n \ + NSS_DRV_IPSEC_ENABLE=n \ + NSS_DRV_LAG_ENABLE=n \ + NSS_DRV_L2TP_ENABLE=n \ + NSS_DRV_MAPT_ENABLE=n \ + NSS_DRV_OAM_ENABLE=n \ + NSS_DRV_PPTP_ENABLE=n \ + NSS_DRV_PORTID_ENABLE=n \ + NSS_DRV_PVXLAN_ENABLE=n \ + NSS_DRV_QRFS_ENABLE=n \ + NSS_DRV_QVPN_ENABLE=n \ + NSS_DRV_RMNET_ENABLE=n \ + NSS_DRV_SHAPER_ENABLE=n \ + NSS_DRV_SJACK_ENABLE=n \ + NSS_DRV_TLS_ENABLE=n \ + NSS_DRV_TRUSTSEC_ENABLE=n \ + NSS_DRV_TSTAMP_ENABLE=n \ + NSS_DRV_TUN6RD_ENABLE=n \ + NSS_DRV_TUNIPIP6_ENABLE=n \ + NSS_DRV_VXLAN_ENABLE=n \ + NSS_DRV_MATCH_ENABLE=n \ + NSS_DRV_MIRROR_ENABLE=n +endif + +ifeq ($(CONFIG_TARGET_BOARD), "ipq807x") + SOC="ipq807x_64" +else ifeq ($(CONFIG_TARGET_BOARD), "ipq60xx") + SOC="ipq60xx_64" +endif + +define Build/Configure + $(LN) arch/nss_$(SOC).h $(PKG_BUILD_DIR)/exports/nss_arch.h + sed -i "s/define NSS_FW_VERSION_MAJOR.*/define NSS_FW_VERSION_MAJOR 11/" $(PKG_BUILD_DIR)/exports/nss_fw_version.h + sed -i "s/define NSS_FW_VERSION_MINOR.*/define NSS_FW_VERSION_MINOR 3/" $(PKG_BUILD_DIR)/exports/nss_fw_version.h +endef + +define Build/Compile + +$(MAKE) -C "$(LINUX_DIR)" $(strip $(DRV_MAKE_OPTS)) \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + ARCH="$(LINUX_KARCH)" \ + M="$(PKG_BUILD_DIR)" \ + EXTRA_CFLAGS="$(EXTRA_CFLAGS)" SoC=$(SOC) \ + $(KERNEL_MAKE_FLAGS) \ + $(PKG_JOBS) \ + modules +endef + +$(eval $(call KernelPackage,qca-nss-drv-64)) diff --git a/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.conf b/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.conf new file mode 100644 index 00000000..a8a1fbf4 --- /dev/null +++ b/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.conf @@ -0,0 +1,6 @@ +config nss_firmware 'qca_nss_0' + +config nss_firmware 'qca_nss_1' + +config general + option enable_rps '1' diff --git a/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.debug b/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.debug new file mode 100644 index 00000000..5d435c3a --- /dev/null +++ b/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.debug @@ -0,0 +1,26 @@ +#!/bin/sh /sbin/sysdebug +# +# Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +log cat /sys/kernel/debug/qca-nss-drv/stats/pppoe +log cat /sys/kernel/debug/qca-nss-drv/stats/n2h +log cat /sys/kernel/debug/qca-nss-drv/stats/ipv6 +log cat /sys/kernel/debug/qca-nss-drv/stats/ipv4 +log cat /sys/kernel/debug/qca-nss-drv/stats/gmac +log cat /sys/kernel/debug/qca-nss-drv/stats/drv +log cat /sys/kernel/debug/qca-nss-drv/stats/wifi +log cat /sys/kernel/debug/qca-nss-drv/stats/wifi_if +log cat /sys/kernel/debug/qca-nss-drv/stats/eth_rx diff --git a/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.hotplug b/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.hotplug new file mode 100644 index 00000000..1e481383 --- /dev/null +++ b/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.hotplug @@ -0,0 +1,70 @@ +#!/bin/sh +# +# Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +KERNEL=`uname -r` +case "${KERNEL}" in + 3.4*) + select_or_load=load_nss_fw + ;; + *) + select_or_load=select_nss_fw + ;; +esac + +load_nss_fw () { + ls -l $1 | awk ' { print $9,$5 } '> /dev/console + echo 1 > /sys/class/firmware/$DEVICENAME/loading + cat $1 > /sys/class/firmware/$DEVICENAME/data + echo 0 > /sys/class/firmware/$DEVICENAME/loading +} + +select_nss_fw () { + rm -f /lib/firmware/$DEVICENAME + ln -s $1 /lib/firmware/$DEVICENAME + ls -l /lib/firmware/$DEVICENAME | awk ' { print $9,$5 } '> /dev/console +} + +[ "$ACTION" != "add" ] && exit + +# dev name for UCI, since it doesn't let you use . or - +SDEVNAME=$(echo ${DEVICENAME} | sed s/[.-]/_/g) + +SELECTED_FW=$(uci get nss.${SDEVNAME}.firmware 2>/dev/null) +[ -e "${SELECTED_FW}" ] && { + $select_or_load ${SELECTED_FW} + exit +} + +case $DEVICENAME in + qca-nss0* | qca-nss.0*) + if [ -e /lib/firmware/qca-nss0-enterprise.bin ] ; then + $select_or_load /lib/firmware/qca-nss0-enterprise.bin + else + $select_or_load /lib/firmware/qca-nss0-retail.bin + fi + exit + ;; + qca-nss1* | qca-nss.1*) + if [ -e /lib/firmware/qca-nss1-enterprise.bin ] ; then + $select_or_load /lib/firmware/qca-nss1-enterprise.bin + else + $select_or_load /lib/firmware/qca-nss1-retail.bin + fi + exit + ;; +esac + diff --git a/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.init b/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.init new file mode 100644 index 00000000..de12cb6d --- /dev/null +++ b/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.init @@ -0,0 +1,50 @@ +#!/bin/sh /etc/rc.common +# +# Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +START=70 + +enable_rps() { + irq_nss_rps=`grep nss_queue1 /proc/interrupts | cut -d ':' -f 1 | tr -d ' '` + for entry in $irq_nss_rps + do + echo 2 > /proc/irq/$entry/smp_affinity + done + + irq_nss_rps=`grep nss_queue2 /proc/interrupts | cut -d ':' -f 1 | tr -d ' '` + for entry in $irq_nss_rps + do + echo 4 > /proc/irq/$entry/smp_affinity + done + + irq_nss_rps=`grep nss_queue3 /proc/interrupts | cut -d ':' -f 1 | tr -d ' '` + for entry in $irq_nss_rps + do + echo 8 > /proc/irq/$entry/smp_affinity + done + + # Enable NSS RPS + sysctl -w dev.nss.rps.enable=1 >/dev/null 2>/dev/null + +} + + +start() { + local rps_enabled="$(uci_get nss @general[0] enable_rps)" + if [ "$rps_enabled" -eq 1 ]; then + enable_rps + fi +} diff --git a/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.sysctl b/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.sysctl new file mode 100644 index 00000000..fc36c33e --- /dev/null +++ b/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.sysctl @@ -0,0 +1,4 @@ +# Default Number of connection configuration +dev.nss.ipv4cfg.ipv4_conn=4096 +dev.nss.ipv6cfg.ipv6_conn=4096 + diff --git a/root/package/qca/nss/qca-nss-drv-64/patches/0001-core-add-5.10-kernel-to-version-check.patch b/root/package/qca/nss/qca-nss-drv-64/patches/0001-core-add-5.10-kernel-to-version-check.patch new file mode 100644 index 00000000..3fea9b5c --- /dev/null +++ b/root/package/qca/nss/qca-nss-drv-64/patches/0001-core-add-5.10-kernel-to-version-check.patch @@ -0,0 +1,25 @@ +From 3885c752e12f74cad6c97888b797e5903ad1930d Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Thu, 13 May 2021 23:22:38 +0200 +Subject: [PATCH] core: add 5.10 kernel to version check + +NSS DRV has a kernel version check, so simply add +5.10 as supported. + +Signed-off-by: Robert Marko +--- + nss_core.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/nss_core.c ++++ b/nss_core.c +@@ -52,7 +52,8 @@ + (((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0)))) || \ + (((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)))) || \ + (((LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0)))) || \ +-(((LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(5, 5, 0)))))) ++(((LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(5, 5, 0)))) || \ ++(((LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0)))))) + #error "Check skb recycle code in this file to match Linux version" + #endif + diff --git a/root/package/qca/nss/qca-nss-drv-64/patches/0002-nss-drv-replace-ioremap_nocache-with-ioremap.patch b/root/package/qca/nss/qca-nss-drv-64/patches/0002-nss-drv-replace-ioremap_nocache-with-ioremap.patch new file mode 100644 index 00000000..77155750 --- /dev/null +++ b/root/package/qca/nss/qca-nss-drv-64/patches/0002-nss-drv-replace-ioremap_nocache-with-ioremap.patch @@ -0,0 +1,164 @@ +From b5e2a7167ca3df9fce34f0d7c05468d4f5597275 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Thu, 13 May 2021 23:33:18 +0200 +Subject: [PATCH] nss-drv: replace ioremap_nocache() with ioremap() + +ioremap_nocache() does not exist anymore. + +Signed-off-by: Robert Marko +--- + nss_hal/ipq50xx/nss_hal_pvt.c | 6 +++--- + nss_hal/ipq60xx/nss_hal_pvt.c | 8 ++++---- + nss_hal/ipq806x/nss_hal_pvt.c | 4 ++-- + nss_hal/ipq807x/nss_hal_pvt.c | 6 +++--- + nss_hal/nss_hal.c | 4 ++-- + nss_meminfo.c | 2 +- + nss_ppe.c | 2 +- + 7 files changed, 16 insertions(+), 16 deletions(-) + +--- a/nss_hal/ipq50xx/nss_hal_pvt.c ++++ b/nss_hal/ipq50xx/nss_hal_pvt.c +@@ -184,13 +184,13 @@ static struct nss_platform_data *__nss_h + npd->nphys = res_nphys.start; + npd->qgic_phys = res_qgic_phys.start; + +- npd->nmap = ioremap_nocache(npd->nphys, resource_size(&res_nphys)); ++ npd->nmap = ioremap(npd->nphys, resource_size(&res_nphys)); + if (!npd->nmap) { + nss_info_always("%px: nss%d: ioremap() fail for nphys\n", nss_ctx, nss_ctx->id); + goto out; + } + +- npd->qgic_map = ioremap_nocache(npd->qgic_phys, resource_size(&res_qgic_phys)); ++ npd->qgic_map = ioremap(npd->qgic_phys, resource_size(&res_qgic_phys)); + if (!npd->qgic_map) { + nss_info_always("%px: nss%d: ioremap() fail for qgic map\n", nss_ctx, nss_ctx->id); + goto out; +@@ -348,7 +348,7 @@ static int __nss_hal_common_reset(struct + + of_node_put(cmn); + +- nss_misc_reset = ioremap_nocache(res_nss_misc_reset.start, resource_size(&res_nss_misc_reset)); ++ nss_misc_reset = ioremap(res_nss_misc_reset.start, resource_size(&res_nss_misc_reset)); + if (!nss_misc_reset) { + pr_err("%px: ioremap fail for nss_misc_reset\n", nss_dev); + return -EFAULT; +--- a/nss_hal/ipq60xx/nss_hal_pvt.c ++++ b/nss_hal/ipq60xx/nss_hal_pvt.c +@@ -207,13 +207,13 @@ static struct nss_platform_data *__nss_h + npd->nphys = res_nphys.start; + npd->qgic_phys = res_qgic_phys.start; + +- npd->nmap = ioremap_nocache(npd->nphys, resource_size(&res_nphys)); ++ npd->nmap = ioremap(npd->nphys, resource_size(&res_nphys)); + if (!npd->nmap) { + nss_info_always("%px: nss%d: ioremap() fail for nphys\n", nss_ctx, nss_ctx->id); + goto out; + } + +- npd->qgic_map = ioremap_nocache(npd->qgic_phys, resource_size(&res_qgic_phys)); ++ npd->qgic_map = ioremap(npd->qgic_phys, resource_size(&res_qgic_phys)); + if (!npd->qgic_map) { + nss_info_always("%px: nss%d: ioremap() fail for qgic map\n", nss_ctx, nss_ctx->id); + goto out; +@@ -433,13 +433,13 @@ static int __nss_hal_common_reset(struct + + of_node_put(cmn); + +- nss_misc_reset = ioremap_nocache(res_nss_misc_reset.start, resource_size(&res_nss_misc_reset)); ++ nss_misc_reset = ioremap(res_nss_misc_reset.start, resource_size(&res_nss_misc_reset)); + if (!nss_misc_reset) { + pr_err("%px: ioremap fail for nss_misc_reset\n", nss_dev); + return -EFAULT; + } + +- nss_misc_reset_flag = ioremap_nocache(res_nss_misc_reset_flag.start, resource_size(&res_nss_misc_reset_flag)); ++ nss_misc_reset_flag = ioremap(res_nss_misc_reset_flag.start, resource_size(&res_nss_misc_reset_flag)); + if (!nss_misc_reset_flag) { + pr_err("%px: ioremap fail for nss_misc_reset_flag\n", nss_dev); + return -EFAULT; +--- a/nss_hal/ipq806x/nss_hal_pvt.c ++++ b/nss_hal/ipq806x/nss_hal_pvt.c +@@ -458,7 +458,7 @@ static struct nss_platform_data *__nss_h + npd->nphys = res_nphys.start; + npd->vphys = res_vphys.start; + +- npd->nmap = ioremap_nocache(npd->nphys, resource_size(&res_nphys)); ++ npd->nmap = ioremap(npd->nphys, resource_size(&res_nphys)); + if (!npd->nmap) { + nss_info_always("%px: nss%d: ioremap() fail for nphys\n", nss_ctx, nss_ctx->id); + goto out; +@@ -711,7 +711,7 @@ static int __nss_hal_common_reset(struct + } + of_node_put(cmn); + +- fpb_base = ioremap_nocache(res_nss_fpb_base.start, resource_size(&res_nss_fpb_base)); ++ fpb_base = ioremap(res_nss_fpb_base.start, resource_size(&res_nss_fpb_base)); + if (!fpb_base) { + pr_err("%px: ioremap fail for nss_fpb_base\n", nss_dev); + return -EFAULT; +--- a/nss_hal/ipq807x/nss_hal_pvt.c ++++ b/nss_hal/ipq807x/nss_hal_pvt.c +@@ -234,7 +234,7 @@ static struct nss_platform_data *__nss_h + npd->vphys = res_vphys.start; + npd->qgic_phys = res_qgic_phys.start; + +- npd->nmap = ioremap_nocache(npd->nphys, resource_size(&res_nphys)); ++ npd->nmap = ioremap(npd->nphys, resource_size(&res_nphys)); + if (!npd->nmap) { + nss_info_always("%px: nss%d: ioremap() fail for nphys\n", nss_ctx, nss_ctx->id); + goto out; +@@ -247,7 +247,7 @@ static struct nss_platform_data *__nss_h + goto out; + } + +- npd->qgic_map = ioremap_nocache(npd->qgic_phys, resource_size(&res_qgic_phys)); ++ npd->qgic_map = ioremap(npd->qgic_phys, resource_size(&res_qgic_phys)); + if (!npd->qgic_map) { + nss_info_always("%px: nss%d: ioremap() fail for qgic map\n", nss_ctx, nss_ctx->id); + goto out; +@@ -467,7 +467,7 @@ static int __nss_hal_common_reset(struct + } + of_node_put(cmn); + +- nss_misc_reset = ioremap_nocache(res_nss_misc_reset.start, resource_size(&res_nss_misc_reset)); ++ nss_misc_reset = ioremap(res_nss_misc_reset.start, resource_size(&res_nss_misc_reset)); + if (!nss_misc_reset) { + pr_err("%px: ioremap fail for nss_misc_reset\n", nss_dev); + return -EFAULT; +--- a/nss_hal/nss_hal.c ++++ b/nss_hal/nss_hal.c +@@ -78,9 +78,9 @@ int nss_hal_firmware_load(struct nss_ctx + return rc; + } + +- load_mem = ioremap_nocache(npd->load_addr, nss_fw->size); ++ load_mem = ioremap(npd->load_addr, nss_fw->size); + if (!load_mem) { +- nss_info_always("%px: ioremap_nocache failed: %x", nss_ctx, npd->load_addr); ++ nss_info_always("%px: ioremap failed: %x", nss_ctx, npd->load_addr); + release_firmware(nss_fw); + return rc; + } +--- a/nss_meminfo.c ++++ b/nss_meminfo.c +@@ -728,7 +728,7 @@ bool nss_meminfo_init(struct nss_ctx_ins + /* + * meminfo_start is the label where the start address of meminfo map is stored. + */ +- meminfo_start = (uint32_t *)ioremap_nocache(nss_ctx->load + NSS_MEMINFO_MAP_START_OFFSET, ++ meminfo_start = (uint32_t *)ioremap(nss_ctx->load + NSS_MEMINFO_MAP_START_OFFSET, + NSS_MEMINFO_RESERVE_AREA_SIZE); + if (!meminfo_start) { + nss_info_always("%px: cannot remap meminfo start\n", nss_ctx); +--- a/nss_ppe.c ++++ b/nss_ppe.c +@@ -357,7 +357,7 @@ void nss_ppe_init(void) + /* + * Get the PPE base address + */ +- ppe_pvt.ppe_base = ioremap_nocache(PPE_BASE_ADDR, PPE_REG_SIZE); ++ ppe_pvt.ppe_base = ioremap(PPE_BASE_ADDR, PPE_REG_SIZE); + if (!ppe_pvt.ppe_base) { + nss_warning("DRV can't get PPE base address\n"); + return; diff --git a/root/package/qca/nss/qca-nss-drv-64/patches/0003-DMA-Fix-NULL-pointer-exceptions.patch b/root/package/qca/nss/qca-nss-drv-64/patches/0003-DMA-Fix-NULL-pointer-exceptions.patch new file mode 100644 index 00000000..0c13a788 --- /dev/null +++ b/root/package/qca/nss/qca-nss-drv-64/patches/0003-DMA-Fix-NULL-pointer-exceptions.patch @@ -0,0 +1,49 @@ +From 62e457f262aaa0db7113ad3ccbcb7ae49d4d7ea8 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Tue, 8 Jun 2021 23:24:43 +0200 +Subject: [PATCH] DMA: Fix NULL pointer exceptions + +There are multiple instances that pass NULL instead +of device to DMA functions. +That is incorrect and will cause kernel NULL pointer +exceptions. + +So, simply pass the device structure pointers. + +Signed-off-by: Robert Marko +--- + nss_core.c | 2 +- + nss_coredump.c | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +--- a/nss_core.c ++++ b/nss_core.c +@@ -1617,7 +1617,7 @@ static int32_t nss_core_handle_cause_que + * + */ + if (unlikely((buffer_type == N2H_BUFFER_CRYPTO_RESP))) { +- dma_unmap_single(NULL, (desc->buffer + desc->payload_offs), desc->payload_len, DMA_FROM_DEVICE); ++ dma_unmap_single(nss_ctx->dev, (desc->buffer + desc->payload_offs), desc->payload_len, DMA_FROM_DEVICE); + goto consume; + } + +--- a/nss_coredump.c ++++ b/nss_coredump.c +@@ -154,7 +154,7 @@ void nss_fw_coredump_notify(struct nss_c + dma_addr = nss_own->meminfo_ctx.logbuffer_dma; + } + +- dma_sync_single_for_cpu(NULL, dma_addr, sizeof(struct nss_log_descriptor), DMA_FROM_DEVICE); ++ dma_sync_single_for_cpu(nss_own->dev, dma_addr, sizeof(struct nss_log_descriptor), DMA_FROM_DEVICE); + + /* + * If the current entry is smaller than or equal to the number of NSS_LOG_COREDUMP_LINE_NUM, +@@ -181,7 +181,7 @@ void nss_fw_coredump_notify(struct nss_c + + offset = (index * sizeof(struct nss_log_entry)) + + offsetof(struct nss_log_descriptor, log_ring_buffer); +- dma_sync_single_for_cpu(NULL, dma_addr + offset, ++ dma_sync_single_for_cpu(nss_own->dev, dma_addr + offset, + sizeof(struct nss_log_entry), DMA_FROM_DEVICE); + nss_info_always("%px: %s\n", nss_own, nle_print->message); + nle_print++; diff --git a/root/package/qca/nss/qca-nss-drv-64/patches/0005-nss-drv-add-support-for-kernel-5.15.patch b/root/package/qca/nss/qca-nss-drv-64/patches/0005-nss-drv-add-support-for-kernel-5.15.patch new file mode 100644 index 00000000..dfebd0d6 --- /dev/null +++ b/root/package/qca/nss/qca-nss-drv-64/patches/0005-nss-drv-add-support-for-kernel-5.15.patch @@ -0,0 +1,73 @@ +From 6e65f6daecb09463688eaea0a234018a728196b8 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Tue, 5 Apr 2022 18:10:57 +0200 +Subject: [PATCH 5/8] nss-drv: add support for kernel 5.15 + +- Fix coredump panic notifier include change. +- Fix skb ZEROCOPY flag. +- Add skb reuse support for 5.15 kernel version. + +Signed-off-by: Ansuel Smith +--- + nss_core.c | 5 +++-- + nss_coredump.c | 4 ++++ + nss_hal/nss_hal.c | 1 + + 3 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/nss_core.c b/nss_core.c +index f9e6014..8cd1d4b 100644 +--- a/nss_core.c ++++ b/nss_core.c +@@ -53,7 +53,8 @@ + (((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)))) || \ + (((LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0)))) || \ + (((LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(5, 5, 0)))) || \ +-(((LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0)))))) ++(((LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0)))) || \ ++(((LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0)))))) + #error "Check skb recycle code in this file to match Linux version" + #endif + +@@ -2623,7 +2624,11 @@ static inline bool nss_core_skb_can_reuse(struct nss_ctx_instance *nss_ctx, + if (unlikely(irqs_disabled())) + return false; + ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0)) + if (unlikely(skb_shinfo(nbuf)->tx_flags & SKBTX_DEV_ZEROCOPY)) ++#else ++ if (unlikely(skb_shinfo(nbuf)->flags & SKBFL_ZEROCOPY_ENABLE)) ++#endif + return false; + + if (unlikely(skb_is_nonlinear(nbuf))) +diff --git a/nss_coredump.c b/nss_coredump.c +index ecad659..3ecef7e 100644 +--- a/nss_coredump.c ++++ b/nss_coredump.c +@@ -23,7 +23,11 @@ + #include "nss_hal.h" + #include "nss_log.h" + #include ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0)) + #include /* for panic_notifier_list */ ++#else ++#include ++#endif + #include /* for time */ + #include "nss_tx_rx_common.h" + +diff --git a/nss_hal/nss_hal.c b/nss_hal/nss_hal.c +index 57974c1..d8c703b 100644 +--- a/nss_hal/nss_hal.c ++++ b/nss_hal/nss_hal.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + + #include "nss_hal.h" + #include "nss_arch.h" +-- +2.34.1 + diff --git a/root/package/qca/nss/qca-nss-drv-64/patches/0005-nss-drv-use-standard-skb_skip_tc_classify-instead-of.patch b/root/package/qca/nss/qca-nss-drv-64/patches/0005-nss-drv-use-standard-skb_skip_tc_classify-instead-of.patch new file mode 100644 index 00000000..73c923d3 --- /dev/null +++ b/root/package/qca/nss/qca-nss-drv-64/patches/0005-nss-drv-use-standard-skb_skip_tc_classify-instead-of.patch @@ -0,0 +1,29 @@ +From 4dd701916186803172a9f35e7e982a953613ad55 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Mon, 11 Apr 2022 21:32:41 +0200 +Subject: [PATCH 5/9] nss-drv: use standard skb_skip_tc_classify instead of + custom api + +Use skb_skip_tc_classify to skip classify for packet handled by nss +instead of custom api. + +Signed-off-by: Ansuel Smith +--- + nss_core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/nss_core.c b/nss_core.c +index f9e6014..6ab8038 100644 +--- a/nss_core.c ++++ b/nss_core.c +@@ -1075,7 +1075,7 @@ static inline void nss_core_set_skb_classify(struct sk_buff *nbuf) + #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0)) + nbuf->tc_verd = SET_TC_NCLS_NSS(nbuf->tc_verd); + #else +- skb_set_tc_classify_offload(nbuf); ++ skb_skip_tc_classify(nbuf); + #endif + #endif + } +-- +2.34.1 diff --git a/root/package/qca/nss/qca-nss-drv-64/patches/0999-treewide-hack-support-for-mismatched-firmware.patch b/root/package/qca/nss/qca-nss-drv-64/patches/0999-treewide-hack-support-for-mismatched-firmware.patch new file mode 100644 index 00000000..46025b82 --- /dev/null +++ b/root/package/qca/nss/qca-nss-drv-64/patches/0999-treewide-hack-support-for-mismatched-firmware.patch @@ -0,0 +1,344 @@ +From d0bffc800a50305315a0d7cf37140291ef5b1b61 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Thu, 27 May 2021 03:52:47 +0200 +Subject: [PATCH] treewide: hack support for mismatched firmware + +Make new qsdk feature configurable to support old half compatible +firmware. + +Signed-off-by: Ansuel Smith +--- + exports/nss_fw_version.h | 11 +++++++++++ + exports/nss_ipv4.h | 8 ++++++++ + exports/nss_ipv6.h | 7 +++++++ + exports/nss_wifi_vdev.h | 14 ++++++++++++++ + exports/nss_wifili_if.h | 8 ++++++++ + nss_ipv4_stats.c | 2 ++ + nss_ipv4_strings.c | 2 ++ + nss_ipv6_stats.c | 2 ++ + nss_ipv6_strings.c | 2 ++ + 9 files changed, 56 insertions(+) + create mode 100644 exports/nss_fw_version.h + +diff --git a/exports/nss_fw_version.h b/exports/nss_fw_version.h +new file mode 100644 +index 0000000..895d523 +--- /dev/null ++++ b/exports/nss_fw_version.h +@@ -0,0 +1,11 @@ ++#ifndef __NSS_FW_VERSION_H ++#define __NSS_FW_VERSION_H ++ ++#define NSS_FW_VERSION_MAJOR 11 ++#define NSS_FW_VERSION_MINOR 4 ++ ++#define NSS_FW_VERSION(a,b) (((a) << 8) + (b)) ++ ++#define NSS_FW_VERSION_CODE NSS_FW_VERSION(NSS_FW_VERSION_MAJOR, NSS_FW_VERSION_MINOR) ++ ++#endif /* __NSS_FW_VERSION_H */ +\ No newline at end of file +diff --git a/exports/nss_ipv4.h b/exports/nss_ipv4.h +index ee3a552..25c4d82 100644 +--- a/exports/nss_ipv4.h ++++ b/exports/nss_ipv4.h +@@ -26,6 +26,8 @@ + #include "nss_stats_public.h" + #endif + ++#include "nss_fw_version.h" ++ + /** + * @addtogroup nss_ipv4_subsystem + * @{ +@@ -216,12 +218,14 @@ enum nss_ipv4_stats_types { + /**< Number of IPv4 multicast connection destroy requests that missed the cache. */ + NSS_IPV4_STATS_MC_CONNECTION_FLUSHES, + /**< Number of IPv4 multicast connection flushes. */ ++#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) + NSS_IPV4_STATS_CONNECTION_CREATE_INVALID_MIRROR_IFNUM, + /**< Number of IPv4 mirror connection requests with an invalid interface number. */ + NSS_IPV4_STATS_CONNECTION_CREATE_INVALID_MIRROR_IFTYPE, + /**< Number of IPv4 mirror connection requests with an invalid interface type. */ + NSS_IPV4_STATS_MIRROR_FAILURES, + /**< Number of IPv4 mirror failures. */ ++#endif + NSS_IPV4_STATS_MAX, + /**< Maximum message type. */ + }; +@@ -609,8 +613,10 @@ struct nss_ipv4_rule_create_msg { + /**< Ingress shaping related accleration parameters. */ + struct nss_ipv4_identifier_rule identifier; + /**< Rule for adding identifier. */ ++#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) + struct nss_ipv4_mirror_rule mirror_rule; + /**< Mirror rule parameter. */ ++#endif + }; + + /** +@@ -955,6 +961,7 @@ struct nss_ipv4_node_sync { + uint32_t ipv4_mc_connection_flushes; + /**< Number of multicast connection flushes. */ + ++#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) + uint32_t ipv4_connection_create_invalid_mirror_ifnum; + /**< Number of create request failed with an invalid mirror interface number. */ + +@@ -963,6 +970,7 @@ struct nss_ipv4_node_sync { + + uint32_t ipv4_mirror_failures; + /**< Mirror packet failed. */ ++#endif + + uint32_t exception_events[NSS_IPV4_EXCEPTION_EVENT_MAX]; + /**< Number of exception events. */ +diff --git a/exports/nss_ipv6.h b/exports/nss_ipv6.h +index 930e74c..a21f939 100644 +--- a/exports/nss_ipv6.h ++++ b/exports/nss_ipv6.h +@@ -195,6 +195,8 @@ enum nss_ipv6_stats_types { + /**< Number of IPv6 multicast connection destroy requests that missed the cache. */ + NSS_IPV6_STATS_MC_CONNECTION_FLUSHES, + /**< Number of IPv6 multicast connection flushes. */ ++ ++#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) + NSS_IPV6_STATS_CONNECTION_CREATE_INVALID_MIRROR_IFNUM, + /**< Number of IPv6 mirror connection requests with an invalid interface number. */ + NSS_IPV6_STATS_CONNECTION_CREATE_INVALID_MIRROR_IFTYPE, +@@ -202,6 +204,7 @@ enum nss_ipv6_stats_types { + + NSS_IPV6_STATS_MIRROR_FAILURES, + /**< Number of IPv6 mirror failures. */ ++#endif + + NSS_IPV6_STATS_MAX, + /**< Maximum message type. */ +@@ -702,8 +705,10 @@ struct nss_ipv6_rule_create_msg { + /**< Ingress shaping related accleration parameters. */ + struct nss_ipv6_identifier_rule identifier; + /**< Rule for adding identifier. */ ++#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) + struct nss_ipv6_mirror_rule mirror_rule; + /**< Mirror rule parameter. */ ++#endif + }; + + /** +@@ -950,6 +955,7 @@ struct nss_ipv6_node_sync { + uint32_t ipv6_mc_connection_flushes; + /**< Number of multicast connection flushes. */ + ++#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) + uint32_t ipv6_connection_create_invalid_mirror_ifnum; + /**< Number of create request failed with an invalid mirror interface number. */ + +@@ -958,6 +964,7 @@ struct nss_ipv6_node_sync { + + uint32_t ipv6_mirror_failures; + /**< Mirror packet failed. */ ++#endif + + uint32_t exception_events[NSS_IPV6_EXCEPTION_EVENT_MAX]; + /**< Number of exception events. */ +diff --git a/exports/nss_wifi_vdev.h b/exports/nss_wifi_vdev.h +index 1b52f66..da91b56 100644 +--- a/exports/nss_wifi_vdev.h ++++ b/exports/nss_wifi_vdev.h +@@ -74,8 +74,10 @@ enum nss_wifi_vdev_msg_types { + NSS_WIFI_VDEV_INTERFACE_RECOVERY_RESET_MSG, + NSS_WIFI_VDEV_INTERFACE_RECOVERY_RECONF_MSG, + NSS_WIFI_VDEV_SET_GROUP_KEY, ++#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) + NSS_WIFI_VDEV_HMMC_MEMBER_ADD_MSG, + NSS_WIFI_VDEV_HMMC_MEMBER_DEL_MSG, ++#endif + NSS_WIFI_VDEV_MAX_MSG + }; + +@@ -130,6 +132,7 @@ enum nss_wifi_vdev_err_types { + NSS_WIFI_VDEV_VLAN_MODE_CONFIG_FAIL, + NSS_WIFI_VDEV_RECOVERY_RESET_FAIL, + NSS_WIFI_VDEV_RECOVERY_RECONF_FAIL, ++#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) + NSS_WIFI_VDEV_CONFIG_GROUP_KEY_FAIL, + NSS_WIFI_VDEV_MULTIPASS_NOT_ENABLED, + NSS_WIFI_VDEV_ALLOC_VLAN_MAP_FAILED, +@@ -139,6 +142,7 @@ enum nss_wifi_vdev_err_types { + NSS_WIFI_VDEV_PPE_PORT_DESTROY_FAIL, + NSS_WIFI_VDEV_PPE_VSI_ASSIGN_FAIL, + NSS_WIFI_VDEV_PPE_VSI_UNASSIGN_FAIL, ++#endif + NSS_WIFI_VDEV_EINV_MAX_CFG + }; + +@@ -161,11 +165,13 @@ enum nss_wifi_vdev_ext_data_pkt_type { + NSS_WIFI_VDEV_EXT_TX_COMPL_PKT_TYPE = 11, /**< Tx completion. */ + NSS_WIFI_VDEV_EXT_DATA_PKT_TYPE_WDS_LEARN = 12, /**< WDS source port learning command. */ + NSS_WIFI_VDEV_EXT_DATA_PPDU_INFO = 13, /**< PPDU metadata information. */ ++#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) + NSS_WIFI_VDEV_EXT_DATA_PKT_TYPE_MCBC_RX = 14, /**< Multicast/broadcast packet received. */ + NSS_WIFI_VDEV_MESH_EXT_DATA_PKT_TYPE_RX_SPL_PACKET = 15, + /**< Mesh link VAP special packet. */ + NSS_WIFI_VDEV_MESH_EXT_DATA_PKT_TYPE_RX_MCAST_EXC = 16, + /**< Mesh link VAP multicast packet. */ ++#endif + NSS_WIFI_VDEV_EXT_DATA_PKT_TYPE_MAX + }; + +@@ -201,9 +207,11 @@ enum nss_wifi_vdev_cmd { + NSS_WIFI_VDEV_ENABLE_IGMP_ME_CMD, /**< Configuration to set IGMP multicast enhancement on VAP. */ + NSS_WIFI_VDEV_CFG_WDS_BACKHAUL_CMD, + /**< Configuration to set WDS backhaul extension on VAP. */ ++#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) + NSS_WIFI_VDEV_CFG_MCBC_EXC_TO_HOST_CMD, /**< Configuration to set multicast/broadcast exception to host on VAP. */ + NSS_WIFI_VDEV_CFG_PEER_AUTHORIZE_CMD, + /**< Configuration to enable peer authorization on VAP. */ ++#endif + NSS_WIFI_VDEV_MAX_CMD + }; + +@@ -271,7 +279,9 @@ struct nss_wifi_vdev_config_msg { + uint8_t is_nss_qwrap_en; /**< VAP is configured for NSS firmware QWRAP logic. */ + uint8_t tx_per_pkt_vdev_id_check; /**< Transmit per-packet virtual device ID check. */ + uint8_t align_pad; /**< Reserved field. */ ++#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) + uint32_t vap_ext_mode; /**< Different VAP extended modes. */ ++#endif + }; + + /** +@@ -1037,8 +1047,10 @@ struct nss_wifi_vdev_stats_sync_msg { + uint32_t rx_mcast_bytes; /**< Receive multicast bytes count. */ + uint32_t rx_decrypt_err; /**< Receive decryption error */ + uint32_t rx_mic_err; /**< Receive MIC error */ ++#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) + uint32_t mcbc_exc_host_fail_cnt; + /**< Number of multicast/broadcast packets failed to send to host through exception path. */ ++#endif + }; + + /** +@@ -1070,6 +1082,7 @@ struct nss_wifi_vdev_msg { + /**< Updates a snooplist group member. */ + struct nss_wifi_vdev_me_snptbl_deny_grp_add_msg vdev_deny_member_add; + /**< Add a snooplist member to the deny list. */ ++#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) + struct nss_wifi_vdev_me_hmmc_add_msg vdev_hmmc_member_add; + /**< Adds a new member into the HMMC list. */ + struct nss_wifi_vdev_me_hmmc_del_msg vdev_hmmc_member_del; +@@ -1078,6 +1091,7 @@ struct nss_wifi_vdev_msg { + /**< Adds a new member into the deny list. */ + struct nss_wifi_vdev_me_deny_ip_del_msg vdev_deny_list_member_del; + /**< Delete a member from the deny list. */ ++#endif + struct nss_wifi_vdev_txmsg vdev_txmsgext; + /**< Transmits special data. */ + struct nss_wifi_vdev_vow_dbg_cfg_msg vdev_vow_dbg_cfg; +diff --git a/exports/nss_wifili_if.h b/exports/nss_wifili_if.h +index fce20fd..1f26d67 100644 +--- a/exports/nss_wifili_if.h ++++ b/exports/nss_wifili_if.h +@@ -62,8 +62,12 @@ + /**< Maximum number of bandwidth supported. */ + #define NSS_WIFILI_REPT_MU_MIMO 1 + #define NSS_WIFILI_REPT_MU_OFDMA_MIMO 3 ++#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) ++#define NSS_WIFILI_MAX_RESERVED_TYPE 3 ++#else + #define NSS_WIFILI_MAX_RESERVED_TYPE 2 + /**< Maximum reserved type. */ ++#endif + #define NSS_WIFILI_SOC_PER_PACKET_METADATA_SIZE 60 + /**< Metadata area total size. */ + #define NSS_WIFILI_MEC_PEER_ID 0xDEAD +@@ -1333,7 +1337,9 @@ struct nss_wifili_rx_err { + struct nss_wifili_rx_ctrl_stats { + struct nss_wifili_rx_err err; /**< Rx peer errors. */ + uint32_t multipass_rx_pkt_drop; /**< Total number of multipass packets without a VLAN header. */ ++#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) + uint32_t peer_unauth_rx_pkt_drop; /**< Number of receive packets dropped due to an authorized peer. */ ++#endif + uint32_t reserved_type[NSS_WIFILI_MAX_RESERVED_TYPE]; /**< Reserved type for future use. */ + uint32_t non_amsdu_cnt; /**< Number of MSDUs with no MSDU level aggregation. */ + uint32_t amsdu_cnt; /**< Number of MSDUs part of AMSDU. */ +@@ -1810,10 +1816,12 @@ struct nss_wifili_msg { + /**< Peer four-address event message. */ + struct nss_wifili_dbdc_repeater_loop_detection_msg wdrldm; + /**< Wifili DBDC repeater loop detection message. */ ++#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) + struct nss_wifili_peer_update_auth_flag peer_auth; + /**< Peer authentication flag message. */ + struct nss_wifili_mesh_capability_info cap_info; + /**< Mesh capability flag. */ ++#endif + } msg; /**< Message payload. */ + }; + +diff --git a/nss_ipv4_stats.c b/nss_ipv4_stats.c +index 39b162c..c875a63 100644 +--- a/nss_ipv4_stats.c ++++ b/nss_ipv4_stats.c +@@ -177,9 +177,11 @@ void nss_ipv4_stats_node_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_ + nss_ipv4_stats[NSS_IPV4_STATS_MC_CONNECTION_DESTROY_REQUESTS] += nins->ipv4_mc_connection_destroy_requests; + nss_ipv4_stats[NSS_IPV4_STATS_MC_CONNECTION_DESTROY_MISSES] += nins->ipv4_mc_connection_destroy_misses; + nss_ipv4_stats[NSS_IPV4_STATS_MC_CONNECTION_FLUSHES] += nins->ipv4_mc_connection_flushes; ++#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) + nss_ipv4_stats[NSS_IPV4_STATS_CONNECTION_CREATE_INVALID_MIRROR_IFNUM] += nins->ipv4_connection_create_invalid_mirror_ifnum; + nss_ipv4_stats[NSS_IPV4_STATS_CONNECTION_CREATE_INVALID_MIRROR_IFTYPE] += nins->ipv4_connection_create_invalid_mirror_iftype; + nss_ipv4_stats[NSS_IPV4_STATS_MIRROR_FAILURES] += nins->ipv4_mirror_failures; ++#endif + + for (i = 0; i < NSS_IPV4_EXCEPTION_EVENT_MAX; i++) { + nss_ipv4_exception_stats[i] += nins->exception_events[i]; +diff --git a/nss_ipv4_strings.c b/nss_ipv4_strings.c +index 77ff352..ce4c249 100644 +--- a/nss_ipv4_strings.c ++++ b/nss_ipv4_strings.c +@@ -137,9 +137,11 @@ struct nss_stats_info nss_ipv4_strings_stats[NSS_IPV4_STATS_MAX] = { + {"mc_destroy_requests" , NSS_STATS_TYPE_SPECIAL}, + {"mc_destroy_misses" , NSS_STATS_TYPE_SPECIAL}, + {"mc_flushes" , NSS_STATS_TYPE_SPECIAL}, ++#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) + {"mirror_invalid_ifnum_conn_create_req" , NSS_STATS_TYPE_SPECIAL}, + {"mirror_invalid_iftype_conn_create_req" , NSS_STATS_TYPE_SPECIAL}, + {"mirror_failures" , NSS_STATS_TYPE_SPECIAL}, ++#endif + }; + + /* +diff --git a/nss_ipv6_stats.c b/nss_ipv6_stats.c +index 617f55b..a492a6c 100644 +--- a/nss_ipv6_stats.c ++++ b/nss_ipv6_stats.c +@@ -180,9 +180,11 @@ void nss_ipv6_stats_node_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_ + nss_ipv6_stats[NSS_IPV6_STATS_MC_CONNECTION_DESTROY_REQUESTS] += nins->ipv6_mc_connection_destroy_requests; + nss_ipv6_stats[NSS_IPV6_STATS_MC_CONNECTION_DESTROY_MISSES] += nins->ipv6_mc_connection_destroy_misses; + nss_ipv6_stats[NSS_IPV6_STATS_MC_CONNECTION_FLUSHES] += nins->ipv6_mc_connection_flushes; ++#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) + nss_ipv6_stats[NSS_IPV6_STATS_CONNECTION_CREATE_INVALID_MIRROR_IFNUM] += nins->ipv6_connection_create_invalid_mirror_ifnum; + nss_ipv6_stats[NSS_IPV6_STATS_CONNECTION_CREATE_INVALID_MIRROR_IFTYPE] += nins->ipv6_connection_create_invalid_mirror_iftype; + nss_ipv6_stats[NSS_IPV6_STATS_MIRROR_FAILURES] += nins->ipv6_mirror_failures; ++#endif + + for (i = 0; i < NSS_IPV6_EXCEPTION_EVENT_MAX; i++) { + nss_ipv6_exception_stats[i] += nins->exception_events[i]; +diff --git a/nss_ipv6_strings.c b/nss_ipv6_strings.c +index 57b100f..29df9c9 100644 +--- a/nss_ipv6_strings.c ++++ b/nss_ipv6_strings.c +@@ -115,9 +115,11 @@ struct nss_stats_info nss_ipv6_strings_stats[NSS_IPV6_STATS_MAX] = { + {"mc_destroy_requests" ,NSS_STATS_TYPE_SPECIAL}, + {"mc_destroy_misses" ,NSS_STATS_TYPE_SPECIAL}, + {"mc_flushes" ,NSS_STATS_TYPE_SPECIAL}, ++#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) + {"mirror_invalid_ifnum_conn_create_req" ,NSS_STATS_TYPE_SPECIAL}, + {"mirror_invalid_iftype_conn_create_req" ,NSS_STATS_TYPE_SPECIAL}, + {"mirror_failures" ,NSS_STATS_TYPE_SPECIAL}, ++#endif + }; + + /* +-- +2.31.1 + diff --git a/root/package/qca/nss/qca-nss-drv/Makefile b/root/package/qca/nss/qca-nss-drv/Makefile new file mode 100644 index 00000000..7e695ca3 --- /dev/null +++ b/root/package/qca/nss/qca-nss-drv/Makefile @@ -0,0 +1,125 @@ +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=qca-nss-drv +PKG_RELEASE:=2 + +PKG_SOURCE_URL:=https://source.codeaurora.org/quic/qsdk/oss/lklm/nss-drv +PKG_SOURCE_PROTO:=git +PKG_SOURCE_VERSION:=809a00deffe9f3d4ecd15965790a152757073437 +PKG_MIRROR_HASH:=9c4340561fe9d6ccaa094bbfc5c7f98c27867d2d9a3f1a3f9a7483bca9bbedf8 + +NSS_CLIENTS_DIR:=$(TOPDIR)/qca/src/qca-nss-clients + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/qca-nss-drv + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + DEPENDS:=@TARGET_ipq806x||TARGET_ipq_ipq806x||TARGET_ipq_ipq807x||TARGET_ipq_ipq807x_64||TARGET_ipq807x||TARGET_ipq807x_64||TARGET_ipq_ipq60xx||TARGET_ipq_ipq60xx_64||TARGET_ipq_ipq50xx||TARGET_ipq_ipq50xx_64 \ + +PACKAGE_kmod-qca-nss-gmac:kmod-qca-nss-gmac @LINUX_5_4 + TITLE:=Kernel driver for NSS (core driver) + FILES:=$(PKG_BUILD_DIR)/qca-nss-drv.ko + AUTOLOAD:=$(call AutoLoad,32,qca-nss-drv) +endef + +define KernelPackage/qca-nss-drv/install + $(INSTALL_DIR) $(1)/lib/debug + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_DIR) $(1)/etc/sysctl.d + $(INSTALL_DIR) $(1)/etc/hotplug.d/firmware + $(INSTALL_DIR) $(1)/etc/config + $(INSTALL_DIR) $(1)/lib/firmware + + $(INSTALL_BIN) ./files/qca-nss-drv.debug $(1)/lib/debug/qca-nss-drv + $(INSTALL_BIN) ./files/qca-nss-drv.init $(1)/etc/init.d/qca-nss-drv + $(INSTALL_BIN) ./files/qca-nss-drv.sysctl $(1)/etc/sysctl.d/qca-nss-drv.conf + $(INSTALL_BIN) ./files/qca-nss-drv.hotplug $(1)/etc/hotplug.d/firmware/10-qca-nss-fw + $(INSTALL_BIN) ./files/qca-nss-drv.conf $(1)/etc/config/nss + $(INSTALL_BIN) ./files/nss-firmware/qca-nss0-retail.bin $(1)/lib/firmware/qca-nss0.bin + $(INSTALL_BIN) ./files/nss-firmware/qca-nss1-retail.bin $(1)/lib/firmware/qca-nss1.bin + +endef + +define KernelPackage/qca-nss-drv/Description +This package contains a NSS driver for QCA chipset +endef + +define Build/InstallDev + mkdir -p $(1)/usr/include/qca-nss-drv + $(CP) $(PKG_BUILD_DIR)/exports/* $(1)/usr/include/qca-nss-drv/ +ifneq (, $(findstring $(subtarget), "ipq807x" "ipq807x_64" "ipq60xx" "ipq60xx_64" "ipq50xx" "ipq50xx_64")) + $(RM) $(1)/usr/include/qca-nss-drv/nss_ipsecmgr.h + $(INSTALL_DIR) $(1)/usr/include/qca-nss-clients + $(CP) $(NSS_CLIENTS_DIR)/exports/nss_ipsecmgr.h $(1)/usr/include/qca-nss-clients/. +endif +endef + +EXTRA_CFLAGS+= -I$(STAGING_DIR)/usr/include/qca-nss-gmac + +# Keeping default as ipq806x for branches that does not have subtarget framework +ifeq ($(CONFIG_TARGET_ipq),y) +subtarget:=$(SUBTARGET) +else +subtarget:=$(CONFIG_TARGET_BOARD) +endif + +ifeq ($(CONFIG_KERNEL_IPQ_MEM_PROFILE),256) +EXTRA_CFLAGS+= -DNSS_MEM_PROFILE_LOW +endif + +ifeq ($(CONFIG_KERNEL_IPQ_MEM_PROFILE),512) +EXTRA_CFLAGS+= -DNSS_MEM_PROFILE_MEDIUM +endif + +ifeq ($(CONFIG_KERNEL_SKB_FIXED_SIZE_2K),y) +EXTRA_CFLAGS+= -DNSS_SKB_FIXED_SIZE_2K +endif + +DRV_MAKE_OPTS:= +ifeq ($(CONFIG_KERNEL_IPQ_MEM_PROFILE),256) +DRV_MAKE_OPTS+=NSS_DRV_C2C_ENABLE=n \ + NSS_DRV_CAPWAP_ENABLE=n \ + NSS_DRV_CLMAP_ENABLE=n \ + NSS_DRV_CRYPTO_ENABLE=n \ + NSS_DRV_DTLS_ENABLE=n \ + NSS_DRV_GRE_ENABLE=n \ + NSS_DRV_GRE_REDIR_ENABLE=n \ + NSS_DRV_GRE_TUNNEL_ENABLE=n \ + NSS_DRV_IGS_ENABLE=n \ + NSS_DRV_IPSEC_ENABLE=n \ + NSS_DRV_LAG_ENABLE=n \ + NSS_DRV_L2TP_ENABLE=n \ + NSS_DRV_MAPT_ENABLE=n \ + NSS_DRV_OAM_ENABLE=n \ + NSS_DRV_PPTP_ENABLE=n \ + NSS_DRV_PORTID_ENABLE=n \ + NSS_DRV_PVXLAN_ENABLE=n \ + NSS_DRV_QRFS_ENABLE=n \ + NSS_DRV_QVPN_ENABLE=n \ + NSS_DRV_RMNET_ENABLE=n \ + NSS_DRV_SHAPER_ENABLE=n \ + NSS_DRV_SJACK_ENABLE=n \ + NSS_DRV_TLS_ENABLE=n \ + NSS_DRV_TRUSTSEC_ENABLE=n \ + NSS_DRV_TSTAMP_ENABLE=n \ + NSS_DRV_TUN6RD_ENABLE=n \ + NSS_DRV_TUNIPIP6_ENABLE=n \ + NSS_DRV_VXLAN_ENABLE=n +endif + +define Build/Configure + $(LN) arch/nss_$(subtarget).h $(PKG_BUILD_DIR)/exports/nss_arch.h +endef + +define Build/Compile + $(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" $(strip $(DRV_MAKE_OPTS)) \ + $(KERNEL_MAKE_FLAGS) \ + $(PKG_MAKE_FLAGS) \ + M="$(PKG_BUILD_DIR)" \ + EXTRA_CFLAGS="$(EXTRA_CFLAGS)" SoC="$(subtarget)" \ + modules +endef + +$(eval $(call KernelPackage,qca-nss-drv)) diff --git a/root/package/qca/nss/qca-nss-drv/files/nss-firmware/LICENSE.TXT b/root/package/qca/nss/qca-nss-drv/files/nss-firmware/LICENSE.TXT new file mode 100644 index 00000000..41631989 --- /dev/null +++ b/root/package/qca/nss/qca-nss-drv/files/nss-firmware/LICENSE.TXT @@ -0,0 +1,45 @@ +Copyright (c) 2014 Qualcomm Atheros, Inc. + +All rights reserved. + +Redistribution and use in binary forms, without +modification, are permitted (subject to the limitations in the +disclaimer below) provided that the following conditions are met: + +*Redistributions must reproduce the above copyright + notice, this list of conditions, and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +*Neither the name of Qualcomm Atheros, Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +*No Reverse engineering, decompiling, decrypting, or disassembling of this + software is permitted. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. NO LICENSES OR OTHER RIGHTS, +WHETHER EXPRESS, IMPLIED, BASED ON ESTOPPEL OR OTHERWISE, ARE GRANTED +TO ANY PARTY'S PATENTS, PATENT APPLICATIONS, OR PATENTABLE INVENTIONS +BY VIRTUE OF THIS LICENSE OR THE DELIVERY OR PROVISION BY QUALCOMM +ATHEROS, INC. OF THE SOFTWARE. + +IN NO EVENT SHALL THE COPYRIGHT OWNER OR ANY CONTRIBUTOR BE LIABLE FOR +ANY INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND REGARDLESS OF ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF OR RESULTING FROM THE USE OF THE +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. IN ANY +EVENT, THE TOTAL AGGREGATE LIABILITY THAT MAY BE IMPOSED ON QUALCOMM +ATHEROS, INC. FOR ANY DIRECT DAMAGES ARISING UNDER OR RESULTING FROM +THIS AGREEMENT OR IN CONNECTION WITH ANY USE OF THE SOFTWARE SHALL NOT +EXCEED A TOTAL AMOUNT OF US$5.00. + +IF ANY OF THE ABOVE PROVISIONS ARE HELD TO BE VOID, INVALID, +UNENFORCEABLE, OR ILLEGAL, THE OTHER PROVISIONS SHALL CONTINUE IN FULL +FORCE AND EFFECT. + diff --git a/root/package/qca/nss/qca-nss-drv/files/nss-firmware/NOTICE.TXT b/root/package/qca/nss/qca-nss-drv/files/nss-firmware/NOTICE.TXT new file mode 100644 index 00000000..ab54aa01 --- /dev/null +++ b/root/package/qca/nss/qca-nss-drv/files/nss-firmware/NOTICE.TXT @@ -0,0 +1,217 @@ +============================================================================= + +This Notice.txt file contains certain notices of software components included +with the software that Qualcomm Atheros, Inc. ("Qualcomm Atheros") is required +to provide you. Except where prohibited by the open source license, the content +of this notices file is only provided to satisfy Qualcomm Atheros's attribution +and notice requirement; your use of these software components together with the +Qualcomm Atheros software (Qualcomm Atheros software hereinafter referred to as +"Software") is subject to the terms of your license from Qualcomm Atheros. +Compliance with all copyright laws and software license agreements included in +the notice section of this file are the responsibility of the user. Except as +may be granted by separate express written agreement, this file provides no +license to any Qualcomm Atheros patents, trademarks, copyrights, or other +intellectual property. + +Copyright (c) 2014 Qualcomm Atheros, Inc. All rights reserved. + +Qualcomm is a trademark of Qualcomm Incorporated, registered in the United +States and other countries. All Qualcomm Incorporated trademarks are used with +permission. Atheros is a trademark of Qualcomm Atheros, Inc., registered in the +United States and other countries. Other products and brand names may be +trademarks or registered trademarks of their respective owners. + +NOTICES: + +============================================================================= + +/* + * doprint.c + * Formatted string print support. + * + * Copyright 2001-2012 Qualcomm Atheros, Inc. All Rights Reserved. + * + * Qualcomm Atheros Confidential and Proprietary. + * + * This code originates with BSD Unix however it has been extensively + * modified. The original copyright is reproduced below: + * + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted provided + * that: (1) source distributions retain this entire copyright notice and + * comment, and (2) distributions including binaries display the following + * acknowledgement: ``This product includes software developed by the + * University of California, Berkeley and its contributors'' in the + * documentation or other materials provided with the distribution and in + * all advertising materials mentioning features or use of this software. + * Neither the name of the University nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + + +/* + * math.c + * Support for the standard C library. + * + * Copyright 2006-2012 Qualcomm Atheros, Inc. All Rights Reserved. + * + * Qualcomm Atheros Confidential and Proprietary. + * + * Software contained within this file was originally released with the + * following + * copyright and license statement: + * + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + + +/* + * stdlib.c + * Routines from stdlib.h. + * + * Copyright 2004-2012 Qualcomm Atheros, Inc. All Rights Reserved. + * + * Qualcomm Atheros Confidential and Proprietary. + * + * The code for strtol() and strtoul() are also subject to the following: + * + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +drr_alg_utils.h: +/****************************************************************************/ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +shaper_list_utils.h: +/****************************************************************************/ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +codel_alg_inv_sqrt.h +/****************************************************************************/ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ diff --git a/root/package/qca/nss/qca-nss-drv/files/nss-firmware/README.md b/root/package/qca/nss/qca-nss-drv/files/nss-firmware/README.md new file mode 100644 index 00000000..2d0b4750 --- /dev/null +++ b/root/package/qca/nss/qca-nss-drv/files/nss-firmware/README.md @@ -0,0 +1,10 @@ +NSS FIRMWARE +============ + +This repo contains firmware files to enable the NSS MAC on QCA IPQ806x SoC. + +This product includes software developed by the University of California, +Berkeley and its contributors. + +NSS firmware extracted from Synology RT2600ac SRM 1.2 - Version: 1.2-7742-4 + diff --git a/root/package/qca/nss/qca-nss-drv/files/nss-firmware/qca-nss0-retail.bin b/root/package/qca/nss/qca-nss-drv/files/nss-firmware/qca-nss0-retail.bin new file mode 100644 index 0000000000000000000000000000000000000000..08f6efe6c8d8c476a7b68c8b44e125db75276cef GIT binary patch literal 536324 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 z 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

4|GJx3IMG;WZSS-@ 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ΠfAA56W)Al)uy*Y5hcMjv&o6EXSJ?Ho3 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

  • 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 literal 0 HcmV?d00001 diff --git a/root/package/qca/nss/qca-nss-drv/files/nss-firmware/qca-nss1-retail.bin b/root/package/qca/nss/qca-nss-drv/files/nss-firmware/qca-nss1-retail.bin new file mode 100644 index 0000000000000000000000000000000000000000..e79510f34de55c649a7fb48f1ba40c59294bb525 GIT binary patch literal 218224 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 literal 0 HcmV?d00001 diff --git a/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.conf b/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.conf new file mode 100644 index 00000000..a8a1fbf4 --- /dev/null +++ b/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.conf @@ -0,0 +1,6 @@ +config nss_firmware 'qca_nss_0' + +config nss_firmware 'qca_nss_1' + +config general + option enable_rps '1' diff --git a/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.debug b/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.debug new file mode 100644 index 00000000..5d435c3a --- /dev/null +++ b/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.debug @@ -0,0 +1,26 @@ +#!/bin/sh /sbin/sysdebug +# +# Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +log cat /sys/kernel/debug/qca-nss-drv/stats/pppoe +log cat /sys/kernel/debug/qca-nss-drv/stats/n2h +log cat /sys/kernel/debug/qca-nss-drv/stats/ipv6 +log cat /sys/kernel/debug/qca-nss-drv/stats/ipv4 +log cat /sys/kernel/debug/qca-nss-drv/stats/gmac +log cat /sys/kernel/debug/qca-nss-drv/stats/drv +log cat /sys/kernel/debug/qca-nss-drv/stats/wifi +log cat /sys/kernel/debug/qca-nss-drv/stats/wifi_if +log cat /sys/kernel/debug/qca-nss-drv/stats/eth_rx diff --git a/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.hotplug b/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.hotplug new file mode 100644 index 00000000..1e481383 --- /dev/null +++ b/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.hotplug @@ -0,0 +1,70 @@ +#!/bin/sh +# +# Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +KERNEL=`uname -r` +case "${KERNEL}" in + 3.4*) + select_or_load=load_nss_fw + ;; + *) + select_or_load=select_nss_fw + ;; +esac + +load_nss_fw () { + ls -l $1 | awk ' { print $9,$5 } '> /dev/console + echo 1 > /sys/class/firmware/$DEVICENAME/loading + cat $1 > /sys/class/firmware/$DEVICENAME/data + echo 0 > /sys/class/firmware/$DEVICENAME/loading +} + +select_nss_fw () { + rm -f /lib/firmware/$DEVICENAME + ln -s $1 /lib/firmware/$DEVICENAME + ls -l /lib/firmware/$DEVICENAME | awk ' { print $9,$5 } '> /dev/console +} + +[ "$ACTION" != "add" ] && exit + +# dev name for UCI, since it doesn't let you use . or - +SDEVNAME=$(echo ${DEVICENAME} | sed s/[.-]/_/g) + +SELECTED_FW=$(uci get nss.${SDEVNAME}.firmware 2>/dev/null) +[ -e "${SELECTED_FW}" ] && { + $select_or_load ${SELECTED_FW} + exit +} + +case $DEVICENAME in + qca-nss0* | qca-nss.0*) + if [ -e /lib/firmware/qca-nss0-enterprise.bin ] ; then + $select_or_load /lib/firmware/qca-nss0-enterprise.bin + else + $select_or_load /lib/firmware/qca-nss0-retail.bin + fi + exit + ;; + qca-nss1* | qca-nss.1*) + if [ -e /lib/firmware/qca-nss1-enterprise.bin ] ; then + $select_or_load /lib/firmware/qca-nss1-enterprise.bin + else + $select_or_load /lib/firmware/qca-nss1-retail.bin + fi + exit + ;; +esac + diff --git a/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.init b/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.init new file mode 100644 index 00000000..de12cb6d --- /dev/null +++ b/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.init @@ -0,0 +1,50 @@ +#!/bin/sh /etc/rc.common +# +# Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +START=70 + +enable_rps() { + irq_nss_rps=`grep nss_queue1 /proc/interrupts | cut -d ':' -f 1 | tr -d ' '` + for entry in $irq_nss_rps + do + echo 2 > /proc/irq/$entry/smp_affinity + done + + irq_nss_rps=`grep nss_queue2 /proc/interrupts | cut -d ':' -f 1 | tr -d ' '` + for entry in $irq_nss_rps + do + echo 4 > /proc/irq/$entry/smp_affinity + done + + irq_nss_rps=`grep nss_queue3 /proc/interrupts | cut -d ':' -f 1 | tr -d ' '` + for entry in $irq_nss_rps + do + echo 8 > /proc/irq/$entry/smp_affinity + done + + # Enable NSS RPS + sysctl -w dev.nss.rps.enable=1 >/dev/null 2>/dev/null + +} + + +start() { + local rps_enabled="$(uci_get nss @general[0] enable_rps)" + if [ "$rps_enabled" -eq 1 ]; then + enable_rps + fi +} diff --git a/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.sysctl b/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.sysctl new file mode 100644 index 00000000..fc36c33e --- /dev/null +++ b/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.sysctl @@ -0,0 +1,4 @@ +# Default Number of connection configuration +dev.nss.ipv4cfg.ipv4_conn=4096 +dev.nss.ipv6cfg.ipv6_conn=4096 + diff --git a/root/package/qca/nss/qca-nss-drv/patches/100-kernel-5.4-support.patch b/root/package/qca/nss/qca-nss-drv/patches/100-kernel-5.4-support.patch new file mode 100644 index 00000000..4268225c --- /dev/null +++ b/root/package/qca/nss/qca-nss-drv/patches/100-kernel-5.4-support.patch @@ -0,0 +1,107 @@ +diff --git a/Makefile b/Makefile +index d998548..b1a4a83 100644 +--- a/Makefile ++++ b/Makefile +@@ -161,7 +161,7 @@ endif + ccflags-y += -I$(obj)/nss_hal/include -I$(obj)/nss_data_plane/include -I$(obj)/exports -DNSS_DEBUG_LEVEL=0 -DNSS_PKT_STATS_ENABLED=1 + + ccflags-y += -DNSS_PM_DEBUG_LEVEL=0 -DNSS_SKB_REUSE_SUPPORT=1 +-ccflags-y += -Werror ++# ccflags-y += -Werror + + ifneq ($(findstring 3.4, $(KERNELVERSION)),) + NSS_CCFLAGS = -DNSS_DT_SUPPORT=0 -DNSS_FW_DBG_SUPPORT=1 -DNSS_PM_SUPPORT=1 -DNSS_EMPTY_BUFFER_SIZE=1984 +diff --git a/nss_core.c b/nss_core.c +index 6c9716a..8956eb5 100644 +--- a/nss_core.c ++++ b/nss_core.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include "nss_tx_rx_common.h" + #include "nss_data_plane.h" + +@@ -45,7 +46,8 @@ + (((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0)))) || \ + (((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0)))) || \ + (((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)))) || \ +-(((LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0)))))) ++(((LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0)))) || \ ++(((LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(5, 5, 0)))))) + #error "Check skb recycle code in this file to match Linux version" + #endif + +@@ -395,7 +397,11 @@ static void nss_get_ddr_info(struct nss_mmu_ddr_info *mmu, char *name) + struct device_node *node; + + si_meminfo(&vals); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) ++ cached = global_zone_page_state(NR_FILE_PAGES); ++#else + cached = global_page_state(NR_FILE_PAGES); ++#endif /*KERNEL_VERSION(4, 14, 0)*/ + avail_ddr = (vals.totalram + cached + vals.sharedram) * vals.mem_unit; + + /* +@@ -679,7 +685,11 @@ static inline void nss_core_handle_virt_if_pkt(struct nss_ctx_instance *nss_ctx, + * Mimic Linux behavior to allow multi-queue netdev choose which queue to use + */ + if (ndev->netdev_ops->ndo_select_queue) { ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) ++ queue_offset = ndev->netdev_ops->ndo_select_queue(ndev, nbuf, NULL); ++#else + queue_offset = ndev->netdev_ops->ndo_select_queue(ndev, nbuf, NULL, NULL); ++#endif /*KERNEL_VERSION(5, 3, 0)*/ + } + + skb_set_queue_mapping(nbuf, queue_offset); +@@ -2269,7 +2279,11 @@ static inline bool nss_skb_can_reuse(struct nss_ctx_instance *nss_ctx, + * This check is added to avoid deadlock from nf_conntrack + * when ecm is trying to flush a rule. + */ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) ++ if (unlikely(skb_nfct(nbuf))) { ++#else + if (unlikely(nbuf->nfct)) { ++#endif /*KERNEL_VERSION(4, 11, 0)*/ + return false; + } + #endif +@@ -2279,7 +2285,11 @@ static inline bool nss_skb_can_reuse(struct nss_ctx_instance *nss_ctx, + * This check is added to avoid deadlock from nf_bridge + * when ecm is trying to flush a rule. + */ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) ++ if (unlikely(skb_ext_exist(nbuf, SKB_EXT_BRIDGE_NF))) { ++#else + if (unlikely(nbuf->nf_bridge)) { ++#endif /*KERNEL_VERSION(4, 11, 0)*/ + return false; + } + #endif +diff --git a/nss_n2h.c b/nss_n2h.c +index 781ce2b..695ac13 100644 +--- a/nss_n2h.c ++++ b/nss_n2h.c +@@ -19,6 +19,7 @@ + * NSS N2H node APIs + */ + ++#include + #include "nss_tx_rx_common.h" + #include "nss_n2h_stats.h" + + +--- a/nss_data_plane/nss_data_plane_gmac.c ++++ b/nss_data_plane/nss_data_plane_gmac.c +@@ -20,7 +20,7 @@ + #include "nss_tx_rx_common.h" + #include + +-#define NSS_DP_GMAC_SUPPORTED_FEATURES (NETIF_F_HIGHDMA | NETIF_F_HW_CSUM | NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_FRAGLIST | (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_UFO)) ++#define NSS_DP_GMAC_SUPPORTED_FEATURES (NETIF_F_HIGHDMA | NETIF_F_HW_CSUM | NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_FRAGLIST | (NETIF_F_TSO | NETIF_F_TSO6)) + #define NSS_DATA_PLANE_GMAC_MAX_INTERFACES 4 + + static DEFINE_SPINLOCK(nss_data_plane_gmac_stats_lock); diff --git a/root/package/qca/nss/qca-nss-drv/patches/101-nss-drv-Control-fab-scaling-from-package-Makefile.patch b/root/package/qca/nss/qca-nss-drv/patches/101-nss-drv-Control-fab-scaling-from-package-Makefile.patch new file mode 100644 index 00000000..b0facc85 --- /dev/null +++ b/root/package/qca/nss/qca-nss-drv/patches/101-nss-drv-Control-fab-scaling-from-package-Makefile.patch @@ -0,0 +1,38 @@ +From 40d4b080f17883ac6b39c74a5feb1af384ab6a51 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Thu, 11 Jun 2020 16:57:39 +0200 +Subject: [PATCH] nss-drv: Control fab scaling from package Makefile + +Lets control the fab scaling from the package Makefile +instead of using kernel checks that dont work. +Fab scaling in OpenWrt is done in a external way. + +Signed-off-by: Robert Marko +--- + Makefile | 9 --------- + 1 file changed, 9 deletions(-) + +diff --git a/Makefile b/Makefile +index 20729ab..2567dd4 100644 +--- a/Makefile ++++ b/Makefile +@@ -405,15 +405,8 @@ NSS_CCFLAGS = -DNSS_DT_SUPPORT=1 -DNSS_FW_DBG_SUPPORT=0 -DNSS_PM_SUPPORT=0 + ccflags-y += -I$(obj) + endif + +-# Fabric scaling is supported in 3.14 and 4.4 only +-ifneq ($(findstring 3.14, $(KERNELVERSION)),) +-NSS_CCFLAGS += -DNSS_FABRIC_SCALING_SUPPORT=1 +-else ifneq ($(findstring 4.4, $(KERNELVERSION)),) +-NSS_CCFLAGS += -DNSS_FABRIC_SCALING_SUPPORT=1 +-else +-NSS_CCFLAGS += -DNSS_FABRIC_SCALING_SUPPORT=0 +-endif ++NSS_CCFLAGS += -DNSS_FABRIC_SCALING_SUPPORT=0 + + # Disable Frequency scaling + ifeq "$(NSS_FREQ_SCALE_DISABLE)" "y" + ccflags-y += -DNSS_FREQ_SCALE_SUPPORT=0 +-- +2.26.2 + diff --git a/root/package/qca/nss/qca-nss-drv/patches/200-fix-NULL-pointer-exception.patch b/root/package/qca/nss/qca-nss-drv/patches/200-fix-NULL-pointer-exception.patch new file mode 100644 index 00000000..3d8bba95 --- /dev/null +++ b/root/package/qca/nss/qca-nss-drv/patches/200-fix-NULL-pointer-exception.patch @@ -0,0 +1,11 @@ +--- a/nss_core.c ++++ b/nss_core.c +@@ -1599,7 +1599,7 @@ static int32_t nss_core_handle_cause_que + * + */ + if (unlikely((buffer_type == N2H_BUFFER_CRYPTO_RESP))) { +- dma_unmap_single(NULL, (desc->buffer + desc->payload_offs), desc->payload_len, DMA_FROM_DEVICE); ++ dma_unmap_single(nss_ctx->dev, (desc->buffer + desc->payload_offs), desc->payload_len, DMA_FROM_DEVICE); + goto consume; + } + diff --git a/root/package/qca/nss/qca-nss-drv/patches/201-Fix-Kernel-Panic-dma-with-NULL-dev.patch b/root/package/qca/nss/qca-nss-drv/patches/201-Fix-Kernel-Panic-dma-with-NULL-dev.patch new file mode 100644 index 00000000..addfef1b --- /dev/null +++ b/root/package/qca/nss/qca-nss-drv/patches/201-Fix-Kernel-Panic-dma-with-NULL-dev.patch @@ -0,0 +1,82 @@ +From 89949decfd9a0f86427b502aae4fbc3a3ef399f0 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Tue, 23 Jun 2020 19:50:28 +0200 +Subject: [PATCH] Fix Kernel Panic dma with NULL dev + +--- + nss_coredump.c | 4 ++-- + nss_log.c | 8 +++++--- + 2 files changed, 8 insertions(+), 6 deletions(-) + +diff --git a/nss_coredump.c b/nss_coredump.c +index aa4ba82..957eca0 100644 +--- a/nss_coredump.c ++++ b/nss_coredump.c +@@ -154,7 +154,7 @@ void nss_fw_coredump_notify(struct nss_ctx_instance *nss_own, + dma_addr = nss_own->meminfo_ctx.logbuffer_dma; + } + +- dma_sync_single_for_cpu(NULL, dma_addr, sizeof(struct nss_log_descriptor), DMA_FROM_DEVICE); ++ dma_sync_single_for_cpu(nss_own->dev, dma_addr, sizeof(struct nss_log_descriptor), DMA_FROM_DEVICE); + + /* + * If the current entry is smaller than or equal to the number of NSS_LOG_COREDUMP_LINE_NUM, +@@ -181,7 +181,7 @@ void nss_fw_coredump_notify(struct nss_ctx_instance *nss_own, + + offset = (index * sizeof(struct nss_log_entry)) + + offsetof(struct nss_log_descriptor, log_ring_buffer); +- dma_sync_single_for_cpu(NULL, dma_addr + offset, ++ dma_sync_single_for_cpu(nss_own->dev, dma_addr + offset, + sizeof(struct nss_log_entry), DMA_FROM_DEVICE); + nss_info_always("%p: %s\n", nss_own, nle_print->message); + nle_print++; +diff --git a/nss_log.c b/nss_log.c +index 06ebba4..f9bd6c8 100644 +--- a/nss_log.c ++++ b/nss_log.c +@@ -44,6 +44,7 @@ struct nss_log_data { + uint32_t last_entry; /* Last known sampled entry (or index) */ + uint32_t nentries; /* Caches the total number of entries of log buffer */ + int nss_id; /* NSS Core id being used */ ++ struct device *nss_dev; + }; + + struct nss_log_ring_buffer_addr nss_rbe[NSS_MAX_CORES]; +@@ -125,6 +126,7 @@ static int nss_log_open(struct inode *inode, struct file *filp) + data->last_entry = 0; + data->nentries = nss_rbe[nss_id].nentries; + data->dma_addr = nss_rbe[nss_id].dma_addr; ++ data->nss_dev = nss_ctx->dev; + + /* + * Increment the reference count so that we don't free +@@ -207,7 +209,7 @@ static ssize_t nss_log_read(struct file *filp, char __user *buf, size_t size, lo + /* + * Get the current index + */ +- dma_sync_single_for_cpu(NULL, data->dma_addr, sizeof(struct nss_log_descriptor), DMA_FROM_DEVICE); ++ dma_sync_single_for_cpu(data->nss_dev, data->dma_addr, sizeof(struct nss_log_descriptor), DMA_FROM_DEVICE); + entry = nss_log_current_entry(desc); + + /* +@@ -251,7 +253,7 @@ static ssize_t nss_log_read(struct file *filp, char __user *buf, size_t size, lo + offset = (offset * sizeof(struct nss_log_entry)) + + offsetof(struct nss_log_descriptor, log_ring_buffer); + +- dma_sync_single_for_cpu(NULL, data->dma_addr + offset, ++ dma_sync_single_for_cpu(data->nss_dev, data->dma_addr + offset, + sizeof(struct nss_log_entry), DMA_FROM_DEVICE); + rb = &desc->log_ring_buffer[index]; + +@@ -510,7 +512,7 @@ bool nss_debug_log_buffer_alloc(uint8_t nss_id, uint32_t nentry) + return true; + + fail: +- dma_unmap_single(NULL, dma_addr, size, DMA_FROM_DEVICE); ++ dma_unmap_single(nss_ctx->dev, dma_addr, size, DMA_FROM_DEVICE); + kfree(addr); + wake_up(&nss_log_wq); + return false; +-- +2.27.0 + diff --git a/root/package/qca/nss/qca-nss-drv/patches/400-Exported-set-nexthop-function.patch b/root/package/qca/nss/qca-nss-drv/patches/400-Exported-set-nexthop-function.patch new file mode 100644 index 00000000..8c0ffe77 --- /dev/null +++ b/root/package/qca/nss/qca-nss-drv/patches/400-Exported-set-nexthop-function.patch @@ -0,0 +1,47 @@ +From f8cf061454a3707c0c84d0fca685e84455f91362 Mon Sep 17 00:00:00 2001 +From: Suruchi Suman +Date: Tue, 3 Dec 2019 12:57:38 +0530 +Subject: [qca-nss-drv] Exported set nexhop function from drv. + +Change-Id: I3df6658bef72fe574ac9acfb7aac61785769766f +Signed-off-by: Suruchi Suman +--- + nss_phys_if.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/nss_phys_if.c b/nss_phys_if.c +index 4f9b20f..0c58d95 100644 +--- a/nss_phys_if.c ++++ b/nss_phys_if.c +@@ -1,6 +1,6 @@ + /* + ************************************************************************** +- * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved. + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. +@@ -583,6 +583,12 @@ nss_tx_status_t nss_phys_if_set_nexthop(struct nss_ctx_instance *nss_ctx, uint32 + struct nss_phys_if_msg nim; + + NSS_VERIFY_CTX_MAGIC(nss_ctx); ++ ++ if (nexthop >= NSS_MAX_NET_INTERFACES) { ++ nss_warning("%p: Invalid nexthop interface number: %d", nss_ctx, nexthop); ++ return NSS_TX_FAILURE_BAD_PARAM; ++ } ++ + nss_info("%p: Phys If nexthop will be set to %d, id:%d\n", nss_ctx, nexthop, if_num); + + nss_cmn_msg_init(&nim.cm, if_num, NSS_PHYS_IF_SET_NEXTHOP, +@@ -591,6 +597,7 @@ nss_tx_status_t nss_phys_if_set_nexthop(struct nss_ctx_instance *nss_ctx, uint32 + + return nss_phys_if_msg_sync(nss_ctx, &nim); + } ++EXPORT_SYMBOL(nss_phys_if_set_nexthop); + + /* + * nss_get_state() +-- +cgit v1.1 + diff --git a/root/package/qca/nss/qca-nss-ecm-64/Makefile b/root/package/qca/nss/qca-nss-ecm-64/Makefile new file mode 100644 index 00000000..a22d3285 --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm-64/Makefile @@ -0,0 +1,96 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=qca-nss-ecm-64 +PKG_RELEASE:=$(AUTORELEASE) + +PKG_SOURCE_URL:=https://source.codeaurora.org/quic/cc-qrdk/oss/lklm/qca-nss-ecm +PKG_SOURCE_PROTO:=git +PKG_SOURCE_DATE:=2021-04-29 +PKG_SOURCE_VERSION:=c115aec34867b582e2e5ea79fc5315971e0e953c +PKG_MIRROR_HASH:=962385b45daa2e552a15018bf2930c2df1f6f575d885375bf935a142b4255da5 + +PKG_BUILD_PARALLEL:=1 + +include $(INCLUDE_DIR)/kernel.mk +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/qca-nss-ecm-64 + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Support + DEPENDS:=@(TARGET_ipq807x||TARGET_ipq60xx) \ + +kmod-qca-nss-drv-64 \ + +iptables-mod-extra \ + +kmod-ipt-conntrack \ + +kmod-ipt-physdev \ + +iptables-mod-physdev \ + +kmod-ppp \ + +kmod-pppoe + TITLE:=QCA NSS Enhanced Connection Manager (ECM) + FILES:=$(PKG_BUILD_DIR)/*.ko + KCONFIG:=CONFIG_BRIDGE_NETFILTER=y \ + CONFIG_NF_CONNTRACK_EVENTS=y \ + CONFIG_NF_CONNTRACK_CHAIN_EVENTS=y \ + CONFIG_NF_CONNTRACK_DSCPREMARK_EXT=n +endef + +define KernelPackage/qca-nss-ecm-64/Description +This package contains the QCA NSS Enhanced Connection Manager +endef + +define KernelPackage/qca-nss-ecm-64/install + $(INSTALL_DIR) $(1)/etc/firewall.d $(1)/etc/init.d $(1)/usr/bin $(1)/lib/netifd/offload $(1)/etc/config $(1)/etc/uci-defaults $(1)/etc/sysctl.d + $(INSTALL_DATA) ./files/qca-nss-ecm.firewall $(1)/etc/firewall.d/qca-nss-ecm + $(INSTALL_BIN) ./files/qca-nss-ecm.init $(1)/etc/init.d/qca-nss-ecm + $(INSTALL_BIN) ./files/ecm_dump.sh $(1)/usr/bin/ + $(INSTALL_BIN) ./files/on-demand-down $(1)/lib/netifd/offload/on-demand-down + $(INSTALL_DATA) ./files/qca-nss-ecm.uci $(1)/etc/config/ecm + $(INSTALL_DATA) ./files/qca-nss-ecm.defaults $(1)/etc/uci-defaults/99-qca-nss-ecm + $(INSTALL_BIN) ./files/qca-nss-ecm.sysctl $(1)/etc/sysctl.d/qca-nss-ecm.conf +endef + +EXTRA_CFLAGS+=-I$(STAGING_DIR)/usr/include/qca-nss-drv + +ifneq (, $(findstring $(CONFIG_TARGET_BOARD), "ipq807x" "ipq60xx")) +ECM_MAKE_OPTS+= ECM_FRONT_END_NSS_ENABLE=y \ + ECM_CLASSIFIER_HYFI_ENABLE=n \ + ECM_MULTICAST_ENABLE=n \ + ECM_INTERFACE_IPSEC_ENABLE=n \ + ECM_INTERFACE_PPTP_ENABLE=n \ + ECM_INTERFACE_L2TPV2_ENABLE=n \ + ECM_INTERFACE_GRE_TAP_ENABLE=n \ + ECM_INTERFACE_GRE_TUN_ENABLE=n \ + ECM_INTERFACE_SIT_ENABLE=n \ + ECM_INTERFACE_TUNIPIP6_ENABLE=n \ + ECM_INTERFACE_RAWIP_ENABLE=n \ + ECM_INTERFACE_VLAN_ENABLE=n \ + ECM_CLASSIFIER_MARK_ENABLE=n \ + ECM_CLASSIFIER_DSCP_ENABLE=n \ + ECM_CLASSIFIER_PCC_ENABLE=n \ + ECM_BAND_STEERING_ENABLE=n \ + ECM_INTERFACE_PPPOE_ENABLE=y +endif + +ifeq ($(CONFIG_TARGET_BOARD), "ipq807x") + SOC="ipq807x_64" +else ifeq ($(CONFIG_TARGET_BOARD), "ipq60xx") + SOC="ipq60xx_64" +endif + +define Build/InstallDev + mkdir -p $(1)/usr/include/qca-nss-ecm + $(CP) $(PKG_BUILD_DIR)/exports/* $(1)/usr/include/qca-nss-ecm +endef + +define Build/Compile + +$(MAKE) -C "$(LINUX_DIR)" $(strip $(ECM_MAKE_OPTS)) \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + ARCH="$(LINUX_KARCH)" \ + M="$(PKG_BUILD_DIR)" \ + EXTRA_CFLAGS="$(EXTRA_CFLAGS)" SoC=$(SOC) \ + $(KERNEL_MAKE_FLAGS) \ + $(PKG_JOBS) \ + modules +endef + +$(eval $(call KernelPackage,qca-nss-ecm-64)) diff --git a/root/package/qca/nss/qca-nss-ecm-64/files/ecm_dump.sh b/root/package/qca/nss/qca-nss-ecm-64/files/ecm_dump.sh new file mode 100644 index 00000000..dbf7de75 --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm-64/files/ecm_dump.sh @@ -0,0 +1,95 @@ +#!/bin/sh +# +# Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +ECM_MODULE=${1:-ecm_state} +MOUNT_ROOT=/dev/ecm + +# +# usage: ecm_dump.sh [module=ecm_db] +# +# with no parameters, ecm_dump.sh will attempt to mount the +# ecm_db state file and cat its contents. +# +# example with a parameter: ecm_dump.sh ecm_classifier_default +# +# this will cause ecm_dump to attempt to find and mount the state +# file for the ecm_classifier_default module, and if successful +# cat the contents. +# + +# this is one of the state files, which happens to be the +# last module started in ecm +ECM_STATE=/sys/kernel/debug/ecm/ecm_state/state_dev_major + +# tests to see if ECM is up and ready to receive commands. +# returns 0 if ECM is fully up and ready, else 1 +ecm_is_ready() { + if [ ! -e "${ECM_STATE}" ] + then + return 1 + fi + return 0 +} + +# +# module_state_mount(module_name) +# Mounts the state file of the module, if supported +# +module_state_mount() { + local module_name=$1 + local mount_dir=$2 + local state_file="/sys/kernel/debug/ecm/${module_name}/state_dev_major" + + if [ -e "${mount_dir}/${module_name}" ] + then + # already mounted + return 0 + fi + + #echo "Mount state file for $module_name ..." + if [ ! -e "$state_file" ] + then + #echo "... $module_name does not support state" + return 1 + fi + + local major="`cat $state_file`" + #echo "... Mounting state $state_file with major: $major" + mknod "${mount_dir}/${module_name}" c $major 0 +} + +# +# main +# +ecm_is_ready || { + #echo "ECM is not running" + exit 1 +} + +# all state files are mounted under MOUNT_ROOT, so make sure it exists +mkdir -p ${MOUNT_ROOT} + +# +# attempt to mount state files for the requested module and cat it +# if the mount succeeded +# +module_state_mount ${ECM_MODULE} ${MOUNT_ROOT} && { + cat ${MOUNT_ROOT}/${ECM_MODULE} + exit 0 +} + +exit 2 diff --git a/root/package/qca/nss/qca-nss-ecm-64/files/on-demand-down b/root/package/qca/nss/qca-nss-ecm-64/files/on-demand-down new file mode 100644 index 00000000..02d708e0 --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm-64/files/on-demand-down @@ -0,0 +1,6 @@ +#!/bin/sh +# Copyright (c) 2016 The Linux Foundation. All rights reserved. + +[ -e "/sys/kernel/debug/ecm/ecm_db/defunct_all" ] && { + echo 1 > /sys/kernel/debug/ecm/ecm_db/defunct_all +} diff --git a/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.defaults b/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.defaults new file mode 100644 index 00000000..308e265c --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.defaults @@ -0,0 +1,28 @@ +#!/bin/sh +# +# Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +uci -q batch << EOF + delete firewall.qcanssecm + set firewall.qcanssecm=include + set firewall.qcanssecm.type=script + set firewall.qcanssecm.path=/etc/firewall.d/qca-nss-ecm + set firewall.qcanssecm.family=any + set firewall.qcanssecm.reload=1 + commit firewall +EOF + +exit 0 diff --git a/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.firewall b/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.firewall new file mode 100644 index 00000000..24c64def --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.firewall @@ -0,0 +1,18 @@ +#!/bin/sh +# +# Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +iptables -A FORWARD -m physdev --physdev-is-bridged -j ACCEPT diff --git a/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.init b/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.init new file mode 100644 index 00000000..78cf16dc --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.init @@ -0,0 +1,137 @@ +#!/bin/sh /etc/rc.common +# +# Copyright (c) 2014, 2019-2020 The Linux Foundation. All rights reserved. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +# The shebang above has an extra space intentially to avoid having +# openwrt build scripts automatically enable this package starting +# at boot. + +START=19 + +get_front_end_mode() { + config_load "ecm" + config_get front_end global acceleration_engine "auto" + + case $front_end in + auto) + echo '0' + ;; + nss) + echo '1' + ;; + sfe) + echo '2' + ;; + *) + echo 'uci_option_acceleration_engine is invalid' + esac +} + +support_bridge() { + #NSS support bridge acceleration + [ -d /sys/kernel/debug/ecm/ecm_nss_ipv4 ] && return 0 + #SFE doesn't support bridge acceleration + [ -d /sys/kernel/debug/ecm/ecm_sfe_ipv4 ] && return 1 +} + +load_sfe() { + local kernel_version=$(uname -r) + + [ -e "/lib/modules/$kernel_version/shortcut-fe.ko" ] && { + [ -d /sys/module/shortcut_fe ] || insmod shortcut-fe + } + + [ -e "/lib/modules/$kernel_version/shortcut-fe-ipv6.ko" ] && { + [ -d /sys/module/shortcut_fe_ipv6 ] || insmod shortcut-fe-ipv6 + } + + [ -e "/lib/modules/$kernel_version/shortcut-fe-cm.ko" ] && { + [ -d /sys/module/shortcut_fe_cm ] || insmod shortcut-fe-cm + } + + [ -e "/lib/modules/$kernel_version/shortcut-fe-drv.ko" ] && { + [ -d /sys/module/shortcut_fe_drv ] || insmod shortcut-fe-drv + } +} + +load_ecm() { + [ -d /sys/module/ecm ] || { + [ ! -e /proc/device-tree/MP_256 ] && load_sfe + insmod ecm front_end_selection=$(get_front_end_mode) + } + + support_bridge && { + sysctl -w net.bridge.bridge-nf-call-ip6tables=1 + sysctl -w net.bridge.bridge-nf-call-iptables=1 + } +} + +unload_ecm() { + sysctl -w net.bridge.bridge-nf-call-ip6tables=0 + sysctl -w net.bridge.bridge-nf-call-iptables=0 + + if [ -d /sys/module/ecm ]; then + # + # Stop ECM frontends + # + echo 1 > /sys/kernel/debug/ecm/front_end_ipv4_stop + echo 1 > /sys/kernel/debug/ecm/front_end_ipv6_stop + + # + # Defunct the connections + # + echo 1 > /sys/kernel/debug/ecm/ecm_db/defunct_all + sleep 5; + + rmmod ecm + sleep 1 + fi +} + +start() { + load_ecm + + # If the acceleration engine is NSS, enable wifi redirect. + [ -d /sys/kernel/debug/ecm/ecm_nss_ipv4 ] && sysctl -w dev.nss.general.redirect=1 + + support_bridge && { + echo 'net.bridge.bridge-nf-call-ip6tables=1' >> /etc/sysctl.d/qca-nss-ecm.conf + echo 'net.bridge.bridge-nf-call-iptables=1' >> /etc/sysctl.d/qca-nss-ecm.conf + } + + if [ -d /sys/module/qca_ovsmgr ]; then + insmod ecm_ovs + fi + +} + +stop() { + # If ECM is already not loaded, just return. + if [ ! -d /sys/module/ecm ]; then + return + fi + + # If the acceleration engine is NSS, disable wifi redirect. + [ -d /sys/kernel/debug/ecm/ecm_nss_ipv4 ] && sysctl -w dev.nss.general.redirect=0 + + sed '/net.bridge.bridge-nf-call-ip6tables=1/d' -i /etc/sysctl.d/qca-nss-ecm.conf + sed '/net.bridge.bridge-nf-call-iptables=1/d' -i /etc/sysctl.d/qca-nss-ecm.conf + + if [ -d /sys/module/ecm_ovs ]; then + rmmod ecm_ovs + fi + + unload_ecm +} diff --git a/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.sysctl b/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.sysctl new file mode 100644 index 00000000..1a3d76b1 --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.sysctl @@ -0,0 +1,2 @@ +# nf_conntrack_tcp_no_window_check is 0 by default, set it to 1 +net.netfilter.nf_conntrack_tcp_no_window_check=1 diff --git a/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.uci b/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.uci new file mode 100644 index 00000000..4f2de687 --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.uci @@ -0,0 +1,2 @@ +config ecm 'global' + option acceleration_engine 'auto' diff --git a/root/package/qca/nss/qca-nss-ecm-64/patches/001-treewide-componentize-the-module-even-more.patch b/root/package/qca/nss/qca-nss-ecm-64/patches/001-treewide-componentize-the-module-even-more.patch new file mode 100644 index 00000000..4e7932c9 --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm-64/patches/001-treewide-componentize-the-module-even-more.patch @@ -0,0 +1,335 @@ +From 73345c87b28a473b35b57e673f8de963c3d73da1 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Wed, 19 May 2021 02:38:53 +0200 +Subject: [PATCH] treewide: componentize the module even more + +Signed-off-by: Ansuel Smith +--- + Makefile | 56 +++++++++++++++++++++++++------- + ecm_db/ecm_db_connection.c | 8 +++++ + ecm_db/ecm_db_node.c | 4 +++ + ecm_interface.c | 8 +++++ + frontends/ecm_front_end_common.c | 7 ++++ + 5 files changed, 72 insertions(+), 11 deletions(-) + +--- a/Makefile ++++ b/Makefile +@@ -82,10 +82,18 @@ ccflags-$(ECM_INTERFACE_BOND_ENABLE) += + # Define ECM_INTERFACE_PPPOE_ENABLE=y in order + # to enable support for PPPoE acceleration. + # ############################################################################# +-ECM_INTERFACE_PPPOE_ENABLE=y ++ifndef $(ECM_INTERFACE_PPPOE_ENABLE) ++ ECM_INTERFACE_PPPOE_ENABLE=y ++endif + ccflags-$(ECM_INTERFACE_PPPOE_ENABLE) += -DECM_INTERFACE_PPPOE_ENABLE + + # ############################################################################# ++# Define ECM_INTERFACE_L2TPV2_PPTP_ENABLE=y in order ++# to enable support for l2tpv2 or PPTP detection. ++# ############################################################################# ++ccflags-$(ECM_INTERFACE_L2TPV2_PPTP_ENABLE) += -DECM_INTERFACE_L2TPV2_PPTP_ENABLE ++ ++# ############################################################################# + # Define ECM_INTERFACE_L2TPV2_ENABLE=y in order + # to enable support for l2tpv2 acceleration. + # ############################################################################# +@@ -118,6 +126,12 @@ ccflags-$(ECM_INTERFACE_PPP_ENABLE) += - + ccflags-$(ECM_INTERFACE_MAP_T_ENABLE) += -DECM_INTERFACE_MAP_T_ENABLE + + # ############################################################################# ++# Define ECM_INTERFACE_GRE_ENABLE=y in order ++# to enable support for GRE detection. ++# ############################################################################# ++ccflags-$(ECM_INTERFACE_GRE_ENABLE) += -DECM_INTERFACE_GRE_ENABLE ++ ++# ############################################################################# + # Define ECM_INTERFACE_GRE_TAP_ENABLE=y in order + # to enable support for GRE TAP interface. + # ############################################################################# +@@ -186,7 +200,9 @@ ccflags-$(ECM_INTERFACE_OVS_BRIDGE_ENABL + # ############################################################################# + # Define ECM_INTERFACE_VLAN_ENABLE=y in order to enable support for VLAN + # ############################################################################# +-ECM_INTERFACE_VLAN_ENABLE=y ++ifndef $(ECM_INTERFACE_VLAN_ENABLE) ++ ECM_INTERFACE_VLAN_ENABLE=y ++endif + ccflags-$(ECM_INTERFACE_VLAN_ENABLE) += -DECM_INTERFACE_VLAN_ENABLE + + # ############################################################################# +@@ -228,7 +244,9 @@ ccflags-$(ECM_CLASSIFIER_OVS_ENABLE) += + # ############################################################################# + # Define ECM_CLASSIFIER_MARK_ENABLE=y in order to enable mark classifier. + # ############################################################################# +-ECM_CLASSIFIER_MARK_ENABLE=y ++ifndef $(ECM_CLASSIFIER_MARK_ENABLE) ++ ECM_CLASSIFIER_MARK_ENABLE=y ++endif + ecm-$(ECM_CLASSIFIER_MARK_ENABLE) += ecm_classifier_mark.o + ccflags-$(ECM_CLASSIFIER_MARK_ENABLE) += -DECM_CLASSIFIER_MARK_ENABLE + +@@ -247,7 +265,9 @@ ccflags-$(ECM_CLASSIFIER_NL_ENABLE) += - + # ############################################################################# + # Define ECM_CLASSIFIER_DSCP_ENABLE=y in order to enable DSCP classifier. + # ############################################################################# +-ECM_CLASSIFIER_DSCP_ENABLE=y ++ifndef $(ECM_CLASSIFIER_DSCP_ENABLE) ++ ECM_CLASSIFIER_DSCP_ENABLE=y ++endif + ecm-$(ECM_CLASSIFIER_DSCP_ENABLE) += ecm_classifier_dscp.o + ccflags-$(ECM_CLASSIFIER_DSCP_ENABLE) += -DECM_CLASSIFIER_DSCP_ENABLE + ccflags-$(ECM_CLASSIFIER_DSCP_IGS) += -DECM_CLASSIFIER_DSCP_IGS +@@ -274,7 +294,9 @@ endif + # the Parental Controls subsystem classifier in ECM. Currently disabled until + # customers require it / if they need to integrate their Parental Controls with it. + # ############################################################################# +-ECM_CLASSIFIER_PCC_ENABLE=y ++ifndef $(ECM_CLASSIFIER_PCC_ENABLE) ++ ECM_CLASSIFIER_PCC_ENABLE=y ++endif + ecm-$(ECM_CLASSIFIER_PCC_ENABLE) += ecm_classifier_pcc.o + ccflags-$(ECM_CLASSIFIER_PCC_ENABLE) += -DECM_CLASSIFIER_PCC_ENABLE + +@@ -301,28 +323,36 @@ ccflags-$(ECM_NON_PORTED_SUPPORT_ENABLE) + # ############################################################################# + # Define ECM_STATE_OUTPUT_ENABLE=y to support XML state output + # ############################################################################# +-ECM_STATE_OUTPUT_ENABLE=y ++ifndef $(ECM_STATE_OUTPUT_ENABLE) ++ ECM_STATE_OUTPUT_ENABLE=y ++endif + ecm-$(ECM_STATE_OUTPUT_ENABLE) += ecm_state.o + ccflags-$(ECM_STATE_OUTPUT_ENABLE) += -DECM_STATE_OUTPUT_ENABLE + + # ############################################################################# + # Define ECM_DB_ADVANCED_STATS_ENABLE to support XML state output + # ############################################################################# +-ECM_DB_ADVANCED_STATS_ENABLE=y ++ifndef $(ECM_DB_ADVANCED_STATS_ENABLE) ++ ECM_DB_ADVANCED_STATS_ENABLE=y ++endif + ccflags-$(ECM_DB_ADVANCED_STATS_ENABLE) += -DECM_DB_ADVANCED_STATS_ENABLE + + # ############################################################################# + # Define ECM_DB_CONNECTION_CROSS_REFERENCING_ENABLE=y in order to enable + # the database to track relationships between objects. + # ############################################################################# +-ECM_DB_CONNECTION_CROSS_REFERENCING_ENABLE=y ++ifndef $(ECM_DB_CONNECTION_CROSS_REFERENCING_ENABLE) ++ ECM_DB_CONNECTION_CROSS_REFERENCING_ENABLE=y ++endif + ccflags-$(ECM_DB_CONNECTION_CROSS_REFERENCING_ENABLE) += -DECM_DB_XREF_ENABLE + + # ############################################################################# + # Define ECM_TRACKER_DPI_SUPPORT_ENABLE=y in order to enable support for + # deep packet inspection and tracking of data with the trackers. + # ############################################################################# +-ECM_TRACKER_DPI_SUPPORT_ENABLE=y ++ifndef $(ECM_TRACKER_DPI_SUPPORT_ENABLE) ++ ECM_TRACKER_DPI_SUPPORT_ENABLE=y ++endif + ccflags-$(ECM_TRACKER_DPI_SUPPORT_ENABLE) += -DECM_TRACKER_DPI_SUPPORT_ENABLE + + # ############################################################################# +@@ -330,14 +360,18 @@ ccflags-$(ECM_TRACKER_DPI_SUPPORT_ENABLE + # support for the database keeping lists of connections that are assigned + # on a per TYPE of classifier basis. + # ############################################################################# +-ECM_DB_CLASSIFIER_TYPE_ASSIGNMENTS_TRACK_ENABLE=y ++ifndef $(ECM_DB_CLASSIFIER_TYPE_ASSIGNMENTS_TRACK_ENABLE) ++ ECM_DB_CLASSIFIER_TYPE_ASSIGNMENTS_TRACK_ENABLE=y ++endif + ccflags-$(ECM_DB_CLASSIFIER_TYPE_ASSIGNMENTS_TRACK_ENABLE) += -DECM_DB_CTA_TRACK_ENABLE + + # ############################################################################# + # Define ECM_BAND_STEERING_ENABLE=y in order to enable + # band steering feature. + # ############################################################################# +-ECM_BAND_STEERING_ENABLE=y ++ifndef $(ECM_BAND_STEERING_ENABLE) ++ ECM_BAND_STEERING_ENABLE=y ++endif + ccflags-$(ECM_BAND_STEERING_ENABLE) += -DECM_BAND_STEERING_ENABLE + + # ############################################################################# +--- a/ecm_db/ecm_db_connection.c ++++ b/ecm_db/ecm_db_connection.c +@@ -430,7 +430,9 @@ EXPORT_SYMBOL(ecm_db_connection_make_def + */ + void ecm_db_connection_data_totals_update(struct ecm_db_connection_instance *ci, bool is_from, uint64_t size, uint64_t packets) + { ++#ifdef ECM_DB_ADVANCED_STATS_ENABLE + int32_t i; ++#endif + + DEBUG_CHECK_MAGIC(ci, ECM_DB_CONNECTION_INSTANCE_MAGIC, "%px: magic failed\n", ci); + +@@ -529,7 +531,9 @@ EXPORT_SYMBOL(ecm_db_connection_data_tot + */ + void ecm_db_connection_data_totals_update_dropped(struct ecm_db_connection_instance *ci, bool is_from, uint64_t size, uint64_t packets) + { ++#ifdef ECM_DB_ADVANCED_STATS_ENABLE + int32_t i; ++#endif + + DEBUG_CHECK_MAGIC(ci, ECM_DB_CONNECTION_INSTANCE_MAGIC, "%px: magic failed\n", ci); + +@@ -1508,6 +1512,7 @@ void ecm_db_connection_defunct_all(void) + } + EXPORT_SYMBOL(ecm_db_connection_defunct_all); + ++#ifdef ECM_INTERFACE_OVS_BRIDGE_ENABLE + /* + * ecm_db_connection_defunct_by_classifier() + * Make defunct based on masked fields +@@ -1667,6 +1672,7 @@ next_ci: + ECM_IP_ADDR_TO_OCTAL(dest_addr_mask), dest_port_mask, proto_mask, cnt); + } + } ++#endif + + /* + * ecm_db_connection_defunct_by_port() +@@ -1956,6 +1962,7 @@ struct ecm_db_node_instance *ecm_db_conn + } + EXPORT_SYMBOL(ecm_db_connection_node_get_and_ref); + ++#ifdef ECM_DB_XREF_ENABLE + /* + * ecm_db_connection_mapping_get_and_ref_next() + * Return reference to next connection in the mapping chain in the specified direction. +@@ -1997,6 +2004,7 @@ struct ecm_db_connection_instance *ecm_d + return nci; + } + EXPORT_SYMBOL(ecm_db_connection_iface_get_and_ref_next); ++#endif + + /* + * ecm_db_connection_mapping_get_and_ref() +--- a/ecm_db/ecm_db_node.c ++++ b/ecm_db/ecm_db_node.c +@@ -224,9 +224,11 @@ EXPORT_SYMBOL(ecm_db_node_get_and_ref_ne + */ + int ecm_db_node_deref(struct ecm_db_node_instance *ni) + { ++#ifdef ECM_DB_XREF_ENABLE + #if (DEBUG_LEVEL >= 1) + int dir; + #endif ++#endif + DEBUG_CHECK_MAGIC(ni, ECM_DB_NODE_INSTANCE_MAGIC, "%px: magic failed\n", ni); + + spin_lock_bh(&ecm_db_lock); +@@ -486,9 +488,11 @@ EXPORT_SYMBOL(ecm_db_node_iface_get_and_ + void ecm_db_node_add(struct ecm_db_node_instance *ni, struct ecm_db_iface_instance *ii, uint8_t *address, + ecm_db_node_final_callback_t final, void *arg) + { ++#ifdef ECM_DB_XREF_ENABLE + #if (DEBUG_LEVEL >= 1) + int dir; + #endif ++#endif + ecm_db_node_hash_t hash_index; + struct ecm_db_listener_instance *li; + +--- a/ecm_interface.c ++++ b/ecm_interface.c +@@ -1343,6 +1343,7 @@ struct neighbour *ecm_interface_ipv6_nei + */ + bool ecm_interface_is_pptp(struct sk_buff *skb, const struct net_device *out) + { ++#ifdef ECM_INTERFACE_PPTP_ENABLE + struct net_device *in; + + /* +@@ -1367,6 +1368,7 @@ bool ecm_interface_is_pptp(struct sk_buf + } + + dev_put(in); ++#endif + return false; + } + +@@ -1379,6 +1381,7 @@ bool ecm_interface_is_pptp(struct sk_buf + */ + bool ecm_interface_is_l2tp_packet_by_version(struct sk_buff *skb, const struct net_device *out, int ver) + { ++#ifdef ECM_INTERFACE_L2TPV2_PPTP_ENABLE + uint32_t flag = 0; + struct net_device *in; + +@@ -1411,6 +1414,7 @@ bool ecm_interface_is_l2tp_packet_by_ver + } + + dev_put(in); ++#endif + return false; + } + +@@ -1423,6 +1427,7 @@ bool ecm_interface_is_l2tp_packet_by_ver + */ + bool ecm_interface_is_l2tp_pptp(struct sk_buff *skb, const struct net_device *out) + { ++#ifdef ECM_INTERFACE_L2TPV2_PPTP_ENABLE + struct net_device *in; + + /* +@@ -1445,6 +1450,7 @@ bool ecm_interface_is_l2tp_pptp(struct s + } + + dev_put(in); ++#endif + return false; + } + +@@ -6630,6 +6636,7 @@ static void ecm_interface_regenerate_con + return; + } + ++#ifdef ECM_DB_XREF_ENABLE + for (dir = 0; dir < ECM_DB_OBJ_DIR_MAX; dir++) { + /* + * Re-generate all connections associated with this interface +@@ -6645,6 +6652,7 @@ static void ecm_interface_regenerate_con + ci[dir] = cin; + } + } ++#endif + + #ifdef ECM_MULTICAST_ENABLE + /* +--- a/frontends/ecm_front_end_common.c ++++ b/frontends/ecm_front_end_common.c +@@ -106,6 +106,7 @@ bool ecm_front_end_gre_proto_is_accel_al + struct nf_conntrack_tuple *tuple, + int ip_version) + { ++#ifdef ECM_INTERFACE_GRE_ENABLE + struct net_device *dev; + struct gre_base_hdr *greh; + +@@ -117,10 +118,12 @@ bool ecm_front_end_gre_proto_is_accel_al + /* + * Case 1: PPTP locally terminated + */ ++#ifdef ECM_INTERFACE_PPTP_ENABLE + if (ecm_interface_is_pptp(skb, outdev)) { + DEBUG_TRACE("%px: PPTP GRE locally terminated - allow acceleration\n", skb); + return true; + } ++#endif + + /* + * Case 2: PPTP pass through +@@ -223,6 +226,10 @@ bool ecm_front_end_gre_proto_is_accel_al + */ + DEBUG_TRACE("%px: GRE IPv%d pass through - allow acceleration\n", skb, ip_version); + return true; ++#else ++ DEBUG_TRACE("%px: GRE%d feature is disabled - do not allow acceleration\n", skb, ip_version); ++ return false; ++#endif + } + + #ifdef ECM_CLASSIFIER_DSCP_ENABLE diff --git a/root/package/qca/nss/qca-nss-ecm-64/patches/002-kernel-5.10-support.patch b/root/package/qca/nss/qca-nss-ecm-64/patches/002-kernel-5.10-support.patch new file mode 100644 index 00000000..107b9571 --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm-64/patches/002-kernel-5.10-support.patch @@ -0,0 +1,831 @@ +From e8b642c23af9146c973e828a7f4e0fb56cfc8d0b Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Sat, 15 May 2021 03:51:14 +0200 +Subject: [PATCH] add support for kernel 5.10 + +Signed-off-by: Ansuel Smith +--- + ecm_classifier_default.c | 24 +++--------- + ecm_classifier_dscp.c | 8 +--- + ecm_classifier_emesh.c | 16 ++------ + ecm_classifier_hyfi.c | 7 +--- + ecm_classifier_mark.c | 8 +--- + ecm_classifier_ovs.c | 8 +--- + ecm_classifier_pcc.c | 8 +--- + ecm_conntrack_notifier.c | 8 +--- + ecm_db/ecm_db_connection.c | 7 +--- + ecm_db/ecm_db_host.c | 7 +--- + ecm_db/ecm_db_iface.c | 7 +--- + ecm_db/ecm_db_mapping.c | 7 +--- + ecm_db/ecm_db_node.c | 7 +--- + ecm_interface.c | 4 +- + ecm_state.c | 14 ++----- + frontends/ecm_front_end_common.c | 4 +- + frontends/ecm_front_end_ipv4.c | 7 +--- + frontends/ecm_front_end_ipv6.c | 7 +--- + frontends/nss/ecm_nss_bond_notifier.c | 8 +--- + frontends/nss/ecm_nss_ipv4.c | 49 +++++++------------------ + frontends/nss/ecm_nss_ipv6.c | 49 +++++++------------------ + frontends/nss/ecm_nss_multicast_ipv4.c | 7 +--- + frontends/nss/ecm_nss_multicast_ipv6.c | 7 +--- + frontends/nss/ecm_nss_non_ported_ipv4.c | 7 +--- + frontends/nss/ecm_nss_non_ported_ipv6.c | 7 +--- + frontends/nss/ecm_nss_ported_ipv4.c | 8 +--- + frontends/nss/ecm_nss_ported_ipv6.c | 8 +--- + frontends/sfe/ecm_sfe_ipv4.c | 49 +++++++------------------ + frontends/sfe/ecm_sfe_ipv6.c | 49 +++++++------------------ + frontends/sfe/ecm_sfe_non_ported_ipv4.c | 7 +--- + frontends/sfe/ecm_sfe_non_ported_ipv6.c | 7 +--- + frontends/sfe/ecm_sfe_ported_ipv4.c | 8 +--- + frontends/sfe/ecm_sfe_ported_ipv6.c | 8 +--- + 33 files changed, 122 insertions(+), 314 deletions(-) + +--- a/ecm_classifier_default.c ++++ b/ecm_classifier_default.c +@@ -776,26 +776,14 @@ int ecm_classifier_default_init(struct d + return -1; + } + +- if (!debugfs_create_u32("enabled", S_IRUGO | S_IWUSR, ecm_classifier_default_dentry, +- (u32 *)&ecm_classifier_default_enabled)) { +- DEBUG_ERROR("Failed to create ecm deafult classifier enabled file in debugfs\n"); +- debugfs_remove_recursive(ecm_classifier_default_dentry); +- return -1; +- } ++ debugfs_create_u32("enabled", S_IRUGO | S_IWUSR, ecm_classifier_default_dentry, ++ (u32 *)&ecm_classifier_default_enabled); + +- if (!debugfs_create_u32("accel_mode", S_IRUGO | S_IWUSR, ecm_classifier_default_dentry, +- (u32 *)&ecm_classifier_default_accel_mode)) { +- DEBUG_ERROR("Failed to create ecm deafult classifier accel_mode file in debugfs\n"); +- debugfs_remove_recursive(ecm_classifier_default_dentry); +- return -1; +- } ++ debugfs_create_u32("accel_mode", S_IRUGO | S_IWUSR, ecm_classifier_default_dentry, ++ (u32 *)&ecm_classifier_default_accel_mode); + +- if (!debugfs_create_u32("accel_delay_pkts", S_IRUGO | S_IWUSR, ecm_classifier_default_dentry, +- (u32 *)&ecm_classifier_accel_delay_pkts)) { +- DEBUG_ERROR("Failed to create accel delay packet counts in debugfs\n"); +- debugfs_remove_recursive(ecm_classifier_default_dentry); +- return -1; +- } ++ debugfs_create_u32("accel_delay_pkts", S_IRUGO | S_IWUSR, ecm_classifier_default_dentry, ++ (u32 *)&ecm_classifier_accel_delay_pkts); + + return 0; + } +--- a/ecm_classifier_dscp.c ++++ b/ecm_classifier_dscp.c +@@ -747,12 +747,8 @@ int ecm_classifier_dscp_init(struct dent + return -1; + } + +- if (!debugfs_create_u32("enabled", S_IRUGO | S_IWUSR, ecm_classifier_dscp_dentry, +- (u32 *)&ecm_classifier_dscp_enabled)) { +- DEBUG_ERROR("Failed to create dscp enabled file in debugfs\n"); +- debugfs_remove_recursive(ecm_classifier_dscp_dentry); +- return -1; +- } ++ debugfs_create_u32("enabled", S_IRUGO | S_IWUSR, ecm_classifier_dscp_dentry, ++ (u32 *)&ecm_classifier_dscp_enabled); + + return 0; + } +--- a/ecm_classifier_emesh.c ++++ b/ecm_classifier_emesh.c +@@ -977,19 +977,11 @@ int ecm_classifier_emesh_init(struct den + return -1; + } + +- if (!debugfs_create_u32("enabled", S_IRUGO | S_IWUSR, ecm_classifier_emesh_dentry, +- (u32 *)&ecm_classifier_emesh_enabled)) { +- DEBUG_ERROR("Failed to create ecm emesh classifier enabled file in debugfs\n"); +- debugfs_remove_recursive(ecm_classifier_emesh_dentry); +- return -1; +- } ++ debugfs_create_u32("enabled", S_IRUGO | S_IWUSR, ecm_classifier_emesh_dentry, ++ (u32 *)&ecm_classifier_emesh_enabled); + +- if (!debugfs_create_u32("latency_config_enabled", S_IRUGO | S_IWUSR, ecm_classifier_emesh_dentry, +- (u32 *)&ecm_classifier_emesh_latency_config_enabled)) { +- DEBUG_ERROR("Failed to create ecm emesh classifier latency config enabled file in debugfs\n"); +- debugfs_remove_recursive(ecm_classifier_emesh_dentry); +- return -1; +- } ++ debugfs_create_u32("latency_config_enabled", S_IRUGO | S_IWUSR, ecm_classifier_emesh_dentry, ++ (u32 *)&ecm_classifier_emesh_latency_config_enabled); + + /* + * Register for service prioritization notification update. +--- a/ecm_classifier_hyfi.c ++++ b/ecm_classifier_hyfi.c +@@ -1099,11 +1099,8 @@ int ecm_classifier_hyfi_rules_init(struc + goto classifier_task_cleanup; + } + +- if (!debugfs_create_u32("enabled", S_IRUGO | S_IWUSR, ecm_classifier_hyfi_dentry, +- (u32 *)&ecm_classifier_hyfi_enabled)) { +- DEBUG_ERROR("Failed to create ecm hyfi classifier enabled file in debugfs\n"); +- goto classifier_task_cleanup; +- } ++ debugfs_create_u32("enabled", S_IRUGO | S_IWUSR, ecm_classifier_hyfi_dentry, ++ (u32 *)&ecm_classifier_hyfi_enabled); + + if (!debugfs_create_file("cmd", S_IWUSR, ecm_classifier_hyfi_dentry, + NULL, &ecm_classifier_hyfi_cmd_fops)) { +--- a/ecm_classifier_mark.c ++++ b/ecm_classifier_mark.c +@@ -753,12 +753,8 @@ int ecm_classifier_mark_init(struct dent + return -1; + } + +- if (!debugfs_create_u32("enabled", S_IRUGO | S_IWUSR, ecm_classifier_mark_dentry, +- (u32 *)&ecm_classifier_mark_enabled)) { +- DEBUG_ERROR("Failed to create mark enabled file in debugfs\n"); +- debugfs_remove_recursive(ecm_classifier_mark_dentry); +- return -1; +- } ++ debugfs_create_u32("enabled", S_IRUGO | S_IWUSR, ecm_classifier_mark_dentry, ++ (u32 *)&ecm_classifier_mark_enabled); + + return 0; + } +--- a/ecm_classifier_ovs.c ++++ b/ecm_classifier_ovs.c +@@ -2200,12 +2200,8 @@ int ecm_classifier_ovs_init(struct dentr + return -1; + } + +- if (!debugfs_create_u32("enabled", S_IRUGO | S_IWUSR, ecm_classifier_ovs_dentry, +- (u32 *)&ecm_classifier_ovs_enabled)) { +- DEBUG_ERROR("Failed to create ovs enabled file in debugfs\n"); +- debugfs_remove_recursive(ecm_classifier_ovs_dentry); +- return -1; +- } ++ debugfs_create_u32("enabled", S_IRUGO | S_IWUSR, ecm_classifier_ovs_dentry, ++ (u32 *)&ecm_classifier_ovs_enabled); + + return 0; + } +--- a/ecm_classifier_pcc.c ++++ b/ecm_classifier_pcc.c +@@ -1308,12 +1308,8 @@ int ecm_classifier_pcc_init(struct dentr + return -1; + } + +- if (!debugfs_create_u32("enabled", S_IRUGO, ecm_classifier_pcc_dentry, +- (u32 *)&ecm_classifier_pcc_enabled)) { +- DEBUG_ERROR("Failed to create pcc enabled file in debugfs\n"); +- debugfs_remove_recursive(ecm_classifier_pcc_dentry); +- return -1; +- } ++ debugfs_create_u32("enabled", S_IRUGO, ecm_classifier_pcc_dentry, ++ (u32 *)&ecm_classifier_pcc_enabled); + + return 0; + } +--- a/ecm_conntrack_notifier.c ++++ b/ecm_conntrack_notifier.c +@@ -414,12 +414,8 @@ int ecm_conntrack_notifier_init(struct d + return -1; + } + +- if (!debugfs_create_u32("stop", S_IRUGO | S_IWUSR, ecm_conntrack_notifier_dentry, +- (u32 *)&ecm_conntrack_notifier_stopped)) { +- DEBUG_ERROR("Failed to create ecm conntrack notifier stopped file in debugfs\n"); +- debugfs_remove_recursive(ecm_conntrack_notifier_dentry); +- return -1; +- } ++ debugfs_create_u32("stop", S_IRUGO | S_IWUSR, ecm_conntrack_notifier_dentry, ++ (u32 *)&ecm_conntrack_notifier_stopped); + + #ifdef CONFIG_NF_CONNTRACK_EVENTS + /* +--- a/ecm_db/ecm_db_connection.c ++++ b/ecm_db/ecm_db_connection.c +@@ -3642,11 +3642,8 @@ static struct file_operations ecm_db_con + */ + bool ecm_db_connection_init(struct dentry *dentry) + { +- if (!debugfs_create_u32("connection_count", S_IRUGO, dentry, +- (u32 *)&ecm_db_connection_count)) { +- DEBUG_ERROR("Failed to create ecm db connection count file in debugfs\n"); +- return false; +- } ++ debugfs_create_u32("connection_count", S_IRUGO, dentry, ++ (u32 *)&ecm_db_connection_count); + + if (!debugfs_create_file("connection_count_simple", S_IRUGO, dentry, + NULL, &ecm_db_connection_count_simple_fops)) { +--- a/ecm_db/ecm_db_host.c ++++ b/ecm_db/ecm_db_host.c +@@ -770,11 +770,8 @@ EXPORT_SYMBOL(ecm_db_host_alloc); + bool ecm_db_host_init(struct dentry *dentry) + { + +- if (!debugfs_create_u32("host_count", S_IRUGO, dentry, +- (u32 *)&ecm_db_host_count)) { +- DEBUG_ERROR("Failed to create ecm db host count file in debugfs\n"); +- return false;; +- } ++ debugfs_create_u32("host_count", S_IRUGO, dentry, ++ (u32 *)&ecm_db_host_count); + + ecm_db_host_table = vzalloc(sizeof(struct ecm_db_host_instance *) * ECM_DB_HOST_HASH_SLOTS); + if (!ecm_db_host_table) { +--- a/ecm_db/ecm_db_iface.c ++++ b/ecm_db/ecm_db_iface.c +@@ -3670,11 +3670,8 @@ EXPORT_SYMBOL(ecm_db_iface_alloc); + */ + bool ecm_db_iface_init(struct dentry *dentry) + { +- if (!debugfs_create_u32("iface_count", S_IRUGO, dentry, +- (u32 *)&ecm_db_iface_count)) { +- DEBUG_ERROR("Failed to create ecm db iface count file in debugfs\n"); +- return false; +- } ++ debugfs_create_u32("iface_count", S_IRUGO, dentry, ++ (u32 *)&ecm_db_iface_count); + + return true; + } +--- a/ecm_db/ecm_db_mapping.c ++++ b/ecm_db/ecm_db_mapping.c +@@ -806,11 +806,8 @@ EXPORT_SYMBOL(ecm_db_mapping_alloc); + */ + bool ecm_db_mapping_init(struct dentry *dentry) + { +- if (!debugfs_create_u32("mapping_count", S_IRUGO, dentry, +- (u32 *)&ecm_db_mapping_count)) { +- DEBUG_ERROR("Failed to create ecm db mapping count file in debugfs\n"); +- return false; +- } ++ debugfs_create_u32("mapping_count", S_IRUGO, dentry, ++ (u32 *)&ecm_db_mapping_count); + + ecm_db_mapping_table = vzalloc(sizeof(struct ecm_db_mapping_instance *) * ECM_DB_MAPPING_HASH_SLOTS); + if (!ecm_db_mapping_table) { +--- a/ecm_db/ecm_db_node.c ++++ b/ecm_db/ecm_db_node.c +@@ -1187,11 +1187,8 @@ keep_sni_conn: + */ + bool ecm_db_node_init(struct dentry *dentry) + { +- if (!debugfs_create_u32("node_count", S_IRUGO, dentry, +- (u32 *)&ecm_db_node_count)) { +- DEBUG_ERROR("Failed to create ecm db node count file in debugfs\n"); +- return false; +- } ++ debugfs_create_u32("node_count", S_IRUGO, dentry, ++ (u32 *)&ecm_db_node_count); + + ecm_db_node_table = vzalloc(sizeof(struct ecm_db_node_instance *) * ECM_DB_NODE_HASH_SLOTS); + if (!ecm_db_node_table) { +--- a/ecm_interface.c ++++ b/ecm_interface.c +@@ -332,7 +332,7 @@ static struct net_device *ecm_interface_ + struct net_device *dev; + + ECM_IP_ADDR_TO_NIN6_ADDR(addr6, addr); +- dev = (struct net_device *)ipv6_dev_find(&init_net, &addr6, 1); ++ dev = (struct net_device *)ipv6_dev_find_and_hold(&init_net, &addr6, 1); + return dev; + } + #endif +@@ -734,7 +734,7 @@ static bool ecm_interface_mac_addr_get_i + * Get the MAC address that corresponds to IP address given. + */ + ECM_IP_ADDR_TO_NIN6_ADDR(daddr, addr); +- local_dev = ipv6_dev_find(&init_net, &daddr, 1); ++ local_dev = ipv6_dev_find_and_hold(&init_net, &daddr, 1); + if (local_dev) { + DEBUG_TRACE("%pi6 is a local address\n", &daddr); + memcpy(mac_addr, dev->dev_addr, ETH_ALEN); +--- a/ecm_state.c ++++ b/ecm_state.c +@@ -899,17 +899,11 @@ int ecm_state_init(struct dentry *dentry + return -1; + } + +- if (!debugfs_create_u32("state_dev_major", S_IRUGO, ecm_state_dentry, +- (u32 *)&ecm_state_dev_major_id)) { +- DEBUG_ERROR("Failed to create ecm state dev major file in debugfs\n"); +- goto init_cleanup; +- } ++ debugfs_create_u32("state_dev_major", S_IRUGO, ecm_state_dentry, ++ (u32 *)&ecm_state_dev_major_id); + +- if (!debugfs_create_u32("state_file_output_mask", S_IRUGO | S_IWUSR, ecm_state_dentry, +- (u32 *)&ecm_state_file_output_mask)) { +- DEBUG_ERROR("Failed to create ecm state output mask file in debugfs\n"); +- goto init_cleanup; +- } ++ debugfs_create_u32("state_file_output_mask", S_IRUGO | S_IWUSR, ecm_state_dentry, ++ (u32 *)&ecm_state_file_output_mask); + + /* + * Register a char device that we will use to provide a dump of our state +--- a/frontends/ecm_front_end_common.c ++++ b/frontends/ecm_front_end_common.c +@@ -192,7 +192,7 @@ bool ecm_front_end_gre_proto_is_accel_al + return false; + } + } else { +- dev = ipv6_dev_find(&init_net, &(tuple->src.u3.in6), 1); ++ dev = ipv6_dev_find_and_hold(&init_net, &(tuple->src.u3.in6), 1); + if (dev) { + /* + * Source IP address is local +@@ -202,7 +202,7 @@ bool ecm_front_end_gre_proto_is_accel_al + return false; + } + +- dev = ipv6_dev_find(&init_net, &(tuple->dst.u3.in6), 1); ++ dev = ipv6_dev_find_and_hold(&init_net, &(tuple->dst.u3.in6), 1); + if (dev) { + /* + * Destination IP address is local +--- a/frontends/ecm_front_end_ipv4.c ++++ b/frontends/ecm_front_end_ipv4.c +@@ -376,11 +376,8 @@ void ecm_front_end_ipv4_stop(int num) + */ + int ecm_front_end_ipv4_init(struct dentry *dentry) + { +- if (!debugfs_create_u32("front_end_ipv4_stop", S_IRUGO | S_IWUSR, dentry, +- (u32 *)&ecm_front_end_ipv4_stopped)) { +- DEBUG_ERROR("Failed to create ecm front end ipv4 stop file in debugfs\n"); +- return -1; +- } ++ debugfs_create_u32("front_end_ipv4_stop", S_IRUGO | S_IWUSR, dentry, ++ (u32 *)&ecm_front_end_ipv4_stopped); + + switch (ecm_front_end_type_get()) { + case ECM_FRONT_END_TYPE_NSS: +--- a/frontends/ecm_front_end_ipv6.c ++++ b/frontends/ecm_front_end_ipv6.c +@@ -255,11 +255,8 @@ void ecm_front_end_ipv6_stop(int num) + */ + int ecm_front_end_ipv6_init(struct dentry *dentry) + { +- if (!debugfs_create_u32("front_end_ipv6_stop", S_IRUGO | S_IWUSR, dentry, +- (u32 *)&ecm_front_end_ipv6_stopped)) { +- DEBUG_ERROR("Failed to create ecm front end ipv6 stop file in debugfs\n"); +- return -1; +- } ++ debugfs_create_u32("front_end_ipv6_stop", S_IRUGO | S_IWUSR, dentry, ++ (u32 *)&ecm_front_end_ipv6_stopped); + + switch (ecm_front_end_type_get()) { + case ECM_FRONT_END_TYPE_NSS: +--- a/frontends/nss/ecm_nss_bond_notifier.c ++++ b/frontends/nss/ecm_nss_bond_notifier.c +@@ -240,12 +240,8 @@ int ecm_nss_bond_notifier_init(struct de + return -1; + } + +- if (!debugfs_create_u32("stop", S_IRUGO | S_IWUSR, ecm_nss_bond_notifier_dentry, +- (u32 *)&ecm_nss_bond_notifier_stopped)) { +- DEBUG_ERROR("Failed to create ecm bond notifier stopped file in debugfs\n"); +- debugfs_remove_recursive(ecm_nss_bond_notifier_dentry); +- return -1; +- } ++ debugfs_create_u32("stop", S_IRUGO | S_IWUSR, ecm_nss_bond_notifier_dentry, ++ (u32 *)&ecm_nss_bond_notifier_stopped); + + /* + * Register Link Aggregation callbacks with the bonding driver +--- a/frontends/nss/ecm_nss_ipv4.c ++++ b/frontends/nss/ecm_nss_ipv4.c +@@ -2802,41 +2802,23 @@ int ecm_nss_ipv4_init(struct dentry *den + return result; + } + +- if (!debugfs_create_u32("no_action_limit_default", S_IRUGO | S_IWUSR, ecm_nss_ipv4_dentry, +- (u32 *)&ecm_nss_ipv4_no_action_limit_default)) { +- DEBUG_ERROR("Failed to create ecm nss ipv4 no_action_limit_default file in debugfs\n"); +- goto task_cleanup; +- } ++ debugfs_create_u32("no_action_limit_default", S_IRUGO | S_IWUSR, ecm_nss_ipv4_dentry, ++ (u32 *)&ecm_nss_ipv4_no_action_limit_default); + +- if (!debugfs_create_u32("driver_fail_limit_default", S_IRUGO | S_IWUSR, ecm_nss_ipv4_dentry, +- (u32 *)&ecm_nss_ipv4_driver_fail_limit_default)) { +- DEBUG_ERROR("Failed to create ecm nss ipv4 driver_fail_limit_default file in debugfs\n"); +- goto task_cleanup; +- } ++ debugfs_create_u32("driver_fail_limit_default", S_IRUGO | S_IWUSR, ecm_nss_ipv4_dentry, ++ (u32 *)&ecm_nss_ipv4_driver_fail_limit_default); + +- if (!debugfs_create_u32("nack_limit_default", S_IRUGO | S_IWUSR, ecm_nss_ipv4_dentry, +- (u32 *)&ecm_nss_ipv4_nack_limit_default)) { +- DEBUG_ERROR("Failed to create ecm nss ipv4 nack_limit_default file in debugfs\n"); +- goto task_cleanup; +- } ++ debugfs_create_u32("nack_limit_default", S_IRUGO | S_IWUSR, ecm_nss_ipv4_dentry, ++ (u32 *)&ecm_nss_ipv4_nack_limit_default); + +- if (!debugfs_create_u32("accelerated_count", S_IRUGO, ecm_nss_ipv4_dentry, +- (u32 *)&ecm_nss_ipv4_accelerated_count)) { +- DEBUG_ERROR("Failed to create ecm nss ipv4 accelerated_count file in debugfs\n"); +- goto task_cleanup; +- } ++ debugfs_create_u32("accelerated_count", S_IRUGO, ecm_nss_ipv4_dentry, ++ (u32 *)&ecm_nss_ipv4_accelerated_count); + +- if (!debugfs_create_u32("pending_accel_count", S_IRUGO, ecm_nss_ipv4_dentry, +- (u32 *)&ecm_nss_ipv4_pending_accel_count)) { +- DEBUG_ERROR("Failed to create ecm nss ipv4 pending_accel_count file in debugfs\n"); +- goto task_cleanup; +- } ++ debugfs_create_u32("pending_accel_count", S_IRUGO, ecm_nss_ipv4_dentry, ++ (u32 *)&ecm_nss_ipv4_pending_accel_count); + +- if (!debugfs_create_u32("pending_decel_count", S_IRUGO, ecm_nss_ipv4_dentry, +- (u32 *)&ecm_nss_ipv4_pending_decel_count)) { +- DEBUG_ERROR("Failed to create ecm nss ipv4 pending_decel_count file in debugfs\n"); +- goto task_cleanup; +- } ++ debugfs_create_u32("pending_decel_count", S_IRUGO, ecm_nss_ipv4_dentry, ++ (u32 *)&ecm_nss_ipv4_pending_decel_count); + + if (!debugfs_create_file("accel_limit_mode", S_IRUGO | S_IWUSR, ecm_nss_ipv4_dentry, + NULL, &ecm_nss_ipv4_accel_limit_mode_fops)) { +@@ -2867,11 +2849,8 @@ int ecm_nss_ipv4_init(struct dentry *den + goto task_cleanup; + } + +- if (!debugfs_create_u32("vlan_passthrough_set", S_IRUGO | S_IWUSR, ecm_nss_ipv4_dentry, +- (u32 *)&ecm_nss_ipv4_vlan_passthrough_enable)) { +- DEBUG_ERROR("Failed to create ecm nss ipv4 vlan passthrough file in debugfs\n"); +- goto task_cleanup; +- } ++ debugfs_create_u32("vlan_passthrough_set", S_IRUGO | S_IWUSR, ecm_nss_ipv4_dentry, ++ (u32 *)&ecm_nss_ipv4_vlan_passthrough_enable); + + #ifdef ECM_NON_PORTED_SUPPORT_ENABLE + if (!ecm_nss_non_ported_ipv4_debugfs_init(ecm_nss_ipv4_dentry)) { +--- a/frontends/nss/ecm_nss_ipv6.c ++++ b/frontends/nss/ecm_nss_ipv6.c +@@ -2542,41 +2542,23 @@ int ecm_nss_ipv6_init(struct dentry *den + return result; + } + +- if (!debugfs_create_u32("no_action_limit_default", S_IRUGO | S_IWUSR, ecm_nss_ipv6_dentry, +- (u32 *)&ecm_nss_ipv6_no_action_limit_default)) { +- DEBUG_ERROR("Failed to create ecm nss ipv6 no_action_limit_default file in debugfs\n"); +- goto task_cleanup; +- } ++ debugfs_create_u32("no_action_limit_default", S_IRUGO | S_IWUSR, ecm_nss_ipv6_dentry, ++ (u32 *)&ecm_nss_ipv6_no_action_limit_default); + +- if (!debugfs_create_u32("driver_fail_limit_default", S_IRUGO | S_IWUSR, ecm_nss_ipv6_dentry, +- (u32 *)&ecm_nss_ipv6_driver_fail_limit_default)) { +- DEBUG_ERROR("Failed to create ecm nss ipv6 driver_fail_limit_default file in debugfs\n"); +- goto task_cleanup; +- } ++ debugfs_create_u32("driver_fail_limit_default", S_IRUGO | S_IWUSR, ecm_nss_ipv6_dentry, ++ (u32 *)&ecm_nss_ipv6_driver_fail_limit_default); + +- if (!debugfs_create_u32("nack_limit_default", S_IRUGO | S_IWUSR, ecm_nss_ipv6_dentry, +- (u32 *)&ecm_nss_ipv6_nack_limit_default)) { +- DEBUG_ERROR("Failed to create ecm nss ipv6 nack_limit_default file in debugfs\n"); +- goto task_cleanup; +- } ++ debugfs_create_u32("nack_limit_default", S_IRUGO | S_IWUSR, ecm_nss_ipv6_dentry, ++ (u32 *)&ecm_nss_ipv6_nack_limit_default); + +- if (!debugfs_create_u32("accelerated_count", S_IRUGO, ecm_nss_ipv6_dentry, +- (u32 *)&ecm_nss_ipv6_accelerated_count)) { +- DEBUG_ERROR("Failed to create ecm nss ipv6 accelerated_count file in debugfs\n"); +- goto task_cleanup; +- } ++ debugfs_create_u32("accelerated_count", S_IRUGO, ecm_nss_ipv6_dentry, ++ (u32 *)&ecm_nss_ipv6_accelerated_count); + +- if (!debugfs_create_u32("pending_accel_count", S_IRUGO, ecm_nss_ipv6_dentry, +- (u32 *)&ecm_nss_ipv6_pending_accel_count)) { +- DEBUG_ERROR("Failed to create ecm nss ipv6 pending_accel_count file in debugfs\n"); +- goto task_cleanup; +- } ++ debugfs_create_u32("pending_accel_count", S_IRUGO, ecm_nss_ipv6_dentry, ++ (u32 *)&ecm_nss_ipv6_pending_accel_count); + +- if (!debugfs_create_u32("pending_decel_count", S_IRUGO, ecm_nss_ipv6_dentry, +- (u32 *)&ecm_nss_ipv6_pending_decel_count)) { +- DEBUG_ERROR("Failed to create ecm nss ipv6 pending_decel_count file in debugfs\n"); +- goto task_cleanup; +- } ++ debugfs_create_u32("pending_decel_count", S_IRUGO, ecm_nss_ipv6_dentry, ++ (u32 *)&ecm_nss_ipv6_pending_decel_count); + + if (!debugfs_create_file("accel_limit_mode", S_IRUGO | S_IWUSR, ecm_nss_ipv6_dentry, + NULL, &ecm_nss_ipv6_accel_limit_mode_fops)) { +@@ -2607,11 +2589,8 @@ int ecm_nss_ipv6_init(struct dentry *den + goto task_cleanup; + } + +- if (!debugfs_create_u32("vlan_passthrough_set", S_IRUGO | S_IWUSR, ecm_nss_ipv6_dentry, +- (u32 *)&ecm_nss_ipv6_vlan_passthrough_enable)) { +- DEBUG_ERROR("Failed to create ecm nss ipv6 vlan passthrough file in debugfs\n"); +- goto task_cleanup; +- } ++ debugfs_create_u32("vlan_passthrough_set", S_IRUGO | S_IWUSR, ecm_nss_ipv6_dentry, ++ (u32 *)&ecm_nss_ipv6_vlan_passthrough_enable); + + #ifdef ECM_NON_PORTED_SUPPORT_ENABLE + if (!ecm_nss_non_ported_ipv6_debugfs_init(ecm_nss_ipv6_dentry)) { +--- a/frontends/nss/ecm_nss_multicast_ipv4.c ++++ b/frontends/nss/ecm_nss_multicast_ipv4.c +@@ -4139,11 +4139,8 @@ void ecm_nss_multicast_ipv4_stop(int num + */ + int ecm_nss_multicast_ipv4_init(struct dentry *dentry) + { +- if (!debugfs_create_u32("ecm_nss_multicast_ipv4_stop", S_IRUGO | S_IWUSR, dentry, +- (u32 *)&ecm_front_end_ipv4_mc_stopped)) { +- DEBUG_ERROR("Failed to create ecm front end ipv4 mc stop file in debugfs\n"); +- return -1; +- } ++ debugfs_create_u32("ecm_nss_multicast_ipv4_stop", S_IRUGO | S_IWUSR, dentry, ++ (u32 *)&ecm_front_end_ipv4_mc_stopped); + + /* + * Register multicast update callback to MCS snooper +--- a/frontends/nss/ecm_nss_multicast_ipv6.c ++++ b/frontends/nss/ecm_nss_multicast_ipv6.c +@@ -3939,11 +3939,8 @@ void ecm_nss_multicast_ipv6_stop(int num + */ + int ecm_nss_multicast_ipv6_init(struct dentry *dentry) + { +- if (!debugfs_create_u32("ecm_nss_multicast_ipv6_stop", S_IRUGO | S_IWUSR, dentry, +- (u32 *)&ecm_front_end_ipv6_mc_stopped)) { +- DEBUG_ERROR("Failed to create ecm front end ipv6 mc stop file in debugfs\n"); +- return -1; +- } ++ debugfs_create_u32("ecm_nss_multicast_ipv6_stop", S_IRUGO | S_IWUSR, dentry, ++ (u32 *)&ecm_front_end_ipv6_mc_stopped); + + /* + * Register multicast update callback to MCS snooper +--- a/frontends/nss/ecm_nss_non_ported_ipv4.c ++++ b/frontends/nss/ecm_nss_non_ported_ipv4.c +@@ -2615,11 +2615,8 @@ done: + */ + bool ecm_nss_non_ported_ipv4_debugfs_init(struct dentry *dentry) + { +- if (!debugfs_create_u32("non_ported_accelerated_count", S_IRUGO, dentry, +- (u32 *)&ecm_nss_non_ported_ipv4_accelerated_count)) { +- DEBUG_ERROR("Failed to create ecm nss ipv4 non_ported_accelerated_count file in debugfs\n"); +- return false; +- } ++ debugfs_create_u32("non_ported_accelerated_count", S_IRUGO, dentry, ++ (u32 *)&ecm_nss_non_ported_ipv4_accelerated_count); + + return true; + } +--- a/frontends/nss/ecm_nss_non_ported_ipv6.c ++++ b/frontends/nss/ecm_nss_non_ported_ipv6.c +@@ -2329,11 +2329,8 @@ done: + */ + bool ecm_nss_non_ported_ipv6_debugfs_init(struct dentry *dentry) + { +- if (!debugfs_create_u32("non_ported_accelerated_count", S_IRUGO, dentry, +- (u32 *)&ecm_nss_non_ported_ipv6_accelerated_count)) { +- DEBUG_ERROR("Failed to create ecm nss ipv6 non_ported_accelerated_count file in debugfs\n"); +- return false; +- } ++ debugfs_create_u32("non_ported_accelerated_count", S_IRUGO, dentry, ++ (u32 *)&ecm_nss_non_ported_ipv6_accelerated_count); + + return true; + } +--- a/frontends/nss/ecm_nss_ported_ipv4.c ++++ b/frontends/nss/ecm_nss_ported_ipv4.c +@@ -2944,12 +2944,8 @@ bool ecm_nss_ported_ipv4_debugfs_init(st + return false; + } + +- if (!debugfs_create_u32("tcp_accelerated_count", S_IRUGO, dentry, +- &ecm_nss_ported_ipv4_accelerated_count[ECM_NSS_PORTED_IPV4_PROTO_TCP])) { +- DEBUG_ERROR("Failed to create ecm nss ipv4 tcp_accelerated_count file in debugfs\n"); +- debugfs_remove(udp_dentry); +- return false; +- } ++ debugfs_create_u32("tcp_accelerated_count", S_IRUGO, dentry, ++ &ecm_nss_ported_ipv4_accelerated_count[ECM_NSS_PORTED_IPV4_PROTO_TCP]); + + return true; + } +--- a/frontends/nss/ecm_nss_ported_ipv6.c ++++ b/frontends/nss/ecm_nss_ported_ipv6.c +@@ -2732,12 +2732,8 @@ bool ecm_nss_ported_ipv6_debugfs_init(st + return false; + } + +- if (!debugfs_create_u32("tcp_accelerated_count", S_IRUGO, dentry, +- &ecm_nss_ported_ipv6_accelerated_count[ECM_NSS_PORTED_IPV6_PROTO_TCP])) { +- DEBUG_ERROR("Failed to create ecm nss ipv6 tcp_accelerated_count file in debugfs\n"); +- debugfs_remove(udp_dentry); +- return false; +- } ++ debugfs_create_u32("tcp_accelerated_count", S_IRUGO, dentry, ++ &ecm_nss_ported_ipv6_accelerated_count[ECM_NSS_PORTED_IPV6_PROTO_TCP]); + + return true; + } +--- a/frontends/sfe/ecm_sfe_ipv4.c ++++ b/frontends/sfe/ecm_sfe_ipv4.c +@@ -1808,48 +1808,27 @@ int ecm_sfe_ipv4_init(struct dentry *den + } + + #ifdef CONFIG_XFRM +- if (!debugfs_create_u32("reject_acceleration_for_ipsec", S_IRUGO | S_IWUSR, ecm_sfe_ipv4_dentry, +- (u32 *)&ecm_sfe_ipv4_reject_acceleration_for_ipsec)) { +- DEBUG_ERROR("Failed to create ecm sfe ipv4 reject_acceleration_for_ipsec file in debugfs\n"); +- goto task_cleanup; +- } ++ debugfs_create_u32("reject_acceleration_for_ipsec", S_IRUGO | S_IWUSR, ecm_sfe_ipv4_dentry, ++ (u32 *)&ecm_sfe_ipv4_reject_acceleration_for_ipsec); + #endif + +- if (!debugfs_create_u32("no_action_limit_default", S_IRUGO | S_IWUSR, ecm_sfe_ipv4_dentry, +- (u32 *)&ecm_sfe_ipv4_no_action_limit_default)) { +- DEBUG_ERROR("Failed to create ecm sfe ipv4 no_action_limit_default file in debugfs\n"); +- goto task_cleanup; +- } ++ debugfs_create_u32("no_action_limit_default", S_IRUGO | S_IWUSR, ecm_sfe_ipv4_dentry, ++ (u32 *)&ecm_sfe_ipv4_no_action_limit_default); + +- if (!debugfs_create_u32("driver_fail_limit_default", S_IRUGO | S_IWUSR, ecm_sfe_ipv4_dentry, +- (u32 *)&ecm_sfe_ipv4_driver_fail_limit_default)) { +- DEBUG_ERROR("Failed to create ecm sfe ipv4 driver_fail_limit_default file in debugfs\n"); +- goto task_cleanup; +- } ++ debugfs_create_u32("driver_fail_limit_default", S_IRUGO | S_IWUSR, ecm_sfe_ipv4_dentry, ++ (u32 *)&ecm_sfe_ipv4_driver_fail_limit_default); + +- if (!debugfs_create_u32("nack_limit_default", S_IRUGO | S_IWUSR, ecm_sfe_ipv4_dentry, +- (u32 *)&ecm_sfe_ipv4_nack_limit_default)) { +- DEBUG_ERROR("Failed to create ecm sfe ipv4 nack_limit_default file in debugfs\n"); +- goto task_cleanup; +- } ++ debugfs_create_u32("nack_limit_default", S_IRUGO | S_IWUSR, ecm_sfe_ipv4_dentry, ++ (u32 *)&ecm_sfe_ipv4_nack_limit_default); + +- if (!debugfs_create_u32("accelerated_count", S_IRUGO, ecm_sfe_ipv4_dentry, +- (u32 *)&ecm_sfe_ipv4_accelerated_count)) { +- DEBUG_ERROR("Failed to create ecm sfe ipv4 accelerated_count file in debugfs\n"); +- goto task_cleanup; +- } ++ debugfs_create_u32("accelerated_count", S_IRUGO, ecm_sfe_ipv4_dentry, ++ (u32 *)&ecm_sfe_ipv4_accelerated_count); + +- if (!debugfs_create_u32("pending_accel_count", S_IRUGO, ecm_sfe_ipv4_dentry, +- (u32 *)&ecm_sfe_ipv4_pending_accel_count)) { +- DEBUG_ERROR("Failed to create ecm sfe ipv4 pending_accel_count file in debugfs\n"); +- goto task_cleanup; +- } ++ debugfs_create_u32("pending_accel_count", S_IRUGO, ecm_sfe_ipv4_dentry, ++ (u32 *)&ecm_sfe_ipv4_pending_accel_count); + +- if (!debugfs_create_u32("pending_decel_count", S_IRUGO, ecm_sfe_ipv4_dentry, +- (u32 *)&ecm_sfe_ipv4_pending_decel_count)) { +- DEBUG_ERROR("Failed to create ecm sfe ipv4 pending_decel_count file in debugfs\n"); +- goto task_cleanup; +- } ++ debugfs_create_u32("pending_decel_count", S_IRUGO, ecm_sfe_ipv4_dentry, ++ (u32 *)&ecm_sfe_ipv4_pending_decel_count); + + if (!debugfs_create_file("accel_limit_mode", S_IRUGO | S_IWUSR, ecm_sfe_ipv4_dentry, + NULL, &ecm_sfe_ipv4_accel_limit_mode_fops)) { +--- a/frontends/sfe/ecm_sfe_ipv6.c ++++ b/frontends/sfe/ecm_sfe_ipv6.c +@@ -1532,48 +1532,27 @@ int ecm_sfe_ipv6_init(struct dentry *den + } + + #ifdef CONFIG_XFRM +- if (!debugfs_create_u32("reject_acceleration_for_ipsec", S_IRUGO | S_IWUSR, ecm_sfe_ipv6_dentry, +- (u32 *)&ecm_sfe_ipv6_reject_acceleration_for_ipsec)) { +- DEBUG_ERROR("Failed to create ecm sfe ipv6 reject_acceleration_for_ipsec file in debugfs\n"); +- goto task_cleanup; +- } ++ debugfs_create_u32("reject_acceleration_for_ipsec", S_IRUGO | S_IWUSR, ecm_sfe_ipv6_dentry, ++ (u32 *)&ecm_sfe_ipv6_reject_acceleration_for_ipsec); + #endif + +- if (!debugfs_create_u32("no_action_limit_default", S_IRUGO | S_IWUSR, ecm_sfe_ipv6_dentry, +- (u32 *)&ecm_sfe_ipv6_no_action_limit_default)) { +- DEBUG_ERROR("Failed to create ecm sfe ipv6 no_action_limit_default file in debugfs\n"); +- goto task_cleanup; +- } ++ debugfs_create_u32("no_action_limit_default", S_IRUGO | S_IWUSR, ecm_sfe_ipv6_dentry, ++ (u32 *)&ecm_sfe_ipv6_no_action_limit_default); + +- if (!debugfs_create_u32("driver_fail_limit_default", S_IRUGO | S_IWUSR, ecm_sfe_ipv6_dentry, +- (u32 *)&ecm_sfe_ipv6_driver_fail_limit_default)) { +- DEBUG_ERROR("Failed to create ecm sfe ipv6 driver_fail_limit_default file in debugfs\n"); +- goto task_cleanup; +- } ++ debugfs_create_u32("driver_fail_limit_default", S_IRUGO | S_IWUSR, ecm_sfe_ipv6_dentry, ++ (u32 *)&ecm_sfe_ipv6_driver_fail_limit_default); + +- if (!debugfs_create_u32("nack_limit_default", S_IRUGO | S_IWUSR, ecm_sfe_ipv6_dentry, +- (u32 *)&ecm_sfe_ipv6_nack_limit_default)) { +- DEBUG_ERROR("Failed to create ecm sfe ipv6 nack_limit_default file in debugfs\n"); +- goto task_cleanup; +- } ++ debugfs_create_u32("nack_limit_default", S_IRUGO | S_IWUSR, ecm_sfe_ipv6_dentry, ++ (u32 *)&ecm_sfe_ipv6_nack_limit_default); + +- if (!debugfs_create_u32("accelerated_count", S_IRUGO, ecm_sfe_ipv6_dentry, +- (u32 *)&ecm_sfe_ipv6_accelerated_count)) { +- DEBUG_ERROR("Failed to create ecm sfe ipv6 accelerated_count file in debugfs\n"); +- goto task_cleanup; +- } ++ debugfs_create_u32("accelerated_count", S_IRUGO, ecm_sfe_ipv6_dentry, ++ (u32 *)&ecm_sfe_ipv6_accelerated_count); + +- if (!debugfs_create_u32("pending_accel_count", S_IRUGO, ecm_sfe_ipv6_dentry, +- (u32 *)&ecm_sfe_ipv6_pending_accel_count)) { +- DEBUG_ERROR("Failed to create ecm sfe ipv6 pending_accel_count file in debugfs\n"); +- goto task_cleanup; +- } ++ debugfs_create_u32("pending_accel_count", S_IRUGO, ecm_sfe_ipv6_dentry, ++ (u32 *)&ecm_sfe_ipv6_pending_accel_count); + +- if (!debugfs_create_u32("pending_decel_count", S_IRUGO, ecm_sfe_ipv6_dentry, +- (u32 *)&ecm_sfe_ipv6_pending_decel_count)) { +- DEBUG_ERROR("Failed to create ecm sfe ipv6 pending_decel_count file in debugfs\n"); +- goto task_cleanup; +- } ++ debugfs_create_u32("pending_decel_count", S_IRUGO, ecm_sfe_ipv6_dentry, ++ (u32 *)&ecm_sfe_ipv6_pending_decel_count); + + if (!debugfs_create_file("accel_limit_mode", S_IRUGO | S_IWUSR, ecm_sfe_ipv6_dentry, + NULL, &ecm_sfe_ipv6_accel_limit_mode_fops)) { +--- a/frontends/sfe/ecm_sfe_non_ported_ipv4.c ++++ b/frontends/sfe/ecm_sfe_non_ported_ipv4.c +@@ -2284,11 +2284,8 @@ done: + */ + bool ecm_sfe_non_ported_ipv4_debugfs_init(struct dentry *dentry) + { +- if (!debugfs_create_u32("non_ported_accelerated_count", S_IRUGO, dentry, +- (u32 *)&ecm_sfe_non_ported_ipv4_accelerated_count)) { +- DEBUG_ERROR("Failed to create ecm sfe ipv4 non_ported_accelerated_count file in debugfs\n"); +- return false; +- } ++ debugfs_create_u32("non_ported_accelerated_count", S_IRUGO, dentry, ++ (u32 *)&ecm_sfe_non_ported_ipv4_accelerated_count); + + return true; + } +--- a/frontends/sfe/ecm_sfe_non_ported_ipv6.c ++++ b/frontends/sfe/ecm_sfe_non_ported_ipv6.c +@@ -2083,11 +2083,8 @@ done: + */ + bool ecm_sfe_non_ported_ipv6_debugfs_init(struct dentry *dentry) + { +- if (!debugfs_create_u32("non_ported_accelerated_count", S_IRUGO, dentry, +- (u32 *)&ecm_sfe_non_ported_ipv6_accelerated_count)) { +- DEBUG_ERROR("Failed to create ecm sfe ipv6 non_ported_accelerated_count file in debugfs\n"); +- return false; +- } ++ debugfs_create_u32("non_ported_accelerated_count", S_IRUGO, dentry, ++ (u32 *)&ecm_sfe_non_ported_ipv6_accelerated_count); + + return true; + } +--- a/frontends/sfe/ecm_sfe_ported_ipv4.c ++++ b/frontends/sfe/ecm_sfe_ported_ipv4.c +@@ -2528,12 +2528,8 @@ bool ecm_sfe_ported_ipv4_debugfs_init(st + return false; + } + +- if (!debugfs_create_u32("tcp_accelerated_count", S_IRUGO, dentry, +- &ecm_sfe_ported_ipv4_accelerated_count[ECM_SFE_PORTED_IPV4_PROTO_TCP])) { +- DEBUG_ERROR("Failed to create ecm sfe ipv4 tcp_accelerated_count file in debugfs\n"); +- debugfs_remove(udp_dentry); +- return false; +- } ++ debugfs_create_u32("tcp_accelerated_count", S_IRUGO, dentry, ++ &ecm_sfe_ported_ipv4_accelerated_count[ECM_SFE_PORTED_IPV4_PROTO_TCP]); + + return true; + } +--- a/frontends/sfe/ecm_sfe_ported_ipv6.c ++++ b/frontends/sfe/ecm_sfe_ported_ipv6.c +@@ -2374,12 +2374,8 @@ bool ecm_sfe_ported_ipv6_debugfs_init(st + return false; + } + +- if (!debugfs_create_u32("tcp_accelerated_count", S_IRUGO, dentry, +- &ecm_sfe_ported_ipv6_accelerated_count[ECM_SFE_PORTED_IPV6_PROTO_TCP])) { +- DEBUG_ERROR("Failed to create ecm sfe ipv6 tcp_accelerated_count file in debugfs\n"); +- debugfs_remove(udp_dentry); +- return false; +- } ++ debugfs_create_u32("tcp_accelerated_count", S_IRUGO, dentry, ++ &ecm_sfe_ported_ipv6_accelerated_count[ECM_SFE_PORTED_IPV6_PROTO_TCP]); + + return true; + } diff --git a/root/package/qca/nss/qca-nss-ecm-64/patches/003-rework-nfct-notification.patch b/root/package/qca/nss/qca-nss-ecm-64/patches/003-rework-nfct-notification.patch new file mode 100644 index 00000000..72005cd7 --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm-64/patches/003-rework-nfct-notification.patch @@ -0,0 +1,25 @@ +--- a/ecm_conntrack_notifier.c ++++ b/ecm_conntrack_notifier.c +@@ -421,7 +421,11 @@ int ecm_conntrack_notifier_init(struct d + /* + * Eventing subsystem is available so we register a notifier hook to get fast notifications of expired connections + */ ++#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS ++ result = nf_conntrack_register_chain_notifier(&init_net, &ecm_conntrack_notifier); ++#else + result = nf_conntrack_register_notifier(&init_net, &ecm_conntrack_notifier); ++#endif + if (result < 0) { + DEBUG_ERROR("Can't register nf notifier hook.\n"); + debugfs_remove_recursive(ecm_conntrack_notifier_dentry); +@@ -439,7 +443,9 @@ EXPORT_SYMBOL(ecm_conntrack_notifier_ini + void ecm_conntrack_notifier_exit(void) + { + DEBUG_INFO("ECM Conntrack Notifier exit\n"); +-#ifdef CONFIG_NF_CONNTRACK_EVENTS ++#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS ++ nf_conntrack_unregister_chain_notifier(&init_net, &ecm_conntrack_notifier); ++#else + nf_conntrack_unregister_notifier(&init_net, &ecm_conntrack_notifier); + #endif + /* diff --git a/root/package/qca/nss/qca-nss-ecm-64/patches/004-More-compile-fixes.patch b/root/package/qca/nss/qca-nss-ecm-64/patches/004-More-compile-fixes.patch new file mode 100644 index 00000000..a998d829 --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm-64/patches/004-More-compile-fixes.patch @@ -0,0 +1,58 @@ +From e6d701c0d454d841366c556b2ef07a5203ffb35d Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 21 May 2021 21:41:31 +0200 +Subject: [PATCH] More compile fixes + +More runtime compile fixes. + +Signed-off-by: Robert Marko +--- + frontends/nss/ecm_nss_ported_ipv4.c | 12 +++--------- + frontends/nss/ecm_nss_ported_ipv6.c | 12 +++--------- + 2 files changed, 6 insertions(+), 18 deletions(-) + +diff --git a/frontends/nss/ecm_nss_ported_ipv4.c b/frontends/nss/ecm_nss_ported_ipv4.c +index 3522f0f..7f5fcd1 100644 +--- a/frontends/nss/ecm_nss_ported_ipv4.c ++++ b/frontends/nss/ecm_nss_ported_ipv4.c +@@ -2935,14 +2935,8 @@ done: + */ + bool ecm_nss_ported_ipv4_debugfs_init(struct dentry *dentry) + { +- struct dentry *udp_dentry; +- +- udp_dentry = debugfs_create_u32("udp_accelerated_count", S_IRUGO, dentry, ++ debugfs_create_u32("udp_accelerated_count", S_IRUGO, dentry, + &ecm_nss_ported_ipv4_accelerated_count[ECM_NSS_PORTED_IPV4_PROTO_UDP]); +- if (!udp_dentry) { +- DEBUG_ERROR("Failed to create ecm nss ipv4 udp_accelerated_count file in debugfs\n"); +- return false; +- } + + debugfs_create_u32("tcp_accelerated_count", S_IRUGO, dentry, + &ecm_nss_ported_ipv4_accelerated_count[ECM_NSS_PORTED_IPV4_PROTO_TCP]); +diff --git a/frontends/nss/ecm_nss_ported_ipv6.c b/frontends/nss/ecm_nss_ported_ipv6.c +index f43ac95..e0f779c 100644 +--- a/frontends/nss/ecm_nss_ported_ipv6.c ++++ b/frontends/nss/ecm_nss_ported_ipv6.c + /* + * ecm_nss_ported_ipv6_connection_callback() +@@ -2723,14 +2723,8 @@ done: + */ + bool ecm_nss_ported_ipv6_debugfs_init(struct dentry *dentry) + { +- struct dentry *udp_dentry; +- +- udp_dentry = debugfs_create_u32("udp_accelerated_count", S_IRUGO, dentry, ++ debugfs_create_u32("udp_accelerated_count", S_IRUGO, dentry, + &ecm_nss_ported_ipv6_accelerated_count[ECM_NSS_PORTED_IPV6_PROTO_UDP]); +- if (!udp_dentry) { +- DEBUG_ERROR("Failed to create ecm nss ipv6 udp_accelerated_count file in debugfs\n"); +- return false; +- } + + debugfs_create_u32("tcp_accelerated_count", S_IRUGO, dentry, + &ecm_nss_ported_ipv6_accelerated_count[ECM_NSS_PORTED_IPV6_PROTO_TCP]); +-- +2.31.1 + diff --git a/root/package/qca/nss/qca-nss-ecm-64/patches/005-resolve-high-load.patch b/root/package/qca/nss/qca-nss-ecm-64/patches/005-resolve-high-load.patch new file mode 100644 index 00000000..f4106a35 --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm-64/patches/005-resolve-high-load.patch @@ -0,0 +1,61 @@ +From 6924b71ed809b37fffd74d6428a8ca83e5919746 Mon Sep 17 00:00:00 2001 +From: Dirk Buchwalder +Date: Sun, 27 Jun 2021 16:52:39 +0200 +Subject: [PATCH] qca-nss-ecm: resolve the cpu high load regarding ecm + +If using ECM, cpu load goes up (around 1.0) and stucks there. +This is due to using uninterruptible sleep function, +the patch changes this to interruptible sleep function. + +Signed-off-by: Dirk Buchwalder buchwalder@posteo.de +--- + frontends/nss/ecm_nss_ipv4.c | 4 ++-- + frontends/nss/ecm_nss_ipv6.c | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/frontends/nss/ecm_nss_ipv4.c b/frontends/nss/ecm_nss_ipv4.c +index e00553c..94b39cd 100644 +--- a/frontends/nss/ecm_nss_ipv4.c ++++ b/frontends/nss/ecm_nss_ipv4.c +@@ -2471,7 +2471,7 @@ static void ecm_nss_ipv4_stats_sync_req_work(struct work_struct *work) + } + spin_unlock_bh(&ecm_nss_ipv4_lock); + +- usleep_range(ECM_NSS_IPV4_STATS_SYNC_UDELAY - 100, ECM_NSS_IPV4_STATS_SYNC_UDELAY); ++ msleep_interruptible(ECM_NSS_IPV4_STATS_SYNC_UDELAY / 1000); + + /* + * If index is 0, we are starting a new round, but if we still have time remain +@@ -2485,7 +2485,7 @@ static void ecm_nss_ipv4_stats_sync_req_work(struct work_struct *work) + } + + if (time_after(ecm_nss_ipv4_next_req_time, current_jiffies)) { +- msleep(jiffies_to_msecs(ecm_nss_ipv4_next_req_time - current_jiffies)); ++ msleep_interruptible(jiffies_to_msecs(ecm_nss_ipv4_next_req_time - current_jiffies)); + } + ecm_nss_ipv4_roll_check_jiffies = jiffies; + ecm_nss_ipv4_next_req_time = ecm_nss_ipv4_roll_check_jiffies + ECM_NSS_IPV4_STATS_SYNC_PERIOD; +diff --git a/frontends/nss/ecm_nss_ipv6.c b/frontends/nss/ecm_nss_ipv6.c +index 82e739f..30af050 100644 +--- a/frontends/nss/ecm_nss_ipv6.c ++++ b/frontends/nss/ecm_nss_ipv6.c +@@ -2210,7 +2210,7 @@ static void ecm_nss_ipv6_stats_sync_req_work(struct work_struct *work) + } + spin_unlock_bh(&ecm_nss_ipv6_lock); + +- usleep_range(ECM_NSS_IPV6_STATS_SYNC_UDELAY - 100, ECM_NSS_IPV6_STATS_SYNC_UDELAY); ++ msleep_interruptible(ECM_NSS_IPV6_STATS_SYNC_UDELAY / 1000); + + /* + * If index is 0, we are starting a new round, but if we still have time remain +@@ -2224,7 +2224,7 @@ static void ecm_nss_ipv6_stats_sync_req_work(struct work_struct *work) + } + + if (time_after(ecm_nss_ipv6_next_req_time, current_jiffies)) { +- msleep(jiffies_to_msecs(ecm_nss_ipv6_next_req_time - current_jiffies)); ++ msleep_interruptible(jiffies_to_msecs(ecm_nss_ipv6_next_req_time - current_jiffies)); + } + ecm_nss_ipv6_roll_check_jiffies = jiffies; + ecm_nss_ipv6_next_req_time = ecm_nss_ipv6_roll_check_jiffies + ECM_NSS_IPV6_STATS_SYNC_PERIOD; +-- +2.31.1 diff --git a/root/package/qca/nss/qca-nss-ecm-64/patches/006-ecm_interface-switch-to-kernel_recvmsg-api.patch b/root/package/qca/nss/qca-nss-ecm-64/patches/006-ecm_interface-switch-to-kernel_recvmsg-api.patch new file mode 100644 index 00000000..caa591ab --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm-64/patches/006-ecm_interface-switch-to-kernel_recvmsg-api.patch @@ -0,0 +1,40 @@ +diff --git a/ecm_interface.c b/ecm_interface.c +index b461456..6be872a 100644 +--- a/ecm_interface.c ++++ b/ecm_interface.c +@@ -7493,9 +7493,13 @@ + static int ecm_interface_wifi_event_rx(struct socket *sock, struct sockaddr_nl *addr, unsigned char *buf, int len) + { + struct msghdr msg; ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)) + struct iovec iov; + mm_segment_t oldfs; + int size; ++#else ++ struct kvec iov; ++#endif + + iov.iov_base = buf; + iov.iov_len = len; +@@ -7505,9 +7509,10 @@ + msg.msg_namelen = sizeof(struct sockaddr_nl); + msg.msg_control = NULL; + msg.msg_controllen = 0; +- iov_iter_init(&msg.msg_iter, READ, &iov, 1, 1); ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)) + oldfs = get_fs(); + set_fs(KERNEL_DS); ++ iov_iter_init(&msg.msg_iter, READ, &iov, 1, 1); + #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0)) + size = sock_recvmsg(sock, &msg, len, msg.msg_flags); + #else +@@ -7516,6 +7521,9 @@ + set_fs(oldfs); + + return size; ++#else ++ return kernel_recvmsg(sock, &msg, &iov, 1, iov.iov_len, 0); ++#endif + } + + /* diff --git a/root/package/qca/nss/qca-nss-ecm-64/patches/007-treewide-rework-notifier-changes-for-5.15.patch b/root/package/qca/nss/qca-nss-ecm-64/patches/007-treewide-rework-notifier-changes-for-5.15.patch new file mode 100644 index 00000000..262a8fb8 --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm-64/patches/007-treewide-rework-notifier-changes-for-5.15.patch @@ -0,0 +1,72 @@ +From e9073363a50a25bddd96e808f04bcf56c45da4ac Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Sun, 8 May 2022 18:19:47 +0200 +Subject: [PATCH 07/12] treewide: rework notifier changes for 5.15 + +Rework notifier changes for 5.15 conntrack new implementation. + +Signed-off-by: Ansuel Smith +--- + ecm_conntrack_notifier.c | 16 +++++++++++++++- + 1 file changed, 15 insertions(+), 1 deletion(-) + +diff --git a/ecm_conntrack_notifier.c b/ecm_conntrack_notifier.c +index 9c8a45e..9f2cdae 100644 +--- a/ecm_conntrack_notifier.c ++++ b/ecm_conntrack_notifier.c +@@ -322,7 +322,7 @@ EXPORT_SYMBOL(ecm_conntrack_ipv4_event); + #ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS + static int ecm_conntrack_event(struct notifier_block *this, unsigned long events, void *ptr) + #else +-static int ecm_conntrack_event(unsigned int events, struct nf_ct_event *item) ++static int ecm_conntrack_event(unsigned int events, const struct nf_ct_event *item) + #endif + { + #ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS +@@ -388,7 +388,11 @@ static struct notifier_block ecm_conntrack_notifier = { + * Netfilter conntrack event system to monitor connection tracking changes + */ + static struct nf_ct_event_notifier ecm_conntrack_notifier = { ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)) + .fcn = ecm_conntrack_event, ++#else ++ .ct_event = ecm_conntrack_event, ++#endif + }; + #endif + #endif +@@ -426,13 +430,19 @@ int ecm_conntrack_notifier_init(struct dentry *dentry) + #ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS + result = nf_conntrack_register_chain_notifier(&init_net, &ecm_conntrack_notifier); + #else ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)) + result = nf_conntrack_register_notifier(&init_net, &ecm_conntrack_notifier); ++#else ++ nf_conntrack_register_notifier(&init_net, &ecm_conntrack_notifier); ++#endif + #endif ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)) + if (result < 0) { + DEBUG_ERROR("Can't register nf notifier hook.\n"); + debugfs_remove_recursive(ecm_conntrack_notifier_dentry); + return result; + } ++#endif + #endif + + return 0; +@@ -448,7 +458,11 @@ void ecm_conntrack_notifier_exit(void) + #ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS + nf_conntrack_unregister_chain_notifier(&init_net, &ecm_conntrack_notifier); + #else ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)) + nf_conntrack_unregister_notifier(&init_net, &ecm_conntrack_notifier); ++#else ++ nf_conntrack_unregister_notifier(&init_net); ++#endif + #endif + /* + * Remove the debugfs files recursively. +-- +2.34.1 + diff --git a/root/package/qca/nss/qca-nss-ecm-64/patches/008-frontends-drop-use-of-static-be_liberal-and-no_windo.patch b/root/package/qca/nss/qca-nss-ecm-64/patches/008-frontends-drop-use-of-static-be_liberal-and-no_windo.patch new file mode 100644 index 00000000..c5989cc1 --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm-64/patches/008-frontends-drop-use-of-static-be_liberal-and-no_windo.patch @@ -0,0 +1,156 @@ +--- a/frontends/nss/ecm_nss_ported_ipv4.c ++++ b/frontends/nss/ecm_nss_ported_ipv4.c +@@ -125,6 +125,7 @@ + static int ecm_nss_ported_ipv4_accelerated_count[ECM_NSS_PORTED_IPV4_PROTO_MAX] = {0}; + /* Array of Number of TCP and UDP connections currently offloaded */ + ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0) + /* + * Expose what should be a static flag in the TCP connection tracker. + */ +@@ -132,6 +133,7 @@ + extern int nf_ct_tcp_no_window_check; + #endif + extern int nf_ct_tcp_be_liberal; ++#endif + + /* + * ecm_nss_ported_ipv4_connection_callback() +@@ -372,6 +374,10 @@ + uint8_t dest_mac_xlate[ETH_ALEN]; + ecm_db_direction_t ecm_dir; + ecm_front_end_acceleration_mode_t result_mode; ++#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 12, 0) ++ struct net *net = nf_ct_net(ct); ++ struct nf_tcp_net *tn = nf_tcp_pernet(net); ++#endif + + DEBUG_CHECK_MAGIC(npci, ECM_NSS_PORTED_IPV4_CONNECTION_INSTANCE_MAGIC, "%px: magic failed", npci); + +@@ -1236,9 +1242,17 @@ + nircm->tcp_rule.return_end = ct->proto.tcp.seen[return_dir].td_end; + nircm->tcp_rule.return_max_end = ct->proto.tcp.seen[return_dir].td_maxend; + #ifdef ECM_OPENWRT_SUPPORT ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0) + if (nf_ct_tcp_be_liberal || nf_ct_tcp_no_window_check + #else ++ if (tn->tcp_be_liberal || tn->tcp_no_window_check ++#endif ++#else ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0) + if (nf_ct_tcp_be_liberal ++#else ++ if (tn->tcp_be_liberal ++#endif + #endif + || (ct->proto.tcp.seen[flow_dir].flags & IP_CT_TCP_FLAG_BE_LIBERAL) + || (ct->proto.tcp.seen[return_dir].flags & IP_CT_TCP_FLAG_BE_LIBERAL)) { +--- a/frontends/nss/ecm_nss_ported_ipv6.c ++++ b/frontends/nss/ecm_nss_ported_ipv6.c +@@ -125,6 +125,7 @@ + static int ecm_nss_ported_ipv6_accelerated_count[ECM_NSS_PORTED_IPV6_PROTO_MAX] = {0}; + /* Array of Number of TCP and UDP connections currently offloaded */ + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0) + /* + * Expose what should be a static flag in the TCP connection tracker. + */ +@@ -132,6 +133,7 @@ + extern int nf_ct_tcp_no_window_check; + #endif + extern int nf_ct_tcp_be_liberal; ++#endif + + /* + * ecm_nss_ported_ipv6_connection_callback() +@@ -376,6 +378,10 @@ + ip_addr_t src_ip; + ip_addr_t dest_ip; + ecm_front_end_acceleration_mode_t result_mode; ++#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 12, 0) ++ struct net *net = nf_ct_net(ct); ++ struct nf_tcp_net *tn = nf_tcp_pernet(net); ++#endif + + DEBUG_CHECK_MAGIC(npci, ECM_NSS_PORTED_IPV6_CONNECTION_INSTANCE_MAGIC, "%px: magic failed", npci); + +@@ -1162,9 +1168,17 @@ + nircm->tcp_rule.return_end = ct->proto.tcp.seen[return_dir].td_end; + nircm->tcp_rule.return_max_end = ct->proto.tcp.seen[return_dir].td_maxend; + #ifdef ECM_OPENWRT_SUPPORT ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0) + if (nf_ct_tcp_be_liberal || nf_ct_tcp_no_window_check + #else ++ if (tn->tcp_be_liberal || tn->tcp_no_window_check ++#endif ++#else ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0) + if (nf_ct_tcp_be_liberal ++#else ++ if (tn->tcp_be_liberal ++#endif + #endif + || (ct->proto.tcp.seen[flow_dir].flags & IP_CT_TCP_FLAG_BE_LIBERAL) + || (ct->proto.tcp.seen[return_dir].flags & IP_CT_TCP_FLAG_BE_LIBERAL)) { +--- a/frontends/sfe/ecm_sfe_ported_ipv4.c ++++ b/frontends/sfe/ecm_sfe_ported_ipv4.c +@@ -422,6 +422,10 @@ + int32_t interface_type_counts[ECM_DB_IFACE_TYPE_COUNT]; + bool rule_invalid; + ecm_db_direction_t ecm_dir; ++#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 12, 0) ++ struct net *net = nf_ct_net(ct); ++ struct nf_tcp_net *tn = nf_tcp_pernet(net); ++#endif + ecm_front_end_acceleration_mode_t result_mode; + + DEBUG_CHECK_MAGIC(npci, ECM_SFE_PORTED_IPV4_CONNECTION_INSTANCE_MAGIC, "%px: magic failed", npci); +@@ -1333,9 +1337,17 @@ + nircm->tcp_rule.return_end = ct->proto.tcp.seen[return_dir].td_end; + nircm->tcp_rule.return_max_end = ct->proto.tcp.seen[return_dir].td_maxend; + #ifdef ECM_OPENWRT_SUPPORT ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0) + if (nf_ct_tcp_be_liberal || nf_ct_tcp_no_window_check + #else ++ if (tn->tcp_be_liberal || tn->tcp_no_window_check) ++#endif ++#else ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0) + if (nf_ct_tcp_be_liberal ++#else ++ if (tn->tcp_be_liberal) ++#endif + #endif + || (ct->proto.tcp.seen[flow_dir].flags & IP_CT_TCP_FLAG_BE_LIBERAL) + || (ct->proto.tcp.seen[return_dir].flags & IP_CT_TCP_FLAG_BE_LIBERAL)) { +--- a/frontends/sfe/ecm_sfe_ported_ipv6.c ++++ b/frontends/sfe/ecm_sfe_ported_ipv6.c +@@ -426,6 +426,10 @@ + int32_t interface_type_counts[ECM_DB_IFACE_TYPE_COUNT]; + bool rule_invalid; + ip_addr_t src_ip; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0) ++ struct net *net = nf_ct_net(ct); ++ struct nf_tcp_net *tn = nf_tcp_pernet(net); ++#endif + ip_addr_t dest_ip; + ecm_front_end_acceleration_mode_t result_mode; + +@@ -1293,9 +1297,17 @@ + nircm->tcp_rule.return_end = ct->proto.tcp.seen[return_dir].td_end; + nircm->tcp_rule.return_max_end = ct->proto.tcp.seen[return_dir].td_maxend; + #ifdef ECM_OPENWRT_SUPPORT ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0) + if (nf_ct_tcp_be_liberal || nf_ct_tcp_no_window_check + #else ++ if (tn->tcp_be_liberal || tn->tcp_no_window_check) ++#endif ++#else ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0) + if (nf_ct_tcp_be_liberal ++#else ++ if (tn->tcp_be_liberal) ++#endif + #endif + || (ct->proto.tcp.seen[flow_dir].flags & IP_CT_TCP_FLAG_BE_LIBERAL) + || (ct->proto.tcp.seen[return_dir].flags & IP_CT_TCP_FLAG_BE_LIBERAL)) { diff --git a/root/package/qca/nss/qca-nss-ecm-64/patches/009-ecm_tracker_datagram-drop-static-for-EXPORT_SYMBOL.patch b/root/package/qca/nss/qca-nss-ecm-64/patches/009-ecm_tracker_datagram-drop-static-for-EXPORT_SYMBOL.patch new file mode 100644 index 00000000..1bcaa12e --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm-64/patches/009-ecm_tracker_datagram-drop-static-for-EXPORT_SYMBOL.patch @@ -0,0 +1,55 @@ +From 9827d8597545ecfee17eba7b08d48dbcdf55c614 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Sun, 8 May 2022 18:39:39 +0200 +Subject: [PATCH 09/12] ecm_tracker_datagram: drop static for EXPORT_SYMBOL + +EXPORT_SYMBOL should NOT be static + +Signed-off-by: Ansuel Smith +--- + ecm_tracker_datagram.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/ecm_tracker_datagram.c b/ecm_tracker_datagram.c +index 9c04d73..ae14146 100644 +--- a/ecm_tracker_datagram.c ++++ b/ecm_tracker_datagram.c +@@ -203,7 +203,7 @@ static void ecm_tracker_datagram_datagram_discard(struct ecm_tracker_datagram_in + * ecm_tracker_datagram_discard_all() + * Discard all tracked data + */ +-static void ecm_tracker_datagram_discard_all(struct ecm_tracker_datagram_internal_instance *dtii) ++void ecm_tracker_datagram_discard_all(struct ecm_tracker_datagram_internal_instance *dtii) + { + int32_t src_count; + int32_t dest_count; +@@ -364,7 +364,7 @@ static void ecm_tracker_datagram_datagram_discard_callback(struct ecm_tracker_in + * ecm_tracker_datagram_datagram_size_get() + * Return size in bytes of datagram at index i that was sent to the target + */ +-static int32_t ecm_tracker_datagram_datagram_size_get(struct ecm_tracker_datagram_instance *uti, ecm_tracker_sender_type_t sender, int32_t i) ++int32_t ecm_tracker_datagram_datagram_size_get(struct ecm_tracker_datagram_instance *uti, ecm_tracker_sender_type_t sender, int32_t i) + { + struct ecm_tracker_datagram_internal_instance *dtii = (struct ecm_tracker_datagram_internal_instance *)uti; + +@@ -412,7 +412,7 @@ static int32_t ecm_tracker_datagram_datagram_size_get_callback(struct ecm_tracke + * ecm_tracker_datagram_datagram_read() + * Read size bytes from datagram at index i into the buffer + */ +-static int ecm_tracker_datagram_datagram_read(struct ecm_tracker_datagram_instance *uti, ecm_tracker_sender_type_t sender, int32_t i, int32_t offset, int32_t size, void *buffer) ++int ecm_tracker_datagram_datagram_read(struct ecm_tracker_datagram_instance *uti, ecm_tracker_sender_type_t sender, int32_t i, int32_t offset, int32_t size, void *buffer) + { + struct ecm_tracker_datagram_internal_instance *dtii = (struct ecm_tracker_datagram_internal_instance *)uti; + int res; +@@ -466,7 +466,7 @@ static int ecm_tracker_datagram_datagram_read_callback(struct ecm_tracker_instan + * ecm_tracker_datagram_datagram_add() + * Append the datagram onto the tracker queue for the given target + */ +-static bool ecm_tracker_datagram_datagram_add(struct ecm_tracker_datagram_instance *uti, ecm_tracker_sender_type_t sender, struct sk_buff *skb) ++bool ecm_tracker_datagram_datagram_add(struct ecm_tracker_datagram_instance *uti, ecm_tracker_sender_type_t sender, struct sk_buff *skb) + { + struct ecm_tracker_datagram_internal_instance *dtii = (struct ecm_tracker_datagram_internal_instance *)uti; + struct sk_buff *skbc; +-- +2.34.1 + diff --git a/root/package/qca/nss/qca-nss-ecm-64/patches/010-frontends-drop-udp_get_timeouts-and-use-standard-ups.patch b/root/package/qca/nss/qca-nss-ecm-64/patches/010-frontends-drop-udp_get_timeouts-and-use-standard-ups.patch new file mode 100644 index 00000000..da88eea4 --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm-64/patches/010-frontends-drop-udp_get_timeouts-and-use-standard-ups.patch @@ -0,0 +1,74 @@ +From ef638a84405c9f6556a9d7c257ccbba74efd228e Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Sat, 14 May 2022 20:15:10 +0200 +Subject: [PATCH 10/12] frontends: drop udp_get_timeouts and use standard + upstream api + +Drop udp_get_timeouts and use nf_udp_pernet and ->timeoutrs +instead or relying on a downstream api not present upstream. +--- + frontends/nss/ecm_nss_ipv4.c | 3 ++- + frontends/nss/ecm_nss_ipv6.c | 3 ++- + frontends/sfe/ecm_sfe_ipv4.c | 3 ++- + frontends/sfe/ecm_sfe_ipv6.c | 3 ++- + 4 files changed, 8 insertions(+), 4 deletions(-) + +diff --git a/frontends/nss/ecm_nss_ipv4.c b/frontends/nss/ecm_nss_ipv4.c +index 719a747..558819a 100644 +--- a/frontends/nss/ecm_nss_ipv4.c ++++ b/frontends/nss/ecm_nss_ipv4.c +@@ -607,7 +607,8 @@ sync_conntrack: + #else + timeouts = nf_ct_timeout_lookup(ct); + if (!timeouts) { +- timeouts = udp_get_timeouts(nf_ct_net(ct)); ++ struct nf_udp_net *un = nf_udp_pernet(nf_ct_net(ct)); ++ timeouts = un->timeouts; + } + + spin_lock_bh(&ct->lock); +diff --git a/frontends/nss/ecm_nss_ipv6.c b/frontends/nss/ecm_nss_ipv6.c +index 67ee364..51eb069 100644 +--- a/frontends/nss/ecm_nss_ipv6.c ++++ b/frontends/nss/ecm_nss_ipv6.c +@@ -586,7 +586,8 @@ sync_conntrack: + #else + timeouts = nf_ct_timeout_lookup(ct); + if (!timeouts) { +- timeouts = udp_get_timeouts(nf_ct_net(ct)); ++ struct nf_udp_net *un = nf_udp_pernet(nf_ct_net(ct)); ++ timeouts = un->timeouts; + } + + spin_lock_bh(&ct->lock); +diff --git a/frontends/sfe/ecm_sfe_ipv4.c b/frontends/sfe/ecm_sfe_ipv4.c +index 3f30821..931af5d 100644 +--- a/frontends/sfe/ecm_sfe_ipv4.c ++++ b/frontends/sfe/ecm_sfe_ipv4.c +@@ -527,7 +527,8 @@ sync_conntrack: + #else + timeouts = nf_ct_timeout_lookup(ct); + if (!timeouts) { +- timeouts = udp_get_timeouts(nf_ct_net(ct)); ++ struct nf_udp_net *un = nf_udp_pernet(nf_ct_net(ct)); ++ timeouts = un->timeouts; + } + + spin_lock_bh(&ct->lock); +diff --git a/frontends/sfe/ecm_sfe_ipv6.c b/frontends/sfe/ecm_sfe_ipv6.c +index 54fdbf3..63d8888 100644 +--- a/frontends/sfe/ecm_sfe_ipv6.c ++++ b/frontends/sfe/ecm_sfe_ipv6.c +@@ -516,7 +516,8 @@ sync_conntrack: + #else + timeouts = nf_ct_timeout_lookup(ct); + if (!timeouts) { +- timeouts = udp_get_timeouts(nf_ct_net(ct)); ++ struct nf_udp_net *un = nf_udp_pernet(nf_ct_net(ct)); ++ timeouts = un->timeouts; + } + + spin_lock_bh(&ct->lock); +-- +2.34.1 + diff --git a/root/package/qca/nss/qca-nss-ecm-64/patches/901-qca-nss-ecm-fix-a-memcpy-overflow-in-ecm_db.patch b/root/package/qca/nss/qca-nss-ecm-64/patches/901-qca-nss-ecm-fix-a-memcpy-overflow-in-ecm_db.patch new file mode 100644 index 00000000..491cbedc --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm-64/patches/901-qca-nss-ecm-fix-a-memcpy-overflow-in-ecm_db.patch @@ -0,0 +1,67 @@ +From 1958e34c4c1b8b4fb62eba693fbd7693536947b9 Mon Sep 17 00:00:00 2001 +From: flebourse +Date: Thu, 23 Dec 2021 16:11:06 +0100 +Subject: [PATCH] qca-nss-ecm: fix a memcpy overflow in ecm_db + +Calls to ipv6_addr_prefix() trigger a memcpy overflow if the prefix len +argument is greater than 128, cap it at this value. + +stack bactrace: +detected buffer overflow in memcpy +Kernel BUG at fortify_panic+0x20/0x24 +Internal error: Oops - BUG: 0 [#1] SMP +CPU: 2 PID: 2592 Comm: netifd Not tainted 5.10.80 #0 +Hardware name: Xiaomi AX9000 (DT) +Call trace: + fortify_panic+0x20/0x24 + ecm_db_exit+0x42c/0x49c [ecm] + ecm_db_exit+0x464/0x49c [ecm] + atomic_notifier_call_chain+0x5c/0x90 + ip6_route_add+0x13c/0x1a4 + inet6_rtm_newroute+0x98/0xa0 + rtnetlink_rcv_msg+0x10c/0x34c + netlink_rcv_skb+0x5c/0x130 + rtnetlink_rcv+0x1c/0x2c + netlink_unicast+0x1ec/0x2e0 + netlink_sendmsg+0x1a4/0x394 + ____sys_sendmsg+0x270/0x2b4 + ___sys_sendmsg+0x7c/0xc0 + __sys_sendmsg+0x5c/0xb0 + __arm64_sys_sendmsg+0x28/0x34 + el0_svc_common.constprop.0+0x88/0x190 + do_el0_svc+0x74/0x94 + el0_svc+0x14/0x20 + el0_sync_handler+0xa8/0x130 + el0_sync+0x184/0x1c0 +Code: aa0003e1 912b4040 910003fd 97fff56c (d4210000) + +Signed-off-By: Francis Le Bourse +--- + ecm_db/ecm_db.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/ecm_db/ecm_db.c b/ecm_db/ecm_db.c +index c6f408d..df04afd 100644 +--- a/ecm_db/ecm_db.c ++++ b/ecm_db/ecm_db.c +@@ -298,7 +298,7 @@ static int ecm_db_ipv6_route_table_update_event(struct notifier_block *nb, + * Compute ECM connection's prefix destination address by masking it with the + * route config's destination address prefix length. + */ +- ipv6_addr_prefix(&prefix_addr, &ecm_in6, cfg->fc_dst_len); ++ ipv6_addr_prefix(&prefix_addr, &ecm_in6, min(128, cfg->fc_dst_len)); + + DEBUG_TRACE("dest addr prefix: %pI6 prefix_len: %d ecm_in6: %pI6\n", &prefix_addr, cfg->fc_dst_len, &ecm_in6); + +@@ -326,7 +326,7 @@ static int ecm_db_ipv6_route_table_update_event(struct notifier_block *nb, + * Compute ECM connection's prefix source address by masking it with the + * route config's destination address prefix length. + */ +- ipv6_addr_prefix(&prefix_addr, &ecm_in6, cfg->fc_dst_len); ++ ipv6_addr_prefix(&prefix_addr, &ecm_in6, min(128, cfg->fc_dst_len)); + + DEBUG_TRACE("src addr prefix: %pI6 prefix_len: %d ecm_in6: %pI6\n", &prefix_addr, cfg->fc_dst_len, &ecm_in6); + +-- +2.1.4 + diff --git a/root/package/qca/nss/qca-nss-ecm/Makefile b/root/package/qca/nss/qca-nss-ecm/Makefile new file mode 100644 index 00000000..0053ff12 --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm/Makefile @@ -0,0 +1,278 @@ +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=qca-nss-ecm +PKG_RELEASE:=1 + +PKG_SOURCE_URL:=https://source.codeaurora.org/quic/qsdk/oss/lklm/qca-nss-ecm +PKG_SOURCE_PROTO:=git +PKG_SOURCE_VERSION:=9228212b4238c0d8c296f795948ede8f2ca0242e +PKG_MIRROR_HASH:=02fe4c86c8c88fb15704b1b253ab756a2658f24ce5db64a7909cb60bf9c1cdff + +LOCAL_VARIANT=$(patsubst qca-nss-ecm-%,%,$(patsubst qca-nss-ecm-%,%,$(BUILD_VARIANT))) +include $(INCLUDE_DIR)/package.mk + +ifeq ($(CONFIG_QCA_NSS_ECM_EXAMPLES_PCC),y) + FILES_EXAMPLES=$(PKG_BUILD_DIR)/examples/ecm_pcc_test.ko +endif + +ifeq ($(CONFIG_QCA_NSS_ECM_EXAMPLES_MARK),y) + FILES_EXAMPLES+=$(PKG_BUILD_DIR)/examples/ecm_mark_test.ko +endif + +#Explicitly enable OVS external module, if ovsmgr is enabled. +ifneq ($(CONFIG_PACKAGE_kmod-qca-ovsmgr),) +CONFIG_QCA_NSS_ECM_OVS=y +endif + +ifeq ($(CONFIG_QCA_NSS_ECM_OVS),y) + FILES_EXAMPLES+=$(PKG_BUILD_DIR)/examples/ecm_ovs.ko +endif + +define KernelPackage/qca-nss-ecm/Default + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Support + DEPENDS:=+TARGET_ipq806x:kmod-qca-nss-drv \ + +TARGET_ipq_ipq806x:kmod-qca-nss-drv \ + +TARGET_ipq_ipq807x:kmod-qca-nss-drv \ + +TARGET_ipq_ipq807x_64:kmod-qca-nss-drv \ + +TARGET_ipq807x:kmod-qca-nss-drv \ + +TARGET_ipq807x_64:kmod-qca-nss-drv \ + +TARGET_ipq_ipq60xx:kmod-qca-nss-drv \ + +TARGET_ipq_ipq60xx_64:kmod-qca-nss-drv \ + +TARGET_ipq_ipq50xx:kmod-qca-nss-drv \ + +TARGET_ipq_ipq50xx_64:kmod-qca-nss-drv \ + +iptables-mod-extra +kmod-ipt-conntrack \ + +kmod-pppoe @LINUX_5_4 \ + +kmod-ipsec + TITLE:=QCA NSS Enhanced Connection Manager (ECM) + FILES:=$(PKG_BUILD_DIR)/*.ko $(FILES_EXAMPLES) + KCONFIG:=CONFIG_BRIDGE_NETFILTER=y \ + CONFIG_NF_CONNTRACK_EVENTS=y \ + CONFIG_NF_CONNTRACK_CHAIN_EVENTS=y \ + CONFIG_NF_CONNTRACK_DSCPREMARK_EXT=y + MENU:=1 + PROVIDES:=kmod-qca-nss-ecm +endef + +define KernelPackage/qca-nss-ecm/Description/Default +This package contains the QCA NSS Enhanced Connection Manager +endef + +define KernelPackage/qca-nss-ecm/Default/install + $(INSTALL_DIR) $(1)/etc/firewall.d $(1)/etc/init.d $(1)/usr/bin $(1)/lib/netifd/offload $(1)/etc/config $(1)/etc/uci-defaults $(1)/etc/sysctl.d + $(INSTALL_DATA) ./files/qca-nss-ecm.firewall $(1)/etc/firewall.d/qca-nss-ecm + $(INSTALL_BIN) ./files/qca-nss-ecm.init $(1)/etc/init.d/qca-nss-ecm + $(INSTALL_BIN) ./files/ecm_dump.sh $(1)/usr/bin/ + $(INSTALL_BIN) ./files/on-demand-down $(1)/lib/netifd/offload/on-demand-down + $(INSTALL_DATA) ./files/qca-nss-ecm.uci $(1)/etc/config/ecm + $(INSTALL_DATA) ./files/qca-nss-ecm.defaults $(1)/etc/uci-defaults/99-qca-nss-ecm + $(INSTALL_BIN) ./files/qca-nss-ecm.sysctl $(1)/etc/sysctl.d/qca-nss-ecm.conf +ifeq ($(CONFIG_KERNEL_IPQ_MEM_PROFILE),256) + echo 'net.netfilter.nf_conntrack_max=2048' >> $(1)/etc/sysctl.d/qca-nss-ecm.conf +endif +ifeq ($(CONFIG_KERNEL_IPQ_MEM_PROFILE),512) + echo 'net.netfilter.nf_conntrack_max=8192' >> $(1)/etc/sysctl.d/qca-nss-ecm.conf +endif +endef + +define KernelPackage/qca-nss-ecm-standard + $(call KernelPackage/qca-nss-ecm/Default) + VARIANT:=standard + DEPENDS+=+PACKAGE_kmod-qca-mcs:kmod-qca-mcs +endef + +define KernelPackage/qca-nss-ecm-standard/Description + $(call KernelPackage/qca-nss-ecm/Description/Default) +endef + +define KernelPackage/qca-nss-ecm-standard/install +$(call KernelPackage/qca-nss-ecm/Default/install, $(1)) +endef + +# Variant with additional features enabled for premium profile +define KernelPackage/qca-nss-ecm-premium/Default +$(call KernelPackage/qca-nss-ecm/Default) + TITLE+= (with premium features) + VARIANT:=premium + DEPENDS+=+kmod-nat46 \ + +kmod-l2tp +kmod-pppol2tp +kmod-pptp \ + +kmod-bonding +endef + +define KernelPackage/qca-nss-ecm-premium/Description/Default +$(call KernelPackage/qca-nss-ecm/Description/Default) +with the premium features enabled +endef + +define KernelPackage/qca-nss-ecm-premium/Default/install +$(call KernelPackage/qca-nss-ecm/install) +endef + +define KernelPackage/qca-nss-ecm-premium +$(call KernelPackage/qca-nss-ecm-premium/Default) +endef + +define KernelPackage/qca-nss-ecm-premium/Description +$(call KernelPackage/qca-nss-ecm-premium/Description/Default) +endef + +define KernelPackage/qca-nss-ecm-premium/install +$(call KernelPackage/qca-nss-ecm-standard/install, $(1)) +endef + +# Variant with additional features enabled for noload profile +define KernelPackage/qca-nss-ecm-noload + $(call KernelPackage/qca-nss-ecm/Default) + TITLE+= (with noload features) + PROVIDES:=kmod-qca-nss-ecm + VARIANT:=noload + DEPENDS+=+kmod-l2tp +kmod-pppol2tp +kmod-pptp \ + +kmod-bonding +endef + +define KernelPackage/qca-nss-ecm-noload/Description + $(call KernelPackage/qca-nss-ecm/Description/Default) + When selected, this package installs the driver but does not load it at init. +endef + +define KernelPackage/qca-nss-ecm-noload/install +$(call KernelPackage/qca-nss-ecm/Default/install, $(1)) + # + # Remove the START line from the init script, so that the symlink + # in the /etc/rc.d directory is not created. + # + sed -i '/START=/d' $(1)/etc/init.d/qca-nss-ecm +endef + +define KernelPackage/qca-nss-ecm-premium-noload + $(call KernelPackage/qca-nss-ecm-premium/Default) + PROVIDES:=kmod-qca-nss-ecm-premium +endef + +define KernelPackage/qca-nss-ecm-premium-noload/Description + $(call KernelPackage/qca-nss-ecm-premium/Description/Default) + When selected, this package installs the driver but does not load it at init. +endef + +define KernelPackage/qca-nss-ecm-premium-noload/install +$(call KernelPackage/qca-nss-ecm-premium/Default/install, $(1)) +endef + +define Build/InstallDev/qca-nss-ecm + $(INSTALL_DIR) $(1)/usr/include/qca-nss-ecm + $(CP) $(PKG_BUILD_DIR)/exports/* $(1)/usr/include/qca-nss-ecm/ +endef + +define Build/InstallDev + $(call Build/InstallDev/qca-nss-ecm,$(1)) +endef + +EXTRA_CFLAGS+= \ + -I$(STAGING_DIR)/usr/include/hyfibr \ + -I$(STAGING_DIR)/usr/include/qca-mcs \ + -I$(STAGING_DIR)/usr/include/qca-nss-drv \ + -I$(STAGING_DIR)/usr/include/shortcut-fe \ + -I$(STAGING_DIR)/usr/include/nat46 + +ECM_MAKE_OPTS:=ECM_CLASSIFIER_HYFI_ENABLE=y +ifneq ($(LOCAL_VARIANT),standard) +ECM_MAKE_OPTS+=ECM_MULTICAST_ENABLE=y \ + ECM_INTERFACE_IPSEC_ENABLE=y \ + # ECM_INTERFACE_PPTP_ENABLE=y \ + ECM_INTERFACE_L2TPV2_ENABLE=y \ + ECM_INTERFACE_GRE_TAP_ENABLE=y \ + ECM_INTERFACE_GRE_TUN_ENABLE=y \ + ECM_INTERFACE_SIT_ENABLE=y \ + ECM_INTERFACE_TUNIPIP6_ENABLE=y \ + ECM_INTERFACE_RAWIP_ENABLE=y + +ifeq ($(CONFIG_TARGET_ipq_ipq40xx)$(CONFIG_TARGET_ipq40xx),) +ECM_MAKE_OPTS+=ECM_INTERFACE_BOND_ENABLE=y +endif +endif + +ifeq ($(filter $(CONFIG_KERNEL_IPQ_MEM_PROFILE), 256),) +ECM_MAKE_OPTS+=ECM_XFRM_ENABLE=y +endif + +# ifneq ($(CONFIG_PACKAGE_kmod-nat46),) +# ECM_MAKE_OPTS+=ECM_INTERFACE_MAP_T_ENABLE=y +# endif + +ifneq ($(CONFIG_PACKAGE_kmod-qca-mcs),) +ECM_MAKE_OPTS+=ECM_MULTICAST_ENABLE=y +endif + +ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-ovpn-link),) +ECM_MAKE_OPTS+=ECM_INTERFACE_OVPN_ENABLE=y +endif + +ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-vxlanmgr),) +ECM_MAKE_OPTS+=ECM_INTERFACE_VXLAN_ENABLE=y +endif + +ifneq ($(CONFIG_PACKAGE_kmod-qca-ovsmgr),) +ECM_MAKE_OPTS+=ECM_INTERFACE_OVS_BRIDGE_ENABLE=y \ + ECM_CLASSIFIER_OVS_ENABLE=y +EXTRA_CFLAGS+= -I$(STAGING_DIR)/usr/include/qca-ovsmgr +endif + +# Keeping default as ipq806x for branches that does not have subtarget framework +ifeq ($(CONFIG_TARGET_ipq),y) +subtarget:=$(SUBTARGET) +else +subtarget:=$(CONFIG_TARGET_BOARD) +endif + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include/qca-nss-ecm + $(CP) $(PKG_BUILD_DIR)/exports/* $(1)/usr/include/qca-nss-ecm +endef + +define Build/Compile + $(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" $(strip $(ECM_MAKE_OPTS)) \ + $(KERNEL_MAKE_FLAGS) \ + $(PKG_MAKE_FLAGS) \ + M="$(PKG_BUILD_DIR)" \ + EXTRA_CFLAGS="$(EXTRA_CFLAGS)" SoC="$(subtarget)" \ + EXAMPLES_BUILD_PCC="$(CONFIG_QCA_NSS_ECM_EXAMPLES_PCC)" \ + EXAMPLES_BUILD_MARK="$(CONFIG_QCA_NSS_ECM_EXAMPLES_MARK)" \ + EXAMPLES_BUILD_OVS="$(CONFIG_QCA_NSS_ECM_OVS)" \ + ECM_FRONT_END_SFE_ENABLE="$(CONFIG_QCA_ECM_SFE_SUPPORT)" \ + modules +endef + +define KernelPackage/qca-nss-ecm-premium/config +menu "ECM Configuration" + depends on PACKAGE_kmod_qca-nss-ecm-premium + + config QCA_NSS_ECM_EXAMPLES_PCC + bool "Build PCC usage example" + help + Selecting this will build the PCC classifier usage example module. + default n + + config QCA_NSS_ECM_EXAMPLES_MARK + bool "Build Mark classifier usage example" + help + Selecting this will build the Mark classifier usage example module. + default n + + config QCA_NSS_ECM_OVS + bool "Build OVS classifier external module" + help + Selecting this will build the OVS classifier external module. + default n + + config QCA_ECM_SFE_SUPPORT + bool "Add SFE support to ECM driver" + default n +endmenu +endef + +$(eval $(call KernelPackage,qca-nss-ecm-noload)) +$(eval $(call KernelPackage,qca-nss-ecm-standard)) +$(eval $(call KernelPackage,qca-nss-ecm-premium-noload)) +$(eval $(call KernelPackage,qca-nss-ecm-premium)) diff --git a/root/package/qca/nss/qca-nss-ecm/files/ecm_dump.sh b/root/package/qca/nss/qca-nss-ecm/files/ecm_dump.sh new file mode 100644 index 00000000..dbf7de75 --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm/files/ecm_dump.sh @@ -0,0 +1,95 @@ +#!/bin/sh +# +# Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +ECM_MODULE=${1:-ecm_state} +MOUNT_ROOT=/dev/ecm + +# +# usage: ecm_dump.sh [module=ecm_db] +# +# with no parameters, ecm_dump.sh will attempt to mount the +# ecm_db state file and cat its contents. +# +# example with a parameter: ecm_dump.sh ecm_classifier_default +# +# this will cause ecm_dump to attempt to find and mount the state +# file for the ecm_classifier_default module, and if successful +# cat the contents. +# + +# this is one of the state files, which happens to be the +# last module started in ecm +ECM_STATE=/sys/kernel/debug/ecm/ecm_state/state_dev_major + +# tests to see if ECM is up and ready to receive commands. +# returns 0 if ECM is fully up and ready, else 1 +ecm_is_ready() { + if [ ! -e "${ECM_STATE}" ] + then + return 1 + fi + return 0 +} + +# +# module_state_mount(module_name) +# Mounts the state file of the module, if supported +# +module_state_mount() { + local module_name=$1 + local mount_dir=$2 + local state_file="/sys/kernel/debug/ecm/${module_name}/state_dev_major" + + if [ -e "${mount_dir}/${module_name}" ] + then + # already mounted + return 0 + fi + + #echo "Mount state file for $module_name ..." + if [ ! -e "$state_file" ] + then + #echo "... $module_name does not support state" + return 1 + fi + + local major="`cat $state_file`" + #echo "... Mounting state $state_file with major: $major" + mknod "${mount_dir}/${module_name}" c $major 0 +} + +# +# main +# +ecm_is_ready || { + #echo "ECM is not running" + exit 1 +} + +# all state files are mounted under MOUNT_ROOT, so make sure it exists +mkdir -p ${MOUNT_ROOT} + +# +# attempt to mount state files for the requested module and cat it +# if the mount succeeded +# +module_state_mount ${ECM_MODULE} ${MOUNT_ROOT} && { + cat ${MOUNT_ROOT}/${ECM_MODULE} + exit 0 +} + +exit 2 diff --git a/root/package/qca/nss/qca-nss-ecm/files/on-demand-down b/root/package/qca/nss/qca-nss-ecm/files/on-demand-down new file mode 100644 index 00000000..02d708e0 --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm/files/on-demand-down @@ -0,0 +1,6 @@ +#!/bin/sh +# Copyright (c) 2016 The Linux Foundation. All rights reserved. + +[ -e "/sys/kernel/debug/ecm/ecm_db/defunct_all" ] && { + echo 1 > /sys/kernel/debug/ecm/ecm_db/defunct_all +} diff --git a/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.defaults b/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.defaults new file mode 100644 index 00000000..308e265c --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.defaults @@ -0,0 +1,28 @@ +#!/bin/sh +# +# Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +uci -q batch << EOF + delete firewall.qcanssecm + set firewall.qcanssecm=include + set firewall.qcanssecm.type=script + set firewall.qcanssecm.path=/etc/firewall.d/qca-nss-ecm + set firewall.qcanssecm.family=any + set firewall.qcanssecm.reload=1 + commit firewall +EOF + +exit 0 diff --git a/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.firewall b/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.firewall new file mode 100644 index 00000000..24c64def --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.firewall @@ -0,0 +1,18 @@ +#!/bin/sh +# +# Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +iptables -A FORWARD -m physdev --physdev-is-bridged -j ACCEPT diff --git a/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.init b/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.init new file mode 100644 index 00000000..0d58c359 --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.init @@ -0,0 +1,133 @@ +#!/bin/sh /etc/rc.common +# +# Copyright (c) 2014, 2019 The Linux Foundation. All rights reserved. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +# The shebang above has an extra space intentially to avoid having +# openwrt build scripts automatically enable this package starting +# at boot. + +START=19 + +get_front_end_mode() { + config_load "ecm" + config_get front_end global acceleration_engine "auto" + + case $front_end in + auto) + echo '0' + ;; + nss) + echo '1' + ;; + sfe) + echo '2' + ;; + *) + echo 'uci_option_acceleration_engine is invalid' + esac +} + +support_bridge() { + #NSS support bridge acceleration + [ -d /sys/kernel/debug/ecm/ecm_nss_ipv4 ] && return 0 + #SFE doesn't support bridge acceleration + [ -d /sys/kernel/debug/ecm/ecm_sfe_ipv4 ] && return 1 +} + +load_sfe() { + local kernel_version=$(uname -r) + + [ -e "/lib/modules/$kernel_version/shortcut-fe.ko" ] && { + [ -d /sys/module/shortcut_fe ] || insmod shortcut-fe + } + + [ -e "/lib/modules/$kernel_version/shortcut-fe-ipv6.ko" ] && { + [ -d /sys/module/shortcut_fe_ipv6 ] || insmod shortcut-fe-ipv6 + } + + [ -e "/lib/modules/$kernel_version/shortcut-fe-cm.ko" ] && { + [ -d /sys/module/shortcut_fe_cm ] || insmod shortcut-fe-cm + } + + [ -e "/lib/modules/$kernel_version/shortcut-fe-drv.ko" ] && { + [ -d /sys/module/shortcut_fe_drv ] || insmod shortcut-fe-drv + } + +} + +load_ecm() { + [ -d /sys/module/ecm ] || { + [ ! -e /proc/device-tree/MP_256 ] && load_sfe + insmod ecm front_end_selection=$(get_front_end_mode) + } + + support_bridge && { + sysctl -w net.bridge.bridge-nf-call-ip6tables=1 + sysctl -w net.bridge.bridge-nf-call-iptables=1 + } +} + +unload_ecm() { + sysctl -w net.bridge.bridge-nf-call-ip6tables=0 + sysctl -w net.bridge.bridge-nf-call-iptables=0 + + if [ -d /sys/module/ecm ]; then + # + # Stop ECM frontends + # + echo 1 > /sys/kernel/debug/ecm/front_end_ipv4_stop + echo 1 > /sys/kernel/debug/ecm/front_end_ipv6_stop + + # + # Defunct the connections + # + echo 1 > /sys/kernel/debug/ecm/ecm_db/defunct_all + sleep 5; + + rmmod ecm + sleep 1 + fi +} + +start() { + load_ecm + + # If the acceleration engine is NSS, enable wifi redirect. + [ -d /sys/kernel/debug/ecm/ecm_nss_ipv4 ] && sysctl -w dev.nss.general.redirect=1 + + support_bridge && { + echo 'net.bridge.bridge-nf-call-ip6tables=1' >> /etc/sysctl.d/qca-nss-ecm.conf + echo 'net.bridge.bridge-nf-call-iptables=1' >> /etc/sysctl.d/qca-nss-ecm.conf + } + + if [ -d /sys/module/qca_ovsmgr ]; then + insmod ecm_ovs + fi + +} + +stop() { + # If the acceleration engine is NSS, disable wifi redirect. + [ -d /sys/kernel/debug/ecm/ecm_nss_ipv4 ] && sysctl -w dev.nss.general.redirect=0 + + sed '/net.bridge.bridge-nf-call-ip6tables=1/d' -i /etc/sysctl.d/qca-nss-ecm.conf + sed '/net.bridge.bridge-nf-call-iptables=1/d' -i /etc/sysctl.d/qca-nss-ecm.conf + + if [ -d /sys/module/ecm_ovs ]; then + rmmod ecm_ovs + fi + + unload_ecm +} diff --git a/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.sysctl b/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.sysctl new file mode 100644 index 00000000..1a3d76b1 --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.sysctl @@ -0,0 +1,2 @@ +# nf_conntrack_tcp_no_window_check is 0 by default, set it to 1 +net.netfilter.nf_conntrack_tcp_no_window_check=1 diff --git a/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.uci b/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.uci new file mode 100644 index 00000000..4f2de687 --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.uci @@ -0,0 +1,2 @@ +config ecm 'global' + option acceleration_engine 'auto' diff --git a/root/package/qca/nss/qca-nss-ecm/patches/001-Drop_SFE_from_ecm.patch b/root/package/qca/nss/qca-nss-ecm/patches/001-Drop_SFE_from_ecm.patch new file mode 100644 index 00000000..b1cd2b7b --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm/patches/001-Drop_SFE_from_ecm.patch @@ -0,0 +1,12 @@ +--- a/Makefile ++++ b/Makefile +@@ -66,8 +66,7 @@ endif + # Define ECM_FRONT_END_SFE_ENABLE=y in order to select + # sfe as ECM's front end. + # ############################################################################# +-ifeq ($(SoC),$(filter $(SoC),ipq806x ipq40xx)) +-ECM_FRONT_END_SFE_ENABLE=y ++ifeq ($(ECM_FRONT_END_SFE_ENABLE), y) + ecm-$(ECM_FRONT_END_SFE_ENABLE) += frontends/sfe/ecm_sfe_ipv4.o + ecm-$(ECM_FRONT_END_SFE_ENABLE) += frontends/sfe/ecm_sfe_ported_ipv4.o + ccflags-$(ECM_FRONT_END_SFE_ENABLE) += -DECM_FRONT_END_SFE_ENABLE diff --git a/root/package/qca/nss/qca-nss-ecm/patches/100-kernel-5.4-support.patch b/root/package/qca/nss/qca-nss-ecm/patches/100-kernel-5.4-support.patch new file mode 100644 index 00000000..b863ad7e --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm/patches/100-kernel-5.4-support.patch @@ -0,0 +1,1276 @@ +--- a/ecm_classifier_default.c ++++ b/ecm_classifier_default.c +@@ -42,7 +42,6 @@ + #include + #include + #include +-#include + #include + #include + #include +--- a/ecm_classifier_dscp.c ++++ b/ecm_classifier_dscp.c +@@ -41,7 +41,6 @@ + #include + #include + #include +-#include + #include + #include + #include +--- a/ecm_classifier_hyfi.c ++++ b/ecm_classifier_hyfi.c +@@ -41,7 +41,6 @@ + #include + #include + #include +-#include + #include + #include + #include +--- a/ecm_classifier_nl.c ++++ b/ecm_classifier_nl.c +@@ -41,7 +41,6 @@ + #include + #include + #include +-#include + #if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 2, 0)) + #include + #else +@@ -146,12 +145,42 @@ static struct genl_multicast_group ecm_c + }, + }; + ++static int ecm_classifier_nl_genl_msg_ACCEL(struct sk_buff *skb, struct genl_info *info); ++static int ecm_classifier_nl_genl_msg_DUMP(struct sk_buff *skb, struct netlink_callback *cb); ++ ++/* ++ * Generic Netlink message-to-handler mapping ++ */ ++static struct genl_ops ecm_cl_nl_genl_ops[] = { ++ { ++ .cmd = ECM_CL_NL_GENL_CMD_ACCEL, ++ .flags = 0, ++ .doit = ecm_classifier_nl_genl_msg_ACCEL, ++ .dumpit = NULL, ++ }, ++ { ++ .cmd = ECM_CL_NL_GENL_CMD_ACCEL_OK, ++ .flags = 0, ++ .doit = NULL, ++ .dumpit = ecm_classifier_nl_genl_msg_DUMP, ++ }, ++ { ++ .cmd = ECM_CL_NL_GENL_CMD_CONNECTION_CLOSED, ++ .flags = 0, ++ .doit = NULL, ++ .dumpit = ecm_classifier_nl_genl_msg_DUMP, ++ }, ++}; ++ + static struct genl_family ecm_cl_nl_genl_family = { +- .id = GENL_ID_GENERATE, + .hdrsize = 0, + .name = ECM_CL_NL_GENL_NAME, + .version = ECM_CL_NL_GENL_VERSION, + .maxattr = ECM_CL_NL_GENL_ATTR_MAX, ++ .ops = ecm_cl_nl_genl_ops, ++ .n_ops = ARRAY_SIZE(ecm_cl_nl_genl_ops), ++ .mcgrps = ecm_cl_nl_genl_mcgrp, ++ .n_mcgrps = ARRAY_SIZE(ecm_cl_nl_genl_mcgrp), + }; + + /* +@@ -215,12 +244,7 @@ ecm_classifier_nl_send_genl_msg(enum ECM + return ret; + } + +- ret = genlmsg_end(skb, msg_head); +- if (ret < 0) { +- DEBUG_WARN("failed to finalize genl msg: %d\n", ret); +- nlmsg_free(skb); +- return ret; +- } ++ genlmsg_end(skb, msg_head); + + /* genlmsg_multicast frees the skb in both success and error cases */ + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) +@@ -1377,85 +1401,14 @@ static struct file_operations ecm_classi + .write = ecm_classifier_nl_set_command, + }; + +-/* +- * Generic Netlink attr checking policies +- */ +-static struct nla_policy +-ecm_cl_nl_genl_policy[ECM_CL_NL_GENL_ATTR_COUNT] = { +- [ECM_CL_NL_GENL_ATTR_TUPLE] = { +- .type = NLA_UNSPEC, +- .len = sizeof(struct ecm_cl_nl_genl_attr_tuple), }, +-}; +- +-/* +- * Generic Netlink message-to-handler mapping +- */ +-static struct genl_ops ecm_cl_nl_genl_ops[] = { +- { +- .cmd = ECM_CL_NL_GENL_CMD_ACCEL, +- .flags = 0, +- .policy = ecm_cl_nl_genl_policy, +- .doit = ecm_classifier_nl_genl_msg_ACCEL, +- .dumpit = NULL, +- }, +- { +- .cmd = ECM_CL_NL_GENL_CMD_ACCEL_OK, +- .flags = 0, +- .policy = ecm_cl_nl_genl_policy, +- .doit = NULL, +- .dumpit = ecm_classifier_nl_genl_msg_DUMP, +- }, +- { +- .cmd = ECM_CL_NL_GENL_CMD_CONNECTION_CLOSED, +- .flags = 0, +- .policy = ecm_cl_nl_genl_policy, +- .doit = NULL, +- .dumpit = ecm_classifier_nl_genl_msg_DUMP, +- }, +-}; +- + static int ecm_classifier_nl_register_genl(void) + { + int result; + +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) +- result = genl_register_family_with_ops_groups(&ecm_cl_nl_genl_family, +- ecm_cl_nl_genl_ops, +- ecm_cl_nl_genl_mcgrp); +- if (result != 0) { +- DEBUG_ERROR("failed to register genl ops: %d\n", result); +- return result; +- } +-#else + result = genl_register_family(&ecm_cl_nl_genl_family); +- if (result != 0) { ++ if (result != 0) + DEBUG_ERROR("failed to register genl family: %d\n", result); +- goto err1; +- } +- +- result = genl_register_ops(&ecm_cl_nl_genl_family, +- ecm_cl_nl_genl_ops); +- if (result != 0) { +- DEBUG_ERROR("failed to register genl ops: %d\n", result); +- goto err2; +- } +- +- result = genl_register_mc_group(&ecm_cl_nl_genl_family, +- ecm_cl_nl_genl_mcgrp); +- if (result != 0) { +- DEBUG_ERROR("failed to register genl multicast group: %d\n", +- result); +- goto err3; +- } +- +- return 0; + +-err3: +- genl_unregister_ops(&ecm_cl_nl_genl_family, ecm_cl_nl_genl_ops); +-err2: +- genl_unregister_family(&ecm_cl_nl_genl_family); +-err1: +-#endif + return result; + } + +--- a/ecm_classifier_pcc.c ++++ b/ecm_classifier_pcc.c +@@ -49,7 +49,6 @@ + #include + #include + #include +-#include + #include + #include + #include +--- a/ecm_conntrack_notifier.c ++++ b/ecm_conntrack_notifier.c +@@ -51,7 +51,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -345,14 +344,6 @@ static int ecm_conntrack_event(unsigned + return NOTIFY_DONE; + } + +- /* +- * Special untracked connection is not monitored +- */ +- if (ct == &nf_conntrack_untracked) { +- DEBUG_TRACE("Fake connection event - ignoring\n"); +- return NOTIFY_DONE; +- } +- + /* + * Only interested if this is IPv4 or IPv6. + */ +--- a/ecm_db/ecm_db.c ++++ b/ecm_db/ecm_db.c +@@ -42,7 +42,6 @@ + #include + #include + #include +-#include + #include + #include + #include +--- a/ecm_db/ecm_db_connection.c ++++ b/ecm_db/ecm_db_connection.c +@@ -41,7 +41,6 @@ + #include + #include + #include +-#include + #include + #include + #include +--- a/ecm_db/ecm_db_host.c ++++ b/ecm_db/ecm_db_host.c +@@ -41,7 +41,6 @@ + #include + #include + #include +-#include + #include + #include + #include +--- a/ecm_db/ecm_db_iface.c ++++ b/ecm_db/ecm_db_iface.c +@@ -41,7 +41,6 @@ + #include + #include + #include +-#include + #include + #include + #include +--- a/ecm_db/ecm_db_listener.c ++++ b/ecm_db/ecm_db_listener.c +@@ -41,7 +41,6 @@ + #include + #include + #include +-#include + #include + #include + #include +--- a/ecm_db/ecm_db_mapping.c ++++ b/ecm_db/ecm_db_mapping.c +@@ -41,7 +41,6 @@ + #include + #include + #include +-#include + #include + #include + #include +--- a/ecm_db/ecm_db_multicast.c ++++ b/ecm_db/ecm_db_multicast.c +@@ -42,7 +42,6 @@ + #include + #include + #include +-#include + #include + #include + #include +--- a/ecm_db/ecm_db_node.c ++++ b/ecm_db/ecm_db_node.c +@@ -41,7 +41,6 @@ + #include + #include + #include +-#include + #include + #include + #include +--- a/ecm_db/ecm_db_timer.c ++++ b/ecm_db/ecm_db_timer.c +@@ -42,7 +42,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -387,7 +386,7 @@ EXPORT_SYMBOL(ecm_db_time_get); + * Manage expiration of connections + * NOTE: This is softirq context + */ +-static void ecm_db_timer_callback(unsigned long data) ++static void ecm_db_timer_callback(struct timer_list *arg) + { + uint32_t timer; + +@@ -425,9 +424,7 @@ void ecm_db_timer_init(void) + /* + * Set a timer to manage cleanup of expired connections + */ +- init_timer(&ecm_db_timer); +- ecm_db_timer.function = ecm_db_timer_callback; +- ecm_db_timer.data = 0; ++ timer_setup(&ecm_db_timer, ecm_db_timer_callback, 0); + ecm_db_timer.expires = jiffies + HZ; + add_timer(&ecm_db_timer); + +--- a/ecm_interface.c ++++ b/ecm_interface.c +@@ -66,7 +66,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -537,7 +536,7 @@ static bool ecm_interface_find_gateway_ipv4(ip_addr_t addr, ip_addr_t gw_addr) + return false; + } + +- ECM_NIN4_ADDR_TO_IP_ADDR(gw_addr, rt->rt_gateway) ++ ECM_NIN4_ADDR_TO_IP_ADDR(gw_addr, rt->rt_gw4) + ecm_interface_route_release(&ecm_rt); + return true; + } +@@ -596,7 +595,7 @@ static bool ecm_interface_mac_addr_get_ipv4(ip_addr_t addr, uint8_t *mac_addr, b + if (rt->rt_uses_gateway || (rt->rt_flags & RTF_GATEWAY)) { + #endif + *on_link = false; +- ECM_NIN4_ADDR_TO_IP_ADDR(gw_addr, rt->rt_gateway) ++ ECM_NIN4_ADDR_TO_IP_ADDR(gw_addr, rt->rt_gw4) + } else { + *on_link = true; + } +@@ -1003,7 +1002,7 @@ static bool ecm_interface_find_route_by_addr_ipv6(ip_addr_t addr, struct ecm_int + * Get a route to the given IP address, this will allow us to also find the interface + * it is using to communicate with that IP address. + */ +- ecm_rt->rt.rtv6 = rt6_lookup(&init_net, &naddr, NULL, 0, 0); ++ ecm_rt->rt.rtv6 = rt6_lookup(&init_net, &naddr, NULL, 0, NULL, 0); + if (!ecm_rt->rt.rtv6) { + DEBUG_TRACE("No output route to: " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(addr)); + return NULL; +@@ -1077,7 +1076,7 @@ void ecm_interface_send_neighbour_solicitation(struct net_device *dev, ip_addr_t + /* + * Find the route entry + */ +- rt6i = rt6_lookup(netf, &dst_addr, NULL, 0, 0); ++ rt6i = rt6_lookup(netf, &dst_addr, NULL, 0, NULL, 0); + if (!rt6i) { + DEBUG_TRACE("IPv6 Route lookup failure for destination IPv6 address " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(addr)); + return; +@@ -1104,7 +1103,7 @@ void ecm_interface_send_neighbour_solicitation(struct net_device *dev, ip_addr_t + #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)) + ndisc_send_ns(dev, neigh, &dst_addr, &mc_dst_addr, &src_addr); + #else +- ndisc_send_ns(dev, &dst_addr, &mc_dst_addr, &src_addr); ++ ndisc_send_ns(dev, &dst_addr, &mc_dst_addr, &src_addr, 0); + #endif + neigh_release(neigh); + dst_release(&rt6i->dst); +@@ -1194,7 +1193,7 @@ struct neighbour *ecm_interface_ipv6_neigh_get(ip_addr_t addr) + struct in6_addr ipv6_addr; + + ECM_IP_ADDR_TO_NIN6_ADDR(ipv6_addr, addr); +- rt = rt6_lookup(&init_net, &ipv6_addr, NULL, 0, 0); ++ rt = rt6_lookup(&init_net, &ipv6_addr, NULL, 0, NULL, 0); + if (!rt) { + return NULL; + } +@@ -1220,7 +1219,7 @@ bool ecm_interface_is_pptp(struct sk_buff *skb, const struct net_device *out) + * skip first pass of l2tp/pptp tunnel encapsulated traffic + */ + if (out->type == ARPHRD_PPP) { +- if (out->priv_flags & IFF_PPP_PPTP) { ++ if (out->priv_flags_qca_ecm & IFF_QCA_ECM_PPP_PPTP) { + return true; + } + } +@@ -1231,7 +1230,7 @@ bool ecm_interface_is_pptp(struct sk_buff *skb, const struct net_device *out) + } + + if (in->type == ARPHRD_PPP) { +- if (in->priv_flags & IFF_PPP_PPTP) { ++ if (in->priv_flags_qca_ecm & IFF_QCA_ECM_PPP_PPTP) { + dev_put(in); + return true; + } +@@ -1256,10 +1255,10 @@ bool ecm_interface_is_l2tp_packet_by_version(struct sk_buff *skb, const struct n + + switch (ver) { + case 2: +- flag = IFF_PPP_L2TPV2; ++ flag = IFF_QCA_ECM_PPP_L2TPV2; + break; + case 3: +- flag = IFF_PPP_L2TPV3; ++ flag = IFF_QCA_ECM_PPP_L2TPV3; + break; + default: + break; +@@ -1268,10 +1267,8 @@ bool ecm_interface_is_l2tp_packet_by_version(struct sk_buff *skb, const struct n + /* + * skip first pass of l2tp/pptp tunnel encapsulated traffic + */ +- if (out->type == ARPHRD_PPP) { +- if (out->priv_flags & flag) { +- return true; +- } ++ if (out->priv_flags_qca_ecm & flag) { ++ return true; + } + + in = dev_get_by_index(&init_net, skb->skb_iif); +@@ -1279,11 +1276,9 @@ bool ecm_interface_is_l2tp_packet_by_version(struct sk_buff *skb, const struct n + return true; + } + +- if (in->type == ARPHRD_PPP) { +- if (in->priv_flags & flag) { +- dev_put(in); +- return true; +- } ++ if (out->priv_flags_qca_ecm & flag) { ++ dev_put(in); ++ return true; + } + + dev_put(in); +@@ -1304,11 +1299,9 @@ bool ecm_interface_is_l2tp_pptp(struct sk_buff *skb, const struct net_device *ou + /* + * skip first pass of l2tp/pptp tunnel encapsulated traffic + */ +- if (out->type == ARPHRD_PPP) { +- if (out->priv_flags & (IFF_PPP_L2TPV2 | IFF_PPP_L2TPV3 | +- IFF_PPP_PPTP)) { +- return true; +- } ++ if (out->priv_flags_qca_ecm & (IFF_QCA_ECM_PPP_L2TPV2 | IFF_QCA_ECM_PPP_L2TPV3 | ++ IFF_QCA_ECM_PPP_PPTP)) { ++ return true; + } + + in = dev_get_by_index(&init_net, skb->skb_iif); +@@ -1316,12 +1309,10 @@ bool ecm_interface_is_l2tp_pptp(struct sk_buff *skb, const struct net_device *ou + return true; + } + +- if (in->type == ARPHRD_PPP) { +- if (in->priv_flags & (IFF_PPP_L2TPV2 | IFF_PPP_L2TPV3 | +- IFF_PPP_PPTP)) { +- dev_put(in); +- return true; +- } ++ if (out->priv_flags_qca_ecm & (IFF_QCA_ECM_PPP_L2TPV2 | IFF_QCA_ECM_PPP_L2TPV3 | ++ IFF_QCA_ECM_PPP_PPTP)) { ++ dev_put(in); ++ return true; + } + + dev_put(in); +@@ -2416,7 +2407,7 @@ struct ecm_db_iface_instance *ecm_interface_establish_and_ref(struct ecm_front_e + /* + * GRE TAP? + */ +- if (dev->priv_flags & (IFF_GRE_V4_TAP | IFF_GRE_V6_TAP)) { ++ if (dev->priv_flags_qca_ecm & (IFF_QCA_ECM_GRE_V4_TAP | IFF_QCA_ECM_GRE_V6_TAP)) { + interface_type = feci->ae_interface_type_get(feci, dev); + ae_interface_num = feci->ae_interface_number_by_dev_type_get(dev, interface_type); + +@@ -2680,7 +2671,7 @@ identifier_update: + /* + * OVPN Tunnel? + */ +- if ((dev_type == ARPHRD_NONE) && (dev->priv_flags & IFF_TUN_TAP)) { ++ if ((dev_type == ARPHRD_NONE) && (dev->priv_flags_qca_ecm & IFF_QCA_ECM_TUN_TAP)) { + struct net_device *tun_dev = NULL; + ip_addr_t saddr, daddr; + +@@ -2746,7 +2737,7 @@ identifier_update: + * ppp_is_multilink() and ppp_hold_channels() which acquire same lock + */ + +- if ((dev->priv_flags & IFF_PPP_L2TPV2) && ppp_is_xmit_locked(dev)) { ++ if ((dev->priv_flags_qca_ecm & IFF_QCA_ECM_PPP_L2TPV2) && ppp_is_xmit_locked(dev)) { + if (skb && (skb->skb_iif == dev->ifindex)) { + struct pppol2tp_common_addr info; + +@@ -2804,7 +2795,7 @@ identifier_update: + #endif + + #ifdef ECM_INTERFACE_PPTP_ENABLE +- if ((protocol == IPPROTO_GRE) && skb && v4_hdr && (dev->priv_flags & IFF_PPP_PPTP)) { ++ if ((protocol == IPPROTO_GRE) && skb && v4_hdr && (dev->priv_flags_qca_ecm & IFF_QCA_ECM_PPP_PPTP)) { + struct gre_hdr_pptp *gre_hdr; + uint16_t proto; + int ret; +@@ -3972,7 +3963,7 @@ int32_t ecm_interface_heirarchy_construct(struct ecm_front_end_connection_instan + if (((ip_version == 4) && (protocol == IPPROTO_IPV6)) || + ((ip_version == 6) && (protocol == IPPROTO_IPIP)) || + (protocol == IPPROTO_GRE) || +- ((given_dest_dev->type == ARPHRD_NONE) && (given_dest_dev->priv_flags & IFF_TUN_TAP))) { ++ ((given_dest_dev->type == ARPHRD_NONE) && (given_dest_dev->priv_flags_qca_ecm & IFF_QCA_ECM_TUN_TAP))) { + dev_put(dest_dev); + dest_dev = given_dest_dev; + if (dest_dev) { +@@ -3991,7 +3982,7 @@ int32_t ecm_interface_heirarchy_construct(struct ecm_front_end_connection_instan + /* + * if the address is a local address and indev=l2tp. + */ +- if ((given_src_dev->type == ARPHRD_PPP) && (given_src_dev->priv_flags & IFF_PPP_L2TPV2) && ppp_is_xmit_locked(given_src_dev)) { ++ if ((given_src_dev->type == ARPHRD_PPP) && (given_src_dev->priv_flags_qca_ecm & IFF_QCA_ECM_PPP_L2TPV2) && ppp_is_xmit_locked(given_src_dev)) { + dev_put(dest_dev); + dest_dev = given_dest_dev; + if (dest_dev) { +@@ -4005,7 +3996,7 @@ int32_t ecm_interface_heirarchy_construct(struct ecm_front_end_connection_instan + /* + * if the address is a local address and indev=PPTP. + */ +- if (protocol == IPPROTO_GRE && given_dest_dev && (given_dest_dev->priv_flags & IFF_PPP_PPTP)){ ++ if (protocol == IPPROTO_GRE && given_dest_dev && (given_dest_dev->priv_flags_qca_ecm & IFF_QCA_ECM_PPP_PPTP)){ + dev_put(dest_dev); + dest_dev = given_dest_dev; + if (dest_dev) { +@@ -4054,7 +4045,7 @@ int32_t ecm_interface_heirarchy_construct(struct ecm_front_end_connection_instan + if (((ip_version == 4) && (protocol == IPPROTO_IPV6)) || + ((ip_version == 6) && (protocol == IPPROTO_IPIP)) || + (protocol == IPPROTO_GRE) || +- ((given_src_dev->type == ARPHRD_NONE) && (given_src_dev->priv_flags & IFF_TUN_TAP))) { ++ ((given_src_dev->type == ARPHRD_NONE) && (given_src_dev->priv_flags_qca_ecm & IFF_QCA_ECM_TUN_TAP))) { + dev_put(src_dev); + src_dev = given_src_dev; + if (src_dev) { +@@ -4504,7 +4495,7 @@ lag_success: + /* + * OVPN ? + */ +- if ((dest_dev_type == ARPHRD_NONE) && (dest_dev->priv_flags & IFF_TUN_TAP)) { ++ if ((dest_dev_type == ARPHRD_NONE) && (dest_dev->priv_flags_qca_ecm & IFF_QCA_ECM_TUN_TAP)) { + DEBUG_TRACE("Net device: %p is OVPN, device name: %s\n", dest_dev, dest_dev->name); + break; + } +@@ -4523,7 +4514,7 @@ lag_success: + DEBUG_TRACE("%p: Net device: %p is PPP\n", feci, dest_dev); + + #ifdef ECM_INTERFACE_L2TPV2_ENABLE +- if ((given_src_dev->priv_flags & IFF_PPP_L2TPV2) && ppp_is_xmit_locked(given_src_dev)) { ++ if ((given_src_dev->priv_flags_qca_ecm & IFF_QCA_ECM_PPP_L2TPV2) && ppp_is_xmit_locked(given_src_dev)) { + if (skb->skb_iif == dest_dev->ifindex) { + DEBUG_TRACE("%p: Net device: %p PPP channel is PPPoL2TPV2\n", feci, dest_dev); + break; +@@ -4532,7 +4523,7 @@ lag_success: + #endif + + #ifdef ECM_INTERFACE_PPTP_ENABLE +- if (protocol == IPPROTO_GRE && dest_dev && (dest_dev->priv_flags & IFF_PPP_PPTP)) { ++ if (protocol == IPPROTO_GRE && dest_dev && (dest_dev->priv_flags_qca_ecm & IFF_QCA_ECM_PPP_PPTP)) { + DEBUG_TRACE("%p: Net device: %p PPP channel is PPTP\n", feci, dest_dev); + break; + } +@@ -4798,7 +4789,7 @@ int32_t ecm_interface_multicast_from_heirarchy_construct(struct ecm_front_end_co + /* + * if the address is a local address and indev=l2tp. + */ +- if ((given_src_dev->type == ARPHRD_PPP) && (given_src_dev->priv_flags & IFF_PPP_L2TPV2) && ppp_is_xmit_locked(given_src_dev)) { ++ if ((given_src_dev->type == ARPHRD_PPP) && (given_src_dev->priv_flags_qca_ecm & IFF_QCA_ECM_PPP_L2TPV2) && ppp_is_xmit_locked(given_src_dev)) { + dev_put(dest_dev); + dest_dev = given_dest_dev; + if (dest_dev) { +@@ -5265,7 +5256,7 @@ int32_t ecm_interface_multicast_from_heirarchy_construct(struct ecm_front_end_co + DEBUG_TRACE("Net device: %p is PPP\n", dest_dev); + + #ifdef ECM_INTERFACE_L2TPV2_ENABLE +- if ((given_src_dev->priv_flags & IFF_PPP_L2TPV2) && ppp_is_xmit_locked(given_src_dev)) { ++ if ((given_src_dev->priv_flags_qca_ecm & IFF_QCA_ECM_PPP_L2TPV2) && ppp_is_xmit_locked(given_src_dev)) { + if (skb->skb_iif == dest_dev->ifindex) { + DEBUG_TRACE("Net device: %p PPP channel is PPPoL2TPV2\n", dest_dev); + break; +@@ -6520,7 +6511,7 @@ static int ecm_interface_wifi_event_rx(struct socket *sock, struct sockaddr_nl * + #endif + oldfs = get_fs(); + set_fs(KERNEL_DS); +- size = sock_recvmsg(sock, &msg, len, msg.msg_flags); ++ size = sock_recvmsg(sock, &msg, msg.msg_flags); + set_fs(oldfs); + + return size; +@@ -6609,7 +6600,7 @@ int ecm_interface_wifi_event_stop(void) + } + + DEBUG_INFO("kill ecm_interface_wifi_event thread\n"); +- force_sig(SIGKILL, __ewn.thread); ++ send_sig(SIGKILL, __ewn.thread, 1); + err = kthread_stop(__ewn.thread); + __ewn.thread = NULL; + +--- a/ecm_tracker.c ++++ b/ecm_tracker.c +@@ -43,7 +43,6 @@ + #include + #include + #include +-#include + #include + #include + #include +--- a/ecm_tracker_datagram.c ++++ b/ecm_tracker_datagram.c +@@ -43,7 +43,6 @@ + #include + #include + #include +-#include + #include + #include + #include +--- a/ecm_tracker_tcp.c ++++ b/ecm_tracker_tcp.c +@@ -43,7 +43,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -1143,7 +1142,7 @@ static bool ecm_tracker_tcp_extract_mss( + const u8 *hash_location; + tcp_parse_options(skb, &opt_rx, &hash_location, 0); + #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) +- tcp_parse_options(skb, &opt_rx, 0, NULL); ++ tcp_parse_options(&init_net, skb, &opt_rx, 0, NULL); + #else + #error "Unsupported kernel version for tcp_parse_options()" + #endif +--- a/ecm_tracker_udp.c ++++ b/ecm_tracker_udp.c +@@ -43,7 +43,6 @@ + #include + #include + #include +-#include + #include + #include + #include +--- a/frontends/ecm_front_end_ipv4.c ++++ b/frontends/ecm_front_end_ipv4.c +@@ -215,7 +215,7 @@ bool ecm_front_end_ipv4_interface_constr + * behind a gateway. + */ + DEBUG_TRACE("Gateway address will be looked up overwrite the rt_dst_addr\n"); +- ECM_NIN4_ADDR_TO_IP_ADDR(rt_dst_addr, rt->rt_gateway) ++ ECM_NIN4_ADDR_TO_IP_ADDR(rt_dst_addr, rt->rt_gw4) + gateway = true; + } + +--- a/frontends/include/ecm_front_end_common.h ++++ b/frontends/include/ecm_front_end_common.h +@@ -98,13 +98,6 @@ static inline bool ecm_front_end_acceler + return false; + } + +- if (unlikely(nf_ct_is_untracked(ct))) { +- /* +- * Untracked traffic certainly can't be accelerated. +- */ +- return true; +- } +- + #if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 6, 0)) + acct = nf_conn_acct_find(ct); + #else +--- a/frontends/nss/ecm_nss_bond_notifier.c ++++ b/frontends/nss/ecm_nss_bond_notifier.c +@@ -52,7 +52,6 @@ + #include + #include + #include +-#include + #include + #include + #include +--- a/frontends/nss/ecm_nss_common.h ++++ b/frontends/nss/ecm_nss_common.h +@@ -144,7 +144,7 @@ static inline int32_t ecm_nss_common_get_interface_type(struct ecm_front_end_con + /* + * If device is not GRETAP then return NONE. + */ +- if (!(dev->priv_flags & (IFF_GRE_V4_TAP | IFF_GRE_V6_TAP))) { ++ if (!(dev->priv_flags_qca_ecm & (IFF_QCA_ECM_GRE_V4_TAP | IFF_QCA_ECM_GRE_V6_TAP))) { + break; + } + #endif +--- a/frontends/nss/ecm_nss_ipv4.c ++++ b/frontends/nss/ecm_nss_ipv4.c +@@ -48,7 +48,6 @@ + #include + #include + #include +-#include + #if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 2, 0)) + #include + #else +@@ -1053,7 +1052,7 @@ static unsigned int ecm_nss_ipv4_ip_process(struct net_device *out_dev, struct n + * If any of the input or output interface is a GRE V4 TAP/TUN interface + * we can continue to accelerate it. + */ +- if ((in_dev->priv_flags & IFF_GRE_V4_TAP) || (out_dev->priv_flags & IFF_GRE_V4_TAP)) { ++ if ((in_dev->priv_flags_qca_ecm & IFF_QCA_ECM_GRE_V4_TAP) || (out_dev->priv_flags_qca_ecm & IFF_QCA_ECM_GRE_V4_TAP)) { + #ifndef ECM_INTERFACE_GRE_TAP_ENABLE + DEBUG_TRACE("GRE TAP acceleration is disabled\n"); + return NF_ACCEPT; +@@ -1082,7 +1081,7 @@ static unsigned int ecm_nss_ipv4_ip_process(struct net_device *out_dev, struct n + reply_tuple.dst.u3.ip = orig_tuple.src.u3.ip; + sender = ECM_TRACKER_SENDER_TYPE_SRC; + } else { +- if (unlikely(ct == &nf_conntrack_untracked)) { ++ if (unlikely(ctinfo == IP_CT_UNTRACKED)) { + DEBUG_TRACE("%p: ct: untracked\n", skb); + return NF_ACCEPT; + } +@@ -2097,7 +2096,6 @@ sync_conntrack: + } + + ct = nf_ct_tuplehash_to_ctrack(h); +- NF_CT_ASSERT(ct->timeout.data == (unsigned long)ct); + DEBUG_TRACE("%p: NSS Sync: conntrack connection\n", ct); + + ecm_front_end_flow_and_return_directions_get(ct, flow_ip, 4, &flow_dir, &return_dir); +@@ -2108,7 +2106,7 @@ sync_conntrack: + */ + if (!test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) { + spin_lock_bh(&ct->lock); +- ct->timeout.expires += delta_jiffies; ++ ct->timeout += delta_jiffies; + spin_unlock_bh(&ct->lock); + } + +@@ -2166,17 +2164,15 @@ sync_conntrack: + u_int64_t reply_pkts = atomic64_read(&acct[IP_CT_DIR_REPLY].packets); + + if (reply_pkts != 0) { +- struct nf_conntrack_l4proto *l4proto; + unsigned int *timeouts; + + set_bit(IPS_SEEN_REPLY_BIT, &ct->status); + set_bit(IPS_ASSURED_BIT, &ct->status); + +- l4proto = __nf_ct_l4proto_find(AF_INET, IPPROTO_UDP); +- timeouts = nf_ct_timeout_lookup(&init_net, ct, l4proto); ++ timeouts = nf_ct_timeout_lookup(ct); + + spin_lock_bh(&ct->lock); +- ct->timeout.expires = jiffies + timeouts[UDP_CT_REPLIED]; ++ ct->timeout = jiffies + timeouts[UDP_CT_REPLIED]; + spin_unlock_bh(&ct->lock); + } + } +@@ -2690,7 +2686,8 @@ int ecm_nss_ipv4_init(struct dentry *dentry) + /* + * Register netfilter hooks + */ +- result = nf_register_hooks(ecm_nss_ipv4_netfilter_hooks, ARRAY_SIZE(ecm_nss_ipv4_netfilter_hooks)); ++ result = nf_register_net_hooks(&init_net, ecm_nss_ipv4_netfilter_hooks, \ ++ ARRAY_SIZE(ecm_nss_ipv4_netfilter_hooks)); + if (result < 0) { + DEBUG_ERROR("Can't register netfilter hooks.\n"); + nss_ipv4_notify_unregister(); +@@ -2702,8 +2699,8 @@ int ecm_nss_ipv4_init(struct dentry *dentry) + if (result < 0) { + DEBUG_ERROR("Failed to init ecm ipv4 multicast frontend\n"); + nss_ipv4_notify_unregister(); +- nf_unregister_hooks(ecm_nss_ipv4_netfilter_hooks, +- ARRAY_SIZE(ecm_nss_ipv4_netfilter_hooks)); ++ nf_unregister_net_hooks(&init_net, ecm_nss_ipv4_netfilter_hooks, ++ ARRAY_SIZE(ecm_nss_ipv4_netfilter_hooks)); + goto task_cleanup; + } + #endif +@@ -2714,8 +2711,8 @@ int ecm_nss_ipv4_init(struct dentry *dentry) + #ifdef ECM_MULTICAST_ENABLE + ecm_nss_multicast_ipv4_exit(); + #endif +- nf_unregister_hooks(ecm_nss_ipv4_netfilter_hooks, +- ARRAY_SIZE(ecm_nss_ipv4_netfilter_hooks)); ++ nf_unregister_net_hooks(&init_net, ecm_nss_ipv4_netfilter_hooks, ++ ARRAY_SIZE(ecm_nss_ipv4_netfilter_hooks)); + goto task_cleanup; + } + +@@ -2742,8 +2739,8 @@ void ecm_nss_ipv4_exit(void) + /* + * Stop the network stack hooks + */ +- nf_unregister_hooks(ecm_nss_ipv4_netfilter_hooks, +- ARRAY_SIZE(ecm_nss_ipv4_netfilter_hooks)); ++ nf_unregister_net_hooks(&init_net, ecm_nss_ipv4_netfilter_hooks, ++ ARRAY_SIZE(ecm_nss_ipv4_netfilter_hooks)); + + /* + * Unregister from the Linux NSS Network driver +--- a/frontends/nss/ecm_nss_ipv6.c ++++ b/frontends/nss/ecm_nss_ipv6.c +@@ -51,7 +51,6 @@ + #include + #include + #include +-#include + #if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 2, 0)) + #include + #else +@@ -1035,7 +1034,7 @@ static unsigned int ecm_nss_ipv6_ip_process(struct net_device *out_dev, struct n + * If any of the input or output interface is a GRE V4 TAP/TUN interface + * we can continue to accelerate it. + */ +- if ((in_dev->priv_flags & IFF_GRE_V4_TAP) || (out_dev->priv_flags & IFF_GRE_V4_TAP)) { ++ if ((in_dev->priv_flags_qca_ecm & IFF_QCA_ECM_GRE_V4_TAP) || (out_dev->priv_flags_qca_ecm & IFF_QCA_ECM_GRE_V4_TAP)) { + #ifndef ECM_INTERFACE_GRE_TAP_ENABLE + DEBUG_TRACE("GRE TAP acceleration is disabled\n"); + return NF_ACCEPT; +@@ -1064,7 +1063,7 @@ static unsigned int ecm_nss_ipv6_ip_process(struct net_device *out_dev, struct n + ECM_IP_ADDR_TO_NIN6_ADDR(reply_tuple.dst.u3.in6, ip_hdr.src_addr); + sender = ECM_TRACKER_SENDER_TYPE_SRC; + } else { +- if (unlikely(ct == &nf_conntrack_untracked)) { ++ if (unlikely(ctinfo == IP_CT_UNTRACKED)) { + DEBUG_TRACE("%p: ct: untracked\n", skb); + return NF_ACCEPT; + } +@@ -1809,7 +1808,6 @@ sync_conntrack: + } + + ct = nf_ct_tuplehash_to_ctrack(h); +- NF_CT_ASSERT(ct->timeout.data == (unsigned long)ct); + DEBUG_TRACE("%p: NSS Sync: conntrack connection\n", ct); + + ecm_front_end_flow_and_return_directions_get(ct, flow_ip, 6, &flow_dir, &return_dir); +@@ -1820,7 +1818,7 @@ sync_conntrack: + */ + if (!test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) { + spin_lock_bh(&ct->lock); +- ct->timeout.expires += delta_jiffies; ++ ct->timeout += delta_jiffies; + spin_unlock_bh(&ct->lock); + } + +@@ -1878,17 +1876,15 @@ sync_conntrack: + u_int64_t reply_pkts = atomic64_read(&acct[IP_CT_DIR_REPLY].packets); + + if (reply_pkts != 0) { +- struct nf_conntrack_l4proto *l4proto; + unsigned int *timeouts; + + set_bit(IPS_SEEN_REPLY_BIT, &ct->status); + set_bit(IPS_ASSURED_BIT, &ct->status); + +- l4proto = __nf_ct_l4proto_find(AF_INET6, IPPROTO_UDP); +- timeouts = nf_ct_timeout_lookup(&init_net, ct, l4proto); ++ timeouts = nf_ct_timeout_lookup(ct); + + spin_lock_bh(&ct->lock); +- ct->timeout.expires = jiffies + timeouts[UDP_CT_REPLIED]; ++ ct->timeout = jiffies + timeouts[UDP_CT_REPLIED]; + spin_unlock_bh(&ct->lock); + } + } +@@ -2402,7 +2398,7 @@ int ecm_nss_ipv6_init(struct dentry *dentry) + /* + * Register netfilter hooks + */ +- result = nf_register_hooks(ecm_nss_ipv6_netfilter_hooks, ARRAY_SIZE(ecm_nss_ipv6_netfilter_hooks)); ++ result = nf_register_net_hooks(&init_net, ecm_nss_ipv6_netfilter_hooks, ARRAY_SIZE(ecm_nss_ipv6_netfilter_hooks)); + if (result < 0) { + DEBUG_ERROR("Can't register netfilter hooks.\n"); + nss_ipv6_notify_unregister(); +@@ -2414,8 +2410,8 @@ int ecm_nss_ipv6_init(struct dentry *dentry) + if (result < 0) { + DEBUG_ERROR("Failed to init ecm ipv6 multicast frontend\n"); + nss_ipv6_notify_unregister(); +- nf_unregister_hooks(ecm_nss_ipv6_netfilter_hooks, +- ARRAY_SIZE(ecm_nss_ipv6_netfilter_hooks)); ++ nf_unregister_net_hooks(&init_net, ecm_nss_ipv6_netfilter_hooks, ++ ARRAY_SIZE(ecm_nss_ipv6_netfilter_hooks)); + goto task_cleanup; + } + #endif +@@ -2426,8 +2422,8 @@ int ecm_nss_ipv6_init(struct dentry *dentry) + #ifdef ECM_MULTICAST_ENABLE + ecm_nss_multicast_ipv6_exit(); + #endif +- nf_unregister_hooks(ecm_nss_ipv6_netfilter_hooks, +- ARRAY_SIZE(ecm_nss_ipv6_netfilter_hooks)); ++ nf_unregister_net_hooks(&init_net, ecm_nss_ipv6_netfilter_hooks, ++ ARRAY_SIZE(ecm_nss_ipv6_netfilter_hooks)); + goto task_cleanup; + } + +@@ -2453,8 +2449,8 @@ void ecm_nss_ipv6_exit(void) + /* + * Stop the network stack hooks + */ +- nf_unregister_hooks(ecm_nss_ipv6_netfilter_hooks, +- ARRAY_SIZE(ecm_nss_ipv6_netfilter_hooks)); ++ nf_unregister_net_hooks(&init_net, ecm_nss_ipv6_netfilter_hooks, ++ ARRAY_SIZE(ecm_nss_ipv6_netfilter_hooks)); + + /* + * Unregister from the Linux NSS Network driver +--- a/frontends/nss/ecm_nss_multicast_ipv4.c ++++ b/frontends/nss/ecm_nss_multicast_ipv4.c +@@ -50,7 +50,6 @@ + #include + #include + #include +-#include + #include + #include + #include +--- a/frontends/nss/ecm_nss_multicast_ipv6.c ++++ b/frontends/nss/ecm_nss_multicast_ipv6.c +@@ -51,7 +51,6 @@ + #include + #include + #include +-#include + #include + #include + #include +--- a/frontends/nss/ecm_nss_non_ported_ipv4.c ++++ b/frontends/nss/ecm_nss_non_ported_ipv4.c +@@ -47,7 +47,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -640,7 +639,7 @@ static void ecm_nss_non_ported_ipv4_connection_accelerate(struct ecm_front_end_c + #ifdef ECM_INTERFACE_GRE_TAP_ENABLE + dev = dev_get_by_index(&init_net, ecm_db_iface_interface_identifier_get(ii)); + if (dev) { +- if (dev->priv_flags & IFF_GRE_V4_TAP) { ++ if (dev->priv_flags_qca_ecm & IFF_QCA_ECM_GRE_V4_TAP) { + /* + * Clear QOS_VALID to prevent outer rule from overwriting + * inner flow's QoS classification. +--- a/frontends/nss/ecm_nss_non_ported_ipv6.c ++++ b/frontends/nss/ecm_nss_non_ported_ipv6.c +@@ -47,7 +47,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -548,7 +547,7 @@ static void ecm_nss_non_ported_ipv6_connection_accelerate(struct ecm_front_end_c + #ifdef ECM_INTERFACE_GRE_TAP_ENABLE + dev = dev_get_by_index(&init_net, ecm_db_iface_interface_identifier_get(ii)); + if (dev) { +- if (dev->priv_flags & IFF_GRE_V6_TAP) { ++ if (dev->priv_flags_qca_ecm & IFF_QCA_ECM_GRE_V6_TAP) { + /* + * Clear QOS_VALID to prevent outer rule from overwriting + * inner flow's QoS classification. +--- a/frontends/nss/ecm_nss_ported_ipv4.c ++++ b/frontends/nss/ecm_nss_ported_ipv4.c +@@ -47,7 +47,6 @@ + #include + #include + #include +-#include + #include + #include + #include +--- a/frontends/nss/ecm_nss_ported_ipv6.c ++++ b/frontends/nss/ecm_nss_ported_ipv6.c +@@ -47,7 +47,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -1996,7 +1995,7 @@ unsigned int ecm_nss_ported_ipv6_process + /* + * Deny acceleration for L2TP-over-UDP tunnel + */ +- if ((in_dev->priv_flags & IFF_PPP_L2TPV2) && ppp_is_xmit_locked(in_dev)) { ++ if ((in_dev->priv_flags_qca_ecm & IFF_QCA_ECM_PPP_L2TPV2) && ppp_is_xmit_locked(in_dev)) { + DEBUG_TRACE("Skip packets for L2TP tunnel in skb %p\n", skb); + can_accel = false; + } +--- a/frontends/sfe/ecm_sfe_ipv4.c ++++ b/frontends/sfe/ecm_sfe_ipv4.c +@@ -47,7 +47,6 @@ + #include + #include + #include +-#include + #if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 2, 0)) + #include + #else +@@ -746,7 +745,8 @@ static unsigned int ecm_sfe_ipv4_ip_proc + * If skb_dst(skb)->xfrm is not null, packet is to be encrypted by ipsec, we can't accelerate it. + * If skb->sp is not null, packet is decrypted by ipsec. We only accelerate it when configuration didn't reject ipsec. + */ +- if (unlikely((skb_dst(skb) && skb_dst(skb)->xfrm) || (ecm_sfe_ipv4_reject_acceleration_for_ipsec && skb->sp))) { ++ if (unlikely((skb_dst(skb) && skb_dst(skb)->xfrm) || \ ++ (ecm_sfe_ipv4_reject_acceleration_for_ipsec && skb_ext_exist(skb, SKB_EXT_SEC_PATH)))) { + DEBUG_TRACE("skip local ipsec flows\n"); + return NF_ACCEPT; + } +@@ -762,7 +762,7 @@ static unsigned int ecm_sfe_ipv4_ip_process(struct net_device *out_dev, struct n + reply_tuple.dst.u3.ip = orig_tuple.src.u3.ip; + sender = ECM_TRACKER_SENDER_TYPE_SRC; + } else { +- if (unlikely(ct == &nf_conntrack_untracked)) { ++ if (unlikely(ctinfo == IP_CT_UNTRACKED)) { + DEBUG_TRACE("%p: ct: untracked\n", skb); + return NF_ACCEPT; + } +@@ -1531,7 +1526,6 @@ sync_conntrack: + } + + ct = nf_ct_tuplehash_to_ctrack(h); +- NF_CT_ASSERT(ct->timeout.data == (unsigned long)ct); + DEBUG_TRACE("%p: SFE Sync: conntrack connection\n", ct); + + ecm_front_end_flow_and_return_directions_get(ct, flow_ip, 4, &flow_dir, &return_dir); +@@ -1551,7 +1545,7 @@ sync_conntrack: + delta_jiffies = ((sync->inc_ticks * HZ) + (MSEC_PER_SEC / 2)) / MSEC_PER_SEC; + + spin_lock_bh(&ct->lock); +- ct->timeout.expires += delta_jiffies; ++ ct->timeout += delta_jiffies; + spin_unlock_bh(&ct->lock); + } + +@@ -1609,17 +1603,15 @@ sync_conntrack: + u_int64_t reply_pkts = atomic64_read(&acct[IP_CT_DIR_REPLY].packets); + + if (reply_pkts != 0) { +- struct nf_conntrack_l4proto *l4proto; + unsigned int *timeouts; + + set_bit(IPS_SEEN_REPLY_BIT, &ct->status); + set_bit(IPS_ASSURED_BIT, &ct->status); + +- l4proto = __nf_ct_l4proto_find(AF_INET, IPPROTO_UDP); +- timeouts = nf_ct_timeout_lookup(&init_net, ct, l4proto); ++ timeouts = nf_ct_timeout_lookup(ct); + + spin_lock_bh(&ct->lock); +- ct->timeout.expires = jiffies + timeouts[UDP_CT_REPLIED]; ++ ct->timeout = jiffies + timeouts[UDP_CT_REPLIED]; + spin_unlock_bh(&ct->lock); + } + } +@@ -1901,7 +1893,7 @@ int ecm_sfe_ipv4_init(struct dentry *den + /* + * Register netfilter hooks + */ +- result = nf_register_hooks(ecm_sfe_ipv4_netfilter_hooks, ARRAY_SIZE(ecm_sfe_ipv4_netfilter_hooks)); ++ result = nf_register_net_hooks(&init_net, ecm_sfe_ipv4_netfilter_hooks, ARRAY_SIZE(ecm_sfe_ipv4_netfilter_hooks)); + if (result < 0) { + DEBUG_ERROR("Can't register netfilter hooks.\n"); + sfe_drv_ipv4_notify_unregister(); +@@ -1934,8 +1926,8 @@ void ecm_sfe_ipv4_exit(void) + /* + * Stop the network stack hooks + */ +- nf_unregister_hooks(ecm_sfe_ipv4_netfilter_hooks, +- ARRAY_SIZE(ecm_sfe_ipv4_netfilter_hooks)); ++ nf_unregister_net_hooks(&init_net, ecm_sfe_ipv4_netfilter_hooks, ++ ARRAY_SIZE(ecm_sfe_ipv4_netfilter_hooks)); + + /* + * Unregister from the simulated sfe driver +--- a/frontends/sfe/ecm_sfe_ipv6.c ++++ b/frontends/sfe/ecm_sfe_ipv6.c +@@ -51,7 +51,6 @@ + #include + #include + #include +-#include + #if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 2, 0)) + #include + #else +@@ -714,7 +713,8 @@ static unsigned int ecm_sfe_ipv6_ip_proc + * If skb_dst(skb)->xfrm is not null, packet is to be encrypted by ipsec, we can't accelerate it. + * If skb->sp is not null, packet is decrypted by ipsec. We only accelerate it when configuration didn't reject ipsec. + */ +- if (unlikely((skb_dst(skb) && skb_dst(skb)->xfrm) || (ecm_sfe_ipv6_reject_acceleration_for_ipsec && skb->sp))) { ++ if (unlikely((skb_dst(skb) && skb_dst(skb)->xfrm) || \ ++ (ecm_sfe_ipv6_reject_acceleration_for_ipsec && skb_ext_exist(skb, SKB_EXT_SEC_PATH)))) { + DEBUG_TRACE("skip local ipsec flows\n"); + return NF_ACCEPT; + } +@@ -733,7 +733,7 @@ static unsigned int ecm_sfe_ipv6_ip_proc + ECM_IP_ADDR_TO_NIN6_ADDR(reply_tuple.dst.u3.in6, ip_hdr.src_addr); + sender = ECM_TRACKER_SENDER_TYPE_SRC; + } else { +- if (unlikely(ct == &nf_conntrack_untracked)) { ++ if (unlikely(ctinfo == IP_CT_UNTRACKED)) { + DEBUG_TRACE("%p: ct: untracked\n", skb); + return NF_ACCEPT; + } +@@ -1255,7 +1255,6 @@ sync_conntrack: + } + + ct = nf_ct_tuplehash_to_ctrack(h); +- NF_CT_ASSERT(ct->timeout.data == (unsigned long)ct); + DEBUG_TRACE("%p: SFE Sync: conntrack connection\n", ct); + + ecm_front_end_flow_and_return_directions_get(ct, flow_ip, 6, &flow_dir, &return_dir); +@@ -1275,7 +1274,7 @@ sync_conntrack: + delta_jiffies = ((sync->inc_ticks * HZ) + (MSEC_PER_SEC / 2)) / MSEC_PER_SEC; + + spin_lock_bh(&ct->lock); +- ct->timeout.expires += delta_jiffies; ++ ct->timeout += delta_jiffies; + spin_unlock_bh(&ct->lock); + } + #if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,6,0)) +@@ -1332,17 +1331,15 @@ sync_conntrack: + u_int64_t reply_pkts = atomic64_read(&acct[IP_CT_DIR_REPLY].packets); + + if (reply_pkts != 0) { +- struct nf_conntrack_l4proto *l4proto; + unsigned int *timeouts; + + set_bit(IPS_SEEN_REPLY_BIT, &ct->status); + set_bit(IPS_ASSURED_BIT, &ct->status); + +- l4proto = __nf_ct_l4proto_find(AF_INET6, IPPROTO_UDP); +- timeouts = nf_ct_timeout_lookup(&init_net, ct, l4proto); ++ timeouts = nf_ct_timeout_lookup(ct); + + spin_lock_bh(&ct->lock); +- ct->timeout.expires = jiffies + timeouts[UDP_CT_REPLIED]; ++ ct->timeout = jiffies + timeouts[UDP_CT_REPLIED]; + spin_unlock_bh(&ct->lock); + } + } +@@ -1624,7 +1621,7 @@ int ecm_sfe_ipv6_init(struct dentry *den + /* + * Register netfilter hooks + */ +- result = nf_register_hooks(ecm_sfe_ipv6_netfilter_hooks, ARRAY_SIZE(ecm_sfe_ipv6_netfilter_hooks)); ++ result = nf_register_net_hooks(&init_net, ecm_sfe_ipv6_netfilter_hooks, ARRAY_SIZE(ecm_sfe_ipv6_netfilter_hooks)); + if (result < 0) { + DEBUG_ERROR("Can't register netfilter hooks.\n"); + sfe_drv_ipv6_notify_unregister(); +@@ -1656,8 +1653,8 @@ void ecm_sfe_ipv6_exit(void) + /* + * Stop the network stack hooks + */ +- nf_unregister_hooks(ecm_sfe_ipv6_netfilter_hooks, +- ARRAY_SIZE(ecm_sfe_ipv6_netfilter_hooks)); ++ nf_unregister_net_hooks(&init_net, ecm_sfe_ipv6_netfilter_hooks, ++ ARRAY_SIZE(ecm_sfe_ipv6_netfilter_hooks)); + + /* + * Unregister from the Linux SFE Network driver +--- a/frontends/sfe/ecm_sfe_non_ported_ipv4.c ++++ b/frontends/sfe/ecm_sfe_non_ported_ipv4.c +@@ -46,7 +46,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -1829,7 +1828,7 @@ unsigned int ecm_sfe_non_ported_ipv4_pro + /* + * Packet has been decrypted by ipsec, mark it in connection. + */ +- if (unlikely(skb->sp)) { ++ if (unlikely(skb_ext_exist(skb, SKB_EXT_SEC_PATH))) { + ((struct ecm_sfe_non_ported_ipv4_connection_instance *)feci)->flow_ipsec_state = ECM_SFE_IPSEC_STATE_WAS_DECRYPTED; + ((struct ecm_sfe_non_ported_ipv4_connection_instance *)feci)->return_ipsec_state = ECM_SFE_IPSEC_STATE_TO_ENCRYPT; + } +--- a/frontends/sfe/ecm_sfe_non_ported_ipv6.c ++++ b/frontends/sfe/ecm_sfe_non_ported_ipv6.c +@@ -47,7 +47,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -1710,7 +1709,7 @@ unsigned int ecm_sfe_non_ported_ipv6_pro + /* + * Packet has been decrypted by ipsec, mark it in connection. + */ +- if (unlikely(skb->sp)) { ++ if (unlikely(skb_ext_exist(skb, SKB_EXT_SEC_PATH))) { + ((struct ecm_sfe_non_ported_ipv6_connection_instance *)feci)->flow_ipsec_state = ECM_SFE_IPSEC_STATE_WAS_DECRYPTED; + ((struct ecm_sfe_non_ported_ipv6_connection_instance *)feci)->return_ipsec_state = ECM_SFE_IPSEC_STATE_TO_ENCRYPT; + } +--- a/frontends/sfe/ecm_sfe_ported_ipv4.c ++++ b/frontends/sfe/ecm_sfe_ported_ipv4.c +@@ -46,7 +46,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -2053,7 +2052,7 @@ unsigned int ecm_sfe_ported_ipv4_process + /* + * Packet has been decrypted by ipsec, mark it in connection. + */ +- if (unlikely(skb->sp)) { ++ if (unlikely(skb_ext_exist(skb, SKB_EXT_SEC_PATH))) { + ((struct ecm_sfe_ported_ipv4_connection_instance *)feci)->flow_ipsec_state = ECM_SFE_IPSEC_STATE_WAS_DECRYPTED; + ((struct ecm_sfe_ported_ipv4_connection_instance *)feci)->return_ipsec_state = ECM_SFE_IPSEC_STATE_TO_ENCRYPT; + } +--- a/frontends/sfe/ecm_sfe_ported_ipv6.c ++++ b/frontends/sfe/ecm_sfe_ported_ipv6.c +@@ -47,7 +47,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -1826,7 +1825,7 @@ unsigned int ecm_sfe_ported_ipv6_process + /* + * Deny acceleration for L2TP-over-UDP tunnel + */ +- if ((in_dev->priv_flags & IFF_PPP_L2TPV2) && ppp_is_xmit_locked(in_dev)) { ++ if ((in_dev->priv_flags_qca_ecm & IFF_QCA_ECM_PPP_L2TPV2) && ppp_is_xmit_locked(in_dev)) { + DEBUG_TRACE("Skip packets for L2TP tunnel in skb %p\n", skb); + can_accel = false; + } +@@ -1958,7 +1957,7 @@ unsigned int ecm_sfe_ported_ipv6_process + /* + * Packet has been decrypted by ipsec, mark it in connection. + */ +- if (unlikely(skb->sp)) { ++ if (unlikely(skb_ext_exist(skb, SKB_EXT_SEC_PATH))) { + ((struct ecm_sfe_ported_ipv6_connection_instance *)feci)->flow_ipsec_state = ECM_SFE_IPSEC_STATE_WAS_DECRYPTED; + ((struct ecm_sfe_ported_ipv6_connection_instance *)feci)->return_ipsec_state = ECM_SFE_IPSEC_STATE_TO_ENCRYPT; + } diff --git a/root/package/qca/nss/qca-nss-ecm/patches/101-Fix_Kern_Panic_on_UDP_CONNTRACK.patch b/root/package/qca/nss/qca-nss-ecm/patches/101-Fix_Kern_Panic_on_UDP_CONNTRACK.patch new file mode 100644 index 00000000..6633f72b --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm/patches/101-Fix_Kern_Panic_on_UDP_CONNTRACK.patch @@ -0,0 +1,60 @@ +diff --git a/frontends/nss/ecm_nss_ipv4.c b/frontends/nss/ecm_nss_ipv4.c +index 1ce4b61..29e70ba 100644 +--- a/frontends/nss/ecm_nss_ipv4.c ++++ b/frontends/nss/ecm_nss_ipv4.c +@@ -2171,6 +2171,10 @@ sync_conntrack: + + timeouts = nf_ct_timeout_lookup(ct); + ++ /* Copy of udp_get_timeouts in kernel */ ++ if (!timeouts) ++ timeouts = nf_udp_pernet(nf_ct_net(ct))->timeouts; ++ + spin_lock_bh(&ct->lock); + ct->timeout = jiffies + timeouts[UDP_CT_REPLIED]; + spin_unlock_bh(&ct->lock); +diff --git a/frontends/nss/ecm_nss_ipv6.c b/frontends/nss/ecm_nss_ipv6.c +index 2adc5ec..08253b6 100644 +--- a/frontends/nss/ecm_nss_ipv6.c ++++ b/frontends/nss/ecm_nss_ipv6.c +@@ -1883,6 +1883,10 @@ sync_conntrack: + + timeouts = nf_ct_timeout_lookup(ct); + ++ /* Copy of udp_get_timeouts in kernel */ ++ if (!timeouts) ++ timeouts = nf_udp_pernet(nf_ct_net(ct))->timeouts; ++ + spin_lock_bh(&ct->lock); + ct->timeout = jiffies + timeouts[UDP_CT_REPLIED]; + spin_unlock_bh(&ct->lock); +diff --git a/frontends/sfe/ecm_sfe_ipv4.c b/frontends/sfe/ecm_sfe_ipv4.c +index 7cfe4fc..8f525ee 100644 +--- a/frontends/sfe/ecm_sfe_ipv4.c ++++ b/frontends/sfe/ecm_sfe_ipv4.c +@@ -1608,6 +1608,10 @@ sync_conntrack: + + timeouts = nf_ct_timeout_lookup(ct); + ++ /* Copy of udp_get_timeouts in kernel */ ++ if (!timeouts) ++ timeouts = nf_udp_pernet(nf_ct_net(ct))->timeouts; ++ + spin_lock_bh(&ct->lock); + ct->timeout = jiffies + timeouts[UDP_CT_REPLIED]; + spin_unlock_bh(&ct->lock); +diff --git a/frontends/sfe/ecm_sfe_ipv6.c b/frontends/sfe/ecm_sfe_ipv6.c +index dfde309..47c531a 100644 +--- a/frontends/sfe/ecm_sfe_ipv6.c ++++ b/frontends/sfe/ecm_sfe_ipv6.c +@@ -1321,6 +1321,10 @@ sync_conntrack: + + timeouts = nf_ct_timeout_lookup(ct); + ++ /* Copy of udp_get_timeouts in kernel */ ++ if (!timeouts) ++ timeouts = nf_udp_pernet(nf_ct_net(ct))->timeouts; ++ + spin_lock_bh(&ct->lock); + ct->timeout = jiffies + timeouts[UDP_CT_REPLIED]; + spin_unlock_bh(&ct->lock); diff --git a/root/package/qca/nss/qca-nss-ecm/patches/200-resolve-high-load.patch b/root/package/qca/nss/qca-nss-ecm/patches/200-resolve-high-load.patch new file mode 100644 index 00000000..2f39d277 --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm/patches/200-resolve-high-load.patch @@ -0,0 +1,44 @@ +The sync update work queue tasks is calling uninterruptible sleep function, which is +causing high CPU load. Changed to interruptible sleep function. The stats update +task should be interruptible. + +--- a/frontends/nss/ecm_nss_ipv4.c ++++ b.frontends/nss/ecm_nss_ipv4.c +@@ -2411,7 +2411,7 @@ static void ecm_nss_ipv4_stats_sync_req_ + } + spin_unlock_bh(&ecm_nss_ipv4_lock); + +- usleep_range(ECM_NSS_IPV4_STATS_SYNC_UDELAY - 100, ECM_NSS_IPV4_STATS_SYNC_UDELAY); ++ msleep_interruptible(ECM_NSS_IPV4_STATS_SYNC_UDELAY / 1000); + + /* + * If index is 0, we are starting a new round, but if we still have time remain +@@ -2425,7 +2425,7 @@ static void ecm_nss_ipv4_stats_sync_req_ + } + + if (ecm_nss_ipv4_next_req_time > current_jiffies) { +- msleep(jiffies_to_msecs(ecm_nss_ipv4_next_req_time - current_jiffies)); ++ msleep_interruptible(jiffies_to_msecs(ecm_nss_ipv4_next_req_time - current_jiffies)); + } + ecm_nss_ipv4_roll_check_jiffies = jiffies; + ecm_nss_ipv4_next_req_time = ecm_nss_ipv4_roll_check_jiffies + ECM_NSS_IPV4_STATS_SYNC_PERIOD; +--- a/frontends/nss/ecm_nss_ipv6.c ++++ b.frontends/nss/ecm_nss_ipv6.c +@@ -2128,7 +2128,7 @@ static void ecm_nss_ipv6_stats_sync_req_ + } + spin_unlock_bh(&ecm_nss_ipv6_lock); + +- usleep_range(ECM_NSS_IPV6_STATS_SYNC_UDELAY - 100, ECM_NSS_IPV6_STATS_SYNC_UDELAY); ++ msleep_interruptible(ECM_NSS_IPV6_STATS_SYNC_UDELAY / 1000); + + /* + * If index is 0, we are starting a new round, but if we still have time remain +@@ -2142,7 +2142,7 @@ static void ecm_nss_ipv6_stats_sync_req_ + } + + if (ecm_nss_ipv6_next_req_time > current_jiffies) { +- msleep(jiffies_to_msecs(ecm_nss_ipv6_next_req_time - current_jiffies)); ++ msleep_interruptible(jiffies_to_msecs(ecm_nss_ipv6_next_req_time - current_jiffies)); + } + ecm_nss_ipv6_roll_check_jiffies = jiffies; + ecm_nss_ipv6_next_req_time = ecm_nss_ipv6_roll_check_jiffies + ECM_NSS_IPV6_STATS_SYNC_PERIOD; diff --git a/root/package/qca/nss/qca-nss-ecm/patches/203-rework-nfct-notification.patch b/root/package/qca/nss/qca-nss-ecm/patches/203-rework-nfct-notification.patch new file mode 100644 index 00000000..a0e09c1f --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm/patches/203-rework-nfct-notification.patch @@ -0,0 +1,20 @@ +--- a/ecm_conntrack_notifier.c ++++ b/ecm_conntrack_notifier.c +@@ -411,7 +411,7 @@ int ecm_conntrack_notifier_init(struct d + /* + * Eventing subsystem is available so we register a notifier hook to get fast notifications of expired connections + */ +- result = nf_conntrack_register_notifier(&init_net, &ecm_conntrack_notifier); ++ result = nf_conntrack_register_chain_notifier(&init_net, &ecm_conntrack_notifier); + if (result < 0) { + DEBUG_ERROR("Can't register nf notifier hook.\n"); + debugfs_remove_recursive(ecm_conntrack_notifier_dentry); +@@ -430,7 +430,7 @@ void ecm_conntrack_notifier_exit(void) + { + DEBUG_INFO("ECM Conntrack Notifier exit\n"); + #ifdef CONFIG_NF_CONNTRACK_EVENTS +- nf_conntrack_unregister_notifier(&init_net, &ecm_conntrack_notifier); ++ nf_conntrack_unregister_chain_notifier(&init_net, &ecm_conntrack_notifier); + #endif + /* + * Remove the debugfs files recursively. diff --git a/root/package/qca/nss/qca-nss-ecm/patches/400-Check-TCP_UDP-conntrack-state-earlier.patch b/root/package/qca/nss/qca-nss-ecm/patches/400-Check-TCP_UDP-conntrack-state-earlier.patch new file mode 100644 index 00000000..b7882c1b --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm/patches/400-Check-TCP_UDP-conntrack-state-earlier.patch @@ -0,0 +1,236 @@ +From 90cace88a342e77ee8ca1e961cf7b7a7930d4c89 Mon Sep 17 00:00:00 2001 +From: Murat Sezgin +Date: Mon, 9 Mar 2020 12:51:03 -0700 +Subject: [qca-nss-ecm] Check TCP/UDP conntrack state earlier + +Check the conntrack state before processing the flow +and adding it to the database. The unconfirmed +connections can be changed after the confirmation. + +Changed the TCP tracker connection state matrix to set the +state of the connection as ESTABLISHED when any of the src or +dest side is set as ESTABLISHED. With this change ECM will not +handle the SYN and SYN-ACK packets of the TCP handshake. Only the +ACK and FIN flaged packets will be used during the creation and +closing the connection respectively. + +Signed-off-by: Murat Sezgin +Change-Id: I3e0a58d604df4c6a85478ca9c05f24d50cd8c894 +--- + ecm_classifier_default.c | 36 ++++++++---------------------------- + ecm_tracker_tcp.c | 4 ++-- + frontends/nss/ecm_nss_ported_ipv4.c | 17 +++++++++++++++++ + frontends/nss/ecm_nss_ported_ipv6.c | 17 +++++++++++++++++ + frontends/sfe/ecm_sfe_ported_ipv4.c | 17 +++++++++++++++++ + frontends/sfe/ecm_sfe_ported_ipv6.c | 17 +++++++++++++++++ + 6 files changed, 78 insertions(+), 30 deletions(-) + +diff --git a/ecm_classifier_default.c b/ecm_classifier_default.c +index 22c4bec..d04cdfa 100644 +--- a/ecm_classifier_default.c ++++ b/ecm_classifier_default.c +@@ -1,6 +1,6 @@ + /* + ************************************************************************** +- * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2014-2016, 2020, The Linux Foundation. All rights reserved. + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. +@@ -285,12 +285,12 @@ static void ecm_classifier_default_process(struct ecm_classifier_instance *aci, + } + + /* +- * Check the TCP connection state. ++ * Check the TCP connection state, when the ct is NULL. ++ * ct valid case was already checked in the ecm_nss{sfe}_ported_ipv4{6}_process functions. + * If we are not established then we deny acceleration. +- * Take lead from conntrack if exists. + */ + ct = nf_ct_get(skb, &ctinfo); +- if (ct == NULL) { ++ if (!ct) { + DEBUG_TRACE("%p: No Conntrack found for packet, using ECM tracker state\n", cdii); + if (unlikely(prevailing_state != ECM_TRACKER_CONNECTION_STATE_ESTABLISHED)) { + cdii->process_response.accel_mode = ECM_CLASSIFIER_ACCELERATION_MODE_NO; +@@ -298,29 +298,10 @@ static void ecm_classifier_default_process(struct ecm_classifier_instance *aci, + } + } else { + /* +- * Unconfirmed connection may be dropped by Linux at the final step, +- * So we don't allow acceleration for the unconfirmed connections. +- */ +- if (!nf_ct_is_confirmed(ct)) { +- DEBUG_TRACE("%p: Unconfirmed connection\n", ct); +- cdii->process_response.accel_mode = ECM_CLASSIFIER_ACCELERATION_MODE_NO; +- goto return_response; +- } +- +- /* +- * Don't try to manage a non-established connection. +- */ +- if (!test_bit(IPS_ASSURED_BIT, &ct->status)) { +- DEBUG_TRACE("%p: Non-established connection\n", ct); +- cdii->process_response.accel_mode = ECM_CLASSIFIER_ACCELERATION_MODE_NO; +- goto return_response; +- } +- +- /* +- * If the connection is shutting down do not manage it. +- * state can not be SYN_SENT, SYN_RECV because connection is assured +- * Not managed states: FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE. +- */ ++ * If the connection is shutting down do not manage it. ++ * state can not be SYN_SENT, SYN_RECV because connection is assured ++ * Not managed states: FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE. ++ */ + spin_lock_bh(&ct->lock); + if (ct->proto.tcp.state != TCP_CONNTRACK_ESTABLISHED) { + spin_unlock_bh(&ct->lock); +@@ -333,7 +314,6 @@ static void ecm_classifier_default_process(struct ecm_classifier_instance *aci, + + return_response: + ; +- + /* + * Return the process response + */ +diff --git a/ecm_tracker_tcp.c b/ecm_tracker_tcp.c +index f073c36..e5b327a 100644 +--- a/ecm_tracker_tcp.c ++++ b/ecm_tracker_tcp.c +@@ -257,9 +257,9 @@ static DEFINE_SPINLOCK(ecm_tracker_tcp_lock); /* Global lock for the tracker gl + */ + static ecm_tracker_connection_state_t ecm_tracker_tcp_connection_state_matrix[ECM_TRACKER_SENDER_STATE_MAX][ECM_TRACKER_SENDER_STATE_MAX] = + { /* Unknown Establishing Established Closing Closed Fault */ +- /* Unknown */ {ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT}, ++ /* Unknown */ {ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_ESTABLISHED, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT}, + /* Establishing */ {ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT}, +- /* Established */ {ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_ESTABLISHED, ECM_TRACKER_CONNECTION_STATE_CLOSING, ECM_TRACKER_CONNECTION_STATE_CLOSING, ECM_TRACKER_CONNECTION_STATE_FAULT}, ++ /* Established */ {ECM_TRACKER_CONNECTION_STATE_ESTABLISHED, ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_ESTABLISHED, ECM_TRACKER_CONNECTION_STATE_CLOSING, ECM_TRACKER_CONNECTION_STATE_CLOSING, ECM_TRACKER_CONNECTION_STATE_FAULT}, + /* Closing */ {ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_CLOSING, ECM_TRACKER_CONNECTION_STATE_CLOSING, ECM_TRACKER_CONNECTION_STATE_CLOSING, ECM_TRACKER_CONNECTION_STATE_FAULT}, + /* Closed */ {ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_CLOSING, ECM_TRACKER_CONNECTION_STATE_CLOSING, ECM_TRACKER_CONNECTION_STATE_CLOSED, ECM_TRACKER_CONNECTION_STATE_FAULT}, + /* Fault */ {ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT}, +diff --git a/frontends/nss/ecm_nss_ported_ipv4.c b/frontends/nss/ecm_nss_ported_ipv4.c +index 1435ec0..34c056f 100644 +--- a/frontends/nss/ecm_nss_ported_ipv4.c ++++ b/frontends/nss/ecm_nss_ported_ipv4.c +@@ -2002,8 +2002,25 @@ unsigned int ecm_nss_ported_ipv4_process(struct net_device *out_dev, struct net_ + int protocol = (int)orig_tuple->dst.protonum; + __be16 *layer4hdr = NULL; + ++ /* ++ * Unconfirmed connection may be dropped by Linux at the final step, ++ * So we don't allow acceleration for the unconfirmed connections. ++ */ ++ if (likely(ct) && !nf_ct_is_confirmed(ct)) { ++ DEBUG_WARN("%p: Unconfirmed connection\n", ct); ++ return NF_ACCEPT; ++ } ++ + if (protocol == IPPROTO_TCP) { + /* ++ * Don't try to manage a non-established connection. ++ */ ++ if (likely(ct) && !test_bit(IPS_ASSURED_BIT, &ct->status)) { ++ DEBUG_WARN("%p: Non-established TCP connection\n", ct); ++ return NF_ACCEPT; ++ } ++ ++ /* + * Extract TCP header to obtain port information + */ + tcp_hdr = ecm_tracker_tcp_check_header_and_read(skb, iph, &tcp_hdr_buff); +diff --git a/frontends/nss/ecm_nss_ported_ipv6.c b/frontends/nss/ecm_nss_ported_ipv6.c +index 4c154a6..bd6349b 100644 +--- a/frontends/nss/ecm_nss_ported_ipv6.c ++++ b/frontends/nss/ecm_nss_ported_ipv6.c +@@ -1914,8 +1914,25 @@ unsigned int ecm_nss_ported_ipv6_process(struct net_device *out_dev, + int protocol = (int)orig_tuple->dst.protonum; + __be16 *layer4hdr = NULL; + ++ /* ++ * Unconfirmed connection may be dropped by Linux at the final step, ++ * So we don't allow acceleration for the unconfirmed connections. ++ */ ++ if (likely(ct) && !nf_ct_is_confirmed(ct)) { ++ DEBUG_WARN("%p: Unconfirmed connection\n", ct); ++ return NF_ACCEPT; ++ } ++ + if (protocol == IPPROTO_TCP) { + /* ++ * Don't try to manage a non-established connection. ++ */ ++ if (likely(ct) && !test_bit(IPS_ASSURED_BIT, &ct->status)) { ++ DEBUG_WARN("%p: Non-established TCP connection\n", ct); ++ return NF_ACCEPT; ++ } ++ ++ /* + * Extract TCP header to obtain port information + */ + tcp_hdr = ecm_tracker_tcp_check_header_and_read(skb, iph, &tcp_hdr_buff); +diff --git a/frontends/sfe/ecm_sfe_ported_ipv4.c b/frontends/sfe/ecm_sfe_ported_ipv4.c +index e034cde..df1ce57 100644 +--- a/frontends/sfe/ecm_sfe_ported_ipv4.c ++++ b/frontends/sfe/ecm_sfe_ported_ipv4.c +@@ -1805,8 +1805,25 @@ unsigned int ecm_sfe_ported_ipv4_process(struct net_device *out_dev, struct net_ + int protocol = (int)orig_tuple->dst.protonum; + __be16 *layer4hdr = NULL; + ++ /* ++ * Unconfirmed connection may be dropped by Linux at the final step, ++ * So we don't allow acceleration for the unconfirmed connections. ++ */ ++ if (likely(ct) && !nf_ct_is_confirmed(ct)) { ++ DEBUG_WARN("%p: Unconfirmed connection\n", ct); ++ return NF_ACCEPT; ++ } ++ + if (protocol == IPPROTO_TCP) { + /* ++ * Don't try to manage a non-established connection. ++ */ ++ if (likely(ct) && !test_bit(IPS_ASSURED_BIT, &ct->status)) { ++ DEBUG_WARN("%p: Non-established TCP connection\n", ct); ++ return NF_ACCEPT; ++ } ++ ++ /* + * Extract TCP header to obtain port information + */ + tcp_hdr = ecm_tracker_tcp_check_header_and_read(skb, iph, &tcp_hdr_buff); +diff --git a/frontends/sfe/ecm_sfe_ported_ipv6.c b/frontends/sfe/ecm_sfe_ported_ipv6.c +index 6ac05ad..657a1c7 100644 +--- a/frontends/sfe/ecm_sfe_ported_ipv6.c ++++ b/frontends/sfe/ecm_sfe_ported_ipv6.c +@@ -1746,8 +1746,25 @@ unsigned int ecm_sfe_ported_ipv6_process(struct net_device *out_dev, + int protocol = (int)orig_tuple->dst.protonum; + __be16 *layer4hdr = NULL; + ++ /* ++ * Unconfirmed connection may be dropped by Linux at the final step, ++ * So we don't allow acceleration for the unconfirmed connections. ++ */ ++ if (likely(ct) && !nf_ct_is_confirmed(ct)) { ++ DEBUG_WARN("%p: Unconfirmed connection\n", ct); ++ return NF_ACCEPT; ++ } ++ + if (protocol == IPPROTO_TCP) { + /* ++ * Don't try to manage a non-established connection. ++ */ ++ if (likely(ct) && !test_bit(IPS_ASSURED_BIT, &ct->status)) { ++ DEBUG_WARN("%p: Non-established TCP connection\n", ct); ++ return NF_ACCEPT; ++ } ++ ++ /* + * Extract TCP header to obtain port information + */ + tcp_hdr = ecm_tracker_tcp_check_header_and_read(skb, iph, &tcp_hdr_buff); +-- +cgit v1.1 + diff --git a/root/package/qca/nss/qca-nss-ecm/patches/401-Fix-NSS-stats-request-roll-over-issue.patch b/root/package/qca/nss/qca-nss-ecm/patches/401-Fix-NSS-stats-request-roll-over-issue.patch new file mode 100644 index 00000000..217054bb --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm/patches/401-Fix-NSS-stats-request-roll-over-issue.patch @@ -0,0 +1,52 @@ +From 9ad19ffdcfdf77baf3abd4fcc933fd3dc8e791a5 Mon Sep 17 00:00:00 2001 +From: Murat Sezgin +Date: Sat, 20 Jun 2020 09:41:01 -0700 +Subject: [qca-nss-ecm] Fix NSS stats request roll over issue + +Use the correct timer API to check the next request time +when jiffies wrap happens. + +Signed-off-by: Murat Sezgin +Change-Id: I18646d28df7e17daeff2986dfe4bd73866d47668 +--- + frontends/nss/ecm_nss_ipv4.c | 4 ++-- + frontends/nss/ecm_nss_ipv6.c | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/frontends/nss/ecm_nss_ipv4.c b/frontends/nss/ecm_nss_ipv4.c +index 3eaf5d8..80e1aee 100644 +--- a/frontends/nss/ecm_nss_ipv4.c ++++ b/frontends/nss/ecm_nss_ipv4.c +@@ -2421,10 +2421,10 @@ static void ecm_nss_ipv4_stats_sync_req_work(struct work_struct *work) + current_jiffies = jiffies; + + if (time_is_after_jiffies(ecm_nss_ipv4_roll_check_jiffies)) { +- ecm_nss_ipv4_next_req_time = 0; ++ ecm_nss_ipv4_next_req_time = jiffies + ECM_NSS_IPV4_STATS_SYNC_PERIOD; + } + +- if (ecm_nss_ipv4_next_req_time > current_jiffies) { ++ if (time_after(ecm_nss_ipv4_next_req_time, current_jiffies)) { + msleep_interruptible(jiffies_to_msecs(ecm_nss_ipv4_next_req_time - current_jiffies)); + } + ecm_nss_ipv4_roll_check_jiffies = jiffies; +diff --git a/frontends/nss/ecm_nss_ipv6.c b/frontends/nss/ecm_nss_ipv6.c +index 288dc55..483421e 100644 +--- a/frontends/nss/ecm_nss_ipv6.c ++++ b/frontends/nss/ecm_nss_ipv6.c +@@ -2135,10 +2135,10 @@ static void ecm_nss_ipv6_stats_sync_req_work(struct work_struct *work) + current_jiffies = jiffies; + + if (time_is_after_jiffies(ecm_nss_ipv6_roll_check_jiffies)) { +- ecm_nss_ipv6_next_req_time = 0; ++ ecm_nss_ipv6_next_req_time = jiffies + ECM_NSS_IPV6_STATS_SYNC_PERIOD; + } + +- if (ecm_nss_ipv6_next_req_time > current_jiffies) { ++ if (time_after(ecm_nss_ipv6_next_req_time, current_jiffies)) { + msleep_interruptible(jiffies_to_msecs(ecm_nss_ipv6_next_req_time - current_jiffies)); + } + ecm_nss_ipv6_roll_check_jiffies = jiffies; +-- +cgit v1.1 + diff --git a/root/package/qca/nss/qca-nss-ecm/patches/401-Fix-for-ref-leak-during-multicast.patch b/root/package/qca/nss/qca-nss-ecm/patches/401-Fix-for-ref-leak-during-multicast.patch new file mode 100644 index 00000000..e1df653b --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm/patches/401-Fix-for-ref-leak-during-multicast.patch @@ -0,0 +1,112 @@ +From 4b41703a181b7187d9ff8cb744eb96d09997387c Mon Sep 17 00:00:00 2001 +From: Suman Ghosh +Date: Wed, 19 Feb 2020 15:09:19 +0530 +Subject: [qca-nss-ecm] Fix for ref leak during multicast 'to' hierarchy + creation + +Change-Id: I89df9dbe5ea054cf3b87d55ce68a751cb1d6c24f +Signed-off-by: Suman Ghosh +--- + ecm_interface.c | 34 ++++++++++++++++++++++++++++++---- + 1 file changed, 30 insertions(+), 4 deletions(-) + +diff --git a/ecm_interface.c b/ecm_interface.c +index 4f7a886..2a0ca5b 100644 +--- a/ecm_interface.c ++++ b/ecm_interface.c +@@ -3885,13 +3885,13 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ + dest_dev = dev_get_by_index(&init_net, *dst_if_index); + if (!dest_dev) { + if (!src_dev_is_bridge) { +- int i; +- + /* + * If already constructed any interface heirarchies before hitting + * this error condition then Deref all interface heirarchies. + */ + if (valid_if > 0) { ++ int i; ++ + for (i = 0; i < valid_if; i++) { + ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i); + ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces); +@@ -3902,11 +3902,14 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ + /* + * If valid netdev not found, Return 0 + */ ++ if (br_dev_src) { ++ dev_put(br_dev_src); ++ } ++ + return 0; + } + + dest_dev = br_dev_src; +- + } + + dest_dev_type = dest_dev->type; +@@ -3945,6 +3948,10 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ + } + } + ++ if (br_dev_src && (dest_dev != br_dev_src)) { ++ dev_put(br_dev_src); ++ } ++ + dev_put(dest_dev); + return 0; + } +@@ -3972,6 +3979,10 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ + ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]); + } + ++ if (br_dev_src && (dest_dev != br_dev_src)) { ++ dev_put(br_dev_src); ++ } ++ + dev_put(dest_dev); + dev_put(mc_br_slave_dev); + return 0; +@@ -3997,6 +4008,10 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ + } + } + ++ if (br_dev_src && (dest_dev != br_dev_src)) { ++ dev_put(br_dev_src); ++ } ++ + dev_put(dest_dev); + dev_put(mc_br_slave_dev); + return 0; +@@ -4032,6 +4047,10 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ + } + } + ++ if (br_dev_src && (dest_dev != br_dev_src)) { ++ dev_put(br_dev_src); ++ } ++ + dev_put(dest_dev); + return 0; + } +@@ -4042,8 +4061,15 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ + valid_if++; + } + +- dev_put(dest_dev); ++ if (dest_dev != br_dev_src) { ++ dev_put(dest_dev); ++ } + } ++ ++ if (br_dev_src) { ++ dev_put(br_dev_src); ++ } ++ + return total_ii_count; + } + EXPORT_SYMBOL(ecm_interface_multicast_heirarchy_construct_routed); +-- +cgit v1.1 + diff --git a/root/package/qca/nss/qca-nss-ecm/patches/401-Fix-neighbour-solicitation-send-function.patch b/root/package/qca/nss/qca-nss-ecm/patches/401-Fix-neighbour-solicitation-send-function.patch new file mode 100644 index 00000000..7d32d6fd --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm/patches/401-Fix-neighbour-solicitation-send-function.patch @@ -0,0 +1,33 @@ +From 72e3ae508906553e7bc982bf3c0d99bb1cbe9008 Mon Sep 17 00:00:00 2001 +From: Murat Sezgin +Date: Wed, 20 Nov 2019 16:23:06 -0800 +Subject: [qca-nss-ecm] Fix neighbour solicitation send function. + +dst_ops->neigh_lookup function pointer is set to the +ip6_neigh_lookup function. This function returns an +error pointer with the ERR_PTR() macro. So, we should +check the return value of this function pointer with +the IS_ERR() macro. + +Change-Id: I188a6e53278faaa68f1854524f612efc1f7451fe +Signed-off-by: Murat Sezgin +--- + ecm_interface.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ecm_interface.c b/ecm_interface.c +index 3f8554b..36509f0 100644 +--- a/ecm_interface.c ++++ b/ecm_interface.c +@@ -1100,7 +1100,7 @@ void ecm_interface_send_neighbour_solicitation(struct net_device *dev, ip_addr_t + #else + neigh = rt6i->dst.ops->neigh_lookup(&rt6i->dst, NULL, &dst_addr); + #endif +- if (neigh == NULL) { ++ if (IS_ERR(neigh)) { + DEBUG_TRACE("Neighbour lookup failure for destination IPv6 address " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(addr)); + dst_release(&rt6i->dst); + return; +-- +cgit v1.1 + diff --git a/root/package/qca/nss/qca-nss-ecm/patches/402-Reference-leak-during-multicast_PPPoE-bridge.patch b/root/package/qca/nss/qca-nss-ecm/patches/402-Reference-leak-during-multicast_PPPoE-bridge.patch new file mode 100644 index 00000000..97ce7a7e --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm/patches/402-Reference-leak-during-multicast_PPPoE-bridge.patch @@ -0,0 +1,260 @@ +From 7c0610828b835b2aab96dd50ec841a3a28689112 Mon Sep 17 00:00:00 2001 +From: Suman Ghosh +Date: Mon, 16 Mar 2020 15:22:18 +0530 +Subject: [qca-nss-ecm] Reference leak during multicast + PPPoE bridge + +Signed-off-by: Suman Ghosh +Change-Id: I4472035f1bbb087e637169762ae2648c0fda792a +--- + ecm_interface.c | 136 +++++++++++++++++++++++++------------------------------- + 1 file changed, 60 insertions(+), 76 deletions(-) + +diff --git a/ecm_interface.c b/ecm_interface.c +index 1614336..c0d2357 100644 +--- a/ecm_interface.c ++++ b/ecm_interface.c +@@ -3796,6 +3796,25 @@ fail: + } + + /* ++ * ecm_interface_hierarchy_delete() ++ * Delete hierarchy of the requested interfaces. ++ */ ++static inline void ecm_interface_hierarchy_delete(struct ecm_db_iface_instance *interfaces, ++ uint32_t *interface_first_base, ++ int valid_if) ++{ ++ struct ecm_db_iface_instance *to_list_single[ECM_DB_IFACE_HEIRARCHY_MAX]; ++ struct ecm_db_iface_instance *ifaces; ++ int i; ++ ++ for (i = 0; i < valid_if; i++) { ++ ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i); ++ ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces); ++ ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]); ++ } ++} ++ ++/* + * ecm_interface_multicast_heirarchy_construct_routed() + * Create destination interface heirarchy for a routed multicast connectiona + * +@@ -3816,7 +3835,6 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ + uint32_t *interface_first_base, bool mfc_update, + __be16 *layer4hdr, struct sk_buff *skb) + { +- struct ecm_db_iface_instance *to_list_single[ECM_DB_IFACE_HEIRARCHY_MAX]; + struct ecm_db_iface_instance *ifaces; + struct net_device *dest_dev = NULL; + struct net_device *br_dev_src = NULL; +@@ -3829,7 +3847,7 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ + int if_index; + int ii_cnt; + int total_ii_count = 0; +- bool src_dev_is_bridge = false; ++ bool src_dev_is_bridge = false, dest_dev_is_br_dev_src = false; + + DEBUG_TRACE("Construct interface heirarchy for dest_addr: " ECM_IP_ADDR_DOT_FMT " src_addr: " ECM_IP_ADDR_DOT_FMT "total destination ifs %d\n", + ECM_IP_ADDR_TO_DOT(packet_dest_addr), ECM_IP_ADDR_TO_DOT(packet_src_addr), max_if); +@@ -3876,6 +3894,7 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ + continue; + } + ++ dest_dev_is_br_dev_src = false; + dest_dev = dev_get_by_index(&init_net, *dst_if_index); + if (!dest_dev) { + if (!src_dev_is_bridge) { +@@ -3884,26 +3903,23 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ + * this error condition then Deref all interface heirarchies. + */ + if (valid_if > 0) { +- int i; +- +- for (i = 0; i < valid_if; i++) { +- ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i); +- ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces); +- ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]); +- } ++ ecm_interface_hierarchy_delete(interfaces, interface_first_base, valid_if); + } + +- /* +- * If valid netdev not found, Return 0 +- */ +- if (br_dev_src) { +- dev_put(br_dev_src); +- } +- +- return 0; ++ goto fail1; + } + + dest_dev = br_dev_src; ++ ++ /* ++ * In some cases when WAN interface is added to bridge and traffic is downstream, ++ * the bridge device is part of the destination list from MFC, and at the same time ++ * 'src_dev_is_bridge' will be true as well. In such cases we will need to release ++ * the hold on the bridge device separately for dest_dev and br_dev_src. ++ * Setting this flag to true indicates that this is not the case, ++ * and that releasing the hold once is enough ++ */ ++ dest_dev_is_br_dev_src = true; + } + + dest_dev_type = dest_dev->type; +@@ -3927,7 +3943,6 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ + } + + if ((if_num < 0) || (if_num > ECM_DB_MULTICAST_IF_MAX)) { +- int i; + DEBUG_WARN("MCS is not ready\n"); + + /* +@@ -3935,19 +3950,10 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ + * this error condition then Deref all interface heirarchies. + */ + if (valid_if > 0) { +- for (i = 0; i < valid_if; i++) { +- ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i); +- ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces); +- ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]); +- } ++ ecm_interface_hierarchy_delete(interfaces, interface_first_base, valid_if); + } + +- if (br_dev_src && (dest_dev != br_dev_src)) { +- dev_put(br_dev_src); +- } +- +- dev_put(dest_dev); +- return 0; ++ goto fail2; + } + + if (in_dev && !mfc_update) { +@@ -3955,34 +3961,20 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ + } + + for (br_if = 0; br_if < if_num; br_if++) { ++ int total_if = valid_if + br_if; ++ + mc_br_slave_dev = dev_get_by_index(&init_net, mc_dst_if_index[br_if]); + if (!mc_br_slave_dev) { + continue; + } + +- if ((valid_if + br_if) > ECM_DB_MULTICAST_IF_MAX) { +- int i; +- +- /* +- * If already constructed any interface heirarchies before hitting +- * this error condition then Deref all interface heirarchies. +- */ +- for (i = 0; i < (valid_if + br_if); i++) { +- ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i); +- ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces); +- ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]); +- } +- +- if (br_dev_src && (dest_dev != br_dev_src)) { +- dev_put(br_dev_src); +- } +- +- dev_put(dest_dev); ++ if (total_if > ECM_DB_MULTICAST_IF_MAX) { ++ ecm_interface_hierarchy_delete(interfaces, interface_first_base, total_if); + dev_put(mc_br_slave_dev); +- return 0; ++ goto fail2; + } + +- ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, valid_if + br_if); ++ ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, total_if); + /* + * Construct a single interface heirarchy of a multicast dev. + */ +@@ -3993,25 +3985,15 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ + * If already constructed any interface heirarchies before hitting + * this error condition then Deref all interface heirarchies. + */ +- if ((valid_if + br_if) > 0) { +- int i; +- for (i = 0; i < (valid_if + br_if); i++) { +- ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i); +- ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces); +- ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]); +- } +- } +- +- if (br_dev_src && (dest_dev != br_dev_src)) { +- dev_put(br_dev_src); ++ if (total_if > 0) { ++ ecm_interface_hierarchy_delete(interfaces, interface_first_base, total_if); + } + +- dev_put(dest_dev); + dev_put(mc_br_slave_dev); +- return 0; ++ goto fail2; + } + +- interface_first = ecm_db_multicast_if_first_get_at_index(interface_first_base, (valid_if + br_if)); ++ interface_first = ecm_db_multicast_if_first_get_at_index(interface_first_base, total_if); + *interface_first = ii_cnt; + total_ii_count += ii_cnt; + dev_put(mc_br_slave_dev); +@@ -4033,20 +4015,10 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ + * this error condition then Deref all interface heirarchies. + */ + if (valid_if > 0) { +- int i; +- for (i = 0; i < valid_if; i++) { +- ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i); +- ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces); +- ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]); +- } +- } +- +- if (br_dev_src && (dest_dev != br_dev_src)) { +- dev_put(br_dev_src); ++ ecm_interface_hierarchy_delete(interfaces, interface_first_base, valid_if); + } + +- dev_put(dest_dev); +- return 0; ++ goto fail2; + } + + interface_first = ecm_db_multicast_if_first_get_at_index(interface_first_base, valid_if); +@@ -4055,7 +4027,7 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ + valid_if++; + } + +- if (dest_dev != br_dev_src) { ++ if (!dest_dev_is_br_dev_src) { + dev_put(dest_dev); + } + } +@@ -4065,6 +4037,18 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ + } + + return total_ii_count; ++ ++fail2: ++ if (!dest_dev_is_br_dev_src) { ++ dev_put(dest_dev); ++ } ++ ++fail1: ++ if (br_dev_src) { ++ dev_put(br_dev_src); ++ } ++ ++ return 0; + } + EXPORT_SYMBOL(ecm_interface_multicast_heirarchy_construct_routed); + +-- +cgit v1.1 + diff --git a/root/package/qca/nss/qca-nss-ecm/patches/403-Access-global-accelerated-count-under-lock.patch b/root/package/qca/nss/qca-nss-ecm/patches/403-Access-global-accelerated-count-under-lock.patch new file mode 100644 index 00000000..d458e113 --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm/patches/403-Access-global-accelerated-count-under-lock.patch @@ -0,0 +1,59 @@ +From 65a49ebd1bd12b9952dfa214de0a2da43ba2abed Mon Sep 17 00:00:00 2001 +From: Bhaskar Valaboju +Date: Tue, 13 Aug 2019 14:21:03 +0530 +Subject: [qca-nss-ecm]: Access global ipv4/ipv6 accelerated count under lock + +Flow accelerated count maintained as global variables are accessed +in multiple kernel contexts. These counters are updated under lock, +but read without lock. Read is in kernel thread context (workqueue) +and sometimes it is taking stale entry (0) and doesn't change. +Lock is added to read correct value. + +Change-Id: I74cf27fe5097c6ae7dfcc06319762a8a322d79a3 +Signed-off-by: Bhaskar Valaboju +--- + frontends/nss/ecm_nss_ipv4.c | 3 +++ + frontends/nss/ecm_nss_ipv6.c | 3 +++ + 2 files changed, 6 insertions(+) + +(limited to 'frontends') + +diff --git a/frontends/nss/ecm_nss_ipv4.c b/frontends/nss/ecm_nss_ipv4.c +index afd660e..4e66cdf 100644 +--- a/frontends/nss/ecm_nss_ipv4.c ++++ b/frontends/nss/ecm_nss_ipv4.c +@@ -2288,10 +2288,13 @@ static void ecm_nss_ipv4_stats_sync_req_work(struct work_struct *work) + int retry = 3; + unsigned long int current_jiffies; + ++ spin_lock_bh(&ecm_nss_ipv4_lock); + if (ecm_nss_ipv4_accelerated_count == 0) { ++ spin_unlock_bh(&ecm_nss_ipv4_lock); + DEBUG_TRACE("There is no accelerated IPv4 connection\n"); + goto reschedule; + } ++ spin_unlock_bh(&ecm_nss_ipv4_lock); + + usleep_range(ECM_NSS_IPV4_STATS_SYNC_UDELAY - 100, ECM_NSS_IPV4_STATS_SYNC_UDELAY); + +diff --git a/frontends/nss/ecm_nss_ipv6.c b/frontends/nss/ecm_nss_ipv6.c +index 1f7f51e..55849e7 100644 +--- a/frontends/nss/ecm_nss_ipv6.c ++++ b/frontends/nss/ecm_nss_ipv6.c +@@ -1998,10 +1998,13 @@ static void ecm_nss_ipv6_stats_sync_req_work(struct work_struct *work) + int retry = 3; + unsigned long int current_jiffies; + ++ spin_lock_bh(&ecm_nss_ipv6_lock); + if (ecm_nss_ipv6_accelerated_count == 0) { ++ spin_unlock_bh(&ecm_nss_ipv6_lock); + DEBUG_TRACE("There is no accelerated IPv6 connection\n"); + goto reschedule; + } ++ spin_unlock_bh(&ecm_nss_ipv6_lock); + + usleep_range(ECM_NSS_IPV6_STATS_SYNC_UDELAY - 100, ECM_NSS_IPV6_STATS_SYNC_UDELAY); + +-- +cgit v1.1 + diff --git a/root/package/qca/nss/qca-nss-ecm/patches/403-Fix-IPv6-neighbor-solicitation-request.patch b/root/package/qca/nss/qca-nss-ecm/patches/403-Fix-IPv6-neighbor-solicitation-request.patch new file mode 100644 index 00000000..7639b88a --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm/patches/403-Fix-IPv6-neighbor-solicitation-request.patch @@ -0,0 +1,83 @@ +From b96002061178f399c1e58a9ad821e5096a64f788 Mon Sep 17 00:00:00 2001 +From: Murat Sezgin +Date: Mon, 23 Mar 2020 10:59:39 -0700 +Subject: [qca-nss-ecm] Fix IPv6 neighbor solicitation request + +Send the solicitation request to the GW address, when +a GW address is found, while establishing the node instance. + +Signed-off-by: Murat Sezgin +Change-Id: I2187569bcfd05b0d091cf8c79171ee3c41c39cb9 +--- + frontends/nss/ecm_nss_ipv6.c | 7 ++++--- + frontends/nss/ecm_nss_multicast_ipv6.c | 9 +++++++++ + frontends/sfe/ecm_sfe_ipv6.c | 7 ++++--- + 3 files changed, 17 insertions(+), 6 deletions(-) + +diff --git a/frontends/nss/ecm_nss_ipv6.c b/frontends/nss/ecm_nss_ipv6.c +index c7dd37f..9011e18 100644 +--- a/frontends/nss/ecm_nss_ipv6.c ++++ b/frontends/nss/ecm_nss_ipv6.c +@@ -527,13 +527,14 @@ struct ecm_db_node_instance *ecm_nss_ipv6_node_establish_and_ref(struct ecm_fron + struct net_device *master; + master = ecm_interface_get_and_hold_dev_master(dev); + DEBUG_ASSERT(master, "Expected a master\n"); +- ecm_interface_send_neighbour_solicitation(master, addr); ++ ecm_interface_send_neighbour_solicitation(master, gw_addr); + dev_put(master); + } else { +- ecm_interface_send_neighbour_solicitation(dev, addr); ++ ecm_interface_send_neighbour_solicitation(dev, gw_addr); + } + +- DEBUG_TRACE("Failed to obtain mac for host " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(addr)); ++ DEBUG_TRACE("Failed to obtain mac for host " ECM_IP_ADDR_OCTAL_FMT " gw: " ECM_IP_ADDR_OCTAL_FMT "\n", ++ ECM_IP_ADDR_TO_OCTAL(addr), ECM_IP_ADDR_TO_OCTAL(gw_addr)); + return NULL; + } + done: +diff --git a/frontends/nss/ecm_nss_multicast_ipv6.c b/frontends/nss/ecm_nss_multicast_ipv6.c +index a361eec..38fde95 100644 +--- a/frontends/nss/ecm_nss_multicast_ipv6.c ++++ b/frontends/nss/ecm_nss_multicast_ipv6.c +@@ -2558,6 +2558,15 @@ static struct ecm_db_node_instance *ecm_nss_multicast_ipv6_node_establish_and_re + #endif + if (!ecm_interface_mac_addr_get(addr, node_addr, &on_link, gw_addr)) { + DEBUG_TRACE("Failed to obtain mac for host " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(addr)); ++ ++ /* ++ * If there is a gw_addr found during the lookup, use that address ++ * for neighbour solicitation request. ++ */ ++ if (!ECM_IP_ADDR_IS_NULL(gw_addr)) { ++ ECM_IP_ADDR_COPY(addr, gw_addr); ++ } ++ + if (ecm_front_end_is_bridge_port(dev)) { + struct net_device *master; + master = ecm_interface_get_and_hold_dev_master(dev); +diff --git a/frontends/sfe/ecm_sfe_ipv6.c b/frontends/sfe/ecm_sfe_ipv6.c +index 3fd5d46..51a9ccb 100644 +--- a/frontends/sfe/ecm_sfe_ipv6.c ++++ b/frontends/sfe/ecm_sfe_ipv6.c +@@ -256,13 +256,14 @@ struct ecm_db_node_instance *ecm_sfe_ipv6_node_establish_and_ref(struct ecm_fron + struct net_device *master; + master = ecm_interface_get_and_hold_dev_master(dev); + DEBUG_ASSERT(master, "Expected a master\n"); +- ecm_interface_send_neighbour_solicitation(master, addr); ++ ecm_interface_send_neighbour_solicitation(master, gw_addr); + dev_put(master); + } else { +- ecm_interface_send_neighbour_solicitation(dev, addr); ++ ecm_interface_send_neighbour_solicitation(dev, gw_addr); + } + +- DEBUG_TRACE("Failed to obtain mac for host " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(addr)); ++ DEBUG_TRACE("Failed to obtain mac for host " ECM_IP_ADDR_OCTAL_FMT " gw: " ECM_IP_ADDR_OCTAL_FMT "\n", ++ ECM_IP_ADDR_TO_OCTAL(addr), ECM_IP_ADDR_TO_OCTAL(gw_addr)); + return NULL; + } + done: +-- +cgit v1.1 + diff --git a/root/package/qca/nss/qca-nss-ecm/patches/404-IPv6-solicitation-fix-with-zero-gateway-address.patch b/root/package/qca/nss/qca-nss-ecm/patches/404-IPv6-solicitation-fix-with-zero-gateway-address.patch new file mode 100644 index 00000000..bdedff44 --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm/patches/404-IPv6-solicitation-fix-with-zero-gateway-address.patch @@ -0,0 +1,63 @@ +From 5b51ae2f1eca61c6f68e40a05333da5a362ff327 Mon Sep 17 00:00:00 2001 +From: Murat Sezgin +Date: Mon, 13 Apr 2020 09:01:48 -0700 +Subject: [qca-nss-ecm] IPv6 solicitation fix with zero gateway address + +The ECM function can find a zero gateway address for +a host IP address. In this case, we need to use the +host IP address while sending the solicitation request. + +Signed-off-by: Murat Sezgin +Change-Id: I1979834088ddfe1843566f51f64348f79e2df0fc +--- + frontends/nss/ecm_nss_ipv6.c | 11 ++++++++++- + frontends/sfe/ecm_sfe_ipv6.c | 11 ++++++++++- + 2 files changed, 20 insertions(+), 2 deletions(-) + +diff --git a/frontends/nss/ecm_nss_ipv6.c b/frontends/nss/ecm_nss_ipv6.c +index a05781b..9eb591c 100644 +--- a/frontends/nss/ecm_nss_ipv6.c ++++ b/frontends/nss/ecm_nss_ipv6.c +@@ -516,7 +516,16 @@ struct ecm_db_node_instance *ecm_nss_ipv6_node_establish_and_ref(struct ecm_fron + return NULL; + } + +- DEBUG_TRACE("Have a gw address " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(gw_addr)); ++ /* ++ * The found gateway address can be all zeros, ++ * so in this case use the host address. ++ */ ++ if (ECM_IP_ADDR_IS_NULL(gw_addr)) { ++ DEBUG_TRACE("GW address is found as zeros, so use host IP\n"); ++ ECM_IP_ADDR_COPY(gw_addr, addr); ++ } else { ++ DEBUG_TRACE("Have a gw address " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(gw_addr)); ++ } + + if (ecm_interface_mac_addr_get_no_route(dev, gw_addr, node_addr)) { + DEBUG_TRACE("Found the mac address for gateway\n"); +diff --git a/frontends/sfe/ecm_sfe_ipv6.c b/frontends/sfe/ecm_sfe_ipv6.c +index 51a9ccb..e609df7 100644 +--- a/frontends/sfe/ecm_sfe_ipv6.c ++++ b/frontends/sfe/ecm_sfe_ipv6.c +@@ -245,7 +245,16 @@ struct ecm_db_node_instance *ecm_sfe_ipv6_node_establish_and_ref(struct ecm_fron + return NULL; + } + +- DEBUG_TRACE("Have a gw address " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(gw_addr)); ++ /* ++ * The found gateway address can be all zeros, ++ * so in this case use the host address. ++ */ ++ if (ECM_IP_ADDR_IS_NULL(gw_addr)) { ++ DEBUG_TRACE("GW address is found as zeros, so use host IP\n"); ++ ECM_IP_ADDR_COPY(gw_addr, addr); ++ } else { ++ DEBUG_TRACE("Have a gw address " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(gw_addr)); ++ } + + if (ecm_interface_mac_addr_get_no_route(dev, gw_addr, node_addr)) { + DEBUG_TRACE("Found the mac address for gateway\n"); +-- +cgit v1.1 + diff --git a/root/package/qca/nss/qca-nss-ecm/patches/405-Allow-egress-on-same-port-when-bridge-hairpin-is-enabled.patch b/root/package/qca/nss/qca-nss-ecm/patches/405-Allow-egress-on-same-port-when-bridge-hairpin-is-enabled.patch new file mode 100644 index 00000000..a236fb75 --- /dev/null +++ b/root/package/qca/nss/qca-nss-ecm/patches/405-Allow-egress-on-same-port-when-bridge-hairpin-is-enabled.patch @@ -0,0 +1,126 @@ +From e23eabd570eabde1d1fc803127a97fd101642467 Mon Sep 17 00:00:00 2001 +From: Varsha Mishra +Date: Fri, 12 Jun 2020 01:06:58 +0530 +Subject: [qca-nss-ecm] Allow egress on same port when bridge hairpin is + enabled. + +When bridge hairpin is enabled, allow egress on same port. Wi-Fi intrabss +frames are getting exceptioned to stack. Bridge gets to make the decision +whether these frames need to be forwarded or dropped. + +Signed-off-by: Varsha Mishra +Change-Id: Ibdd72264d8887330ba0297ed12cbcfc390065bff +--- + frontends/nss/ecm_nss_ipv4.c | 28 ++++++++++++++++++++++------ + frontends/nss/ecm_nss_ipv6.c | 28 ++++++++++++++++++++++------ + 2 files changed, 44 insertions(+), 12 deletions(-) + +diff --git a/frontends/nss/ecm_nss_ipv4.c b/frontends/nss/ecm_nss_ipv4.c +index 60f799b..51c9ebf 100644 +--- a/frontends/nss/ecm_nss_ipv4.c ++++ b/frontends/nss/ecm_nss_ipv4.c +@@ -1756,7 +1756,9 @@ static unsigned int ecm_nss_ipv4_bridge_post_routing_hook(void *priv, + * Case 2: + * For routed packets the skb will have the src mac matching the bridge mac. + * Case 3: +- * If the packet was not local (case 1) or routed (case 2) then we process. ++ * If the packet was not local (case 1) or routed (case 2) then ++ * we process. There is an exception to case 2: when hairpin mode ++ * is enabled, we process. + */ + + /* +@@ -1768,14 +1770,28 @@ static unsigned int ecm_nss_ipv4_bridge_post_routing_hook(void *priv, + dev_put(bridge); + return NF_ACCEPT; + } ++ ++ /* ++ * This flag needs to be checked in slave port(eth0/ath0) ++ * and not on master interface(br-lan). Hairpin flag can be ++ * enabled/disabled for ports individually. ++ */ + if (in == out) { +- DEBUG_TRACE("skb: %p, bridge: %p (%s), port bounce on %p (%s)\n", skb, bridge, bridge->name, out, out->name); +- dev_put(in); +- dev_put(bridge); +- return NF_ACCEPT; ++ if (!br_is_hairpin_enabled(in)) { ++ DEBUG_TRACE("skb: %p, bridge: %p (%s), ignoring" ++ "the packet, hairpin not enabled" ++ "on port %p (%s)\n", skb, bridge, ++ bridge->name, out, out->name); ++ dev_put(in); ++ dev_put(bridge); ++ return NF_ACCEPT; ++ } ++ DEBUG_TRACE("skb: %p, bridge: %p (%s), hairpin enabled on port" ++ "%p (%s)\n", skb, bridge, bridge->name, out, out->name); + } ++ ++ /* ++ * Case 2: Routed trafffic would be handled by the INET post routing. ++ */ + if (!ecm_mac_addr_equal(skb_eth_hdr->h_source, bridge->dev_addr)) { +- /* +- * Case 2: Routed trafffic would be handled by the INET post routing. +- */ + DEBUG_TRACE("skb: %p, Ignoring routed packet to bridge: %p (%s)\n", skb, bridge, bridge->name); + goto skip_ipv4_bridge_flow; + } +diff --git a/frontends/nss/ecm_nss_ipv6.c b/frontends/nss/ecm_nss_ipv6.c +index 6ad425e..160c94c 100644 +--- a/frontends/nss/ecm_nss_ipv6.c ++++ b/frontends/nss/ecm_nss_ipv6.c +@@ -1498,7 +1498,9 @@ static unsigned int ecm_nss_ipv6_bridge_post_routing_hook(void *priv, + * Case 2: + * For routed packets the skb will have the src mac matching the bridge mac. + * Case 3: +- * If the packet was not local (case 1) or routed (case 2) then we process. ++ * If the packet was not local (case 1) or routed (case 2) then ++ * we process. There is an exception to case 2: when hairpin mode ++ * is enabled, we process. + */ + + /* +@@ -1510,14 +1512,28 @@ static unsigned int ecm_nss_ipv6_bridge_post_routing_hook(void *priv, + dev_put(bridge); + return NF_ACCEPT; + } ++ ++ /* ++ * This flag needs to be checked in slave port(eth0/ath0) ++ * and not on master interface(br-lan). Hairpin flag can be ++ * enabled/disabled for ports individually. ++ */ + if (in == out) { +- DEBUG_TRACE("skb: %p, bridge: %p (%s), port bounce on %p (%s)\n", skb, bridge, bridge->name, out, out->name); +- dev_put(in); +- dev_put(bridge); +- return NF_ACCEPT; ++ if (!br_is_hairpin_enabled(in)) { ++ DEBUG_TRACE("skb: %p, bridge: %p (%s), ignoring" ++ "the packet, hairpin not enabled" ++ "on port %p (%s)\n", skb, bridge, ++ bridge->name, out, out->name); ++ dev_put(in); ++ dev_put(bridge); ++ return NF_ACCEPT; ++ } ++ DEBUG_TRACE("skb: %p, bridge: %p (%s), hairpin enabled on port" ++ "%p (%s)\n", skb, bridge, bridge->name, out, out->name); + } ++ ++ /* ++ * Case 2: Routed trafffic would be handled by the INET post routing. ++ */ + if (!ecm_mac_addr_equal(skb_eth_hdr->h_source, bridge->dev_addr)) { +- /* +- * Case 2: Routed trafffic would be handled by the INET post routing. +- */ + DEBUG_TRACE("skb: %p, Ignoring routed packet to bridge: %p (%s)\n", skb, bridge, bridge->name); + goto skip_ipv6_bridge_flow; + } +-- +cgit v1.1 + diff --git a/root/package/qca/nss/qca-nss-gmac/Makefile b/root/package/qca/nss/qca-nss-gmac/Makefile new file mode 100644 index 00000000..8b39f043 --- /dev/null +++ b/root/package/qca/nss/qca-nss-gmac/Makefile @@ -0,0 +1,47 @@ +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=qca-nss-gmac +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://source.codeaurora.org/quic/qsdk/oss/lklm/nss-gmac +PKG_SOURCE_VERSION:=9b74deef2816d91e58926e6fab7a6ff931eb3b22 +PKG_MIRROR_HASH:=a1939caa638414323e60f7d29f797ea831c6036e424b8e7bd6cf2d3d874de064 + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/qca-nss-gmac + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + DEPENDS:=@TARGET_ipq806x @LINUX_5_4 + TITLE:=Kernel driver for NSS gmac + FILES:=$(PKG_BUILD_DIR)/ipq806x/qca-nss-gmac.ko + AUTOLOAD:=$(call AutoLoad,31,qca-nss-gmac) +endef + +define KernelPackage/qca-nss-gmac/Description +This package contains a NSS driver for QCA chipset +endef + +define Build/InstallDev + mkdir -p $(1)/usr/include/qca-nss-gmac + $(CP) $(PKG_BUILD_DIR)/ipq806x/exports/* $(1)/usr/include/qca-nss-gmac/ +endef + +EXTRA_CFLAGS+= \ + -DCONFIG_NSS_DEBUG_LEVEL=4 \ + -I$(PKG_BUILD_DIR)/nss_hal/include \ + -I$(PKG_BUILD_DIR)/nss_hal/$(BOARD) + +define Build/Compile + $(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \ + $(KERNEL_MAKE_FLAGS) \ + $(PKG_MAKE_FLAGS) \ + M="$(PKG_BUILD_DIR)" \ + EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ + modules +endef + +$(eval $(call KernelPackage,qca-nss-gmac)) diff --git a/root/package/qca/nss/qca-nss-gmac/patches/100-kernel-5.4-support.patch b/root/package/qca/nss/qca-nss-gmac/patches/100-kernel-5.4-support.patch new file mode 100644 index 00000000..f3b91abc --- /dev/null +++ b/root/package/qca/nss/qca-nss-gmac/patches/100-kernel-5.4-support.patch @@ -0,0 +1,279 @@ +--- a/ipq806x/nss_gmac_ctrl.c ++++ b/ipq806x/nss_gmac_ctrl.c +@@ -322,16 +322,15 @@ void nss_gmac_tx_rx_desc_init(struct nss + * (for example "ifconfig eth0"). + * @param[in] pointer to net_device structure. + * @param[in] pointer to net_device_stats64 structure. +- * @return Returns pointer to net_device_stats64 structure. + */ +-struct rtnl_link_stats64 *nss_gmac_get_stats64(struct net_device *netdev, ++void nss_gmac_get_stats64(struct net_device *netdev, + struct rtnl_link_stats64 *stats) + { + struct nss_gmac_dev *gmacdev = (struct nss_gmac_dev *)netdev_priv(netdev); + BUG_ON(gmacdev == NULL); + + if (!gmacdev->data_plane_ops) +- return stats; ++ return; + + spin_lock_bh(&gmacdev->stats_lock); + gmacdev->data_plane_ops->get_stats(gmacdev->data_plane_ctx, &gmacdev->nss_stats); +@@ -354,8 +353,6 @@ struct rtnl_link_stats64 *nss_gmac_get_s + stats->tx_fifo_errors = gmacdev->nss_stats.tx_underflow_errors; + stats->tx_window_errors = gmacdev->nss_stats.tx_late_collision_errors; + spin_unlock_bh(&gmacdev->stats_lock); +- +- return stats; + } + + +@@ -439,7 +436,7 @@ static int nss_gmac_mtnp_show(struct dev + static int nss_gmac_tstamp_show(struct device *dev, struct device_attribute *attr, char *buf) + { + struct nss_gmac_dev *gmacdev = (struct nss_gmac_dev *)netdev_priv(to_net_dev(dev)); +- struct timeval tv; ++ struct timespec64 ts64; + uint32_t ret, timeout; + uint32_t ts_hi, ts_lo; + +@@ -459,11 +456,12 @@ static int nss_gmac_tstamp_show(struct d + return -1; + } + +- do_gettimeofday(&tv); ++ ktime_get_real_ts64(&ts64); + + ret = snprintf( + buf, PAGE_SIZE, +- "sec:%u nsec:%u time-of-day: %12d.%06d \n", ts_hi, ts_lo, (int)tv.tv_sec, (int)tv.tv_usec); ++ "sec:%u nsec:%u time-of-day: %12d.%06d \n", \ ++ ts_hi, ts_lo, (int)ts64.tv_sec, (int)(ts64.tv_nsec / NSEC_PER_USEC)); + + return ret; + } +@@ -951,7 +949,7 @@ static const struct net_device_ops nss_g + * @param[in] pointer to advertised features + * @return void + */ +-static void nss_gmac_update_features(uint32_t *supp, uint32_t *adv) ++static void nss_gmac_update_features(long unsigned int *supp, long unsigned int *adv) + { + *supp |= NSS_GMAC_SUPPORTED_FEATURES; + *adv |= NSS_GMAC_ADVERTISED_FEATURES; +@@ -1409,8 +1407,8 @@ static int32_t nss_gmac_probe(struct pla + goto nss_gmac_phy_attach_fail; + } + +- nss_gmac_update_features(&(gmacdev->phydev->supported), +- &(gmacdev->phydev->advertising)); ++ nss_gmac_update_features(gmacdev->phydev->supported, ++ gmacdev->phydev->advertising); + gmacdev->phydev->irq = PHY_POLL; + netdev_dbg(netdev, "PHY %s attach OK\n", phy_id); + +@@ -1440,6 +1438,8 @@ static int32_t nss_gmac_probe(struct pla + netdev_dbg(netdev, "%s MII_PHYSID2 - 0x%04x\n", netdev->name, + nss_gmac_mii_rd_reg(gmacdev, gmacdev->phy_base, MII_PHYSID2)); + } else if (gmacdev->phy_base != NSS_GMAC_NO_MDIO_PHY) { ++ SET_NETDEV_DEV(netdev, gmacdev->miibus->parent); ++ + /* + * Issue a phy_attach for the interface connected to a switch + */ +--- a/ipq806x/nss_gmac_ethtool.c ++++ b/ipq806x/nss_gmac_ethtool.c +@@ -143,9 +143,9 @@ static const struct nss_gmac_ethtool_sta + /** + * @brief Array of strings describing private flag names + */ +-static const char *gmac_strings_priv_flags[] = { +- "linkpoll", +- "tstamp", ++static const char *gmac_strings_priv_flags[][ETH_GSTRING_LEN] = { ++ {"linkpoll"}, ++ {"tstamp"}, + }; + + #define NSS_GMAC_STATS_LEN ARRAY_SIZE(gmac_gstrings_stats) +@@ -292,6 +292,7 @@ static int nss_gmac_set_pauseparam(struc + { + struct nss_gmac_dev *gmacdev = (struct nss_gmac_dev *)netdev_priv(netdev); + struct phy_device *phydev; ++ long unsigned int *advertising; + + BUG_ON(gmacdev == NULL); + BUG_ON(gmacdev->netdev != netdev); +@@ -327,14 +328,15 @@ static int nss_gmac_set_pauseparam(struc + phydev = gmacdev->phydev; + + /* Update flow control advertisment */ +- phydev->advertising &= ~(ADVERTISED_Pause | ADVERTISED_Asym_Pause); ++ advertising = phydev->advertising; ++ *advertising &= ~(ADVERTISED_Pause | ADVERTISED_Asym_Pause); + + if (gmacdev->pause & FLOW_CTRL_RX) +- phydev->advertising |= ++ *advertising |= + (ADVERTISED_Pause | ADVERTISED_Asym_Pause); + + if (gmacdev->pause & FLOW_CTRL_TX) +- phydev->advertising |= ADVERTISED_Asym_Pause; ++ *advertising |= ADVERTISED_Asym_Pause; + + genphy_config_aneg(gmacdev->phydev); + +@@ -396,12 +398,13 @@ static uint32_t nss_gmac_get_msglevel(st + * @param[in] pointer to struct net_device. + * @param[in] pointer to struct ethtool_cmd. + */ +-static int32_t nss_gmac_get_settings(struct net_device *netdev, +- struct ethtool_cmd *ecmd) ++static int nss_gmac_get_settings(struct net_device *netdev, ++ struct ethtool_link_ksettings *elk) + { + struct nss_gmac_dev *gmacdev = (struct nss_gmac_dev *)netdev_priv(netdev); + struct phy_device *phydev = NULL; + uint16_t phyreg; ++ u32 lp_advertising = 0; + + BUG_ON(gmacdev == NULL); + +@@ -413,10 +416,10 @@ static int32_t nss_gmac_get_settings(str + */ + if (!test_bit(__NSS_GMAC_LINKPOLL, &gmacdev->flags)) { + if (gmacdev->forced_speed != SPEED_UNKNOWN) { +- ethtool_cmd_speed_set(ecmd, gmacdev->forced_speed); +- ecmd->duplex = gmacdev->forced_duplex; +- ecmd->mdio_support = 0; +- ecmd->lp_advertising = 0; ++ elk->base.speed = gmacdev->forced_speed; ++ elk->base.duplex = gmacdev->forced_duplex; ++ elk->base.mdio_support = 0; ++ ethtool_convert_legacy_u32_to_link_mode(elk->link_modes.lp_advertising, 0); + return 0; + } else { + /* Non-link polled interfaced must have a forced +@@ -429,63 +429,59 @@ static int32_t nss_gmac_get_settings(struct net_device *netdev, + + /* update PHY status */ + if (phydev->is_c45 == true) { +- ecmd->mdio_support = ETH_MDIO_SUPPORTS_C45; ++ elk->base.mdio_support = ETH_MDIO_SUPPORTS_C45; + } else { + if (genphy_read_status(phydev) != 0) { + return -EIO; + } +- ecmd->mdio_support = ETH_MDIO_SUPPORTS_C22; ++ elk->base.mdio_support = ETH_MDIO_SUPPORTS_C22; + } + + /* Populate capabilities advertised by self */ +- ecmd->advertising = phydev->advertising; ++ bitmap_copy(elk->link_modes.advertising, phydev->advertising, __ETHTOOL_LINK_MODE_MASK_NBITS); + +- ecmd->autoneg = phydev->autoneg; +- +- if (gmacdev->link_state == LINKDOWN) { +- ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN); +- ecmd->duplex = DUPLEX_UNKNOWN; +- } else { +- ethtool_cmd_speed_set(ecmd, phydev->speed); +- ecmd->duplex = phydev->duplex; +- } +- +- ecmd->port = PORT_TP; +- ecmd->phy_address = gmacdev->phy_base; +- ecmd->transceiver = XCVR_EXTERNAL; ++ elk->base.autoneg = phydev->autoneg; ++ elk->base.speed = phydev->speed; ++ elk->base.duplex = phydev->duplex; ++ elk->base.port = PORT_TP; ++ elk->base.phy_address = gmacdev->phy_base; ++ elk->base.transceiver = XCVR_EXTERNAL; + + /* Populate supported capabilities */ +- ecmd->supported = phydev->supported; ++ bitmap_copy(elk->link_modes.supported, phydev->supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + + if (phydev->is_c45 == true) + return 0; + + /* Populate capabilities advertised by link partner */ ++ ethtool_convert_link_mode_to_legacy_u32(&lp_advertising, elk->link_modes.lp_advertising); + phyreg = nss_gmac_mii_rd_reg(gmacdev, gmacdev->phy_base, MII_LPA); + if (phyreg & LPA_10HALF) +- ecmd->lp_advertising |= ADVERTISED_10baseT_Half; ++ lp_advertising |= ADVERTISED_10baseT_Half; + + if (phyreg & LPA_10FULL) +- ecmd->lp_advertising |= ADVERTISED_10baseT_Full; ++ lp_advertising |= ADVERTISED_10baseT_Full; + + if (phyreg & LPA_100HALF) +- ecmd->lp_advertising |= ADVERTISED_100baseT_Half; ++ lp_advertising |= ADVERTISED_100baseT_Half; + + if (phyreg & LPA_100FULL) +- ecmd->lp_advertising |= ADVERTISED_100baseT_Full; ++ lp_advertising |= ADVERTISED_100baseT_Full; + + if (phyreg & LPA_PAUSE_CAP) +- ecmd->lp_advertising |= ADVERTISED_Pause; ++ lp_advertising |= ADVERTISED_Pause; + + if (phyreg & LPA_PAUSE_ASYM) +- ecmd->lp_advertising |= ADVERTISED_Asym_Pause; ++ lp_advertising |= ADVERTISED_Asym_Pause; + + phyreg = nss_gmac_mii_rd_reg(gmacdev, gmacdev->phy_base, MII_STAT1000); + if (phyreg & LPA_1000HALF) +- ecmd->lp_advertising |= ADVERTISED_1000baseT_Half; ++ lp_advertising |= ADVERTISED_1000baseT_Half; + + if (phyreg & LPA_1000FULL) +- ecmd->lp_advertising |= ADVERTISED_1000baseT_Full; ++ lp_advertising |= ADVERTISED_1000baseT_Full; ++ ++ ethtool_convert_legacy_u32_to_link_mode(elk->link_modes.lp_advertising, lp_advertising); + + return 0; + } +@@ -489,8 +495,8 @@ static int32_t nss_gmac_get_settings(str + * @param[in] pointer to struct net_device. + * @param[in] pointer to struct ethtool_cmd. + */ +-static int32_t nss_gmac_set_settings(struct net_device *netdev, +- struct ethtool_cmd *ecmd) ++static int nss_gmac_set_settings(struct net_device *netdev, ++ const struct ethtool_link_ksettings *elk) + { + struct nss_gmac_dev *gmacdev = (struct nss_gmac_dev *)netdev_priv(netdev); + struct phy_device *phydev = NULL; +@@ -512,13 +518,13 @@ static int32_t nss_gmac_set_settings(str + return -EPERM; + } + +- if (ecmd->autoneg == AUTONEG_ENABLE) { ++ if (elk->base.autoneg == AUTONEG_ENABLE) { + set_bit(__NSS_GMAC_AUTONEG, &gmacdev->flags); + } else { + clear_bit(__NSS_GMAC_AUTONEG, &gmacdev->flags); + } + +- return phy_ethtool_sset(phydev, ecmd); ++ return phy_ethtool_ksettings_set(phydev, elk); + } + + /** +@@ -580,8 +586,8 @@ struct ethtool_ops nss_gmac_ethtool_ops + .set_pauseparam = &nss_gmac_set_pauseparam, + .nway_reset = &nss_gmac_nway_reset, + .get_wol = &nss_gmac_get_wol, +- .get_settings = &nss_gmac_get_settings, +- .set_settings = &nss_gmac_set_settings, ++ .get_link_ksettings = &nss_gmac_get_settings, ++ .set_link_ksettings = &nss_gmac_set_settings, + .get_strings = &nss_gmac_get_strings, + .get_sset_count = &nss_gmac_get_strset_count, + .get_ethtool_stats = &nss_gmac_get_ethtool_stats, diff --git a/root/package/qca/nss/qca-nss-gmac/patches/101-nss-gmac-test-ptr.patch b/root/package/qca/nss/qca-nss-gmac/patches/101-nss-gmac-test-ptr.patch new file mode 100644 index 00000000..a5bff16b --- /dev/null +++ b/root/package/qca/nss/qca-nss-gmac/patches/101-nss-gmac-test-ptr.patch @@ -0,0 +1,25 @@ +--- a/ipq806x/nss_gmac_ctrl.c ++++ b/ipq806x/nss_gmac_ctrl.c +@@ -957,7 +957,8 @@ static int32_t nss_gmac_of_get_pdata(struct device_node *np, + struct net_device *netdev, + struct msm_nss_gmac_platform_data *gmaccfg) + { +- uint8_t *maddr = NULL; ++ int ret; ++ u8 maddr[ETH_ALEN]; + struct nss_gmac_dev *gmacdev = (struct nss_gmac_dev *)netdev_priv(netdev); + struct resource memres_devtree = {0}; + +@@ -991,9 +992,9 @@ static int32_t nss_gmac_of_get_pdata(struct device_node *np, + pr_err("%s: Can't map interrupt\n", np->name); + return -EFAULT; + } +- maddr = (uint8_t *)of_get_mac_address(np); +- if (maddr) +- memcpy(gmaccfg->mac_addr, maddr, ETH_ALEN); ++ ret = of_get_mac_address(np, maddr); ++ if (!ret && is_valid_ether_addr(maddr)) ++ ether_addr_copy(gmaccfg->mac_addr, maddr); + + if (of_address_to_resource(np, 0, &memres_devtree) != 0) + return -EFAULT; diff --git a/root/package/qca/nss/qca-nss-gmac/patches/200-work-around-interface-close-warning.patch b/root/package/qca/nss/qca-nss-gmac/patches/200-work-around-interface-close-warning.patch new file mode 100644 index 00000000..7cb6d6fa --- /dev/null +++ b/root/package/qca/nss/qca-nss-gmac/patches/200-work-around-interface-close-warning.patch @@ -0,0 +1,15 @@ +--- a/ipq806x/nss_gmac_tx_rx_offload.c ++++ b/ipq806x/nss_gmac_tx_rx_offload.c +@@ -1027,8 +1027,10 @@ int nss_gmac_close(struct net_device *ne + nss_gmac_disable_interrupt_all(gmacdev); + gmacdev->data_plane_ops->link_state(gmacdev->data_plane_ctx, 0); + +- if (!IS_ERR(gmacdev->phydev)) +- phy_stop(gmacdev->phydev); ++ if (!IS_ERR(gmacdev->phydev)) { ++ if (test_bit(__NSS_GMAC_LINKPOLL, &gmacdev->flags)) ++ phy_stop(gmacdev->phydev); ++ } + + clear_bit(__NSS_GMAC_UP, &gmacdev->flags); + clear_bit(__NSS_GMAC_CLOSING, &gmacdev->flags); diff --git a/root/package/qca/qca-mcs/Makefile b/root/package/qca/qca-mcs/Makefile new file mode 100644 index 00000000..af9372d8 --- /dev/null +++ b/root/package/qca/qca-mcs/Makefile @@ -0,0 +1,54 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=qca-mcs +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_DATE:=2021-10-28 +PKG_SOURCE_URL:=https://source.codeaurora.org/quic/qsdk/oss/lklm/qca-mcs +PKG_SOURCE_VERSION:=31f5cd4b83da5a7c0fdca240b4e72677e4523b6e +PKG_MIRROR_HASH:=3e2e25025dc2e771aafe7d8b12f26ac831d123b34bdd7b7e84bd39c1e933491d + +include $(INCLUDE_DIR)/kernel.mk +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/qca-mcs + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Support + TITLE:=QCA Multicast Snooping Support + DEPENDS:=@(TARGET_ipq806x||TARGET_ipq807x) + KCONFIG:= \ + CONFIG_NETFILTER=y \ + CONFIG_BRIDGE_NETFILTER=y + FILES:=$(PKG_BUILD_DIR)/qca-mcs.ko + AUTOLOAD:=$(call AutoLoad,52,qca-mcs) +endef + +define KernelPackage/qca-mcs/description + This package installs the IGMP/MLD Snooping Module +endef + +QCA_MC_SNOOPING_HEADERS= \ + $(PKG_BUILD_DIR)/mc_api.h \ + $(PKG_BUILD_DIR)/mc_ecm.h \ + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include/qca-mcs + $(foreach header_file,$(QCA_MC_SNOOPING_HEADERS), $(CP) $(header_file) $(1)/usr/include/qca-mcs;) + $(foreach header_file,$(QCA_MC_SNOOPING_HEADERS), $(CP) $(header_file) $(1)/usr/include/;) +endef + +QCA_MC_SNOOPING_MAKE_OPTS:= \ + $(KERNEL_MAKE_FLAGS) \ + CONFIG_SUPPORT_MLD=y \ + MDIR=$(PKG_BUILD_DIR) \ + KBUILDPATH=$(LINUX_DIR) \ + KERNELPATH=$(LINUX_SRC_DIR) \ + KERNELRELEASE=$(LINUX_RELEASE) + +define Build/Compile + $(MAKE) -C $(LINUX_DIR) M=$(PKG_BUILD_DIR) $(strip $(QCA_MC_SNOOPING_MAKE_OPTS)) +endef + +$(eval $(call KernelPackage,qca-mcs)) diff --git a/root/package/qca/qca-rfs/Makefile b/root/package/qca/qca-rfs/Makefile new file mode 100644 index 00000000..7831e4d3 --- /dev/null +++ b/root/package/qca/qca-rfs/Makefile @@ -0,0 +1,51 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=qca-rfs +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://source.codeaurora.org/quic/qsdk/oss/lklm/qca-rfs +PKG_SOURCE_DATE:=2021-03-17 +PKG_SOURCE_VERSION:=75197c386f477c7b3a6f02489d9903a9409fd5cc +PKG_MIRROR_HASH:=90f1c3ec2e984cf8efa79c85d715ebd8a21e347ab57adbd9695de23e64eea1ec + +include $(INCLUDE_DIR)/kernel.mk +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/qca-rfs + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Support + DEPENDS:=@TARGET_ipq40xx +kmod-ipt-conntrack + TITLE:=Kernel module for QCA Receiving Flow Steering + FILES:=$(PKG_BUILD_DIR)/qrfs.ko + KCONFIG:=\ + CONFIG_NF_CONNTRACK_EVENTS=y \ + CONFIG_NF_CONNTRACK_CHAIN_EVENTS=y + AUTOLOAD:=$(call AutoLoad,29,qrfs) +endef + +define KernelPackage/qca-rfs/Description +QCA-RFS is a kernel module for ESS Receive Flow Steering. +endef + +define Build/Compile + $(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \ + $(KERNEL_MAKE_FLAGS) \ + $(PKG_MAKE_FLAGS) \ + M="$(PKG_BUILD_DIR)" \ + EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ + modules +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include/qca-rfs + $(CP) -rf $(PKG_BUILD_DIR)/rfs_dev.h $(1)/usr/include/qca-rfs +endef + +define KernelPackage/qca-rfs/install + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/qrfs.init $(1)/etc/init.d/qrfs +endef + +$(eval $(call KernelPackage,qca-rfs)) diff --git a/root/package/qca/qca-rfs/files/qrfs.init b/root/package/qca/qca-rfs/files/qrfs.init new file mode 100644 index 00000000..f3f8a38c --- /dev/null +++ b/root/package/qca/qca-rfs/files/qrfs.init @@ -0,0 +1,27 @@ +#!/bin/sh /etc/rc.common +# +# Copyright (c) 2015 The Linux Foundation. All rights reserved. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +START=70 + +start() { + echo "1" > /proc/qrfs/enable + ip neigh flush all +} + +stop() { + echo "0" > /proc/qrfs/enable +} diff --git a/root/package/qca/qca-rfs/patches/100-add-kernel-5.4-support.patch b/root/package/qca/qca-rfs/patches/100-add-kernel-5.4-support.patch new file mode 100644 index 00000000..b7b2db55 --- /dev/null +++ b/root/package/qca/qca-rfs/patches/100-add-kernel-5.4-support.patch @@ -0,0 +1,57 @@ +--- a/rfs_cm.c ++++ b/rfs_cm.c +@@ -462,14 +462,6 @@ static int rfs_cm_conntrack_event(unsign + } + + /* +- * If this is an untracked connection then we can't have any state either. +- */ +- if (unlikely(ct == &nf_conntrack_untracked)) { +- RFS_TRACE("ignoring untracked conn\n"); +- return NOTIFY_DONE; +- } +- +- /* + * Ignore anything other than IPv4 connections. + */ + if (unlikely(nf_ct_l3num(ct) != AF_INET)) { +--- a/rfs_rule.c ++++ b/rfs_rule.c +@@ -702,7 +702,7 @@ int rfs_rule_init(void) + + RFS_DEBUG("RFS Rule init\n"); + spin_lock_init(&rr->hash_lock); +- memset(&rr->hash, 0, RFS_RULE_HASH_SIZE); ++ memset(&rr->hash, 0, sizeof(rr->hash)); + + rr->proc_rule = proc_create("rule", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, + rfs_proc_entry, &rule_proc_fops); +@@ -717,7 +717,7 @@ void rfs_rule_exit(void) + struct rfs_rule *rr = &__rr; + + RFS_DEBUG("RFS Rule exit\n"); +- if (rr->proc_rule); ++ if (rr->proc_rule) + remove_proc_entry("rule", rfs_proc_entry); + rfs_rule_destroy_all(); + } +--- a/rfs_wxt.c ++++ b/rfs_wxt.c +@@ -422,7 +422,7 @@ static int rfs_wxt_rx(struct socket *soc + #else + iov_iter_init(&msg.msg_iter, READ, &iov, 1, len); + #endif +- size = sock_recvmsg(sock, &msg, len, msg.msg_flags); ++ size = sock_recvmsg(sock, &msg, msg.msg_flags); + set_fs(oldfs); + + return size; +@@ -510,7 +510,7 @@ int rfs_wxt_stop(void) + } + + RFS_DEBUG("kill rfs_wxt thread"); +- force_sig(SIGKILL, __rwn.thread); ++ send_sig(SIGKILL, __rwn.thread, 1); + if (__rwn.thread) + err = kthread_stop(__rwn.thread); + __rwn.thread = NULL; diff --git a/root/package/qca/qca-rfs/patches/200-rework-nfct-notification.patch b/root/package/qca/qca-rfs/patches/200-rework-nfct-notification.patch new file mode 100644 index 00000000..81e608c0 --- /dev/null +++ b/root/package/qca/qca-rfs/patches/200-rework-nfct-notification.patch @@ -0,0 +1,20 @@ +--- a/rfs_cm.c ++++ b/rfs_cm.c +@@ -709,7 +709,7 @@ int rfs_cm_start(void) + + RFS_DEBUG("RFS cm start\n"); + #ifdef CONFIG_NF_CONNTRACK_EVENTS +- ret = nf_conntrack_register_notifier(&init_net, &rfs_cm_conntrack_notifier); ++ ret = nf_conntrack_register_chain_notifier(&init_net, &rfs_cm_conntrack_notifier); + if (ret < 0) { + RFS_ERROR("can't register nf notifier hook: %d\n", ret); + return -1; +@@ -740,7 +740,7 @@ int rfs_cm_stop(void) + #endif + + #ifdef CONFIG_NF_CONNTRACK_EVENTS +- nf_conntrack_unregister_notifier(&init_net, &rfs_cm_conntrack_notifier); ++ nf_conntrack_unregister_chain_notifier(&init_net, &rfs_cm_conntrack_notifier); + #endif + + rfs_cm_connection_destroy_all(); diff --git a/root/package/qca/qca-ssdk-shell/Makefile b/root/package/qca/qca-ssdk-shell/Makefile new file mode 100644 index 00000000..90e2c2e6 --- /dev/null +++ b/root/package/qca/qca-ssdk-shell/Makefile @@ -0,0 +1,48 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=qca-ssdk-shell +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://source.codeaurora.org/quic/qsdk/oss/ssdk-shell +PKG_SOURCE_DATE:=2021-01-27 +PKG_SOURCE_VERSION:=5661366d471a78314bc7010f985ad8cc15be832a +PKG_MIRROR_HASH:=73111e09e896f0abbe3ee1c358aea7ec14fe5e668ce8753b8968e03c78f9599b + +include $(INCLUDE_DIR)/kernel.mk +include $(INCLUDE_DIR)/package.mk + +define Package/qca-ssdk-shell + SECTION:=utils + CATEGORY:=Utilities + TITLE:=Shell application for QCA SSDK + DEPENDS:=@(TARGET_ipq40xx||TARGET_ipq806x||TARGET_ipq807x) +endef + +define Package/qca-ssdk-shell/Description + This package contains a qca-ssdk shell application for QCA chipset +endef + +ifndef CONFIG_TOOLCHAIN_BIN_PATH +CONFIG_TOOLCHAIN_BIN_PATH=$(TOOLCHAIN_DIR)/bin +endif + +QCASSDK_CONFIG_OPTS+= \ + TOOL_PATH=$(CONFIG_TOOLCHAIN_BIN_PATH) \ + SYS_PATH=$(LINUX_DIR) \ + TOOLPREFIX=$(TARGET_CROSS) \ + KVER=$(LINUX_VERSION) \ + CFLAGS="$(TARGET_CFLAGS)" \ + LDFLAGS="$(TARGET_LDFLAGS)" \ + ARCH=$(LINUX_KARCH) + +define Build/Compile + $(MAKE) -C $(PKG_BUILD_DIR) $(strip $(QCASSDK_CONFIG_OPTS)) +endef + +define Package/qca-ssdk-shell/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/build/bin/ssdk_sh $(1)/usr/sbin/ +endef + +$(eval $(call BuildPackage,qca-ssdk-shell)) diff --git a/root/package/qca/qca-ssdk/Makefile b/root/package/qca/qca-ssdk/Makefile new file mode 100644 index 00000000..487117bb --- /dev/null +++ b/root/package/qca/qca-ssdk/Makefile @@ -0,0 +1,125 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=qca-ssdk +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://source.codeaurora.org/quic/qsdk/oss/lklm/qca-ssdk +PKG_SOURCE_DATE:=2021-04-28 +PKG_SOURCE_VERSION:=c9bc3bc34eaaac78083573524097356e2dcc1b66 +PKG_MIRROR_HASH:=29db78529be32427b8b96fcbfec22a016a243676781ec96d9d65b810944fa405 + +LOCAL_VARIANT=$(patsubst qca-ssdk-%,%,$(patsubst qca-ssdk-%,%,$(BUILD_VARIANT))) + +include $(INCLUDE_DIR)/kernel.mk +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/qca-ssdk/default-nohnat + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + TITLE:=Kernel driver for QCA SSDK + FILES:=$(PKG_BUILD_DIR)/build/bin/qca-ssdk.ko + AUTOLOAD:=$(call AutoLoad,30,qca-ssdk) + PROVIDES:=qca-ssdk +endef + +define KernelPackage/qca-ssdk-nohnat +$(call KernelPackage/qca-ssdk/default-nohnat) + DEPENDS:=@(TARGET_ipq806x||TARGET_ipq807x||TARGET_ipq60xx) + VARIANT:=nohnat +endef + +define KernelPackage/qca-ssdk-nohnat/Description +This package contains a qca-ssdk driver for QCA chipset +endef + +define KernelPackage/qca-ssdk-hnat +$(call KernelPackage/qca-ssdk/default-nohnat) + DEPENDS:=@TARGET_ipq40xx +kmod-ipt-extra +kmod-ipt-filter \ + +kmod-ppp +TARGET_ipq40xx:kmod-qca-rfs + TITLE+= (hnat) + VARIANT:=hnat +endef + +define KernelPackage/qca-ssdk-hnat/Description +This package contains a qca-ssdk-hnat driver for QCA chipset +endef + +ifdef CONFIG_TOOLCHAIN_BIN_PATH +TOOLCHAIN_BIN_PATH=$(CONFIG_TOOLCHAIN_BIN_PATH) +else +TOOLCHAIN_BIN_PATH=$(TOOLCHAIN_DIR)/bin +endif + +QCASSDK_CONFIG_OPTS+= \ + $(KERNEL_MAKE_FLAGS) \ + KVER=$(LINUX_VERSION) \ + SYS_PATH=$(LINUX_DIR) \ + GCC_VERSION=$(GCC_VERSION) \ + TOOLPREFIX=$(TARGET_CROSS) \ + TOOL_PATH=$(TOOLCHAIN_BIN_PATH) \ + TARGET_SUFFIX=$(CONFIG_TARGET_SUFFIX) \ + EXTRA_CFLAGS=-fno-stack-protector -I$(STAGING_DIR)/usr/include + +ifeq ($(LOCAL_VARIANT),hnat) + QCASSDK_CONFIG_OPTS+= HNAT_FEATURE=enable +ifeq ($(BOARD),ipq40xx) + QCASSDK_CONFIG_OPTS+= RFS_FEATURE=enable +endif +endif + +ifeq ($(BOARD),ipq60xx) + QCASSDK_CONFIG_OPTS+= CHIP_TYPE=CPPE +else ifeq ($(BOARD),ipq807x) + QCASSDK_CONFIG_OPTS+= CHIP_TYPE=HPPE +else + QCASSDK_CONFIG_OPTS+= HK_CHIP=enable +endif + +ifneq (, $(findstring $(BOARD), ipq60xx ipq807x)) + QCASSDK_CONFIG_OPTS+= PTP_FEATURE=disable SWCONFIG_FEATURE=disable +endif + +define Build/Compile + $(MAKE) -C $(PKG_BUILD_DIR) $(strip $(QCASSDK_CONFIG_OPTS)) +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include/qca-ssdk + $(INSTALL_DIR) $(1)/usr/include/qca-ssdk/api + $(INSTALL_DIR) $(1)/usr/include/qca-ssdk/ref + $(INSTALL_DIR) $(1)/usr/include/qca-ssdk/fal + $(INSTALL_DIR) $(1)/usr/include/qca-ssdk/sal + $(INSTALL_DIR) $(1)/usr/include/qca-ssdk/init + $(CP) -rf $(PKG_BUILD_DIR)/include/api/sw_ioctl.h $(1)/usr/include/qca-ssdk/api + if [ -f $(PKG_BUILD_DIR)/include/ref/ref_vsi.h ]; then \ + $(CP) -rf $(PKG_BUILD_DIR)/include/ref/ref_vsi.h $(1)/usr/include/qca-ssdk/ref/; \ + fi + if [ -f $(PKG_BUILD_DIR)/include/ref/ref_fdb.h ]; then \ + $(CP) -rf $(PKG_BUILD_DIR)/include/ref/ref_fdb.h $(1)/usr/include/qca-ssdk/ref/; \ + fi + if [ -f $(PKG_BUILD_DIR)/include/ref/ref_port_ctrl.h ]; then \ + $(CP) -rf $(PKG_BUILD_DIR)/include/ref/ref_port_ctrl.h $(1)/usr/include/qca-ssdk/ref/; \ + fi + if [ -f $(PKG_BUILD_DIR)/include/init/ssdk_init.h ]; then \ + $(CP) -rf $(PKG_BUILD_DIR)/include/init/ssdk_init.h $(1)/usr/include/qca-ssdk/init/; \ + fi + $(CP) -rf $(PKG_BUILD_DIR)/include/fal $(1)/usr/include/qca-ssdk + $(CP) -rf $(PKG_BUILD_DIR)/include/common/*.h $(1)/usr/include/qca-ssdk + $(CP) -rf $(PKG_BUILD_DIR)/include/sal/os/linux/*.h $(1)/usr/include/qca-ssdk + $(CP) -rf $(PKG_BUILD_DIR)/include/sal/os/*.h $(1)/usr/include/qca-ssdk +endef + +define KernelPackage/qca-ssdk-nohnat/install + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/qca-ssdk $(1)/etc/init.d/qca-ssdk +endef + +define KernelPackage/qca-ssdk-hnat/install + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/qca-ssdk $(1)/etc/init.d/qca-ssdk +endef + +$(eval $(call KernelPackage,qca-ssdk-nohnat)) +$(eval $(call KernelPackage,qca-ssdk-hnat)) diff --git a/root/package/qca/qca-ssdk/files/qca-ssdk b/root/package/qca/qca-ssdk/files/qca-ssdk new file mode 100644 index 00000000..389279c0 --- /dev/null +++ b/root/package/qca/qca-ssdk/files/qca-ssdk @@ -0,0 +1,206 @@ +#!/bin/sh /etc/rc.common +# Copyright (c) 2018, The Linux Foundation. All rights reserved. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +START=16 + +#!/bin/sh +ruletype="ip4 ip6" +side="wan lan" +qwan="1 3 2 0 5 7 6 4" +qlan="0 1 2 3 4 5 6 7" + +function create_war_acl_rules(){ + for lw in $side + do + #echo $lw + if [ "$lw" == "wan" ];then + listid=254 + queue=$qwan + portmap=0x20 + else + listid=255 + queue=$qlan + portmap=0x1e + fi + #echo $queue + #echo "creating list $listid" + ssdk_sh acl list create $listid 255 + ruleid=0 + for rt in $ruletype + do + for qid in $queue + do + cmd="ssdk_sh acl rule add $listid $ruleid 1 n 0 0" + #echo $cmd + if [ "$rt" == "ip4" ];then + cmd="$cmd ip4 n n n n n n n n n n n n n n n n n n n n n n n n n n n n n" + #echo $cmd + else + cmd="$cmd ip6 n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n" + #echo $cmd + fi + if [ $ruleid -le 3 ];then + #non-zero dscp + cmd="$cmd y 0x0 0xff" + elif [ $ruleid -le 7 ];then + #zero dscp + cmd="$cmd n" + elif [ $ruleid -le 11 ];then + #non-zero dscp + cmd="$cmd y 0x0 0xff" + else + #zero dscp + cmd="$cmd n" + fi + p=$((ruleid/2)) + cmd="$cmd y mask $((ruleid%2)) 0x1 y mask $((p%2)) 0x1 n n n n n n n n n n n n n n n y n n n n n n n y $qid n n 0 0 n n n n n n n n n n n n n n n n n n n n 0" + #echo $cmd + $cmd + ruleid=`expr $ruleid + 1` + done + done + ssdk_sh acl list bind $listid 0 1 $portmap + done +} + +function create_war_cosmap(){ + ssdk_sh cosmap pri2q set 0 0 + ssdk_sh cosmap pri2q set 1 0 + ssdk_sh cosmap pri2q set 2 0 + ssdk_sh cosmap pri2q set 3 0 + ssdk_sh cosmap pri2q set 4 1 + ssdk_sh cosmap pri2q set 5 1 + ssdk_sh cosmap pri2q set 6 1 + ssdk_sh cosmap pri2q set 7 1 + ssdk_sh cosmap pri2ehq set 0 0 + ssdk_sh cosmap pri2ehq set 1 0 + ssdk_sh cosmap pri2ehq set 2 0 + ssdk_sh cosmap pri2ehq set 3 0 + ssdk_sh cosmap pri2ehq set 4 1 + ssdk_sh cosmap pri2ehq set 5 1 + ssdk_sh cosmap pri2ehq set 6 1 + ssdk_sh cosmap pri2ehq set 7 1 +} + +function create_acl_byp_egstp_rules(){ + ssdk_sh debug module_func set servcode 0xf 0x0 0x0 + ssdk_sh servcode config set 1 n 0 0xfffefc7f 0xffbdff 0 0 0 0 0 0 + ssdk_sh debug module_func set servcode 0x0 0x0 0x0 + ssdk_sh acl list create 56 48 + ssdk_sh acl rule add 56 0 1 n 0 0 mac n n n n n y 01-80-c2-00-00-00 ff-ff-ff-ff-ff-ff n n n n n n n n n n n n n n n n n n n n n n n y n n n n n n n n n n 0 0 n n n n n n n n n n n n n y n n n n n n n n n n n n y n n n n n n n n n n n n 0 + ssdk_sh acl rule add 56 1 1 n 0 0 mac n n n n n n n yes 0x8809 0xffff n n n n n n n n n n n n n n n n n n n n n y n n n n n n n n n n 0 0 n n n n n n n n n n n n n y n n n n n n n n n n n n y n n n n n n n n n n n n 0 + ssdk_sh acl rule add 56 2 1 n 0 0 mac n n n n n n n yes 0x888e 0xffff n n n n n n n n n n n n n n n n n n n n n y n n n n n n n n n n 0 0 n n n n n n n n n n n n n y n n n n n n n n n n n n y n n n n n n n n n n n n 0 + ssdk_sh acl list bind 56 0 2 1 +} + +function delete_war_acl_rules(){ + for lw in $side + do + #echo $lw + if [ "$lw" == "wan" ];then + listid=254 + queue=$qwan + portmap=0x20 + else + listid=255 + queue=$qlan + portmap=0x1e + fi + ssdk_sh acl list unbind $listid 0 1 $portmap + for rt in $ruletype + do + for qid in $queue + do + cmd="ssdk_sh acl rule del $listid 0 1" + echo $cmd + $cmd + done + done + #echo "deleting list $listid" + ssdk_sh acl list destroy $listid + done +} + +function delete_war_cosmap(){ + ssdk_sh cosmap pri2q set 0 0 + ssdk_sh cosmap pri2q set 1 0 + ssdk_sh cosmap pri2q set 2 1 + ssdk_sh cosmap pri2q set 3 1 + ssdk_sh cosmap pri2q set 4 2 + ssdk_sh cosmap pri2q set 5 2 + ssdk_sh cosmap pri2q set 6 3 + ssdk_sh cosmap pri2q set 7 3 + ssdk_sh cosmap pri2ehq set 0 1 + ssdk_sh cosmap pri2ehq set 1 0 + ssdk_sh cosmap pri2ehq set 2 2 + ssdk_sh cosmap pri2ehq set 3 2 + ssdk_sh cosmap pri2ehq set 4 3 + ssdk_sh cosmap pri2ehq set 5 3 + ssdk_sh cosmap pri2ehq set 6 4 + ssdk_sh cosmap pri2ehq set 7 5 +} + +function delete_acl_byp_egstp_rules(){ + ssdk_sh debug module_func set servcode 0xf 0x0 0x0 + ssdk_sh servcode config set 1 n 0 0xfffefcff 0xffbfff 0 0 0 0 0 0 + ssdk_sh debug module_func set servcode 0x0 0x0 0x0 + ssdk_sh acl list unbind 56 0 2 1 + ssdk_sh acl rule del 56 0 1 + ssdk_sh acl rule del 56 1 1 + ssdk_sh acl rule del 56 2 1 + ssdk_sh acl list destroy 56 +} + +function edma_war_config_add(){ + create_war_cosmap + ssdk_sh acl status set enable + create_war_acl_rules +} + +function edma_war_config_del(){ + delete_war_acl_rules + delete_war_cosmap +} + +start() { + chip_ver=`ssdk_sh debug reg get 0 4 | grep Data | tr -d 'SSDK Init OK![Data]:'` + #The following commands should be uncommented to enable EDMA WAR + if [ "$chip_ver" = "0x1401" ]; then + #edma_war_config_add + echo '' + fi + #The following commands should be uncommented to add acl egress stp bypass rules + if [ "$chip_ver" = "0x1500" ] || [ "$chip_ver" = "0x1501" ]; then + #create_acl_byp_egstp_rules + echo '' + fi + echo starting +} + +stop() { + chip_ver=`ssdk_sh debug reg get 0 4 | grep Data | tr -d 'SSDK Init OK![Data]:'` + #The following commands should be uncommented to disable EDMA WAR + if [ "$chip_ver" = "0x1401" ]; then + #edma_war_config_del + echo '' + fi + #The following commands should be uncommented to delete acl egress stp bypass rules + if [ "$chip_ver" = "0x1500" ] || [ "$chip_ver" = "0x1501" ]; then + #delete_acl_byp_egstp_rules + echo '' + fi + echo stoping +} diff --git a/root/package/qca/qca-ssdk/patches/0001-SSDK-config-add-kernel-5.10-5.15.patch b/root/package/qca/qca-ssdk/patches/0001-SSDK-config-add-kernel-5.10-5.15.patch new file mode 100644 index 00000000..057652e4 --- /dev/null +++ b/root/package/qca/qca-ssdk/patches/0001-SSDK-config-add-kernel-5.10-5.15.patch @@ -0,0 +1,60 @@ +From 472c0c8132784608312c80c4b02c03ea7c132235 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Wed, 12 May 2021 13:41:12 +0200 +Subject: [PATCH] SSDK: config: add kernel 5.10 + +This is purely to identify it and be able to set +flags correctly. + +Signed-off-by: Robert Marko +--- + config | 6 +++++- + make/linux_opt.mk | 4 ++-- + 2 files changed, 7 insertions(+), 3 deletions(-) + +--- a/config ++++ b/config +@@ -22,6 +22,14 @@ ifeq ($(KVER),$(filter 5.4%,$(KVER))) + OS_VER=5_4 + endif + ++ifeq ($(KVER),$(filter 5.10%,$(KVER))) ++OS_VER=5_10 ++endif ++ ++ifeq ($(KVER),$(filter 5.15%,$(KVER))) ++OS_VER=5_15 ++endif ++ + ifeq ($(KVER), 3.4.0) + OS_VER=3_4 + endif +@@ -123,7 +127,7 @@ endif + endif + + ifeq ($(ARCH), arm64) +-ifeq ($(KVER),$(filter 4.1% 4.4% 4.9% 5.4%,$(KVER))) ++ifeq ($(KVER),$(filter 4.1% 4.4% 4.9% 5.4% 5.10% 5.15%,$(KVER))) + CPU_CFLAG= -DMODULE -Os -pipe -march=armv8-a -mcpu=cortex-a53+crypto -fno-caller-saves -fno-strict-aliasing -Werror -fno-common -Wno-format-security -Wno-pointer-sign -Wno-unused-but-set-variable -Wno-error=unused-result -mcmodel=large + endif + endif +--- a/make/linux_opt.mk ++++ b/make/linux_opt.mk +@@ -388,7 +388,7 @@ ifeq (KSLIB, $(MODULE_TYPE)) + KASAN_SHADOW_SCALE_SHIFT := 3 + endif + +- ifeq (5_4, $(OS_VER)) ++ ifeq ($(OS_VER),$(filter 5_4 5_10 5_15, $(OS_VER))) + ifeq ($(ARCH), arm64) + KASAN_OPTION += -DKASAN_SHADOW_SCALE_SHIFT=$(KASAN_SHADOW_SCALE_SHIFT) + endif +@@ -419,7 +419,7 @@ ifeq (KSLIB, $(MODULE_TYPE)) + + endif + +- ifeq ($(OS_VER),$(filter 4_4 5_4, $(OS_VER))) ++ ifeq ($(OS_VER),$(filter 4_4 5_4 5_10 5_15, $(OS_VER))) + MODULE_CFLAG += -DKVER34 + MODULE_CFLAG += -DKVER32 + MODULE_CFLAG += -DLNX26_22 diff --git a/root/package/qca/qca-ssdk/patches/0002-SSDK-replace-ioremap_nocache-with-ioremap.patch b/root/package/qca/qca-ssdk/patches/0002-SSDK-replace-ioremap_nocache-with-ioremap.patch new file mode 100644 index 00000000..b293ad29 --- /dev/null +++ b/root/package/qca/qca-ssdk/patches/0002-SSDK-replace-ioremap_nocache-with-ioremap.patch @@ -0,0 +1,102 @@ +From 784f2cfdfaf3bdf44917924e157049230a0ef5f8 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Wed, 12 May 2021 13:45:45 +0200 +Subject: [PATCH] SSDK: replace ioremap_nocache with ioremap + +ioremap_nocache was dropped upstream, simply use the +generic variety. + +Signed-off-by: Robert Marko +--- + src/init/ssdk_clk.c | 10 +++++----- + src/init/ssdk_init.c | 2 +- + src/init/ssdk_plat.c | 6 +++--- + 3 files changed, 9 insertions(+), 9 deletions(-) + +--- a/src/init/ssdk_clk.c ++++ b/src/init/ssdk_clk.c +@@ -623,7 +623,7 @@ ssdk_mp_tcsr_get(a_uint32_t tcsr_offset, + { + void __iomem *tcsr_base = NULL; + +- tcsr_base = ioremap_nocache(TCSR_ETH_ADDR, TCSR_ETH_SIZE); ++ tcsr_base = ioremap(TCSR_ETH_ADDR, TCSR_ETH_SIZE); + if (!tcsr_base) + { + SSDK_ERROR("Failed to map tcsr eth address!\n"); +@@ -640,7 +640,7 @@ ssdk_mp_tcsr_set(a_uint32_t tcsr_offset, + { + void __iomem *tcsr_base = NULL; + +- tcsr_base = ioremap_nocache(TCSR_ETH_ADDR, TCSR_ETH_SIZE); ++ tcsr_base = ioremap(TCSR_ETH_ADDR, TCSR_ETH_SIZE); + if (!tcsr_base) + { + SSDK_ERROR("Failed to map tcsr eth address!\n"); +@@ -688,7 +688,7 @@ ssdk_mp_cmnblk_stable_check(void) + a_uint32_t reg_val; + int i, loops = 20; + +- pll_lock = ioremap_nocache(CMN_PLL_LOCKED_ADDR, CMN_PLL_LOCKED_SIZE); ++ pll_lock = ioremap(CMN_PLL_LOCKED_ADDR, CMN_PLL_LOCKED_SIZE); + if (!pll_lock) { + SSDK_ERROR("Failed to map CMN PLL LOCK register!\n"); + return A_FALSE; +@@ -745,7 +745,7 @@ static void ssdk_cmnblk_pll_src_set(enum + void __iomem *cmn_pll_src_base = NULL; + a_uint32_t reg_val; + +- cmn_pll_src_base = ioremap_nocache(CMN_BLK_PLL_SRC_ADDR, CMN_BLK_SIZE); ++ cmn_pll_src_base = ioremap(CMN_BLK_PLL_SRC_ADDR, CMN_BLK_SIZE); + if (!cmn_pll_src_base) { + SSDK_ERROR("Failed to map cmn pll source address!\n"); + return; +@@ -766,7 +766,7 @@ static void ssdk_cmnblk_init(enum cmnblk + void __iomem *gcc_pll_base = NULL; + a_uint32_t reg_val; + +- gcc_pll_base = ioremap_nocache(CMN_BLK_ADDR, CMN_BLK_SIZE); ++ gcc_pll_base = ioremap(CMN_BLK_ADDR, CMN_BLK_SIZE); + if (!gcc_pll_base) { + SSDK_ERROR("Failed to map gcc pll address!\n"); + return; +--- a/src/init/ssdk_init.c ++++ b/src/init/ssdk_init.c +@@ -2770,7 +2770,7 @@ static int ssdk_dess_mac_mode_init(a_uin + (a_uint8_t *)®_value, 4); + mdelay(10); + /*softreset psgmii, fixme*/ +- gcc_addr = ioremap_nocache(0x1812000, 0x200); ++ gcc_addr = ioremap(0x1812000, 0x200); + if (!gcc_addr) { + SSDK_ERROR("gcc map fail!\n"); + return 0; +--- a/src/init/ssdk_plat.c ++++ b/src/init/ssdk_plat.c +@@ -1312,7 +1312,7 @@ ssdk_plat_init(ssdk_init_cfg *cfg, a_uin + reg_mode = ssdk_uniphy_reg_access_mode_get(dev_id); + if(reg_mode == HSL_REG_LOCAL_BUS) { + ssdk_uniphy_reg_map_info_get(dev_id, &map); +- qca_phy_priv_global[dev_id]->uniphy_hw_addr = ioremap_nocache(map.base_addr, ++ qca_phy_priv_global[dev_id]->uniphy_hw_addr = ioremap(map.base_addr, + map.size); + if (!qca_phy_priv_global[dev_id]->uniphy_hw_addr) { + SSDK_ERROR("%s ioremap fail.", __func__); +@@ -1327,7 +1327,7 @@ ssdk_plat_init(ssdk_init_cfg *cfg, a_uin + reg_mode = ssdk_switch_reg_access_mode_get(dev_id); + if(reg_mode == HSL_REG_LOCAL_BUS) { + ssdk_switch_reg_map_info_get(dev_id, &map); +- qca_phy_priv_global[dev_id]->hw_addr = ioremap_nocache(map.base_addr, ++ qca_phy_priv_global[dev_id]->hw_addr = ioremap(map.base_addr, + map.size); + if (!qca_phy_priv_global[dev_id]->hw_addr) { + SSDK_ERROR("%s ioremap fail.", __func__); +@@ -1358,7 +1358,7 @@ ssdk_plat_init(ssdk_init_cfg *cfg, a_uin + return -1; + } + +- qca_phy_priv_global[dev_id]->psgmii_hw_addr = ioremap_nocache(map.base_addr, ++ qca_phy_priv_global[dev_id]->psgmii_hw_addr = ioremap(map.base_addr, + map.size); + if (!qca_phy_priv_global[dev_id]->psgmii_hw_addr) { + SSDK_ERROR("%s ioremap fail.", __func__); diff --git a/root/package/qca/qca-ssdk/patches/0004-platform-use-of_mdio_find_bus-to-get-MDIO-bus.patch b/root/package/qca/qca-ssdk/patches/0004-platform-use-of_mdio_find_bus-to-get-MDIO-bus.patch new file mode 100644 index 00000000..3bcbcccf --- /dev/null +++ b/root/package/qca/qca-ssdk/patches/0004-platform-use-of_mdio_find_bus-to-get-MDIO-bus.patch @@ -0,0 +1,40 @@ +From b6190ca46287d01a895c7cc14de30410c09ff1b8 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Wed, 12 May 2021 17:15:46 +0200 +Subject: [PATCH] SSDK: platform: use of_mdio_find_bus() to get MDIO bus + +Kernel has a generic of_mdio_find_bus() which can get the appropriate +MDIO bus based on the DT node. +So, drop the getting MDIO from platform data, which no longer works +in 5.4 and later and use of_mdio_find_bus(). + +Signed-off-by: Baruch Siach +Signed-off-by: Robert Marko +--- + src/init/ssdk_plat.c | 8 +------- + 1 file changed, 1 insertion(+), 7 deletions(-) + +--- a/src/init/ssdk_plat.c ++++ b/src/init/ssdk_plat.c +@@ -551,7 +551,6 @@ static int miibus_get(a_uint32_t dev_id) + struct device_node *mdio_node = NULL; + struct device_node *switch_node = NULL; + struct platform_device *mdio_plat = NULL; +- struct ipq40xx_mdio_data *mdio_data = NULL; + struct qca_phy_priv *priv; + hsl_reg_mode reg_mode = HSL_REG_LOCAL_BUS; + priv = qca_phy_priv_global[dev_id]; +@@ -584,12 +583,7 @@ static int miibus_get(a_uint32_t dev_id) + + if(reg_mode == HSL_REG_LOCAL_BUS) + { +- mdio_data = dev_get_drvdata(&mdio_plat->dev); +- if (!mdio_data) { +- SSDK_ERROR("cannot get mdio_data reference from device data\n"); +- return 1; +- } +- priv->miibus = mdio_data->mii_bus; ++ priv->miibus = of_mdio_find_bus(mdio_node); + } + else + priv->miibus = dev_get_drvdata(&mdio_plat->dev); diff --git a/root/package/qca/qca-ssdk/patches/0005-add-kernel-5.4-support.patch b/root/package/qca/qca-ssdk/patches/0005-add-kernel-5.4-support.patch new file mode 100644 index 00000000..6b08b05a --- /dev/null +++ b/root/package/qca/qca-ssdk/patches/0005-add-kernel-5.4-support.patch @@ -0,0 +1,108 @@ +--- a/app/nathelper/linux/lib/nat_helper_dt.c ++++ b/app/nathelper/linux/lib/nat_helper_dt.c +@@ -721,7 +721,7 @@ napt_ct_counter_sync(a_uint32_t hw_index) + } + + if (!test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) { +- ct->timeout.expires += delta_jiffies; ++ ct->timeout += delta_jiffies; + } + + if((cct != NULL) && (napt_hw_get_by_index(&napt, hw_index) == 0)) +@@ -770,7 +770,7 @@ napt_ct_timer_update(a_uint32_t hw_index) + } + + if (!test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) { +- ct->timeout.expires += delta_jiffies; ++ ct->timeout += delta_jiffies; + } + + return 0; +--- a/app/nathelper/linux/napt_helper.c ++++ b/app/nathelper/linux/napt_helper.c +@@ -64,11 +64,6 @@ napt_ct_aging_disable(uint32_t ct_addr) + } + + ct = (struct nf_conn *)ct_addr; +- +- if (timer_pending(&ct->timeout)) +- { +- del_timer(&ct->timeout); +- } + } + + int +@@ -85,7 +80,7 @@ napt_ct_aging_is_enable(uint32_t ct_addr) + + ct = (struct nf_conn *)ct_addr; + +- return timer_pending(&(((struct nf_conn *)ct)->timeout)); ++ return (nf_ct_is_expired(ct)); + } + + void +@@ -111,18 +106,17 @@ napt_ct_aging_enable(uint32_t ct_addr) + l3num = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; + protonum = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum; + +- ct->timeout.expires = jiffies+10*HZ; ++ ct->timeout = jiffies+10*HZ; + + if ((l3num == AF_INET) && (protonum == IPPROTO_TCP)) + { + if (ct->proto.tcp.state == TCP_CONNTRACK_ESTABLISHED) + { +- ct->timeout.expires = jiffies+(5*24*60*60*HZ); ++ ct->timeout = jiffies+(5*24*60*60*HZ); + } + } + + HNAT_PRINTK(" ct:[%x] add timeout again\n", ct_addr); +- add_timer(&ct->timeout); + } + + void +@@ -339,7 +333,6 @@ napt_ct_list_unlock(void) + uint32_t + napt_ct_list_iterate(uint32_t *hash, uint32_t *iterate) + { +- struct net *net = &init_net; + struct nf_conntrack_tuple_hash *h = NULL; + struct nf_conn *ct = NULL; + struct hlist_nulls_node *pos = (struct hlist_nulls_node *) (*iterate); +@@ -349,7 +342,7 @@ napt_ct_list_iterate(uint32_t *hash, uint32_t *iterate) + if(pos == 0) + { + /*get head for list*/ +- pos = rcu_dereference((&net->ct.hash[*hash])->first); ++ pos = rcu_dereference(hlist_nulls_first_rcu(&nf_conntrack_hash[*hash])); + } + + hlist_nulls_for_each_entry_from(h, pos, hnnode) +--- a/app/nathelper/linux/nat_ipt_helper.c ++++ b/app/nathelper/linux/nat_ipt_helper.c +@@ -534,10 +534,10 @@ nat_ipt_data_init(void) + memset(&old_replace, 0, sizeof (old_replace)); + + /*record ipt rule(SNAT) sequence for hw nat*/ +- memset(hw_nat_ipt_seq, 0, NAT_HW_NUM); ++ memset(hw_nat_ipt_seq, 0, sizeof(hw_nat_ipt_seq)); + + /*record ipt rule(SNAT) pubip index for hw nat*/ +- memset(hw_nat_pip_idx, 0, NAT_HW_NUM); ++ memset(hw_nat_pip_idx, 0, sizeof(hw_nat_pip_idx)); + } + + static void +--- a/make/linux_opt.mk ++++ b/make/linux_opt.mk +@@ -449,9 +449,6 @@ ifeq (KSLIB, $(MODULE_TYPE)) + else ifeq ($(ARCH), arm) + MODULE_INC += -I$(SYS_PATH) \ + -I$(TOOL_PATH)/../lib/gcc/$(TARGET_NAME)/$(GCC_VERSION)/include/ \ +- -I$(TOOL_PATH)/../lib/gcc/$(TARGET_NAME)/7.5.0/include/ \ +- -I$(TOOL_PATH)/../../lib/armv7a-vfp-neon-rdk-linux-gnueabi/gcc/arm-rdk-linux-gnueabi/4.8.4/include/ \ +- -I$(TOOL_PATH)/../../lib/arm-rdk-linux-musleabi/gcc/arm-rdk-linux-musleabi/6.4.0/include/ \ + -I$(SYS_PATH)/include \ + -I$(SYS_PATH)/source \ + -I$(SYS_PATH)/source/include \ diff --git a/root/package/qca/qca-ssdk/patches/0006-fix-mdio-probe-on-ipq806x.patch b/root/package/qca/qca-ssdk/patches/0006-fix-mdio-probe-on-ipq806x.patch new file mode 100644 index 00000000..8e802fe2 --- /dev/null +++ b/root/package/qca/qca-ssdk/patches/0006-fix-mdio-probe-on-ipq806x.patch @@ -0,0 +1,11 @@ +--- a/src/init/ssdk_plat.c ++++ b/src/init/ssdk_plat.c +@@ -568,7 +568,7 @@ static int miibus_get(a_uint32_t dev_id) + if(reg_mode == HSL_REG_LOCAL_BUS) + mdio_node = of_find_compatible_node(NULL, NULL, "qcom,ipq40xx-mdio"); + else +- mdio_node = of_find_compatible_node(NULL, NULL, "virtual,mdio-gpio"); ++ mdio_node = of_find_compatible_node(NULL, NULL, "qcom,ipq8064-mdio"); + + if (!mdio_node) { + SSDK_ERROR("No MDIO node found in DTS!\n"); diff --git a/root/package/qca/qca-ssdk/patches/0007-SSDK-dts-fix-of_get_mac_address.patch b/root/package/qca/qca-ssdk/patches/0007-SSDK-dts-fix-of_get_mac_address.patch new file mode 100644 index 00000000..29be9312 --- /dev/null +++ b/root/package/qca/qca-ssdk/patches/0007-SSDK-dts-fix-of_get_mac_address.patch @@ -0,0 +1,42 @@ +From f3a7b93137c1a6a1b8010b86296242178eed5d9e Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 13 Aug 2021 20:03:21 +0200 +Subject: [PATCH] SSDK: dts: fix of_get_mac_address() + +Recently OpenWrt backported the updated of_get_mac_address() +function which returns and error code instead. + +So, patch the SSDK to use it and fix the compilation error. + +Signed-off-by: Robert Marko +--- + src/init/ssdk_dts.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/src/init/ssdk_dts.c ++++ b/src/init/ssdk_dts.c +@@ -779,8 +779,9 @@ static void ssdk_dt_parse_intf_mac(void) + { + struct device_node *dp_node = NULL; + a_uint32_t dp = 0; +- a_uint8_t *maddr = NULL; ++ u8 maddr[ETH_ALEN]; + char dp_name[8] = {0}; ++ int ret; + + for (dp = 1; dp <= SSDK_MAX_NR_ETH; dp++) { + snprintf(dp_name, sizeof(dp_name), "dp%d", dp); +@@ -788,11 +789,11 @@ static void ssdk_dt_parse_intf_mac(void) + if (!dp_node) { + continue; + } +- maddr = (a_uint8_t *)of_get_mac_address(dp_node); ++ ret = of_get_mac_address(dp_node, maddr); + #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)) + if (maddr && is_valid_ether_addr(maddr)) { + #else +- if (!IS_ERR(maddr) && is_valid_ether_addr(maddr)) { ++ if (!ret && is_valid_ether_addr(maddr)) { + #endif + ssdk_dt_global.num_intf_mac++; + ether_addr_copy(ssdk_dt_global.intf_mac[dp-1].uc, maddr); diff --git a/root/package/qca/qca-ssdk/patches/0008-add-aquantia-phy-id-113CB0.patch b/root/package/qca/qca-ssdk/patches/0008-add-aquantia-phy-id-113CB0.patch new file mode 100644 index 00000000..fba52635 --- /dev/null +++ b/root/package/qca/qca-ssdk/patches/0008-add-aquantia-phy-id-113CB0.patch @@ -0,0 +1,37 @@ +From 440ab349813e5aa9dbeddab4d82ab64ff5347c5f Mon Sep 17 00:00:00 2001 +From: Dirk Buchwalder +Date: Sat, 30 Oct 2021 19:51:06 +0200 +Subject: [PATCH] add aquantia phy id 113CB0 / 0x31c31C12 + +This adds support for the AQR113C with the id +"113CB0 / 0x31c31C12" to the ssdk. + +This is used in the QNAP 301w + +Signed-off-by: Dirk Buchwalder + +--- + include/hsl/phy/hsl_phy.h | 1 + + src/hsl/phy/hsl_phy.c | 1 + + 2 files changed, 2 insertions(+) + +--- a/include/hsl/phy/hsl_phy.h ++++ b/include/hsl/phy/hsl_phy.h +@@ -579,6 +579,7 @@ typedef struct { + #define AQUANTIA_PHY_112 0x03a1b660 + #define AQUANTIA_PHY_113C_A0 0x31c31C10 + #define AQUANTIA_PHY_113C_A1 0x31c31C11 ++#define AQUANTIA_PHY_113C_B0 0x31c31C12 + #define AQUANTIA_PHY_112C 0x03a1b792 + + #define PHY_805XV2 0x004DD082 +--- a/src/hsl/phy/hsl_phy.c ++++ b/src/hsl/phy/hsl_phy.c +@@ -235,6 +235,7 @@ phy_type_t hsl_phytype_get_by_phyid(a_ui + case AQUANTIA_PHY_112: + case AQUANTIA_PHY_113C_A0: + case AQUANTIA_PHY_113C_A1: ++ case AQUANTIA_PHY_113C_B0: + case AQUANTIA_PHY_112C: + phytype = AQUANTIA_PHY_CHIP; + break; diff --git a/root/package/qca/qca-ssdk/patches/0009-qca8081-convert-to-5.11-IRQ-model.patch b/root/package/qca/qca-ssdk/patches/0009-qca8081-convert-to-5.11-IRQ-model.patch new file mode 100644 index 00000000..b0c272b1 --- /dev/null +++ b/root/package/qca/qca-ssdk/patches/0009-qca8081-convert-to-5.11-IRQ-model.patch @@ -0,0 +1,83 @@ +From 25ff0ae02accadd7b05f1dae788505f833d5c019 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 24 Dec 2021 20:02:32 +0100 +Subject: [PATCH] qca8081: convert to 5.11 IRQ model + +Kernel 5.11 introduced new IRQ handling model for PHY-s, +so provide those if 5.11 or later is used. + +Signed-off-by: Robert Marko +--- + src/hsl/phy/qca808x.c | 46 +++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 46 insertions(+) + +--- a/src/hsl/phy/qca808x.c ++++ b/src/hsl/phy/qca808x.c +@@ -238,6 +238,7 @@ static int qca808x_config_intr(struct ph + return err; + } + ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0)) + static int qca808x_ack_interrupt(struct phy_device *phydev) + { + int err; +@@ -257,6 +258,47 @@ static int qca808x_ack_interrupt(struct + + return (err < 0) ? err : 0; + } ++#endif ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(5, 11, 0)) ++static irqreturn_t qca808x_handle_interrupt(struct phy_device *phydev) ++{ ++ a_uint16_t irq_status, int_enabled; ++ a_uint32_t dev_id = 0, phy_id = 0; ++ qca808x_priv *priv = phydev->priv; ++ const struct qca808x_phy_info *pdata = priv->phy_info; ++ ++ if (!pdata) { ++ return SW_FAIL; ++ } ++ ++ dev_id = pdata->dev_id; ++ phy_id = pdata->phy_addr; ++ ++ irq_status = qca808x_phy_reg_read(dev_id, phy_id, ++ QCA808X_PHY_INTR_STATUS); ++ if (irq_status < 0) { ++ phy_error(phydev); ++ return IRQ_NONE; ++ } ++ ++ /* Read the current enabled interrupts */ ++ int_enabled = qca808x_phy_reg_read(dev_id, phy_id, ++ QCA808X_PHY_INTR_MASK); ++ if (int_enabled < 0) { ++ phy_error(phydev); ++ return IRQ_NONE; ++ } ++ ++ /* See if this was one of our enabled interrupts */ ++ if (!(irq_status & int_enabled)) ++ return IRQ_NONE; ++ ++ phy_trigger_machine(phydev); ++ ++ return IRQ_HANDLED; ++} ++#endif + + /* switch linux negtiation capability to fal avariable */ + #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)) +@@ -559,7 +601,11 @@ struct phy_driver qca808x_phy_driver = { + .config_intr = qca808x_config_intr, + .config_aneg = qca808x_config_aneg, + .aneg_done = qca808x_aneg_done, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0)) + .ack_interrupt = qca808x_ack_interrupt, ++#else ++ .handle_interrupt = qca808x_handle_interrupt, ++#endif + .read_status = qca808x_read_status, + .suspend = qca808x_suspend, + .resume = qca808x_resume, diff --git a/root/package/qca/qca-ssdk/patches/0012-include-fix-compilation-error-for-parse_uci_option.patch b/root/package/qca/qca-ssdk/patches/0012-include-fix-compilation-error-for-parse_uci_option.patch new file mode 100644 index 00000000..01b8deda --- /dev/null +++ b/root/package/qca/qca-ssdk/patches/0012-include-fix-compilation-error-for-parse_uci_option.patch @@ -0,0 +1,27 @@ +From 8e3500df074625b3eb3a8ed4e8e0b1b116f13d0c Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Sat, 7 May 2022 19:03:55 +0200 +Subject: [PATCH] include: fix compilation error for parse_uci_option + +Fix missing include for parse_uci_option + +Signed-off-by: Ansuel Smith +--- + include/ref/ref_uci.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/include/ref/ref_uci.h b/include/ref/ref_uci.h +index a42ea153..0906c5ba 100755 +--- a/include/ref/ref_uci.h ++++ b/include/ref/ref_uci.h +@@ -19,6 +19,7 @@ + extern "C" { + #endif /* __cplusplus */ + ++#include + + #if defined(IN_SWCONFIG) + int +-- +2.34.1 + From 1946c35766e510a0d995c37d179d624f5065c427 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Tue, 22 Nov 2022 23:17:38 +0800 Subject: [PATCH 054/102] Revert "addqca" This reverts commit 2822d42d1b84c99a4ec8cd118405a3b2bfb1e675. --- .../qca/firmware/nss-firmware/Makefile | 70 - root/package/qca/nss/nss-ifb/Makefile | 49 - root/package/qca/nss/nss-ifb/README.md | 45 - root/package/qca/nss/nss-ifb/src/Makefile | 3 - root/package/qca/nss/nss-ifb/src/nss_ifb.c | 304 ---- root/package/qca/nss/qca-nss-cfi/Makefile | 99 -- .../patches/0001-compile-only-cryptoapi.patch | 30 - .../patches/0002-wip-support-5.4.patch | 78 - .../0003-Convert-ablkcipher-to-skcipher.patch | 707 --------- .../qca/nss/qca-nss-clients-64/Makefile | 97 -- .../qca-nss-clients-64/files/qca-nss-ipsec | 214 --- .../files/qca-nss-mirred.init | 28 - .../files/qca-nss-ovpn.init | 69 - root/package/qca/nss/qca-nss-clients/Makefile | 469 ------ .../nss/qca-nss-clients/files/qca-nss-ipsec | 92 -- .../qca-nss-clients/files/qca-nss-mirred.init | 28 - .../qca-nss-clients/files/qca-nss-ovpn.init | 69 - .../100-kernel-5.4-support-qdisc.patch | 1145 --------------- .../patches/101-kernel-5.4-support-gre.patch | 106 -- .../102-kernel-5.4-support-ipsec.patch | 29 - .../patches/103-kernel-5.4-support-dtls.patch | 11 - .../patches/104-kernel-5.4-support-l2tp.patch | 64 - .../patches/200-qdisc-fix-compile-error.patch | 14 - .../202-vlanmgr-fix-compile-error.patch | 48 - root/package/qca/nss/qca-nss-crypto/Makefile | 74 - .../patches/100-kernel-5.4-support.patch | 42 - .../200-fix-NULL-pointer-exception.patch | 57 - root/package/qca/nss/qca-nss-dp/Makefile | 62 - ...port-newer-kernels-time-stamping-API.patch | 44 - ...-phy-mode-code-compatible-with-newer.patch | 48 - ...03-Drop-_nocache-variants-of-ioremap.patch | 48 - .../0004-EDMA-Fix-NAPI-packet-counting.patch | 31 - ...-Use-NAPI_POLL_WEIGHT-as-NAPI-weight.patch | 41 - .../0006-NSS-DP-fix-of_get_mac_address.patch | 50 - ...07-NSS-DP-implement-ethernet-IOCTL-s.patch | 29 - ...dev-remove-the-transaction-structure.patch | 48 - ...09-switchdev-use-new-switchdev-flags.patch | 54 - .../0010-switchdev-fix-FDB-roaming.patch | 110 -- ...fusing-printing-of-registered-netdev.patch | 31 - root/package/qca/nss/qca-nss-drv-64/Makefile | 121 -- .../nss/qca-nss-drv-64/files/qca-nss-drv.conf | 6 - .../qca-nss-drv-64/files/qca-nss-drv.debug | 26 - .../qca-nss-drv-64/files/qca-nss-drv.hotplug | 70 - .../nss/qca-nss-drv-64/files/qca-nss-drv.init | 50 - .../qca-nss-drv-64/files/qca-nss-drv.sysctl | 4 - ...ore-add-5.10-kernel-to-version-check.patch | 25 - ...replace-ioremap_nocache-with-ioremap.patch | 164 --- ...0003-DMA-Fix-NULL-pointer-exceptions.patch | 49 - ...-nss-drv-add-support-for-kernel-5.15.patch | 73 - ...dard-skb_skip_tc_classify-instead-of.patch | 29 - ...hack-support-for-mismatched-firmware.patch | 344 ----- root/package/qca/nss/qca-nss-drv/Makefile | 125 -- .../files/nss-firmware/LICENSE.TXT | 45 - .../qca-nss-drv/files/nss-firmware/NOTICE.TXT | 217 --- .../qca-nss-drv/files/nss-firmware/README.md | 10 - .../files/nss-firmware/qca-nss0-retail.bin | Bin 536324 -> 0 bytes .../files/nss-firmware/qca-nss1-retail.bin | Bin 218224 -> 0 bytes .../nss/qca-nss-drv/files/qca-nss-drv.conf | 6 - .../nss/qca-nss-drv/files/qca-nss-drv.debug | 26 - .../nss/qca-nss-drv/files/qca-nss-drv.hotplug | 70 - .../nss/qca-nss-drv/files/qca-nss-drv.init | 50 - .../nss/qca-nss-drv/files/qca-nss-drv.sysctl | 4 - .../patches/100-kernel-5.4-support.patch | 107 -- ...ol-fab-scaling-from-package-Makefile.patch | 38 - .../200-fix-NULL-pointer-exception.patch | 11 - ...1-Fix-Kernel-Panic-dma-with-NULL-dev.patch | 82 -- .../400-Exported-set-nexthop-function.patch | 47 - root/package/qca/nss/qca-nss-ecm-64/Makefile | 96 -- .../qca/nss/qca-nss-ecm-64/files/ecm_dump.sh | 95 -- .../nss/qca-nss-ecm-64/files/on-demand-down | 6 - .../qca-nss-ecm-64/files/qca-nss-ecm.defaults | 28 - .../qca-nss-ecm-64/files/qca-nss-ecm.firewall | 18 - .../nss/qca-nss-ecm-64/files/qca-nss-ecm.init | 137 -- .../qca-nss-ecm-64/files/qca-nss-ecm.sysctl | 2 - .../nss/qca-nss-ecm-64/files/qca-nss-ecm.uci | 2 - ...de-componentize-the-module-even-more.patch | 335 ----- .../patches/002-kernel-5.10-support.patch | 831 ----------- .../003-rework-nfct-notification.patch | 25 - .../patches/004-More-compile-fixes.patch | 58 - .../patches/005-resolve-high-load.patch | 61 - ...terface-switch-to-kernel_recvmsg-api.patch | 40 - ...ide-rework-notifier-changes-for-5.15.patch | 72 - ...se-of-static-be_liberal-and-no_windo.patch | 156 -- ...tagram-drop-static-for-EXPORT_SYMBOL.patch | 55 - ...dp_get_timeouts-and-use-standard-ups.patch | 74 - ...-ecm-fix-a-memcpy-overflow-in-ecm_db.patch | 67 - root/package/qca/nss/qca-nss-ecm/Makefile | 278 ---- .../qca/nss/qca-nss-ecm/files/ecm_dump.sh | 95 -- .../qca/nss/qca-nss-ecm/files/on-demand-down | 6 - .../qca-nss-ecm/files/qca-nss-ecm.defaults | 28 - .../qca-nss-ecm/files/qca-nss-ecm.firewall | 18 - .../nss/qca-nss-ecm/files/qca-nss-ecm.init | 133 -- .../nss/qca-nss-ecm/files/qca-nss-ecm.sysctl | 2 - .../qca/nss/qca-nss-ecm/files/qca-nss-ecm.uci | 2 - .../patches/001-Drop_SFE_from_ecm.patch | 12 - .../patches/100-kernel-5.4-support.patch | 1276 ----------------- .../101-Fix_Kern_Panic_on_UDP_CONNTRACK.patch | 60 - .../patches/200-resolve-high-load.patch | 44 - .../203-rework-nfct-notification.patch | 20 - ...heck-TCP_UDP-conntrack-state-earlier.patch | 236 --- ...ix-NSS-stats-request-roll-over-issue.patch | 52 - ...01-Fix-for-ref-leak-during-multicast.patch | 112 -- ...neighbour-solicitation-send-function.patch | 33 - ...e-leak-during-multicast_PPPoE-bridge.patch | 260 ---- ...-global-accelerated-count-under-lock.patch | 59 - ...x-IPv6-neighbor-solicitation-request.patch | 83 -- ...tation-fix-with-zero-gateway-address.patch | 63 - ...-port-when-bridge-hairpin-is-enabled.patch | 126 -- root/package/qca/nss/qca-nss-gmac/Makefile | 47 - .../patches/100-kernel-5.4-support.patch | 279 ---- .../patches/101-nss-gmac-test-ptr.patch | 25 - ...-work-around-interface-close-warning.patch | 15 - root/package/qca/qca-mcs/Makefile | 54 - root/package/qca/qca-rfs/Makefile | 51 - root/package/qca/qca-rfs/files/qrfs.init | 27 - .../patches/100-add-kernel-5.4-support.patch | 57 - .../200-rework-nfct-notification.patch | 20 - root/package/qca/qca-ssdk-shell/Makefile | 48 - root/package/qca/qca-ssdk/Makefile | 125 -- root/package/qca/qca-ssdk/files/qca-ssdk | 206 --- ...001-SSDK-config-add-kernel-5.10-5.15.patch | 60 - ...replace-ioremap_nocache-with-ioremap.patch | 102 -- ...use-of_mdio_find_bus-to-get-MDIO-bus.patch | 40 - .../patches/0005-add-kernel-5.4-support.patch | 108 -- .../0006-fix-mdio-probe-on-ipq806x.patch | 11 - ...0007-SSDK-dts-fix-of_get_mac_address.patch | 42 - .../0008-add-aquantia-phy-id-113CB0.patch | 37 - ...09-qca8081-convert-to-5.11-IRQ-model.patch | 83 -- ...mpilation-error-for-parse_uci_option.patch | 27 - 129 files changed, 13056 deletions(-) delete mode 100644 root/package/qca/firmware/nss-firmware/Makefile delete mode 100644 root/package/qca/nss/nss-ifb/Makefile delete mode 100644 root/package/qca/nss/nss-ifb/README.md delete mode 100644 root/package/qca/nss/nss-ifb/src/Makefile delete mode 100644 root/package/qca/nss/nss-ifb/src/nss_ifb.c delete mode 100644 root/package/qca/nss/qca-nss-cfi/Makefile delete mode 100644 root/package/qca/nss/qca-nss-cfi/patches/0001-compile-only-cryptoapi.patch delete mode 100644 root/package/qca/nss/qca-nss-cfi/patches/0002-wip-support-5.4.patch delete mode 100644 root/package/qca/nss/qca-nss-cfi/patches/0003-Convert-ablkcipher-to-skcipher.patch delete mode 100644 root/package/qca/nss/qca-nss-clients-64/Makefile delete mode 100644 root/package/qca/nss/qca-nss-clients-64/files/qca-nss-ipsec delete mode 100644 root/package/qca/nss/qca-nss-clients-64/files/qca-nss-mirred.init delete mode 100644 root/package/qca/nss/qca-nss-clients-64/files/qca-nss-ovpn.init delete mode 100644 root/package/qca/nss/qca-nss-clients/Makefile delete mode 100644 root/package/qca/nss/qca-nss-clients/files/qca-nss-ipsec delete mode 100644 root/package/qca/nss/qca-nss-clients/files/qca-nss-mirred.init delete mode 100644 root/package/qca/nss/qca-nss-clients/files/qca-nss-ovpn.init delete mode 100644 root/package/qca/nss/qca-nss-clients/patches/100-kernel-5.4-support-qdisc.patch delete mode 100644 root/package/qca/nss/qca-nss-clients/patches/101-kernel-5.4-support-gre.patch delete mode 100644 root/package/qca/nss/qca-nss-clients/patches/102-kernel-5.4-support-ipsec.patch delete mode 100644 root/package/qca/nss/qca-nss-clients/patches/103-kernel-5.4-support-dtls.patch delete mode 100644 root/package/qca/nss/qca-nss-clients/patches/104-kernel-5.4-support-l2tp.patch delete mode 100644 root/package/qca/nss/qca-nss-clients/patches/200-qdisc-fix-compile-error.patch delete mode 100644 root/package/qca/nss/qca-nss-clients/patches/202-vlanmgr-fix-compile-error.patch delete mode 100644 root/package/qca/nss/qca-nss-crypto/Makefile delete mode 100644 root/package/qca/nss/qca-nss-crypto/patches/100-kernel-5.4-support.patch delete mode 100644 root/package/qca/nss/qca-nss-crypto/patches/200-fix-NULL-pointer-exception.patch delete mode 100644 root/package/qca/nss/qca-nss-dp/Makefile delete mode 100644 root/package/qca/nss/qca-nss-dp/patches/0001-edma_tx_rx-support-newer-kernels-time-stamping-API.patch delete mode 100644 root/package/qca/nss/qca-nss-dp/patches/0002-nss_dp_main-make-phy-mode-code-compatible-with-newer.patch delete mode 100644 root/package/qca/nss/qca-nss-dp/patches/0003-Drop-_nocache-variants-of-ioremap.patch delete mode 100644 root/package/qca/nss/qca-nss-dp/patches/0004-EDMA-Fix-NAPI-packet-counting.patch delete mode 100644 root/package/qca/nss/qca-nss-dp/patches/0005-EDMA-Use-NAPI_POLL_WEIGHT-as-NAPI-weight.patch delete mode 100644 root/package/qca/nss/qca-nss-dp/patches/0006-NSS-DP-fix-of_get_mac_address.patch delete mode 100644 root/package/qca/nss/qca-nss-dp/patches/0007-NSS-DP-implement-ethernet-IOCTL-s.patch delete mode 100644 root/package/qca/nss/qca-nss-dp/patches/0008-switchdev-remove-the-transaction-structure.patch delete mode 100644 root/package/qca/nss/qca-nss-dp/patches/0009-switchdev-use-new-switchdev-flags.patch delete mode 100644 root/package/qca/nss/qca-nss-dp/patches/0010-switchdev-fix-FDB-roaming.patch delete mode 100644 root/package/qca/nss/qca-nss-dp/patches/0011-treewide-fix-confusing-printing-of-registered-netdev.patch delete mode 100644 root/package/qca/nss/qca-nss-drv-64/Makefile delete mode 100644 root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.conf delete mode 100644 root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.debug delete mode 100644 root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.hotplug delete mode 100644 root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.init delete mode 100644 root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.sysctl delete mode 100644 root/package/qca/nss/qca-nss-drv-64/patches/0001-core-add-5.10-kernel-to-version-check.patch delete mode 100644 root/package/qca/nss/qca-nss-drv-64/patches/0002-nss-drv-replace-ioremap_nocache-with-ioremap.patch delete mode 100644 root/package/qca/nss/qca-nss-drv-64/patches/0003-DMA-Fix-NULL-pointer-exceptions.patch delete mode 100644 root/package/qca/nss/qca-nss-drv-64/patches/0005-nss-drv-add-support-for-kernel-5.15.patch delete mode 100644 root/package/qca/nss/qca-nss-drv-64/patches/0005-nss-drv-use-standard-skb_skip_tc_classify-instead-of.patch delete mode 100644 root/package/qca/nss/qca-nss-drv-64/patches/0999-treewide-hack-support-for-mismatched-firmware.patch delete mode 100644 root/package/qca/nss/qca-nss-drv/Makefile delete mode 100644 root/package/qca/nss/qca-nss-drv/files/nss-firmware/LICENSE.TXT delete mode 100644 root/package/qca/nss/qca-nss-drv/files/nss-firmware/NOTICE.TXT delete mode 100644 root/package/qca/nss/qca-nss-drv/files/nss-firmware/README.md delete mode 100644 root/package/qca/nss/qca-nss-drv/files/nss-firmware/qca-nss0-retail.bin delete mode 100644 root/package/qca/nss/qca-nss-drv/files/nss-firmware/qca-nss1-retail.bin delete mode 100644 root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.conf delete mode 100644 root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.debug delete mode 100644 root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.hotplug delete mode 100644 root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.init delete mode 100644 root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.sysctl delete mode 100644 root/package/qca/nss/qca-nss-drv/patches/100-kernel-5.4-support.patch delete mode 100644 root/package/qca/nss/qca-nss-drv/patches/101-nss-drv-Control-fab-scaling-from-package-Makefile.patch delete mode 100644 root/package/qca/nss/qca-nss-drv/patches/200-fix-NULL-pointer-exception.patch delete mode 100644 root/package/qca/nss/qca-nss-drv/patches/201-Fix-Kernel-Panic-dma-with-NULL-dev.patch delete mode 100644 root/package/qca/nss/qca-nss-drv/patches/400-Exported-set-nexthop-function.patch delete mode 100644 root/package/qca/nss/qca-nss-ecm-64/Makefile delete mode 100644 root/package/qca/nss/qca-nss-ecm-64/files/ecm_dump.sh delete mode 100644 root/package/qca/nss/qca-nss-ecm-64/files/on-demand-down delete mode 100644 root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.defaults delete mode 100644 root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.firewall delete mode 100644 root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.init delete mode 100644 root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.sysctl delete mode 100644 root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.uci delete mode 100644 root/package/qca/nss/qca-nss-ecm-64/patches/001-treewide-componentize-the-module-even-more.patch delete mode 100644 root/package/qca/nss/qca-nss-ecm-64/patches/002-kernel-5.10-support.patch delete mode 100644 root/package/qca/nss/qca-nss-ecm-64/patches/003-rework-nfct-notification.patch delete mode 100644 root/package/qca/nss/qca-nss-ecm-64/patches/004-More-compile-fixes.patch delete mode 100644 root/package/qca/nss/qca-nss-ecm-64/patches/005-resolve-high-load.patch delete mode 100644 root/package/qca/nss/qca-nss-ecm-64/patches/006-ecm_interface-switch-to-kernel_recvmsg-api.patch delete mode 100644 root/package/qca/nss/qca-nss-ecm-64/patches/007-treewide-rework-notifier-changes-for-5.15.patch delete mode 100644 root/package/qca/nss/qca-nss-ecm-64/patches/008-frontends-drop-use-of-static-be_liberal-and-no_windo.patch delete mode 100644 root/package/qca/nss/qca-nss-ecm-64/patches/009-ecm_tracker_datagram-drop-static-for-EXPORT_SYMBOL.patch delete mode 100644 root/package/qca/nss/qca-nss-ecm-64/patches/010-frontends-drop-udp_get_timeouts-and-use-standard-ups.patch delete mode 100644 root/package/qca/nss/qca-nss-ecm-64/patches/901-qca-nss-ecm-fix-a-memcpy-overflow-in-ecm_db.patch delete mode 100644 root/package/qca/nss/qca-nss-ecm/Makefile delete mode 100644 root/package/qca/nss/qca-nss-ecm/files/ecm_dump.sh delete mode 100644 root/package/qca/nss/qca-nss-ecm/files/on-demand-down delete mode 100644 root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.defaults delete mode 100644 root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.firewall delete mode 100644 root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.init delete mode 100644 root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.sysctl delete mode 100644 root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.uci delete mode 100644 root/package/qca/nss/qca-nss-ecm/patches/001-Drop_SFE_from_ecm.patch delete mode 100644 root/package/qca/nss/qca-nss-ecm/patches/100-kernel-5.4-support.patch delete mode 100644 root/package/qca/nss/qca-nss-ecm/patches/101-Fix_Kern_Panic_on_UDP_CONNTRACK.patch delete mode 100644 root/package/qca/nss/qca-nss-ecm/patches/200-resolve-high-load.patch delete mode 100644 root/package/qca/nss/qca-nss-ecm/patches/203-rework-nfct-notification.patch delete mode 100644 root/package/qca/nss/qca-nss-ecm/patches/400-Check-TCP_UDP-conntrack-state-earlier.patch delete mode 100644 root/package/qca/nss/qca-nss-ecm/patches/401-Fix-NSS-stats-request-roll-over-issue.patch delete mode 100644 root/package/qca/nss/qca-nss-ecm/patches/401-Fix-for-ref-leak-during-multicast.patch delete mode 100644 root/package/qca/nss/qca-nss-ecm/patches/401-Fix-neighbour-solicitation-send-function.patch delete mode 100644 root/package/qca/nss/qca-nss-ecm/patches/402-Reference-leak-during-multicast_PPPoE-bridge.patch delete mode 100644 root/package/qca/nss/qca-nss-ecm/patches/403-Access-global-accelerated-count-under-lock.patch delete mode 100644 root/package/qca/nss/qca-nss-ecm/patches/403-Fix-IPv6-neighbor-solicitation-request.patch delete mode 100644 root/package/qca/nss/qca-nss-ecm/patches/404-IPv6-solicitation-fix-with-zero-gateway-address.patch delete mode 100644 root/package/qca/nss/qca-nss-ecm/patches/405-Allow-egress-on-same-port-when-bridge-hairpin-is-enabled.patch delete mode 100644 root/package/qca/nss/qca-nss-gmac/Makefile delete mode 100644 root/package/qca/nss/qca-nss-gmac/patches/100-kernel-5.4-support.patch delete mode 100644 root/package/qca/nss/qca-nss-gmac/patches/101-nss-gmac-test-ptr.patch delete mode 100644 root/package/qca/nss/qca-nss-gmac/patches/200-work-around-interface-close-warning.patch delete mode 100644 root/package/qca/qca-mcs/Makefile delete mode 100644 root/package/qca/qca-rfs/Makefile delete mode 100644 root/package/qca/qca-rfs/files/qrfs.init delete mode 100644 root/package/qca/qca-rfs/patches/100-add-kernel-5.4-support.patch delete mode 100644 root/package/qca/qca-rfs/patches/200-rework-nfct-notification.patch delete mode 100644 root/package/qca/qca-ssdk-shell/Makefile delete mode 100644 root/package/qca/qca-ssdk/Makefile delete mode 100644 root/package/qca/qca-ssdk/files/qca-ssdk delete mode 100644 root/package/qca/qca-ssdk/patches/0001-SSDK-config-add-kernel-5.10-5.15.patch delete mode 100644 root/package/qca/qca-ssdk/patches/0002-SSDK-replace-ioremap_nocache-with-ioremap.patch delete mode 100644 root/package/qca/qca-ssdk/patches/0004-platform-use-of_mdio_find_bus-to-get-MDIO-bus.patch delete mode 100644 root/package/qca/qca-ssdk/patches/0005-add-kernel-5.4-support.patch delete mode 100644 root/package/qca/qca-ssdk/patches/0006-fix-mdio-probe-on-ipq806x.patch delete mode 100644 root/package/qca/qca-ssdk/patches/0007-SSDK-dts-fix-of_get_mac_address.patch delete mode 100644 root/package/qca/qca-ssdk/patches/0008-add-aquantia-phy-id-113CB0.patch delete mode 100644 root/package/qca/qca-ssdk/patches/0009-qca8081-convert-to-5.11-IRQ-model.patch delete mode 100644 root/package/qca/qca-ssdk/patches/0012-include-fix-compilation-error-for-parse_uci_option.patch diff --git a/root/package/qca/firmware/nss-firmware/Makefile b/root/package/qca/firmware/nss-firmware/Makefile deleted file mode 100644 index 6ea4a57c..00000000 --- a/root/package/qca/firmware/nss-firmware/Makefile +++ /dev/null @@ -1,70 +0,0 @@ -# -# Copyright (C) 2021 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=nss-firmware -PKG_SOURCE_DATE:=2021-03-12 -PKG_SOURCE_VERSION:=73f378d6be21a9c20a69b77000dbb54a537006a9 -PKG_MIRROR_HASH:=0c21afe29002754edf2983bc9e8543dddd722e75bd12e961e300e99a310d1f62 -PKG_RELEASE:=$(AUTORELEASE) - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://github.com/quic/qca-sdk-nss-fw.git - -PKG_LICENSE_FILES:=LICENSE.md - -PKG_MAINTAINER:=Robert Marko - -include $(INCLUDE_DIR)/package.mk - -VERSION_PATH=$(PKG_BUILD_DIR)/QCA_Networking_2020.SPF_11.3/CS - -define Package/nss-firmware-default - SECTION:=firmware - CATEGORY:=Firmware - URL:=$(PKG_SOURCE_URL) - DEPENDS:=@(TARGET_ipq807x||TARGET_ipq60xx) -endef - -define Package/nss-firmware-ipq6018 -$(Package/nss-firmware-default) - TITLE:=NSS firmware for IPQ6018 devices - NSS_ARCHIVE:=$(VERSION_PATH)/IPQ6018.ATH.11.3/BIN-NSS.CP.11.3-9-R.tar.bz2 -endef - -define Package/nss-firmware-ipq8074 -$(Package/nss-firmware-default) - TITLE:=NSS firmware for IPQ8074 devices - NSS_ARCHIVE:=$(VERSION_PATH)/IPQ8074.ATH.11.3/BIN-NSS.HK.11.3-9-R.tar.bz2 -endef - -define Build/Compile - -endef - -define Package/nss-firmware-ipq6018/install - $(TAR) -C $(PKG_BUILD_DIR) -xf $(NSS_ARCHIVE) - $(INSTALL_DIR) $(1)/lib/firmware/ - $(INSTALL_DATA) \ - $(PKG_BUILD_DIR)/BIN-NSS.CP.11.3-9-R/retail_router0.bin \ - $(1)/lib/firmware/qca-nss0-retail.bin -endef - -define Package/nss-firmware-ipq8074/install - $(TAR) -C $(PKG_BUILD_DIR) -xf $(NSS_ARCHIVE) - $(INSTALL_DIR) $(1)/lib/firmware/ - $(INSTALL_DATA) \ - $(PKG_BUILD_DIR)/BIN-NSS.HK.11.3-9-R/retail_router0.bin \ - $(1)/lib/firmware/qca-nss0-retail.bin - $(INSTALL_DATA) \ - $(PKG_BUILD_DIR)/BIN-NSS.HK.11.3-9-R/retail_router1.bin \ - $(1)/lib/firmware/qca-nss1-retail.bin -endef - -$(eval $(call BuildPackage,nss-firmware-ipq6018)) -$(eval $(call BuildPackage,nss-firmware-ipq8074)) diff --git a/root/package/qca/nss/nss-ifb/Makefile b/root/package/qca/nss/nss-ifb/Makefile deleted file mode 100644 index 6b7f0b48..00000000 --- a/root/package/qca/nss/nss-ifb/Makefile +++ /dev/null @@ -1,49 +0,0 @@ -# -# Copyright (C) 2008-2012 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk -include $(INCLUDE_DIR)/kernel.mk - -PKG_NAME:=nss-ifb -PKG_RELEASE:=1 - -include $(INCLUDE_DIR)/package.mk - -define KernelPackage/nss-ifb - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Devices - TITLE:=NSS IFB Interface - DEPENDS:=+kmod-qca-nss-drv @LINUX_5_4 - FILES:=$(PKG_BUILD_DIR)/nss-ifb.ko - KCONFIG:= -endef - -define KernelPackage/nss-ifb/description - Kernel module to register a NSS aware IFB interface. -endef - -EXTRA_KCONFIG:= \ - CONFIG_NET_CLS=y - -EXTRA_CFLAGS:= \ - -I$(STAGING_DIR)/usr/include/qca-nss-drv - -MAKE_OPTS:= \ - $(KERNEL_MAKE_FLAGS) \ - M="$(PKG_BUILD_DIR)" \ - EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ - $(EXTRA_KCONFIG) - -define Build/Compile - $(MAKE) -C "$(LINUX_DIR)" \ - $(MAKE_OPTS) \ - modules -endef - -$(eval $(call KernelPackage,nss-ifb)) - diff --git a/root/package/qca/nss/nss-ifb/README.md b/root/package/qca/nss/nss-ifb/README.md deleted file mode 100644 index a0af7a5e..00000000 --- a/root/package/qca/nss/nss-ifb/README.md +++ /dev/null @@ -1,45 +0,0 @@ -NSS Physical Interface Ingress Driver -===================================== - -This driver redirect NSS physical interface (namely GMACs) ingress traffic to itself -and sends it back to the Linux network stack (as the source GMACs packets) as it's -egress traffic. - -This allows the NSS QDISC drivers to manage the egress traffic of this driver's -NSS virtual interface. - -This driver will create a single network interface named 'nssifb'. The default -source interface is defined as 'eth0'. It can be changed using the following module -parameter path: - -/sys/module/nss-ifb/parameter/nss_src_dev - -To change the source NSS physical interface to 'eth1', use the following command: - -printf eth1 > /sys/module/nss-ifb/parameter/nss_src_dev - -You need to change the source interface first before bringing up the 'nssifb' -interface. Changing it after the interface is up will have no effect. You need -to bring down the interface and bring it back up to have the changes take effect. - -CPU load imposed on the Krait CPUs appears negligible with this driver intercepting -the physical interface's ingress traffic. Full line speed of the GMAC interface -could still be achieved. - -The commands below shows an example to shape ingress traffic to 500 Mbps and egress -to 200 Mbps for the 'eth0' interface. - -# Load the module if it's not loaded -modprobe nss-ifb - -# Bring up the nssifb interface to active ingress redirect -ip link set up nssifb - -# Shape ingress traffic to 500 Mbit with chained NSSFQ_CODEL -tc qdisc add dev nssifb root handle 1: nsstbl rate 500Mbit burst 1Mb -tc qdisc add dev nssifb parent 1: handle 10: nssfq_codel limit 10240 flows 1024 quantum 1514 target 5ms interval 100ms set_default - -# Shape egress traffic to 200 Mbit with chained NSSFQ_CODEL -tc qdisc add dev eth0 root handle 1: nsstbl rate 200Mbit burst 1Mb -tc qdisc add dev eth0 parent 1: handle 10: nssfq_codel limit 10240 flows 1024 quantum 1514 target 5ms interval 100ms set_default - diff --git a/root/package/qca/nss/nss-ifb/src/Makefile b/root/package/qca/nss/nss-ifb/src/Makefile deleted file mode 100644 index 332b9b4e..00000000 --- a/root/package/qca/nss/nss-ifb/src/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-m += nss-ifb.o - -nss-ifb-objs := nss_ifb.o diff --git a/root/package/qca/nss/nss-ifb/src/nss_ifb.c b/root/package/qca/nss/nss-ifb/src/nss_ifb.c deleted file mode 100644 index 18c017fe..00000000 --- a/root/package/qca/nss/nss-ifb/src/nss_ifb.c +++ /dev/null @@ -1,304 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -/* - * This driver is adapted from the Linux /drivers/net/ifb.c file. - * - * Redirect QCA NSS physical interface ingress traffic to this driver's - * virtual interface. This will allow ingress traffic shaping using the - * QCA NSS shaper. - */ - -#include - -#define TX_Q_LIMIT 32 - -struct nss_ifb_dev_private { - struct nss_virt_if_handle *nssctx; - struct net_device *nss_src_dev; - uint32_t nss_src_if_num; - char nss_src_dev_name[32]; -}; - -char nss_dev_name_array[32] = "eth0"; -char *nss_dev_name = nss_dev_name_array; -module_param(nss_dev_name, charp, 0644); -MODULE_PARM_DESC(nss_dev_name, "NSS physical interface source device name"); - -/* - * Virtual interface egress packet callback. - * - * We send it back to the Linux network stack. - */ -static void nss_ifb_data_cb(struct net_device *netdev, struct sk_buff *skb, struct napi_struct *napi) -{ - struct nss_ifb_dev_private *dp = netdev_priv(netdev); - - skb->protocol = eth_type_trans(skb, dp->nss_src_dev); - skb->ip_summed = CHECKSUM_UNNECESSARY; - - napi_gro_receive(napi, skb); -} - -/* - * Virtual interface ingress packet callback. - * - * We just send it back to the NSS firmware to let the shaper work on it. - */ -static void nss_ifb_xmit_cb(struct net_device *netdev, struct sk_buff *skb) -{ - struct nss_ifb_dev_private *dp = netdev_priv(netdev); - int ret; - - ret = nss_virt_if_tx_buf(dp->nssctx, skb); - if (unlikely(ret)) { - pr_warn("Failed [%d] to send skb [len: %d, protocol: 0x%X] to NSS!\n", - ret, skb->len, ntohs(skb->protocol)); - } -} - -static void nss_ifb_stats64(struct net_device *dev, - struct rtnl_link_stats64 *stats) -{ - -} - -static int nss_ifb_dev_init(struct net_device *dev) -{ - struct nss_ifb_dev_private *dp = netdev_priv(dev); - - dp->nssctx = nss_virt_if_create_sync_nexthop(dev, NSS_ETH_RX_INTERFACE, NSS_ETH_RX_INTERFACE); - if (!dp->nssctx) { - dp->nssctx = NULL; - pr_warn("Could not create a NSS virtual interface for dev [%s]\n", - dev->name); - - return -ENODEV; - } - pr_info("Created a NSS virtual interface for dev [%s]\n", dev->name); - - nss_virt_if_register(dp->nssctx, nss_ifb_data_cb, dev); - pr_info("NSS IFB data callback registered\n"); - - nss_virt_if_xmit_callback_register(dp->nssctx, nss_ifb_xmit_cb); - pr_info("NSS IFB transmit callback registered\n"); - - return 0; -} - -static void nss_ifb_dev_uninit(struct net_device *dev) -{ - struct nss_ifb_dev_private *dp = netdev_priv(dev); - int ret; - - nss_virt_if_xmit_callback_unregister(dp->nssctx); - pr_info("NSS IFB transmit callback unregistered\n"); - - ret = nss_virt_if_destroy_sync(dp->nssctx); - if (ret == NSS_TX_SUCCESS) { - pr_info("NSS virtual interface destroyed for dev [%s]\n", dev->name); - } - else { - pr_warn("Unable to destroy NSS virtual interface for dev [%s], error[%d]\n", - dev->name, ret); - } - dp->nssctx = NULL; -} - -static netdev_tx_t nss_ifb_xmit(struct sk_buff *skb, struct net_device *dev) -{ - return NETDEV_TX_OK; -} - -static int nss_ifb_close(struct net_device *dev) -{ - struct nss_ifb_dev_private *dp = netdev_priv(dev); - struct nss_ctx_instance *nss_ctx; - struct net_device *src_dev; - uint32_t src_if_num; - int ret; - - nss_ctx = dp->nssctx->nss_ctx; - src_dev = dp->nss_src_dev; - src_if_num = dp->nss_src_if_num; - - ret = nss_phys_if_set_nexthop(nss_ctx, src_if_num, NSS_ETH_RX_INTERFACE); - if (ret != NSS_TX_SUCCESS) { - pr_warn("%p: Failed to reset next hop for net device [%s].\n", - nss_ctx, src_dev->name); - } - else { - pr_info("%p: Reset nexthop successful for net device [%s].\n", - nss_ctx, src_dev->name); - } - - dev_put(src_dev); - dp->nss_src_dev = NULL; - dp->nss_src_if_num = -1; - - return 0; -} - -static int nss_ifb_open(struct net_device *dev) -{ - struct nss_ifb_dev_private *dp = netdev_priv(dev); - struct net_device *src_dev; - uint32_t src_if_num; - uint32_t nh_if_num; - nss_tx_status_t nss_tx_status; - struct nss_ctx_instance *nss_ctx; - - nss_ctx = dp->nssctx->nss_ctx; - nh_if_num = dp->nssctx->if_num_n2h; - - strcpy(dp->nss_src_dev_name, nss_dev_name); - - src_dev = dev_get_by_name(&init_net, dp->nss_src_dev_name); - if (!src_dev) { - pr_warn("%p: Cannot find the net device [%s]\n", - nss_ctx, dp->nss_src_dev_name); - - return -ENODEV; - } - pr_info("%p: Found net device [%s]\n", nss_ctx, dp->nss_src_dev_name); - - src_if_num = nss_cmn_get_interface_number_by_dev(src_dev); - if (src_if_num < 0) { - pr_warn("%p: Invalid interface number:%d\n", nss_ctx, src_if_num); - dev_put(src_dev); - - return -ENODEV; - } - pr_info("%p: Net device [%s] has NSS intf_num [%d]\n", - nss_ctx, dp->nss_src_dev_name, src_if_num); - - nss_tx_status = nss_phys_if_set_nexthop(nss_ctx, src_if_num, nh_if_num); - if (nss_tx_status != NSS_TX_SUCCESS) { - pr_warn("%p: Sending message failed, cannot change nexthop for [%s]\n", - nss_ctx, dp->nss_src_dev_name); - } - else { - pr_info("Nexthop successfully set for [%s] to [%s]\n", - dp->nss_src_dev_name, dev->name); - } - - dp->nss_src_dev = src_dev; - dp->nss_src_if_num = src_if_num; - - return 0; -} - -static const struct net_device_ops nss_ifb_netdev_ops = { - .ndo_open = nss_ifb_open, - .ndo_stop = nss_ifb_close, - .ndo_get_stats64 = nss_ifb_stats64, - .ndo_start_xmit = nss_ifb_xmit, - .ndo_validate_addr = eth_validate_addr, - .ndo_init = nss_ifb_dev_init, - .ndo_uninit = nss_ifb_dev_uninit, -}; - -#define IFB_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | NETIF_F_FRAGLIST | \ - NETIF_F_TSO_ECN | NETIF_F_TSO | NETIF_F_TSO6 | \ - NETIF_F_GSO_ENCAP_ALL | \ - NETIF_F_HIGHDMA | NETIF_F_HW_VLAN_CTAG_TX | \ - NETIF_F_HW_VLAN_STAG_TX) - -static void nss_ifb_dev_free(struct net_device *dev) -{ - -} - -static void nss_ifb_setup(struct net_device *dev) -{ - /* Initialize the device structure. */ - dev->netdev_ops = &nss_ifb_netdev_ops; - - /* Fill in device structure with ethernet-generic values. */ - ether_setup(dev); - dev->tx_queue_len = TX_Q_LIMIT; - - dev->features |= IFB_FEATURES; - dev->hw_features |= dev->features; - dev->hw_enc_features |= dev->features; - dev->vlan_features |= IFB_FEATURES & ~(NETIF_F_HW_VLAN_CTAG_TX | - NETIF_F_HW_VLAN_STAG_TX); - - dev->flags |= IFF_NOARP; - dev->flags &= ~IFF_MULTICAST; - dev->priv_flags &= ~IFF_TX_SKB_SHARING; - netif_keep_dst(dev); - eth_hw_addr_random(dev); - dev->needs_free_netdev = true; - dev->priv_destructor = nss_ifb_dev_free; - - dev->min_mtu = 0; - dev->max_mtu = 0; -} - -static int nss_ifb_validate(struct nlattr *tb[], struct nlattr *data[], - struct netlink_ext_ack *extack) -{ - if (tb[IFLA_ADDRESS]) { - if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) - return -EINVAL; - if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) - return -EADDRNOTAVAIL; - } - return 0; -} - -static struct rtnl_link_ops nss_ifb_link_ops __read_mostly = { - .kind = "nss_ifb", - .priv_size = sizeof(struct nss_ifb_dev_private), - .setup = nss_ifb_setup, - .validate = nss_ifb_validate, -}; - -static int __init nss_ifb_init_module(void) -{ - struct net_device *dev; - int err; - - down_write(&pernet_ops_rwsem); - rtnl_lock(); - err = __rtnl_link_register(&nss_ifb_link_ops); - if (err < 0) - goto out; - - dev = alloc_netdev(sizeof(struct nss_ifb_dev_private), "nssifb", - NET_NAME_UNKNOWN, nss_ifb_setup); - - if (dev) { - dev->rtnl_link_ops = &nss_ifb_link_ops; - err = register_netdevice(dev); - } - else { - err = -ENOMEM; - } - - if (err) - __rtnl_link_unregister(&nss_ifb_link_ops); - -out: - rtnl_unlock(); - up_write(&pernet_ops_rwsem); - - if (!err) - pr_info("NSS IFB module loaded.\n"); - else - pr_warn("Failed to load NSS IFB module.\n"); - - return err; -} - -static void __exit nss_ifb_cleanup_module(void) -{ - rtnl_link_unregister(&nss_ifb_link_ops); - - pr_info("NSS IFB module unloaded.\n"); -} - -module_init(nss_ifb_init_module); -module_exit(nss_ifb_cleanup_module); -MODULE_LICENSE("GPL"); -MODULE_ALIAS_RTNL_LINK("nss_ifb"); diff --git a/root/package/qca/nss/qca-nss-cfi/Makefile b/root/package/qca/nss/qca-nss-cfi/Makefile deleted file mode 100644 index 570b45cf..00000000 --- a/root/package/qca/nss/qca-nss-cfi/Makefile +++ /dev/null @@ -1,99 +0,0 @@ -include $(TOPDIR)/rules.mk -include $(INCLUDE_DIR)/kernel.mk - -PKG_NAME:=qca-nss-cfi -PKG_RELEASE:=2 - -PKG_SOURCE_URL:=https://source.codeaurora.org/quic/qsdk/oss/lklm/nss-cfi -PKG_SOURCE_PROTO:=git -PKG_SOURCE_VERSION:=8035a8ddefdcc8a2f06c96b2a82618ca6ce6406d -PKG_MIRROR_HASH:=23316395d1346994d069eb41ef73a5505853687f8beab14f83545b3a05e52429 - -include $(INCLUDE_DIR)/package.mk - -ifeq ($(CONFIG_TARGET_ipq),y) -subtarget:=$(SUBTARGET) -else -subtarget:=$(CONFIG_TARGET_BOARD) -endif - -# v1.0 is for Akronite -# v2.0 is for Hawkeye/Cypress/Maple -ifneq (, $(findstring $(subtarget), "ipq807x" "ipq807x_64" "ipq60xx" "ipq60xx_64")) - CFI_OCF_DIR:=ocf/v2.0 - CFI_CRYPTOAPI_DIR:=cryptoapi/v2.0 -else - CFI_CRYPTOAPI_DIR:=cryptoapi/v1.1 - CFI_OCF_DIR:=ocf/v1.0 - CFI_IPSEC_DIR:=ipsec/v1.0 -endif - -define KernelPackage/qca-nss-cfi-cryptoapi - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Devices - DEPENDS:=@TARGET_ipq806x||TARGET_ipq_ipq806x||TARGET_ipq_ipq807x||TARGET_ipq_ipq807x_64||TARGET_ipq807x||TARGET_ipq807x_64||TARGET_ipq_ipq60xx||TARGET_ipq_ipq60xx_64 \ - +kmod-qca-nss-crypto +kmod-crypto-authenc @LINUX_5_4 - TITLE:=Kernel driver for NSS cfi - FILES:=$(PKG_BUILD_DIR)/$(CFI_CRYPTOAPI_DIR)/qca-nss-cfi-cryptoapi.ko - AUTOLOAD:=$(call AutoLoad,59,qca-nss-cfi-cryptoapi) -endef - -# OCF should be dropped -# define KernelPackage/qca-nss-cfi-ocf -# SECTION:=kernel -# CATEGORY:=Kernel modules -# SUBMENU:=Network Devices -# DEPENDS:=@TARGET_ipq806x||TARGET_ipq_ipq806x||TARGET_ipq_ipq807x||TARGET_ipq_ipq807x_64||TARGET_ipq807x||TARGET_ipq807x_64||TARGET_ipq_ipq60xx||TARGET_ipq_ipq60xx_64 \ -# +kmod-qca-nss-crypto +PACKAGE_kmod-crypto-ocf:kmod-crypto-ocf @!LINUX_3_18 -# TITLE:=Kernel driver for NSS cfi -# FILES:=$(PKG_BUILD_DIR)/$(CFI_OCF_DIR)/qca-nss-cfi-ocf.ko - -# ifdef CFI_IPSEC_DIR -# FILES+=$(PKG_BUILD_DIR)/$(CFI_IPSEC_DIR)/qca-nss-ipsec.ko -# AUTOLOAD:=$(call AutoLoad,61,qca-nss-cfi-ocf qca-nss-ipsec) -# else -# AUTOLOAD:=$(call AutoLoad,61,qca-nss-cfi-ocf) -# endif -# endef - -define Build/InstallDev/qca-nss-cfi - $(INSTALL_DIR) $(1)/usr/include/qca-nss-cfi - $(CP) $(PKG_BUILD_DIR)/$(CFI_CRYPTOAPI_DIR)/../exports/* $(1)/usr/include/qca-nss-cfi - $(CP) $(PKG_BUILD_DIR)/include/* $(1)/usr/include/qca-nss-cfi -endef - -define Build/InstallDev - $(call Build/InstallDev/qca-nss-cfi,$(1)) -endef - -define KernelPackage/qca-nss-cfi/Description -This package contains a NSS cfi driver for QCA chipset -endef - -EXTRA_CFLAGS+= \ - -DCONFIG_NSS_DEBUG_LEVEL=4 \ - -I$(LINUX_DIR)/crypto/ocf \ - -I$(STAGING_DIR)/usr/include/qca-nss-crypto \ - -I$(STAGING_DIR)/usr/include/crypto \ - -I$(STAGING_DIR)/usr/include/qca-nss-drv - -ifneq (, $(findstring $(subtarget), "ipq807x" "ipq807x_64" "ipq60xx" "ipq60xx_64")) -EXTRA_CFLAGS+= -I$(STAGING_DIR)/usr/include/qca-nss-clients -endif - -define Build/Compile - $(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \ - $(KERNEL_MAKE_FLAGS) \ - $(PKG_MAKE_FLAGS) \ - M="$(PKG_BUILD_DIR)" \ - EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ - CFI_CRYPTOAPI_DIR=$(CFI_CRYPTOAPI_DIR) \ - CFI_OCF_DIR=$(CFI_OCF_DIR) \ - CFI_IPSEC_DIR=$(CFI_IPSEC_DIR) \ - SoC=$(subtarget) \ - modules -endef - -$(eval $(call KernelPackage,qca-nss-cfi-cryptoapi)) -#$(eval $(call KernelPackage,qca-nss-cfi-ocf)) diff --git a/root/package/qca/nss/qca-nss-cfi/patches/0001-compile-only-cryptoapi.patch b/root/package/qca/nss/qca-nss-cfi/patches/0001-compile-only-cryptoapi.patch deleted file mode 100644 index 00968f5f..00000000 --- a/root/package/qca/nss/qca-nss-cfi/patches/0001-compile-only-cryptoapi.patch +++ /dev/null @@ -1,30 +0,0 @@ -From a8a573c5ce83bdddca9a60c62161638a5fd906d4 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Sat, 13 Jun 2020 12:57:14 +0200 -Subject: [PATCH 1/3] compile only cryptoapi - ---- - Makefile | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/Makefile b/Makefile -index c42adca..36a9d3f 100644 ---- a/Makefile -+++ b/Makefile -@@ -4,9 +4,9 @@ - - export BUILD_ID = \"Build Id: $(shell date +'%m/%d/%y, %H:%M:%S')\" - --obj-m += $(CFI_OCF_DIR)/ -+# obj-m += $(CFI_OCF_DIR)/ - obj-m += $(CFI_CRYPTOAPI_DIR)/ - --ifeq ($(SoC),$(filter $(SoC),ipq806x)) --obj-m += $(CFI_IPSEC_DIR)/ --endif -+# ifeq ($(SoC),$(filter $(SoC),ipq806x)) -+# obj-m += $(CFI_IPSEC_DIR)/ -+# endif --- -2.27.0.rc0 - diff --git a/root/package/qca/nss/qca-nss-cfi/patches/0002-wip-support-5.4.patch b/root/package/qca/nss/qca-nss-cfi/patches/0002-wip-support-5.4.patch deleted file mode 100644 index d68fc939..00000000 --- a/root/package/qca/nss/qca-nss-cfi/patches/0002-wip-support-5.4.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 202f57bae49947a04301ac8ac9bdc00f28f09355 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Sat, 13 Jun 2020 12:58:26 +0200 -Subject: [PATCH 2/3] wip: support 5.4 - ---- - cryptoapi/v1.1/nss_cryptoapi.c | 1 - - cryptoapi/v1.1/nss_cryptoapi_ablk.c | 12 ++++++------ - cryptoapi/v1.1/nss_cryptoapi_aead.c | 2 +- - 3 files changed, 7 insertions(+), 8 deletions(-) - -diff --git a/cryptoapi/v1.1/nss_cryptoapi.c b/cryptoapi/v1.1/nss_cryptoapi.c -index d1a7313..a10590e 100644 ---- a/cryptoapi/v1.1/nss_cryptoapi.c -+++ b/cryptoapi/v1.1/nss_cryptoapi.c -@@ -231,7 +231,6 @@ static struct crypto_alg cryptoapi_ablkcipher_algs[] = { - .cra_u = { - .ablkcipher = { - .ivsize = CTR_RFC3686_IV_SIZE, -- .geniv = "seqiv", - .min_keysize = AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, - .max_keysize = AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, - .setkey = nss_cryptoapi_ablk_aes_setkey, -diff --git a/cryptoapi/v1.1/nss_cryptoapi_ablk.c b/cryptoapi/v1.1/nss_cryptoapi_ablk.c -index 223591c..9b6c65e 100644 ---- a/cryptoapi/v1.1/nss_cryptoapi_ablk.c -+++ b/cryptoapi/v1.1/nss_cryptoapi_ablk.c -@@ -108,7 +108,7 @@ EXPORT_SYMBOL(nss_cryptoapi_skcipher_ctx2session); - int nss_cryptoapi_ablkcipher_init(struct crypto_tfm *tfm) - { - struct nss_cryptoapi_ctx *ctx = crypto_tfm_ctx(tfm); -- struct crypto_ablkcipher *sw_tfm; -+ struct crypto_cipher *sw_tfm; - - nss_cfi_assert(ctx); - -@@ -122,20 +122,20 @@ int nss_cryptoapi_ablkcipher_init(struct crypto_tfm *tfm) - - nss_cryptoapi_set_magic(ctx); - -- if (!(crypto_tfm_alg_flags(tfm) & CRYPTO_ALG_NEED_FALLBACK)) -+ if (!(crypto_tfm_alg_type(tfm) & CRYPTO_ALG_NEED_FALLBACK)) - return 0; - - /* Alloc fallback transform for future use */ -- sw_tfm = crypto_alloc_ablkcipher(crypto_tfm_alg_name(tfm), 0, CRYPTO_ALG_ASYNC | -- CRYPTO_ALG_NEED_FALLBACK); -+ sw_tfm = crypto_alloc_cipher(crypto_tfm_alg_name(tfm), 0, CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_NEED_FALLBACK); - if (IS_ERR(sw_tfm)) { - nss_cfi_err("unable to alloc software crypto for %s\n", crypto_tfm_alg_name(tfm)); - return -EINVAL; - } - - /* set this tfm reqsize same to fallback tfm */ -- tfm->crt_ablkcipher.reqsize = crypto_ablkcipher_reqsize(sw_tfm); -- ctx->sw_tfm = crypto_ablkcipher_tfm(sw_tfm); -+ tfm->crt_ablkcipher.reqsize = sizeof(struct nss_cryptoapi_ctx); -+ ctx->sw_tfm = crypto_cipher_tfm(sw_tfm); - - return 0; - } -diff --git a/cryptoapi/v1.1/nss_cryptoapi_aead.c b/cryptoapi/v1.1/nss_cryptoapi_aead.c -index 527936b..53e4bed 100644 ---- a/cryptoapi/v1.1/nss_cryptoapi_aead.c -+++ b/cryptoapi/v1.1/nss_cryptoapi_aead.c -@@ -103,7 +103,7 @@ int nss_cryptoapi_aead_init(struct crypto_aead *aead) - - nss_cryptoapi_set_magic(ctx); - -- if (!(crypto_tfm_alg_flags(tfm) & CRYPTO_ALG_NEED_FALLBACK)) -+ if (!(crypto_tfm_alg_type(tfm) & CRYPTO_ALG_NEED_FALLBACK)) - return 0; - - /* Alloc fallback transform for future use */ --- -2.27.0.rc0 - diff --git a/root/package/qca/nss/qca-nss-cfi/patches/0003-Convert-ablkcipher-to-skcipher.patch b/root/package/qca/nss/qca-nss-cfi/patches/0003-Convert-ablkcipher-to-skcipher.patch deleted file mode 100644 index b4520a3d..00000000 --- a/root/package/qca/nss/qca-nss-cfi/patches/0003-Convert-ablkcipher-to-skcipher.patch +++ /dev/null @@ -1,707 +0,0 @@ -From e3a53a6d11b2c1770545a2820a58c117799bcb70 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Tue, 16 Jun 2020 18:12:34 +0200 -Subject: [PATCH 3/3] Convert ablkcipher to skcipher - ---- - cryptoapi/v1.1/nss_cryptoapi.c | 149 +++++++++++-------------- - cryptoapi/v1.1/nss_cryptoapi_ablk.c | 136 +++++++++++----------- - cryptoapi/v1.1/nss_cryptoapi_debugfs.c | 1 + - cryptoapi/v1.1/nss_cryptoapi_private.h | 16 +-- - 4 files changed, 145 insertions(+), 157 deletions(-) - -diff --git a/cryptoapi/v1.1/nss_cryptoapi.c b/cryptoapi/v1.1/nss_cryptoapi.c -index a10590e..3a835dc 100644 ---- a/cryptoapi/v1.1/nss_cryptoapi.c -+++ b/cryptoapi/v1.1/nss_cryptoapi.c -@@ -66,7 +66,7 @@ struct aead_alg cryptoapi_aead_algs[] = { - .cra_name = "echainiv(authenc(hmac(sha1),cbc(aes)))", - .cra_driver_name = "nss-hmac-sha1-cbc-aes", - .cra_priority = 10000, -- .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_NEED_FALLBACK, -+ .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_KERN_DRIVER_ONLY, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct nss_cryptoapi_ctx), - .cra_alignmask = 0, -@@ -87,7 +87,7 @@ struct aead_alg cryptoapi_aead_algs[] = { - .cra_name = "seqiv(authenc(hmac(sha1),rfc3686(ctr(aes))))", - .cra_driver_name = "nss-hmac-sha1-rfc3686-ctr-aes", - .cra_priority = 10000, -- .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_NEED_FALLBACK, -+ .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_KERN_DRIVER_ONLY, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct nss_cryptoapi_ctx), - .cra_alignmask = 0, -@@ -108,7 +108,7 @@ struct aead_alg cryptoapi_aead_algs[] = { - .cra_name = "echainiv(authenc(hmac(sha1),cbc(des3_ede)))", - .cra_driver_name = "nss-hmac-sha1-cbc-3des", - .cra_priority = 300, -- .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NOSUPP_SG, -+ .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_KERN_DRIVER_ONLY, - .cra_blocksize = DES3_EDE_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct nss_cryptoapi_ctx), - .cra_alignmask = 0, -@@ -129,7 +129,7 @@ struct aead_alg cryptoapi_aead_algs[] = { - .cra_name = "echainiv(authenc(hmac(sha256),cbc(aes)))", - .cra_driver_name = "nss-hmac-sha256-cbc-aes", - .cra_priority = 10000, -- .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_NEED_FALLBACK, -+ .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_KERN_DRIVER_ONLY, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct nss_cryptoapi_ctx), - .cra_alignmask = 0, -@@ -150,7 +150,7 @@ struct aead_alg cryptoapi_aead_algs[] = { - .cra_name = "seqiv(authenc(hmac(sha256),rfc3686(ctr(aes))))", - .cra_driver_name = "nss-hmac-sha256-rfc3686-ctr-aes", - .cra_priority = 10000, -- .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_NEED_FALLBACK, -+ .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_KERN_DRIVER_ONLY, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct nss_cryptoapi_ctx), - .cra_alignmask = 0, -@@ -171,7 +171,7 @@ struct aead_alg cryptoapi_aead_algs[] = { - .cra_name = "echainiv(authenc(hmac(sha256),cbc(des3_ede)))", - .cra_driver_name = "nss-hmac-sha256-cbc-3des", - .cra_priority = 300, -- .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NOSUPP_SG, -+ .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_KERN_DRIVER_ONLY, - .cra_blocksize = DES3_EDE_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct nss_cryptoapi_ctx), - .cra_alignmask = 0, -@@ -192,75 +192,66 @@ struct aead_alg cryptoapi_aead_algs[] = { - /* - * ABLK cipher algorithms - */ --static struct crypto_alg cryptoapi_ablkcipher_algs[] = { -+static struct skcipher_alg cryptoapi_skcipher_algs[] = { - { -- .cra_name = "cbc(aes)", -- .cra_driver_name = "nss-cbc-aes", -- .cra_priority = 10000, -- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, -- .cra_blocksize = AES_BLOCK_SIZE, -- .cra_ctxsize = sizeof(struct nss_cryptoapi_ctx), -- .cra_alignmask = 0, -- .cra_type = &crypto_ablkcipher_type, -- .cra_module = THIS_MODULE, -- .cra_init = nss_cryptoapi_ablkcipher_init, -- .cra_exit = nss_cryptoapi_ablkcipher_exit, -- .cra_u = { -- .ablkcipher = { -- .ivsize = AES_BLOCK_SIZE, -- .min_keysize = AES_MIN_KEY_SIZE, -- .max_keysize = AES_MAX_KEY_SIZE, -- .setkey = nss_cryptoapi_ablk_aes_setkey, -- .encrypt = nss_cryptoapi_ablk_aes_encrypt, -- .decrypt = nss_cryptoapi_ablk_aes_decrypt, -- }, -+ .base = { -+ .cra_name = "cbc(aes)", -+ .cra_driver_name = "nss-cbc-aes", -+ .cra_priority = 10000, -+ .cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = AES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct nss_cryptoapi_ctx), -+ .cra_alignmask = 0, -+ .cra_module = THIS_MODULE, - }, -+ .init = nss_cryptoapi_skcipher_init, -+ .exit = nss_cryptoapi_skcipher_exit, -+ .ivsize = AES_BLOCK_SIZE, -+ .min_keysize = AES_MIN_KEY_SIZE, -+ .max_keysize = AES_MAX_KEY_SIZE, -+ .setkey = nss_cryptoapi_ablk_aes_setkey, -+ .encrypt = nss_cryptoapi_ablk_aes_encrypt, -+ .decrypt = nss_cryptoapi_ablk_aes_decrypt, - }, - { -- .cra_name = "rfc3686(ctr(aes))", -- .cra_driver_name = "nss-rfc3686-ctr-aes", -- .cra_priority = 30000, -- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, -- .cra_blocksize = AES_BLOCK_SIZE, -- .cra_ctxsize = sizeof(struct nss_cryptoapi_ctx), -- .cra_alignmask = 0, -- .cra_type = &crypto_ablkcipher_type, -- .cra_module = THIS_MODULE, -- .cra_init = nss_cryptoapi_ablkcipher_init, -- .cra_exit = nss_cryptoapi_ablkcipher_exit, -- .cra_u = { -- .ablkcipher = { -- .ivsize = CTR_RFC3686_IV_SIZE, -- .min_keysize = AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, -- .max_keysize = AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, -- .setkey = nss_cryptoapi_ablk_aes_setkey, -- .encrypt = nss_cryptoapi_ablk_aes_encrypt, -- .decrypt = nss_cryptoapi_ablk_aes_decrypt, -- }, -+ .base = { -+ .cra_name = "rfc3686(ctr(aes))", -+ .cra_driver_name = "nss-rfc3686-ctr-aes", -+ .cra_priority = 30000, -+ .cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = AES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct nss_cryptoapi_ctx), -+ .cra_alignmask = 0, -+ .cra_module = THIS_MODULE, - }, -+ .init = nss_cryptoapi_skcipher_init, -+ .exit = nss_cryptoapi_skcipher_exit, -+ .ivsize = CTR_RFC3686_IV_SIZE, -+ .min_keysize = AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, -+ .max_keysize = AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, -+ .setkey = nss_cryptoapi_ablk_aes_setkey, -+ .encrypt = nss_cryptoapi_ablk_aes_encrypt, -+ .decrypt = nss_cryptoapi_ablk_aes_decrypt, - }, - { -- .cra_name = "cbc(des3_ede)", -- .cra_driver_name = "nss-cbc-3des", -- .cra_priority = 1000, -- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_ASYNC, -- .cra_blocksize = DES3_EDE_BLOCK_SIZE, -- .cra_ctxsize = sizeof(struct nss_cryptoapi_ctx), -- .cra_alignmask = 0, -- .cra_type = &crypto_ablkcipher_type, -- .cra_module = THIS_MODULE, -- .cra_init = nss_cryptoapi_ablkcipher_init, -- .cra_exit = nss_cryptoapi_ablkcipher_exit, -- .cra_u = { -- .ablkcipher = { -- .ivsize = DES3_EDE_BLOCK_SIZE, -- .min_keysize = DES3_EDE_KEY_SIZE, -- .max_keysize = DES3_EDE_KEY_SIZE, -- .setkey = nss_cryptoapi_3des_cbc_setkey, -- .encrypt = nss_cryptoapi_3des_cbc_encrypt, -- .decrypt = nss_cryptoapi_3des_cbc_decrypt, -- }, -+ .base = { -+ .cra_name = "cbc(des3_ede)", -+ .cra_driver_name = "nss-cbc-3des", -+ .cra_priority = 1000, -+ .cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_NOSUPP_SG | CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct nss_cryptoapi_ctx), -+ .cra_alignmask = 0, -+ .cra_module = THIS_MODULE, - }, -+ .init = nss_cryptoapi_skcipher_init, -+ .exit = nss_cryptoapi_skcipher_exit, -+ .ivsize = DES3_EDE_BLOCK_SIZE, -+ .min_keysize = DES3_EDE_KEY_SIZE, -+ .max_keysize = DES3_EDE_KEY_SIZE, -+ .setkey = nss_cryptoapi_3des_cbc_setkey, -+ .encrypt = nss_cryptoapi_3des_cbc_encrypt, -+ .decrypt = nss_cryptoapi_3des_cbc_decrypt, - }, - }; - -@@ -277,14 +268,14 @@ static nss_crypto_user_ctx_t nss_cryptoapi_register(nss_crypto_handle_t crypto) - - sc->crypto = crypto; - -- for (i = 0; i < ARRAY_SIZE(cryptoapi_ablkcipher_algs); i++) { -- rc = crypto_register_alg(&cryptoapi_ablkcipher_algs[i]); -+ for (i = 0; i < ARRAY_SIZE(cryptoapi_skcipher_algs); i++) { -+ rc = crypto_register_skcipher(&cryptoapi_skcipher_algs[i]); - if (rc) { -- nss_cfi_trace("Ablk registration failed, algo: %s\n", cryptoapi_ablkcipher_algs[i].cra_name); -- cryptoapi_ablkcipher_algs[i].cra_flags = 0; -+ nss_cfi_trace("Ablk registration failed, algo: %s\n", cryptoapi_skcipher_algs[i].base.cra_name); -+ cryptoapi_skcipher_algs[i].base.cra_flags = 0; - continue; - } -- nss_cfi_info("Ablk registration succeeded, algo: %s\n", cryptoapi_ablkcipher_algs[i].cra_name); -+ nss_cfi_info("Ablk registration succeeded, algo: %s\n", cryptoapi_skcipher_algs[i].base.cra_name); - } - - for (i = 0; i < ARRAY_SIZE(cryptoapi_aead_algs); i++) { -@@ -317,7 +308,7 @@ static nss_crypto_user_ctx_t nss_cryptoapi_register(nss_crypto_handle_t crypto) - static void nss_cryptoapi_unregister(nss_crypto_user_ctx_t cfi) - { - struct nss_cryptoapi *sc = &gbl_ctx; -- int i, ret = 0; -+ int i; - - nss_cfi_info("unregister nss_cryptoapi\n"); - -@@ -326,16 +317,12 @@ static void nss_cryptoapi_unregister(nss_crypto_user_ctx_t cfi) - */ - atomic_set(&gbl_ctx.registered, 0); - -- for (i = 0; i < ARRAY_SIZE(cryptoapi_ablkcipher_algs); i++) { -- if (!cryptoapi_ablkcipher_algs[i].cra_flags) { -- continue; -- } -- ret = crypto_unregister_alg(&cryptoapi_ablkcipher_algs[i]); -- if (ret) { -- nss_cfi_err("Ablk unregister failed, algo: %s\n", cryptoapi_ablkcipher_algs[i].cra_name); -+ for (i = 0; i < ARRAY_SIZE(cryptoapi_skcipher_algs); i++) { -+ if (!cryptoapi_skcipher_algs[i].base.cra_flags) { - continue; - } -- nss_cfi_info("Ablk unregister succeeded, algo: %s\n", cryptoapi_ablkcipher_algs[i].cra_name); -+ crypto_unregister_skcipher(&cryptoapi_skcipher_algs[i]); -+ nss_cfi_info("Ablk unregister succeeded, algo: %s\n", cryptoapi_skcipher_algs[i].base.cra_name); - } - - for (i = 0; i < ARRAY_SIZE(cryptoapi_aead_algs); i++) { -diff --git a/cryptoapi/v1.1/nss_cryptoapi_ablk.c b/cryptoapi/v1.1/nss_cryptoapi_ablk.c -index 9b6c65e..913e9cc 100644 ---- a/cryptoapi/v1.1/nss_cryptoapi_ablk.c -+++ b/cryptoapi/v1.1/nss_cryptoapi_ablk.c -@@ -102,12 +102,12 @@ int nss_cryptoapi_skcipher_ctx2session(struct crypto_skcipher *sk, uint32_t *sid - EXPORT_SYMBOL(nss_cryptoapi_skcipher_ctx2session); - - /* -- * nss_cryptoapi_ablkcipher_init() -- * Cryptoapi ablkcipher init function. -+ * nss_cryptoapi_skcipher_init() -+ * Cryptoapi skcipher init function. - */ --int nss_cryptoapi_ablkcipher_init(struct crypto_tfm *tfm) -+int nss_cryptoapi_skcipher_init(struct crypto_skcipher *tfm) - { -- struct nss_cryptoapi_ctx *ctx = crypto_tfm_ctx(tfm); -+ struct nss_cryptoapi_ctx *ctx = crypto_skcipher_ctx(tfm); - struct crypto_cipher *sw_tfm; - - nss_cfi_assert(ctx); -@@ -122,31 +122,31 @@ int nss_cryptoapi_ablkcipher_init(struct crypto_tfm *tfm) - - nss_cryptoapi_set_magic(ctx); - -- if (!(crypto_tfm_alg_type(tfm) & CRYPTO_ALG_NEED_FALLBACK)) -+ if (!(crypto_tfm_alg_type(&tfm->base) & CRYPTO_ALG_NEED_FALLBACK)) - return 0; - - /* Alloc fallback transform for future use */ -- sw_tfm = crypto_alloc_cipher(crypto_tfm_alg_name(tfm), 0, CRYPTO_ALG_ASYNC | -+ sw_tfm = crypto_alloc_cipher(crypto_tfm_alg_name(&tfm->base), 0, CRYPTO_ALG_ASYNC | - CRYPTO_ALG_NEED_FALLBACK); - if (IS_ERR(sw_tfm)) { -- nss_cfi_err("unable to alloc software crypto for %s\n", crypto_tfm_alg_name(tfm)); -+ nss_cfi_err("unable to alloc software crypto for %s\n", crypto_tfm_alg_name(&tfm->base)); - return -EINVAL; - } - - /* set this tfm reqsize same to fallback tfm */ -- tfm->crt_ablkcipher.reqsize = sizeof(struct nss_cryptoapi_ctx); -+ crypto_skcipher_set_reqsize(tfm, sizeof(struct nss_cryptoapi_ctx)); - ctx->sw_tfm = crypto_cipher_tfm(sw_tfm); - - return 0; - } - - /* -- * nss_cryptoapi_ablkcipher_exit() -- * Cryptoapi ablkcipher exit function. -+ * nss_cryptoapi_skcipher_exit() -+ * Cryptoapi skcipher exit function. - */ --void nss_cryptoapi_ablkcipher_exit(struct crypto_tfm *tfm) -+void nss_cryptoapi_skcipher_exit(struct crypto_skcipher *tfm) - { -- struct nss_cryptoapi_ctx *ctx = crypto_tfm_ctx(tfm); -+ struct nss_cryptoapi_ctx *ctx = crypto_skcipher_ctx(tfm); - struct nss_cryptoapi *sc = &gbl_ctx; - nss_crypto_status_t status; - -@@ -158,7 +158,7 @@ void nss_cryptoapi_ablkcipher_exit(struct crypto_tfm *tfm) - } - - if (ctx->sw_tfm) { -- crypto_free_ablkcipher(__crypto_ablkcipher_cast(ctx->sw_tfm)); -+ crypto_free_skcipher(__crypto_skcipher_cast(ctx->sw_tfm)); - ctx->sw_tfm = NULL; - } - -@@ -183,9 +183,9 @@ void nss_cryptoapi_ablkcipher_exit(struct crypto_tfm *tfm) - * nss_cryptoapi_ablk_aes_setkey() - * Cryptoapi setkey routine for aes. - */ --int nss_cryptoapi_ablk_aes_setkey(struct crypto_ablkcipher *cipher, const u8 *key, unsigned int keylen) -+int nss_cryptoapi_ablk_aes_setkey(struct crypto_skcipher *cipher, const u8 *key, unsigned int keylen) - { -- struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher); -+ struct crypto_tfm *tfm = crypto_skcipher_tfm(cipher); - struct nss_cryptoapi_ctx *ctx = crypto_tfm_ctx(tfm); - struct nss_cryptoapi *sc = &gbl_ctx; - struct nss_crypto_key cip; -@@ -255,10 +255,10 @@ int nss_cryptoapi_ablk_aes_setkey(struct crypto_ablkcipher *cipher, const u8 *ke - - /* set flag to fallback tfm */ - crypto_tfm_clear_flags(ctx->sw_tfm, CRYPTO_TFM_REQ_MASK); -- crypto_tfm_set_flags(ctx->sw_tfm, crypto_ablkcipher_get_flags(cipher) & CRYPTO_TFM_REQ_MASK); -+ crypto_tfm_set_flags(ctx->sw_tfm, crypto_skcipher_get_flags(cipher) & CRYPTO_TFM_REQ_MASK); - - /* Set key to the fallback tfm */ -- ret = crypto_ablkcipher_setkey(__crypto_ablkcipher_cast(ctx->sw_tfm), key, keylen); -+ ret = crypto_skcipher_setkey(__crypto_skcipher_cast(ctx->sw_tfm), key, keylen); - if (ret) { - nss_cfi_err("Failed to set key to the sw crypto"); - -@@ -266,7 +266,7 @@ int nss_cryptoapi_ablk_aes_setkey(struct crypto_ablkcipher *cipher, const u8 *ke - * Set back the fallback tfm flag to the original flag one after - * doing setkey - */ -- crypto_ablkcipher_set_flags(cipher, crypto_tfm_get_flags(ctx->sw_tfm)); -+ crypto_skcipher_set_flags(cipher, crypto_tfm_get_flags(ctx->sw_tfm)); - } - return ret; - default: -@@ -289,23 +289,23 @@ int nss_cryptoapi_ablk_aes_setkey(struct crypto_ablkcipher *cipher, const u8 *ke - return 0; - - fail: -- crypto_ablkcipher_set_flags(cipher, flag); -+ crypto_skcipher_set_flags(cipher, flag); - return -EINVAL; - } - - /* -- * nss_cryptoapi_ablkcipher_done() -+ * nss_cryptoapi_skcipher_done() - * Cipher operation completion callback function - */ --void nss_cryptoapi_ablkcipher_done(struct nss_crypto_buf *buf) -+void nss_cryptoapi_skcipher_done(struct nss_crypto_buf *buf) - { - struct nss_cryptoapi_ctx *ctx; -- struct ablkcipher_request *req; -+ struct skcipher_request *req; - int err = 0; - - nss_cfi_assert(buf); - -- req = (struct ablkcipher_request *)nss_crypto_get_cb_ctx(buf); -+ req = (struct skcipher_request *)nss_crypto_get_cb_ctx(buf); - - /* - * check cryptoapi context magic number. -@@ -319,7 +319,7 @@ void nss_cryptoapi_ablkcipher_done(struct nss_crypto_buf *buf) - nss_crypto_buf_free(gbl_ctx.crypto, buf); - - nss_cfi_dbg("after transformation\n"); -- nss_cfi_dbg_data(sg_virt(req->dst), req->nbytes, ' '); -+ nss_cfi_dbg_data(sg_virt(req->dst), req->cryptlen, ' '); - - /* - * Passing always pass in case of encrypt. -@@ -337,7 +337,7 @@ void nss_cryptoapi_ablkcipher_done(struct nss_crypto_buf *buf) - * Cryptoapi: obtain sg to virtual address mapping. - * Check for multiple sg in src and dst - */ --int nss_cryptoapi_ablk_checkaddr(struct ablkcipher_request *req) -+int nss_cryptoapi_ablk_checkaddr(struct skcipher_request *req) - { - /* - * Currently only single sg is supported -@@ -356,7 +356,7 @@ int nss_cryptoapi_ablk_checkaddr(struct ablkcipher_request *req) - /* - * If the size of data is more than 65K reject transformation - */ -- if (req->nbytes > NSS_CRYPTOAPI_MAX_DATA_LEN) { -+ if (req->cryptlen > NSS_CRYPTOAPI_MAX_DATA_LEN) { - nss_cfi_err("Buffer length exceeded limit\n"); - return -EINVAL; - } -@@ -368,10 +368,10 @@ int nss_cryptoapi_ablk_checkaddr(struct ablkcipher_request *req) - * nss_cryptoapi_ablk_transform() - * Crytoapi common routine for encryption and decryption operations. - */ --struct nss_crypto_buf *nss_cryptoapi_ablk_transform(struct ablkcipher_request *req, struct nss_cryptoapi_ablk_info *info) -+struct nss_crypto_buf *nss_cryptoapi_ablk_transform(struct skcipher_request *req, struct nss_cryptoapi_ablk_info *info) - { -- struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(req); -- struct nss_cryptoapi_ctx *ctx = crypto_ablkcipher_ctx(cipher); -+ struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(req); -+ struct nss_cryptoapi_ctx *ctx = crypto_skcipher_ctx(cipher); - struct nss_crypto_buf *buf; - struct nss_cryptoapi *sc = &gbl_ctx; - nss_crypto_status_t status; -@@ -382,7 +382,7 @@ struct nss_crypto_buf *nss_cryptoapi_ablk_transform(struct ablkcipher_request *r - nss_cfi_assert(ctx); - - nss_cfi_dbg("src_vaddr: 0x%p, dst_vaddr: 0x%p, iv: 0x%p\n", -- sg_virt(req->src), sg_virt(req->dst), req->info); -+ sg_virt(req->src), sg_virt(req->dst), req->iv); - - info->params->cipher_skip = 0; - info->params->auth_skip = 0; -@@ -419,19 +419,19 @@ struct nss_crypto_buf *nss_cryptoapi_ablk_transform(struct ablkcipher_request *r - /* - * Get IV location and memcpy the IV - */ -- iv_size = crypto_ablkcipher_ivsize(cipher); -+ iv_size = crypto_skcipher_ivsize(cipher); - iv_addr = nss_crypto_get_ivaddr(buf); - - switch (ctx->cip_alg) { - case NSS_CRYPTO_CIPHER_AES_CBC: - case NSS_CRYPTO_CIPHER_DES: -- memcpy(iv_addr, req->info, iv_size); -+ memcpy(iv_addr, req->iv, iv_size); - break; - - case NSS_CRYPTO_CIPHER_AES_CTR: - ((uint32_t *)iv_addr)[0] = ctx->ctx_iv[0]; -- ((uint32_t *)iv_addr)[1] = ((uint32_t *)req->info)[0]; -- ((uint32_t *)iv_addr)[2] = ((uint32_t *)req->info)[1]; -+ ((uint32_t *)iv_addr)[1] = ((uint32_t *)req->iv)[0]; -+ ((uint32_t *)iv_addr)[2] = ((uint32_t *)req->iv)[1]; - ((uint32_t *)iv_addr)[3] = ctx->ctx_iv[3]; - break; - -@@ -446,7 +446,7 @@ struct nss_crypto_buf *nss_cryptoapi_ablk_transform(struct ablkcipher_request *r - /* - * Fill Cipher and Auth len - */ -- cipher_len = req->nbytes; -+ cipher_len = req->cryptlen; - auth_len = 0; - - nss_crypto_set_data(buf, sg_virt(req->src), sg_virt(req->dst), cipher_len); -@@ -463,12 +463,12 @@ struct nss_crypto_buf *nss_cryptoapi_ablk_transform(struct ablkcipher_request *r - } - - /* -- * nss_cryptoapi_ablkcipher_fallback() -- * Cryptoapi fallback for ablkcipher algorithm. -+ * nss_cryptoapi_skcipher_fallback() -+ * Cryptoapi fallback for skcipher algorithm. - */ --int nss_cryptoapi_ablkcipher_fallback(struct nss_cryptoapi_ctx *ctx, struct ablkcipher_request *req, int type) -+int nss_cryptoapi_skcipher_fallback(struct nss_cryptoapi_ctx *ctx, struct skcipher_request *req, int type) - { -- struct crypto_ablkcipher *orig_tfm = crypto_ablkcipher_reqtfm(req); -+ struct crypto_skcipher *orig_tfm = crypto_skcipher_reqtfm(req); - int err; - - if (!ctx->sw_tfm) { -@@ -476,16 +476,16 @@ int nss_cryptoapi_ablkcipher_fallback(struct nss_cryptoapi_ctx *ctx, struct ablk - } - - /* Set new fallback tfm to the request */ -- ablkcipher_request_set_tfm(req, __crypto_ablkcipher_cast(ctx->sw_tfm)); -+ skcipher_request_set_tfm(req, __crypto_skcipher_cast(ctx->sw_tfm)); - - ctx->queued++; - - switch (type) { - case NSS_CRYPTOAPI_ENCRYPT: -- err = crypto_ablkcipher_encrypt(req); -+ err = crypto_skcipher_encrypt(req); - break; - case NSS_CRYPTOAPI_DECRYPT: -- err = crypto_ablkcipher_decrypt(req); -+ err = crypto_skcipher_decrypt(req); - break; - default: - err = -EINVAL; -@@ -495,7 +495,7 @@ int nss_cryptoapi_ablkcipher_fallback(struct nss_cryptoapi_ctx *ctx, struct ablk - ctx->completed++; - - /* Set original tfm to the request */ -- ablkcipher_request_set_tfm(req, orig_tfm); -+ skcipher_request_set_tfm(req, orig_tfm); - - return err; - } -@@ -504,13 +504,13 @@ int nss_cryptoapi_ablkcipher_fallback(struct nss_cryptoapi_ctx *ctx, struct ablk - * nss_cryptoapi_ablk_aes_encrypt() - * Crytoapi encrypt for aes(aes-cbc/rfc3686-aes-ctr) algorithms. - */ --int nss_cryptoapi_ablk_aes_encrypt(struct ablkcipher_request *req) -+int nss_cryptoapi_ablk_aes_encrypt(struct skcipher_request *req) - { - struct nss_crypto_params params = { .req_type = NSS_CRYPTO_REQ_TYPE_ENCRYPT }; -- struct nss_cryptoapi_ablk_info info = {.cb_fn = nss_cryptoapi_ablkcipher_done, -+ struct nss_cryptoapi_ablk_info info = {.cb_fn = nss_cryptoapi_skcipher_done, - .params = ¶ms}; -- struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(req); -- struct nss_cryptoapi_ctx *ctx = crypto_ablkcipher_ctx(cipher); -+ struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(req); -+ struct nss_cryptoapi_ctx *ctx = crypto_skcipher_ctx(cipher); - struct nss_cryptoapi *sc = &gbl_ctx; - struct nss_crypto_buf *buf; - -@@ -520,7 +520,7 @@ int nss_cryptoapi_ablk_aes_encrypt(struct ablkcipher_request *req) - nss_cryptoapi_verify_magic(ctx); - - if (ctx->fallback_req) -- return nss_cryptoapi_ablkcipher_fallback(ctx, req, NSS_CRYPTOAPI_ENCRYPT); -+ return nss_cryptoapi_skcipher_fallback(ctx, req, NSS_CRYPTOAPI_ENCRYPT); - - /* - * Check if previous call to setkey couldn't allocate session with core crypto. -@@ -539,9 +539,9 @@ int nss_cryptoapi_ablk_aes_encrypt(struct ablkcipher_request *req) - * According to RFC3686, AES-CTR algo need not be padded if the - * plaintext or ciphertext is unaligned to block size boundary. - */ -- if (nss_cryptoapi_check_unalign(req->nbytes, AES_BLOCK_SIZE) && (ctx->cip_alg != NSS_CRYPTO_CIPHER_AES_CTR)) { -+ if (nss_cryptoapi_check_unalign(req->cryptlen, AES_BLOCK_SIZE) && (ctx->cip_alg != NSS_CRYPTO_CIPHER_AES_CTR)) { - nss_cfi_err("Invalid cipher len - Not aligned to algo blocksize\n"); -- crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_BLOCK_LEN); -+ crypto_skcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_BLOCK_LEN); - return -EINVAL; - } - -@@ -571,13 +571,13 @@ int nss_cryptoapi_ablk_aes_encrypt(struct ablkcipher_request *req) - * nss_cryptoapi_ablk_aes_decrypt() - * Crytoapi decrypt for aes(aes-cbc/rfc3686-aes-ctr) algorithms. - */ --int nss_cryptoapi_ablk_aes_decrypt(struct ablkcipher_request *req) -+int nss_cryptoapi_ablk_aes_decrypt(struct skcipher_request *req) - { - struct nss_crypto_params params = { .req_type = NSS_CRYPTO_REQ_TYPE_DECRYPT }; -- struct nss_cryptoapi_ablk_info info = {.cb_fn = nss_cryptoapi_ablkcipher_done, -+ struct nss_cryptoapi_ablk_info info = {.cb_fn = nss_cryptoapi_skcipher_done, - .params = ¶ms}; -- struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(req); -- struct nss_cryptoapi_ctx *ctx = crypto_ablkcipher_ctx(cipher); -+ struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(req); -+ struct nss_cryptoapi_ctx *ctx = crypto_skcipher_ctx(cipher); - struct nss_cryptoapi *sc = &gbl_ctx; - struct nss_crypto_buf *buf; - -@@ -587,7 +587,7 @@ int nss_cryptoapi_ablk_aes_decrypt(struct ablkcipher_request *req) - nss_cryptoapi_verify_magic(ctx); - - if (ctx->fallback_req) -- return nss_cryptoapi_ablkcipher_fallback(ctx, req, NSS_CRYPTOAPI_DECRYPT); -+ return nss_cryptoapi_skcipher_fallback(ctx, req, NSS_CRYPTOAPI_DECRYPT); - - /* - * Check if previous call to setkey couldn't allocate session with core crypto. -@@ -606,9 +606,9 @@ int nss_cryptoapi_ablk_aes_decrypt(struct ablkcipher_request *req) - * According to RFC3686, AES-CTR algo need not be padded if the - * plaintext or ciphertext is unaligned to block size boundary. - */ -- if (nss_cryptoapi_check_unalign(req->nbytes, AES_BLOCK_SIZE) && (ctx->cip_alg != NSS_CRYPTO_CIPHER_AES_CTR)) { -+ if (nss_cryptoapi_check_unalign(req->cryptlen, AES_BLOCK_SIZE) && (ctx->cip_alg != NSS_CRYPTO_CIPHER_AES_CTR)) { - nss_cfi_err("Invalid cipher len - Not aligned to algo blocksize\n"); -- crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_BLOCK_LEN); -+ crypto_skcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_BLOCK_LEN); - return -EINVAL; - } - -@@ -638,9 +638,9 @@ int nss_cryptoapi_ablk_aes_decrypt(struct ablkcipher_request *req) - * nss_cryptoapi_3des_cbc_setkey() - * Cryptoapi DES3 CBC setkey function. - */ --int nss_cryptoapi_3des_cbc_setkey(struct crypto_ablkcipher *cipher, const u8 *key, unsigned int keylen) -+int nss_cryptoapi_3des_cbc_setkey(struct crypto_skcipher *cipher, const u8 *key, unsigned int keylen) - { -- struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher); -+ struct crypto_tfm *tfm = crypto_skcipher_tfm(cipher); - struct nss_cryptoapi_ctx *ctx = crypto_tfm_ctx(tfm); - struct nss_cryptoapi *sc = &gbl_ctx; - struct nss_crypto_key cip = { .algo = NSS_CRYPTO_CIPHER_DES }; -@@ -693,7 +693,7 @@ int nss_cryptoapi_3des_cbc_setkey(struct crypto_ablkcipher *cipher, const u8 *ke - return 0; - - fail: -- crypto_ablkcipher_set_flags(cipher, flag); -+ crypto_skcipher_set_flags(cipher, flag); - return -EINVAL; - } - -@@ -701,7 +701,7 @@ fail: - * nss_cryptoapi_3des_cbc_encrypt() - * Cryptoapi DES3 CBC encrypt function. - */ --int nss_cryptoapi_3des_cbc_encrypt(struct ablkcipher_request *req) -+int nss_cryptoapi_3des_cbc_encrypt(struct skcipher_request *req) - { - struct nss_cryptoapi *sc = &gbl_ctx; - struct nss_cryptoapi_ctx *ctx = crypto_tfm_ctx(req->base.tfm); -@@ -727,14 +727,14 @@ int nss_cryptoapi_3des_cbc_encrypt(struct ablkcipher_request *req) - return -EINVAL; - } - -- if (nss_cryptoapi_check_unalign(req->nbytes, DES3_EDE_BLOCK_SIZE)) { -+ if (nss_cryptoapi_check_unalign(req->cryptlen, DES3_EDE_BLOCK_SIZE)) { - nss_cfi_err("Invalid cipher len - Not aligned to algo blocksize\n"); -- crypto_ablkcipher_set_flags(crypto_ablkcipher_reqtfm(req), CRYPTO_TFM_RES_BAD_BLOCK_LEN); -+ crypto_skcipher_set_flags(crypto_skcipher_reqtfm(req), CRYPTO_TFM_RES_BAD_BLOCK_LEN); - return -EINVAL; - } - - info.params = ¶ms; -- info.cb_fn = nss_cryptoapi_ablkcipher_done; -+ info.cb_fn = nss_cryptoapi_skcipher_done; - - buf = nss_cryptoapi_ablk_transform(req, &info); - if (!buf) { -@@ -762,7 +762,7 @@ int nss_cryptoapi_3des_cbc_encrypt(struct ablkcipher_request *req) - * nss_cryptoapi_3des_cbc_decrypt() - * Cryptoapi DES3 CBC decrypt function. - */ --int nss_cryptoapi_3des_cbc_decrypt(struct ablkcipher_request *req) -+int nss_cryptoapi_3des_cbc_decrypt(struct skcipher_request *req) - { - struct nss_cryptoapi *sc = &gbl_ctx; - struct nss_cryptoapi_ctx *ctx = crypto_tfm_ctx(req->base.tfm); -@@ -788,14 +788,14 @@ int nss_cryptoapi_3des_cbc_decrypt(struct ablkcipher_request *req) - return -EINVAL; - } - -- if (nss_cryptoapi_check_unalign(req->nbytes, DES3_EDE_BLOCK_SIZE)) { -+ if (nss_cryptoapi_check_unalign(req->cryptlen, DES3_EDE_BLOCK_SIZE)) { - nss_cfi_err("Invalid cipher len - Not aligned to algo blocksize\n"); -- crypto_ablkcipher_set_flags(crypto_ablkcipher_reqtfm(req), CRYPTO_TFM_RES_BAD_BLOCK_LEN); -+ crypto_skcipher_set_flags(crypto_skcipher_reqtfm(req), CRYPTO_TFM_RES_BAD_BLOCK_LEN); - return -EINVAL; - } - - info.params = ¶ms; -- info.cb_fn = nss_cryptoapi_ablkcipher_done; -+ info.cb_fn = nss_cryptoapi_skcipher_done; - - buf = nss_cryptoapi_ablk_transform(req, &info); - if (!buf) { -diff --git a/cryptoapi/v1.1/nss_cryptoapi_debugfs.c b/cryptoapi/v1.1/nss_cryptoapi_debugfs.c -index dff774c..cf4bc70 100644 ---- a/cryptoapi/v1.1/nss_cryptoapi_debugfs.c -+++ b/cryptoapi/v1.1/nss_cryptoapi_debugfs.c -@@ -55,6 +55,7 @@ - */ - void nss_cryptoapi_debugfs_add_stats(struct dentry *parent, struct nss_cryptoapi_ctx *session_ctx) - { -+ pr_info("add stats"); - debugfs_create_u64("queued", S_IRUGO, parent, &session_ctx->queued); - debugfs_create_u64("completed", S_IRUGO, parent, &session_ctx->completed); - debugfs_create_u64("queue_failed", S_IRUGO, parent, &session_ctx->queue_failed); -diff --git a/cryptoapi/v1.1/nss_cryptoapi_private.h b/cryptoapi/v1.1/nss_cryptoapi_private.h -index 5feb9e3..70c6714 100644 ---- a/cryptoapi/v1.1/nss_cryptoapi_private.h -+++ b/cryptoapi/v1.1/nss_cryptoapi_private.h -@@ -141,16 +141,16 @@ int nss_cryptoapi_sha256_3des_encrypt(struct aead_request *req); - int nss_cryptoapi_sha256_3des_decrypt(struct aead_request *req); - - /* ABLKCIPHER */ --int nss_cryptoapi_ablkcipher_init(struct crypto_tfm *tfm); --void nss_cryptoapi_ablkcipher_exit(struct crypto_tfm *tfm); --int nss_cryptoapi_ablk_aes_setkey(struct crypto_ablkcipher *cipher, const u8 *key, unsigned int len); --int nss_cryptoapi_3des_cbc_setkey(struct crypto_ablkcipher *cipher, const u8 *key, unsigned int len); -+int nss_cryptoapi_skcipher_init(struct crypto_skcipher *tfm); -+void nss_cryptoapi_skcipher_exit(struct crypto_skcipher *tfm); -+int nss_cryptoapi_ablk_aes_setkey(struct crypto_skcipher *cipher, const u8 *key, unsigned int len); -+int nss_cryptoapi_3des_cbc_setkey(struct crypto_skcipher *cipher, const u8 *key, unsigned int len); - --int nss_cryptoapi_ablk_aes_encrypt(struct ablkcipher_request *req); --int nss_cryptoapi_ablk_aes_decrypt(struct ablkcipher_request *req); -+int nss_cryptoapi_ablk_aes_encrypt(struct skcipher_request *req); -+int nss_cryptoapi_ablk_aes_decrypt(struct skcipher_request *req); - --int nss_cryptoapi_3des_cbc_encrypt(struct ablkcipher_request *req); --int nss_cryptoapi_3des_cbc_decrypt(struct ablkcipher_request *req); -+int nss_cryptoapi_3des_cbc_encrypt(struct skcipher_request *req); -+int nss_cryptoapi_3des_cbc_decrypt(struct skcipher_request *req); - - #endif /* __NSS_CRYPTOAPI_PRIVATE_H */ - --- -2.27.0.rc0 - diff --git a/root/package/qca/nss/qca-nss-clients-64/Makefile b/root/package/qca/nss/qca-nss-clients-64/Makefile deleted file mode 100644 index 15316687..00000000 --- a/root/package/qca/nss/qca-nss-clients-64/Makefile +++ /dev/null @@ -1,97 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=qca-nss-clients-64 -PKG_RELEASE:=$(AUTORELEASE) - -PKG_SOURCE_URL:=https://source.codeaurora.org/quic/cc-qrdk/oss/lklm/nss-clients -PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2021-04-29 -PKG_SOURCE_VERSION:=b93c72c1b72c591c2ddc2f0b24f0e2b457720118 -PKG_MIRROR_HASH:=fbfba64a364b095ea7c9a24cd7af96b63ab0bc29c179e1628c675aa223c0d063 - -include $(INCLUDE_DIR)/kernel.mk -include $(INCLUDE_DIR)/package.mk - -define KernelPackage/qca-nss-drv-pppoe-64 - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Devices - TITLE:=Kernel driver for NSS (connection manager) - PPPoE - DEPENDS:=@(TARGET_ipq60xx||TARGET_ipq807x) +kmod-qca-nss-drv-64 +kmod-ppp +kmod-pppoe - FILES:=$(PKG_BUILD_DIR)/pppoe/qca-nss-pppoe.ko - AUTOLOAD:=$(call AutoLoad,51,qca-nss-pppoe) -endef - -define KernelPackage/qca-nss-drv-pppoe-64/Description -Kernel modules for NSS connection manager - Support for PPPoE -endef - -define KernelPackage/qca-nss-drv-bridge-mgr-64 - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Devices - TITLE:=Kernel driver for NSS bridge manager - DEPENDS:=@(LINUX_5_10||LINUX_5_15) @(TARGET_ipq60xx||TARGET_ipq807x) +kmod-qca-nss-drv-64 +kmod-qca-nss-drv-vlan-mgr-64 - FILES:=$(PKG_BUILD_DIR)/bridge/qca-nss-bridge-mgr.ko - AUTOLOAD:=$(call AutoLoad,51,qca-nss-bridge-mgr) -endef - -define KernelPackage/qca-nss-drv-bridge-mgr-64/Description -Kernel modules for NSS bridge manager -endef - -define KernelPackage/qca-nss-drv-vlan-mgr-64 - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Devices - TITLE:=Kernel driver for NSS vlan manager - DEPENDS:=@(LINUX_5_10||LINUX_5_15) @(TARGET_ipq60xx||TARGET_ipq807x) +kmod-qca-nss-drv-64 - FILES:=$(PKG_BUILD_DIR)/vlan/qca-nss-vlan.ko - AUTOLOAD:=$(call AutoLoad,51,qca-nss-vlan) -endef - -define KernelPackage/qca-nss-drv-vlan-mgr-64/Description -Kernel modules for NSS vlan manager -endef - -EXTRA_CFLAGS+= \ - -I$(STAGING_DIR)/usr/include/qca-nss-drv \ - -I$(STAGING_DIR)/usr/include/qca-nss-crypto \ - -I$(STAGING_DIR)/usr/include/qca-nss-cfi \ - -I$(STAGING_DIR)/usr/include/qca-nss-gmac \ - -I$(STAGING_DIR)/usr/include/qca-ssdk \ - -I$(STAGING_DIR)/usr/include/qca-ssdk/fal \ - -I$(STAGING_DIR)/usr/include/nat46 - -ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-pppoe-64),) -NSS_CLIENTS_MAKE_OPTS+=pppoe=y -endif - -ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-bridge-mgr-64),) -NSS_CLIENTS_MAKE_OPTS+=bridge-mgr=y -endif - -ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-vlan-mgr-64),) -NSS_CLIENTS_MAKE_OPTS+=vlan-mgr=y -endif - -ifeq ($(CONFIG_TARGET_BOARD), "ipq807x") - SOC="ipq807x_64" -else ifeq ($(CONFIG_TARGET_BOARD), "ipq60xx") - SOC="ipq60xx_64" -endif - -define Build/Compile - $(MAKE) -C "$(LINUX_DIR)" $(strip $(NSS_CLIENTS_MAKE_OPTS)) \ - CROSS_COMPILE="$(TARGET_CROSS)" \ - ARCH="$(LINUX_KARCH)" \ - M="$(PKG_BUILD_DIR)" \ - EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ - SoC=$(SOC) \ - $(KERNEL_MAKE_FLAGS) \ - modules -endef - -$(eval $(call KernelPackage,qca-nss-drv-pppoe-64)) -$(eval $(call KernelPackage,qca-nss-drv-bridge-mgr-64)) -$(eval $(call KernelPackage,qca-nss-drv-vlan-mgr-64)) diff --git a/root/package/qca/nss/qca-nss-clients-64/files/qca-nss-ipsec b/root/package/qca/nss/qca-nss-clients-64/files/qca-nss-ipsec deleted file mode 100644 index 5f682c8e..00000000 --- a/root/package/qca/nss/qca-nss-clients-64/files/qca-nss-ipsec +++ /dev/null @@ -1,214 +0,0 @@ -#!/bin/sh /etc/rc.common -# -# Copyright (c) 2018-2019, 2021 The Linux Foundation. All rights reserved. -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -NSS_IPSEC_LOG_FILE=/tmp/.nss_ipsec_log -NSS_IPSEC_LOG_STR_ECM="ECM_Loaded" -NSS_IPSEC_OL_FILE=/tmp/qca_nss_ipsec_ol - -ecm_load () { - if [ ! -d /sys/module/ecm ]; then - /etc/init.d/qca-nss-ecm start - if [ -d /sys/module/ecm ]; then - echo ${NSS_IPSEC_LOG_STR_ECM} >> ${NSS_IPSEC_LOG_FILE} - fi - fi -} - -ecm_unload () { - if [ -f /tmp/.nss_ipsec_log ]; then - str=`grep ${NSS_IPSEC_LOG_STR_ECM} ${NSS_IPSEC_LOG_FILE}` - if [[ $str == ${NSS_IPSEC_LOG_STR_ECM} ]]; then - /etc/init.d/qca-nss-ecm stop - `sed 's/${NSS_IPSEC_LOG_STR_ECM}/ /g' $NSS_IPSEC_LOG_FILE > $NSS_IPSEC_LOG_FILE` - fi - fi -} - -ecm_disable() { - - if [ ! -d /sys/module/ecm ]; then - return; - fi - - echo 1 > /sys/kernel/debug/ecm/front_end_ipv4_stop - echo 1 > /sys/kernel/debug/ecm/front_end_ipv6_stop - echo 1 > /sys/kernel/debug/ecm/ecm_db/defunct_all - sleep 2 -} - -ecm_enable() { - if [ ! -d /sys/module/ecm ]; then - return; - fi - - echo 0 > /sys/kernel/debug/ecm/ecm_db/defunct_all - echo 0 > /sys/kernel/debug/ecm/front_end_ipv4_stop - echo 0 > /sys/kernel/debug/ecm/front_end_ipv6_stop -} - -kernel_version_check_5_4() { - major_ver=$(uname -r | awk -F '.' '{print $1}') - minor_ver=$(uname -r | awk -F '.' '{print $2}') - if [ $major_ver -lt 5 ] || ([ $major_ver -eq 5 ] && [ $minor_ver -lt 4 ] ) ; then - return 1 - else - return 0 - fi -} - -start_klips() { - if kernel_version_check_5_4 - then - echo "Kernel 5.4 doesn't support klips stack." - return $? - fi - - touch $NSS_IPSEC_OL_FILE - ecm_load - - local kernel_version=$(uname -r) - - insmod /lib/modules/${kernel_version}/qca-nss-ipsec-klips.ko - if [ "$?" -gt 0 ]; then - echo "Failed to load plugin. Please start ecm if not done already" - ecm_enable - rm $NSS_IPSEC_OL_FILE - return - fi - - /etc/init.d/ipsec start - sleep 2 - ipsec eroute - - ecm_enable -} - -stop_klips() { - if kernel_version_check_5_4 - then - echo "Kernel 5.4 doesn't support klips stack." - return $? - fi - - ecm_disable - - /etc/init.d/ipsec stop - rmmod qca-nss-ipsec-klips - rm $NSS_IPSEC_OL_FILE - - ecm_unload -} - -start_xfrm() { - touch $NSS_IPSEC_OL_FILE - ecm_load - - local kernel_version=$(uname -r) - - # load all NETKEY modules first. - for mod in xfrm_ipcomp ipcomp xfrm6_tunnel ipcomp6 xfrm6_mode_tunnel xfrm6_mode_beet xfrm6_mode_ro \ - xfrm6_mode_transport xfrm4_mode_transport xfrm4_mode_tunnel \ - xfrm4_tunnel xfrm4_mode_beet esp4 esp6 ah4 ah6 af_key - do - insmod $mod 2> /dev/null - done - - # Now load the xfrm plugin - insmod /lib/modules/${kernel_version}/qca-nss-ipsec-xfrm.ko - if [ "$?" -gt 0 ]; then - echo "Failed to load plugin. Please start ecm if not done already" - ecm_enable - rm $NSS_IPSEC_OL_FILE - return - fi - - /etc/init.d/ipsec start - sleep 2 - - ecm_enable -} - -stop_xfrm() { - ecm_disable - - #Shutdown Pluto first. Then only plugin can be removed. - plutopid=/var/run/pluto/pluto.pid - if [ -f $plutopid ]; then - pid=`cat $plutopid` - if [ ! -z "$pid" ]; then - ipsec whack --shutdown | grep -v "002"; - if [ -s $plutopid ]; then - echo "Attempt to shut Pluto down failed! Trying kill:" - kill $pid; - sleep 5; - fi - fi - rm -rf $plutopid - fi - ip xfrm state flush; - ip xfrm policy flush; - sleep 2 - - #Now we can remove the plugin - retries=5 - while [ -d /sys/module/qca_nss_ipsec_xfrm ] - do - rmmod qca-nss-ipsec-xfrm - if [ "$?" -eq 0 ]; then - rm $NSS_IPSEC_OL_FILE - break - fi - - if [ ${retries} -eq 0 ]; then - echo "Failed to unload qca-nss-ipsec-xfrm plugin!" - exit - fi - - echo "XFRM plugin unload failed; retrying ${retries} times" - sleep 1 - retries=`expr ${retries} - 1` - done - - /etc/init.d/ipsec stop - ecm_unload -} - -start() { - local protostack=`uci -q get ipsec.setup.protostack` - if [ "$protostack" = "klips" ]; then - start_klips - return $? - fi - - start_xfrm - return $? -} - -stop() { - local protostack=`uci -q get ipsec.setup.protostack` - if [ "$protostack" = "klips" ]; then - stop_klips - return $? - fi - - stop_xfrm - return $? -} - -restart() { - stop - start -} diff --git a/root/package/qca/nss/qca-nss-clients-64/files/qca-nss-mirred.init b/root/package/qca/nss/qca-nss-clients-64/files/qca-nss-mirred.init deleted file mode 100644 index 1f931f09..00000000 --- a/root/package/qca/nss/qca-nss-clients-64/files/qca-nss-mirred.init +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh /etc/rc.common - -########################################################################### -# Copyright (c) 2019, The Linux Foundation. All rights reserved. -# Permission to use, copy, modify, and/or distribute this software for -# any purpose with or without fee is hereby granted, provided that the -# above copyright notice and this permission notice appear in all copies. -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -########################################################################### - -restart() { - rmmod act_nssmirred.ko - insmod act_nssmirred.ko -} - -start() { - insmod act_nssmirred.ko -} - -stop() { - rmmod act_nssmirred.ko -} diff --git a/root/package/qca/nss/qca-nss-clients-64/files/qca-nss-ovpn.init b/root/package/qca/nss/qca-nss-clients-64/files/qca-nss-ovpn.init deleted file mode 100644 index 622e295e..00000000 --- a/root/package/qca/nss/qca-nss-clients-64/files/qca-nss-ovpn.init +++ /dev/null @@ -1,69 +0,0 @@ -#!/bin/sh /etc/rc.common - -########################################################################### -# Copyright (c) 2019, The Linux Foundation. All rights reserved. -# Permission to use, copy, modify, and/or distribute this software for -# any purpose with or without fee is hereby granted, provided that the -# above copyright notice and this permission notice appear in all copies. -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -########################################################################### - -ecm_disable() { - if [ ! -d /sys/module/ecm ]; then - return - fi - - echo 1 > /sys/kernel/debug/ecm/front_end_ipv4_stop - echo 1 > /sys/kernel/debug/ecm/front_end_ipv6_stop - echo 1 > /sys/kernel/debug/ecm/ecm_db/defunct_all - sleep 2 -} - -ecm_enable() { - if [ ! -d /sys/module/ecm ]; then - return - fi - - echo 0 > /sys/kernel/debug/ecm/ecm_db/defunct_all - echo 0 > /sys/kernel/debug/ecm/front_end_ipv4_stop - echo 0 > /sys/kernel/debug/ecm/front_end_ipv6_stop -} - -restart() { - ecm_disable - - /etc/init.d/openvpn stop - rmmod qca-nss-ovpn-link - rmmod qca-nss-ovpn-mgr - - insmod qca-nss-ovpn-mgr - insmod qca-nss-ovpn-link - - if [ "$?" -gt 0 ]; then - echo "Failed to load plugin. Please start ecm if not done already" - ecm_enable - return - fi - - ecm_enable -} - -start() { - restart -} - -stop() { - ecm_disable - - /etc/init.d/openvpn stop - rmmod qca-nss-ovpn-link - rmmod qca-nss-ovpn-mgr - - ecm_enable -} diff --git a/root/package/qca/nss/qca-nss-clients/Makefile b/root/package/qca/nss/qca-nss-clients/Makefile deleted file mode 100644 index e782cf81..00000000 --- a/root/package/qca/nss/qca-nss-clients/Makefile +++ /dev/null @@ -1,469 +0,0 @@ -include $(TOPDIR)/rules.mk -include $(INCLUDE_DIR)/kernel.mk - -PKG_NAME:=qca-nss-clients -PKG_RELEASE:=2 - -PKG_SOURCE_URL:=https://source.codeaurora.org/quic/qsdk/oss/lklm/nss-clients -PKG_SOURCE_PROTO:=git -PKG_SOURCE_VERSION:=740d0102c518cd49f30c5580982b218b480006b1 -PKG_MIRROR_HASH:=2f427d01dba69b1b89d3a081daf08b36fb345d55b9c9462eb358e5b071e2a171 - -include $(INCLUDE_DIR)/package.mk - -# Keep default as ipq806x for branches that does not have subtarget framework -ifeq ($(CONFIG_TARGET_ipq),y) -subtarget:=$(SUBTARGET) -else -subtarget:=$(CONFIG_TARGET_BOARD) -endif - -ifneq (, $(findstring $(subtarget), "ipq807x" "ipq807x_64" "ipq60xx" "ipq60xx_64")) -# DTLS Manager v2.0 for Hawkeye/Cypress - DTLSMGR_DIR:=v2.0 -# IPsec Manager v2.0 for Hawkeye/Cypress - IPSECMGR_DIR:=v2.0 -# KLIPS plugin - IPSECMGR_KLIPS:= $(PKG_BUILD_DIR)/ipsecmgr/$(IPSECMGR_DIR)/plugins/klips/qca-nss-ipsec-klips.ko -else -# DTLS Manager v1.0 for Akronite. - DTLSMGR_DIR:=v1.0 -# IPsec Manager v1.0 for Akronite. - IPSECMGR_DIR:=v1.0 -# KLIPS plugin not needed - IPSECMGR_KLIPS:= -endif - -define KernelPackage/qca-nss-drv-tun6rd - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Devices - TITLE:=Kernel driver for NSS (connection manager) - tun6rd - DEPENDS:=+kmod-qca-nss-drv +kmod-sit +6rd @!LINUX_3_18 - FILES:=$(PKG_BUILD_DIR)/qca-nss-tun6rd.ko - AUTOLOAD:=$(call AutoLoad,60,qca-nss-tun6rd) -endef - -define KernelPackage/qca-nss-drv-tun6rd/Description -Kernel modules for NSS connection manager - Support for 6rd tunnel -endef - -define KernelPackage/qca-nss-drv-dtlsmgr - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Devices - TITLE:=Kernel driver for NSS (connection manager) - dtlsmgr - DEPENDS:=+kmod-qca-nss-drv +kmod-qca-nss-cfi-cryptoapi @!LINUX_3_18 - FILES:=$(PKG_BUILD_DIR)/dtls/$(DTLSMGR_DIR)/qca-nss-dtlsmgr.ko -endef - -define KernelPackage/qca-nss-drv-dtls/Description -Kernel modules for NSS connection manager - Support for DTLS sessions -endef - -define KernelPackage/qca-nss-drv-l2tpv2 - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Devices - TITLE:=Kernel driver for NSS (connection manager) - l2tp - DEPENDS:=+kmod-qca-nss-drv +kmod-ppp +kmod-l2tp @!LINUX_3_18 - FILES:=$(PKG_BUILD_DIR)/l2tp/l2tpv2/qca-nss-l2tpv2.ko - KCONFIG:=CONFIG_L2TP=y - AUTOLOAD:=$(call AutoLoad,51,qca-nss-l2tpv2) -endef - -define KernelPackage/qca-nss-drv-l2tpv2/Description -Kernel modules for NSS connection manager - Support for l2tp tunnel -endef - -define KernelPackage/qca-nss-drv-pptp - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Devices - TITLE:=Kernel driver for NSS (connection manager) - PPTP - DEPENDS:=+kmod-qca-nss-drv +kmod-pptp @!LINUX_3_18 - FILES:=$(PKG_BUILD_DIR)/pptp/qca-nss-pptp.ko - AUTOLOAD:=$(call AutoLoad,51,qca-nss-pptp) -endef - -define KernelPackage/qca-nss-drv-pptp/Description -Kernel modules for NSS connection manager - Support for PPTP tunnel -endef - -define KernelPackage/qca-nss-drv-pppoe - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Devices - TITLE:=Kernel driver for NSS (connection manager) - PPPoE - DEPENDS:=+kmod-qca-nss-drv +kmod-pppoe @!LINUX_3_18 \ - +!(TARGET_ipq_ipq807x_QSDK_256||TARGET_ipq_ipq60xx_QSDK_256):kmod-bonding - FILES:=$(PKG_BUILD_DIR)/pppoe/qca-nss-pppoe.ko - AUTOLOAD:=$(call AutoLoad,51,qca-nss-pppoe) -endef - -define KernelPackage/qca-nss-drv-pppoe/Description -Kernel modules for NSS connection manager - Support for PPPoE -endef - -define KernelPackage/qca-nss-drv-map-t - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Devices - TITLE:=Kernel driver for NSS (connection manager) - MAP-T - DEPENDS:=+kmod-qca-nss-drv +kmod-nat46 @!LINUX_3_18 - FILES:=$(PKG_BUILD_DIR)/map/map-t/qca-nss-map-t.ko - AUTOLOAD:=$(call AutoLoad,51,qca-nss-map-t) -endef - -define KernelPackage/qca-nss-drv-map-t/Description -Kernel modules for NSS connection manager - Support for MAP-T -endef - -define KernelPackage/qca-nss-drv-gre - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Devices - TITLE:=Kernel driver for NSS (connection manager) - GRE - DEPENDS:=@TARGET_ipq_ipq806x||TARGET_ipq806x||TARGET_ipq_ipq807x||TARGET_ipq_ipq807x_64||TARGET_ipq807x||TARGET_ipq807x_64||TARGET_ipq_ipq60xx||TARGET_ipq_ipq60xx_64||TARGET_ipq_ipq50xx||TARGET_ipq_ipq50xx_64 \ - +kmod-qca-nss-drv @!LINUX_3_18 +kmod-gre6 - FILES:=$(PKG_BUILD_DIR)/gre/qca-nss-gre.ko $(PKG_BUILD_DIR)/gre/test/qca-nss-gre-test.ko - AUTOLOAD:=$(call AutoLoad,51,qca-nss-gre) -endef - -define KernelPackage/qca-nss-drv-gre/Description -Kernel modules for NSS connection manager - Support for GRE -endef - -define KernelPackage/qca-nss-drv-tunipip6 - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Devices - TITLE:=Kernel driver for NSS (connection manager) - DS-lite and ipip6 Tunnel - DEPENDS:=+kmod-qca-nss-drv +kmod-iptunnel6 +kmod-ip6-tunnel @!LINUX_3_18 - FILES:=$(PKG_BUILD_DIR)/qca-nss-tunipip6.ko - AUTOLOAD:=$(call AutoLoad,60,qca-nss-tunipip6) -endef - -define KernelPackage/qca-nss-drv-tunipip6/Description -Kernel modules for NSS connection manager -Add support for DS-lite and ipip6 tunnel -endef - -define KernelPackage/qca-nss-drv-profile - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Devices - DEPENDS:=+kmod-qca-nss-drv @!LINUX_3_18 - TITLE:=Profiler for QCA NSS driver (IPQ806x) - FILES:=$(PKG_BUILD_DIR)/profiler/qca-nss-profile-drv.ko -endef - -define KernelPackage/qca-nss-drv-profile/Description -This package contains a NSS driver profiler for QCA chipset -endef - -define KernelPackage/qca-nss-drv-ipsecmgr - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Devices - TITLE:=Kernel driver for NSS (ipsec manager) - ipsecmgr - DEPENDS:=@TARGET_ipq806x||TARGET_ipq_ipq806x||TARGET_ipq_ipq807x||TARGET_ipq_ipq807x_64||TARGET_ipq807x||TARGET_ipq807x_64||TARGET_ipq_ipq60xx||TARGET_ipq_ipq60xx_64 \ - +kmod-qca-nss-drv +kmod-qca-nss-ecm-standard +kmod-qca-nss-cfi-cryptoapi @!LINUX_3_18 -ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-l2tpv2),) - DEPENDS+=+kmod-qca-nss-drv-l2tpv2 -endif - FILES:=$(PKG_BUILD_DIR)/ipsecmgr/$(IPSECMGR_DIR)/qca-nss-ipsecmgr.ko $(IPSECMGR_KLIPS) - AUTOLOAD:=$(call AutoLoad,60,qca-nss-ipsecmgr) -endef - -define KernelPackage/qca-nss-drv-ipsecmgr/Description -Kernel module for NSS IPsec offload manager -endef - -define KernelPackage/qca-nss-drv-capwapmgr - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Devices - DEPENDS:=+kmod-qca-nss-drv +kmod-qca-nss-drv-dtlsmgr @!LINUX_3_18 - TITLE:=NSS CAPWAP Manager for QCA NSS driver (IPQ806x) - FILES:=$(PKG_BUILD_DIR)/capwapmgr/qca-nss-capwapmgr.ko -endef - -define KernelPackage/qca-nss-drv-capwapmgr/Description -This package contains a NSS CAPWAP Manager -endef - -define KernelPackage/qca-nss-drv-bridge-mgr - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Devices - TITLE:=Kernel driver for NSS bridge manager - DEPENDS:=@TARGET_ipq_ipq807x||TARGET_ipq_ipq807x_64||TARGET_ipq807x||TARGET_ipq807x_64||TARGET_ipq_ipq60xx||TARGET_ipq_ipq60xx_64 \ - +TARGET_ipq_ipq807x:kmod-qca-nss-drv-vlan-mgr \ - +TARGET_ipq_ipq807x_64:kmod-qca-nss-drv-vlan-mgr \ - +TARGET_ipq807x:kmod-qca-nss-drv-vlan-mgr \ - +TARGET_ipq807x_64:kmod-qca-nss-drv-vlan-mgr \ - +TARGET_ipq_ipq60xx:kmod-qca-nss-drv-vlan-mgr \ - +TARGET_ipq_ipq60xx_64:kmod-qca-nss-drv-vlan-mgr @!LINUX_3_18 \ - +!(TARGET_ipq_ipq807x_QSDK_256||TARGET_ipq_ipq60xx_QSDK_256):kmod-bonding - FILES:=$(PKG_BUILD_DIR)/bridge/qca-nss-bridge-mgr.ko - AUTOLOAD:=$(call AutoLoad,51,qca-nss-bridge-mgr) -endef - -define KernelPackage/qca-nss-drv-bridge-mgr/Description -Kernel modules for NSS bridge manager -endef - -define KernelPackage/qca-nss-drv-vlan-mgr - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Devices - TITLE:=Kernel driver for NSS vlan manager - DEPENDS:=@TARGET_ipq806x||TARGET_ipq807x +kmod-qca-nss-drv @!LINUX_3_18 \ - +!(TARGET_ipq_ipq807x_QSDK_256||TARGET_ipq_ipq60xx_QSDK_256):kmod-bonding - FILES:=$(PKG_BUILD_DIR)/vlan/qca-nss-vlan.ko - AUTOLOAD:=$(call AutoLoad,51,qca-nss-vlan) -endef - -define KernelPackage/qca-nss-drv-vlan-mgr/Description -Kernel modules for NSS vlan manager -endef - -define KernelPackage/qca-nss-drv-qdisc - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Support - TITLE:=Qdisc for configuring shapers in NSS - DEPENDS:=+kmod-qca-nss-drv @!LINUX_3_18 - FILES:=$(PKG_BUILD_DIR)/nss_qdisc/qca-nss-qdisc.ko - KCONFIG:=CONFIG_NET_CLS_ACT=y - AUTOLOAD:=$(call AutoLoad,58,qca-nss-qdisc) -endef - -define KernelPackage/qca-nss-drv-qdisc/Description -Linux qdisc that aids in configuring shapers in the NSS -endef - -define KernelPackage/qca-nss-drv-lag-mgr - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Devices - TITLE:=Kernel driver for NSS LAG manager - DEPENDS:=+kmod-qca-nss-drv @!LINUX_3_18 \ - +TARGET_ipq_ipq807x:kmod-qca-nss-drv-vlan-mgr \ - +TARGET_ipq_ipq807x_64:kmod-qca-nss-drv-vlan-mgr @!LINUX_3_18 \ - +TARGET_ipq807x:kmod-qca-nss-drv-vlan-mgr \ - +TARGET_ipq807x_64:kmod-qca-nss-drv-vlan-mgr @!LINUX_3_18 \ - +TARGET_ipq_ipq60xx:kmod-qca-nss-drv-vlan-mgr @!LINUX_3_18 \ - +TARGET_ipq_ipq60xx_64:kmod-qca-nss-drv-vlan-mgr @!LINUX_3_18 \ - +kmod-bonding - FILES:=$(PKG_BUILD_DIR)/lag/qca-nss-lag-mgr.ko - AUTOLOAD:=$(call AutoLoad,51,qca-nss-lag-mgr) -endef - -define KernelPackage/qca-nss-drv-lag-mgr/Description -Kernel modules for NSS LAG manager -endef - -define KernelPackage/qca-nss-drv-netlink - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Devices - DEPENDS:=@TARGET_ipq807x||TARGET_ipq_ipq807x||TARGET_ipq807x_64||TARGET_ipq_ipq807x_64||TARGET_ipq_ipq60xx||TARGET_ipq_ipq60xx_64||TARGET_ipq_ipq50xx||TARGET_ipq_ipq50xx_64 \ - +kmod-qca-nss-drv @!LINUX_3_18 \ - +PACKAGE_kmod-qca-nss-drv-ipsecmgr:kmod-qca-nss-drv-ipsecmgr \ - +PACKAGE_kmod-qca-nss-drv-dtlsmgr:kmod-qca-nss-drv-dtlsmgr \ - +PACKAGE_kmod-qca-nss-drv-capwapmgr:kmod-qca-nss-drv-capwapmgr @!LINUX_3_18 - TITLE:=NSS NETLINK Manager for QCA NSS driver - FILES:=$(PKG_BUILD_DIR)/netlink/qca-nss-netlink.ko -endef - -define KernelPackage/qca-nss-drv-netlink/Description -Kernel module for NSS netlink manager -endef - -define KernelPackage/qca-nss-drv-ovpn-mgr - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Devices - TITLE:=Kernel driver for NSS OpenVPN manager - DEPENDS:=+kmod-qca-nss-drv +kmod-qca-nss-cfi-cryptoapi +kmod-tun +kmod-ipt-conntrack @!LINUX_3_18 \ - @TARGET_ipq_ipq807x||TARGET_ipq_ipq807x_64||TARGET_ipq_ipq60xx||TARGET_ipq_ipq60xx_64 - FILES:=$(PKG_BUILD_DIR)/openvpn/src/qca-nss-ovpn-mgr.ko -endef - -define KernelPackage/qca-nss-drv-ovpn-mgr/Description -Kernel module for NSS OpenVPN manager -endef - -define KernelPackage/qca-nss-drv-ovpn-link - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Devices - TITLE:=Kernel driver for interfacing NSS OpenVPN manager with ECM - DEPENDS:=+kmod-qca-nss-drv-ovpn-mgr +@PACKAGE_kmod-qca-nss-ecm-premium @!LINUX_3_18 \ - @TARGET_ipq_ipq807x||TARGET_ipq_ipq807x_64||TARGET_ipq_ipq60xx||TARGET_ipq_ipq60xx_64 - FILES:=$(PKG_BUILD_DIR)/openvpn/plugins/qca-nss-ovpn-link.ko -endef - -define KernelPackage/qca-nss-drv-ovpn-link/Description -This module registers with ECM and communicates with NSS OpenVPN manager for supporting OpenVPN offload. -endef - -define KernelPackage/qca-nss-drv-pvxlanmgr - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Devices - DEPENDS:=+kmod-qca-nss-drv @!LINUX_3_18 - TITLE:=NSS PVXLAN Manager for QCA NSS driver - FILES:=$(PKG_BUILD_DIR)/pvxlanmgr/qca-nss-pvxlanmgr.ko -endef - -define KernelPackage/qca-nss-drv-pvxlanmgr/Description -Kernel module for managing NSS PVxLAN -endef - -define Build/InstallDev/qca-nss-clients - $(INSTALL_DIR) $(1)/usr/include/qca-nss-clients - $(CP) $(PKG_BUILD_DIR)/netlink/include/* $(1)/usr/include/qca-nss-clients/ - $(CP) $(PKG_BUILD_DIR)/exports/* $(1)/usr/include/qca-nss-clients/ -endef - -define Build/InstallDev - $(call Build/InstallDev/qca-nss-clients,$(1)) -endef - -define KernelPackage/qca-nss-drv-ovpn-mgr/install - $(INSTALL_DIR) $(1)/etc/init.d - $(INSTALL_BIN) ./files/qca-nss-ovpn.init $(1)/etc/init.d/qca-nss-ovpn -endef - -define KernelPackage/qca-nss-drv-ipsecmgr/install - $(INSTALL_DIR) $(1)/etc/init.d - $(INSTALL_BIN) ./files/qca-nss-ipsec $(1)/etc/init.d/qca-nss-ipsec -endef - - -EXTRA_CFLAGS+= \ - -I$(STAGING_DIR)/usr/include/qca-nss-drv \ - -I$(STAGING_DIR)/usr/include/qca-nss-crypto \ - -I$(STAGING_DIR)/usr/include/qca-nss-cfi \ - -I$(STAGING_DIR)/usr/include/qca-nss-gmac \ - -I$(STAGING_DIR)/usr/include/qca-nss-ecm \ - -I$(STAGING_DIR)/usr/include/qca-ssdk \ - -I$(STAGING_DIR)/usr/include/qca-ssdk/fal \ - -I$(STAGING_DIR)/usr/include/nat46 - -# Build individual packages if selected -ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-profile),) -MAKE_OPTS+=profile=y -endif - -ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-capwapmgr),) -MAKE_OPTS+=capwapmgr=y -EXTRA_CFLAGS += -DNSS_CAPWAPMGR_ONE_NETDEV -endif - -ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-tun6rd),) -MAKE_OPTS+=tun6rd=m -endif - -ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-dtlsmgr),) -MAKE_OPTS+=dtlsmgr=y -endif - -ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-l2tpv2),) -MAKE_OPTS+=l2tpv2=y -EXTRA_CFLAGS += -DNSS_L2TPV2_ENABLED -endif - -ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-pptp),) -MAKE_OPTS+=pptp=y -endif - -ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-map-t),) -MAKE_OPTS+=map-t=y -endif - -ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-tunipip6),) -MAKE_OPTS+=tunipip6=m -endif - -ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-qdisc),) -MAKE_OPTS+=qdisc=y -endif - -ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-ipsecmgr),) -EXTRA_CFLAGS+= -I$(PKG_BUILD_DIR)/exports \ - -I$(STAGING_DIR)/usr/include/qca-nss-ecm -MAKE_OPTS+=ipsecmgr=y -endif - -ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-bridge-mgr),) -MAKE_OPTS+=bridge-mgr=y -endif - -ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-vlan-mgr),) -MAKE_OPTS+=vlan-mgr=y -endif - -ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-lag-mgr),) -MAKE_OPTS+=lag-mgr=y -endif - -ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-gre),) -EXTRA_CFLAGS+= -I$(PKG_BUILD_DIR)/exports -MAKE_OPTS+=gre=y -endif - -ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-pppoe),) -MAKE_OPTS+=pppoe=y -endif - -ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-netlink),) -MAKE_OPTS+=netlink=y -endif - -ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-ovpn-mgr),) -MAKE_OPTS+=ovpn-mgr=y -endif - -ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-ovpn-link),) -MAKE_OPTS+=ovpn-link=y -endif - -ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-pvxlanmgr),) -MAKE_OPTS+=pvxlanmgr=y -endif - -define Build/Compile - $(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" $(strip $(MAKE_OPTS)) \ - $(KERNEL_MAKE_FLAGS) \ - $(PKG_MAKE_FLAGS) \ - M="$(PKG_BUILD_DIR)" \ - EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ - SoC="$(subtarget)" \ - DTLSMGR_DIR="$(DTLSMGR_DIR)" \ - IPSECMGR_DIR="$(IPSECMGR_DIR)" \ - modules -endef - -$(eval $(call KernelPackage,qca-nss-drv-profile)) -$(eval $(call KernelPackage,qca-nss-drv-capwapmgr)) -$(eval $(call KernelPackage,qca-nss-drv-tun6rd)) -$(eval $(call KernelPackage,qca-nss-drv-dtlsmgr)) -$(eval $(call KernelPackage,qca-nss-drv-l2tpv2)) -$(eval $(call KernelPackage,qca-nss-drv-pptp)) -$(eval $(call KernelPackage,qca-nss-drv-pppoe)) -$(eval $(call KernelPackage,qca-nss-drv-map-t)) -$(eval $(call KernelPackage,qca-nss-drv-tunipip6)) -$(eval $(call KernelPackage,qca-nss-drv-qdisc)) -$(eval $(call KernelPackage,qca-nss-drv-netlink)) -$(eval $(call KernelPackage,qca-nss-drv-ipsecmgr)) -$(eval $(call KernelPackage,qca-nss-drv-bridge-mgr)) -$(eval $(call KernelPackage,qca-nss-drv-vlan-mgr)) -$(eval $(call KernelPackage,qca-nss-drv-lag-mgr)) -$(eval $(call KernelPackage,qca-nss-drv-gre)) -$(eval $(call KernelPackage,qca-nss-drv-ovpn-mgr)) -$(eval $(call KernelPackage,qca-nss-drv-ovpn-link)) -$(eval $(call KernelPackage,qca-nss-drv-pvxlanmgr)) diff --git a/root/package/qca/nss/qca-nss-clients/files/qca-nss-ipsec b/root/package/qca/nss/qca-nss-clients/files/qca-nss-ipsec deleted file mode 100644 index bb202e8e..00000000 --- a/root/package/qca/nss/qca-nss-clients/files/qca-nss-ipsec +++ /dev/null @@ -1,92 +0,0 @@ -#!/bin/sh /etc/rc.common -# -# Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -NSS_IPSEC_LOG_FILE=/tmp/.nss_ipsec_log -NSS_IPSEC_LOG_STR_ECM="ECM_Loaded" - -ecm_load () { - if [ ! -d /sys/module/ecm ]; then - /etc/init.d/qca-nss-ecm start - if [ -d /sys/module/ecm ]; then - echo ${NSS_IPSEC_LOG_STR_ECM} >> ${NSS_IPSEC_LOG_FILE} - fi - fi -} - -ecm_unload () { - if [ -f /tmp/.nss_ipsec_log ]; then - str=`grep ${NSS_IPSEC_LOG_STR_ECM} ${NSS_IPSEC_LOG_FILE}` - if [[ $str == ${NSS_IPSEC_LOG_STR_ECM} ]]; then - /etc/init.d/qca-nss-ecm stop - `sed 's/${NSS_IPSEC_LOG_STR_ECM}/ /g' $NSS_IPSEC_LOG_FILE > $NSS_IPSEC_LOG_FILE` - fi - fi -} - -ecm_disable() { - - if [ ! -d /sys/module/ecm ]; then - return; - fi - - echo 1 > /sys/kernel/debug/ecm/front_end_ipv4_stop - echo 1 > /sys/kernel/debug/ecm/front_end_ipv6_stop - echo 1 > /sys/kernel/debug/ecm/ecm_db/defunct_all - sleep 2 -} - -ecm_enable() { - if [ ! -d /sys/module/ecm ]; then - return; - fi - - echo 0 > /sys/kernel/debug/ecm/ecm_db/defunct_all - echo 0 > /sys/kernel/debug/ecm/front_end_ipv4_stop - echo 0 > /sys/kernel/debug/ecm/front_end_ipv6_stop -} - -start() { - ecm_load - - local kernel_version=$(uname -r) - - insmod /lib/modules/${kernel_version}/qca-nss-ipsec-klips.ko - if [ "$?" -gt 0 ]; then - echo "Failed to load plugin. Please start ecm if not done already" - ecm_enable - return - fi - - /etc/init.d/ipsec start - sleep 2 - ipsec eroute - - ecm_enable -} - -stop() { - ecm_disable - - /etc/init.d/ipsec stop - rmmod qca-nss-ipsec-klips - - ecm_unload -} - -restart() { - stop - start -} diff --git a/root/package/qca/nss/qca-nss-clients/files/qca-nss-mirred.init b/root/package/qca/nss/qca-nss-clients/files/qca-nss-mirred.init deleted file mode 100644 index 1f931f09..00000000 --- a/root/package/qca/nss/qca-nss-clients/files/qca-nss-mirred.init +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh /etc/rc.common - -########################################################################### -# Copyright (c) 2019, The Linux Foundation. All rights reserved. -# Permission to use, copy, modify, and/or distribute this software for -# any purpose with or without fee is hereby granted, provided that the -# above copyright notice and this permission notice appear in all copies. -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -########################################################################### - -restart() { - rmmod act_nssmirred.ko - insmod act_nssmirred.ko -} - -start() { - insmod act_nssmirred.ko -} - -stop() { - rmmod act_nssmirred.ko -} diff --git a/root/package/qca/nss/qca-nss-clients/files/qca-nss-ovpn.init b/root/package/qca/nss/qca-nss-clients/files/qca-nss-ovpn.init deleted file mode 100644 index 622e295e..00000000 --- a/root/package/qca/nss/qca-nss-clients/files/qca-nss-ovpn.init +++ /dev/null @@ -1,69 +0,0 @@ -#!/bin/sh /etc/rc.common - -########################################################################### -# Copyright (c) 2019, The Linux Foundation. All rights reserved. -# Permission to use, copy, modify, and/or distribute this software for -# any purpose with or without fee is hereby granted, provided that the -# above copyright notice and this permission notice appear in all copies. -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -########################################################################### - -ecm_disable() { - if [ ! -d /sys/module/ecm ]; then - return - fi - - echo 1 > /sys/kernel/debug/ecm/front_end_ipv4_stop - echo 1 > /sys/kernel/debug/ecm/front_end_ipv6_stop - echo 1 > /sys/kernel/debug/ecm/ecm_db/defunct_all - sleep 2 -} - -ecm_enable() { - if [ ! -d /sys/module/ecm ]; then - return - fi - - echo 0 > /sys/kernel/debug/ecm/ecm_db/defunct_all - echo 0 > /sys/kernel/debug/ecm/front_end_ipv4_stop - echo 0 > /sys/kernel/debug/ecm/front_end_ipv6_stop -} - -restart() { - ecm_disable - - /etc/init.d/openvpn stop - rmmod qca-nss-ovpn-link - rmmod qca-nss-ovpn-mgr - - insmod qca-nss-ovpn-mgr - insmod qca-nss-ovpn-link - - if [ "$?" -gt 0 ]; then - echo "Failed to load plugin. Please start ecm if not done already" - ecm_enable - return - fi - - ecm_enable -} - -start() { - restart -} - -stop() { - ecm_disable - - /etc/init.d/openvpn stop - rmmod qca-nss-ovpn-link - rmmod qca-nss-ovpn-mgr - - ecm_enable -} diff --git a/root/package/qca/nss/qca-nss-clients/patches/100-kernel-5.4-support-qdisc.patch b/root/package/qca/nss/qca-nss-clients/patches/100-kernel-5.4-support-qdisc.patch deleted file mode 100644 index 0ec8d766..00000000 --- a/root/package/qca/nss/qca-nss-clients/patches/100-kernel-5.4-support-qdisc.patch +++ /dev/null @@ -1,1145 +0,0 @@ ---- a/nss_qdisc/nss_qdisc.h -+++ b/nss_qdisc/nss_qdisc.h -@@ -338,7 +340,7 @@ extern void nss_qdisc_destroy(struct nss - * Initializes a shaper in NSS, based on the position of this qdisc (child or root) - * and if its a normal interface or a bridge interface. - */ --extern int nss_qdisc_init(struct Qdisc *sch, struct nss_qdisc *nq, nss_shaper_node_type_t type, uint32_t classid, uint32_t accel_mode); -+extern int nss_qdisc_init(struct Qdisc *sch, struct netlink_ext_ack *extack, struct nss_qdisc *nq, nss_shaper_node_type_t type, uint32_t classid, uint32_t accel_mode); - - /* - * nss_qdisc_start_basic_stats_polling() ---- a/nss_qdisc/nss_bf.c -+++ b/nss_qdisc/nss_bf.c -@@ -69,7 +69,7 @@ static inline struct nss_bf_class_data * - * Configures a new class. - */ - static int nss_bf_change_class(struct Qdisc *sch, u32 classid, u32 parentid, -- struct nlattr **tca, unsigned long *arg) -+ struct nlattr **tca, unsigned long *arg, struct netlink_ext_ack *extack) - { - struct nss_bf_sched_data *q = qdisc_priv(sch); - struct nss_bf_class_data *cl = (struct nss_bf_class_data *)*arg; -@@ -121,7 +121,7 @@ static int nss_bf_change_class(struct Qd - * that is registered to Linux. Therefore we initialize the NSSBF_GROUP shaper - * here. - */ -- if (nss_qdisc_init(sch, &cl->nq, NSS_SHAPER_NODE_TYPE_BF_GROUP, classid, accel_mode) < 0) { -+ if (nss_qdisc_init(sch, extack, &cl->nq, NSS_SHAPER_NODE_TYPE_BF_GROUP, classid, accel_mode) < 0) { - nss_qdisc_error("Nss init for class %u failed\n", classid); - kfree(cl); - return -EINVAL; -@@ -260,7 +260,7 @@ static void nss_bf_destroy_class(struct - /* - * And now we destroy the child. - */ -- qdisc_destroy(cl->qdisc); -+ qdisc_put(cl->qdisc); - - /* - * Stop the stats polling timer and free class -@@ -325,7 +325,7 @@ static int nss_bf_delete_class(struct Qd - * Replaces the qdisc attached to the provided class. - */ - static int nss_bf_graft_class(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, -- struct Qdisc **old) -+ struct Qdisc **old, struct netlink_ext_ack *extack) - { - struct nss_bf_sched_data *q = qdisc_priv(sch); - struct nss_bf_class_data *cl = (struct nss_bf_class_data *)arg; -@@ -432,24 +432,6 @@ static unsigned long nss_bf_get_class(st - } - - /* -- * nss_bf_put_class() -- * Reduces reference count for this class. -- */ --static void nss_bf_put_class(struct Qdisc *sch, unsigned long arg) --{ -- struct nss_bf_class_data *cl = (struct nss_bf_class_data *)arg; -- nss_qdisc_info("bf put class for %p\n", cl); -- -- /* -- * We are safe to destroy the qdisc if the reference count -- * goes down to 0. -- */ -- if (atomic_sub_return(1, &cl->nq.refcnt) == 0) { -- nss_bf_destroy_class(sch, cl); -- } --} -- --/* - * nss_bf_dump_class() - * Dumps all configurable parameters pertaining to this class. - */ -@@ -538,7 +520,7 @@ static void nss_bf_walk(struct Qdisc *sc - * nss_bf_change_qdisc() - * Can be used to configure a nssbf qdisc. - */ --static int nss_bf_change_qdisc(struct Qdisc *sch, struct nlattr *opt) -+static int nss_bf_change_qdisc(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) - { - struct nss_bf_sched_data *q = qdisc_priv(sch); - struct tc_nssbf_qopt *qopt; -@@ -684,7 +666,7 @@ static void nss_bf_destroy_qdisc(struct - * nss_bf_init_qdisc() - * Initializes the nssbf qdisc. - */ --static int nss_bf_init_qdisc(struct Qdisc *sch, struct nlattr *opt) -+static int nss_bf_init_qdisc(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) - { - struct nss_bf_sched_data *q = qdisc_priv(sch); - struct tc_nssbf_qopt *qopt; -@@ -720,7 +702,7 @@ static int nss_bf_init_qdisc(struct Qdis - /* - * Initialize the NSSBF shaper in NSS - */ -- if (nss_qdisc_init(sch, &q->nq, NSS_SHAPER_NODE_TYPE_BF, 0, accel_mode) < 0) { -+ if (nss_qdisc_init(sch, extack, &q->nq, NSS_SHAPER_NODE_TYPE_BF, 0, accel_mode) < 0) { - return -EINVAL; - } - -@@ -729,7 +711,7 @@ static int nss_bf_init_qdisc(struct Qdis - /* - * Tune nss_bf parameters. - */ -- if (nss_bf_change_qdisc(sch, opt) < 0) { -+ if (nss_bf_change_qdisc(sch, opt, NULL) < 0) { - nss_qdisc_destroy(&q->nq); - return -EINVAL; - } -@@ -772,7 +754,7 @@ nla_put_failure: - * nss_bf_enqueue() - * Enqueues a skb to nssbf qdisc. - */ --static int nss_bf_enqueue(struct sk_buff *skb, struct Qdisc *sch) -+static int nss_bf_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free) - { - return nss_qdisc_enqueue(skb, sch); - } -@@ -787,18 +769,6 @@ static struct sk_buff *nss_bf_dequeue(st - } - - /* -- * nss_bf_drop() -- * Drops a single skb from linux queue, if not empty. -- * -- * Does not drop packets that are queued in the NSS. -- */ --static unsigned int nss_bf_drop(struct Qdisc *sch) --{ -- printk("In bf drop\n"); -- return nss_qdisc_drop(sch); --} -- --/* - * Registration structure for nssbf class - */ - const struct Qdisc_class_ops nss_bf_class_ops = { -@@ -807,9 +777,8 @@ const struct Qdisc_class_ops nss_bf_clas - .graft = nss_bf_graft_class, - .leaf = nss_bf_leaf_class, - .qlen_notify = nss_bf_qlen_notify, -- .get = nss_bf_get_class, -- .put = nss_bf_put_class, -+ .find = nss_bf_get_class, - .dump = nss_bf_dump_class, - .dump_stats = nss_bf_dump_class_stats, - .walk = nss_bf_walk - }; -@@ -830,7 +798,6 @@ struct Qdisc_ops nss_bf_qdisc_ops __read - .enqueue = nss_bf_enqueue, - .dequeue = nss_bf_dequeue, - .peek = qdisc_peek_dequeued, -- .drop = nss_bf_drop, - .cl_ops = &nss_bf_class_ops, - .priv_size = sizeof(struct nss_bf_sched_data), - .owner = THIS_MODULE ---- a/nss_qdisc/nss_blackhole.c -+++ b/nss_qdisc/nss_blackhole.c -@@ -35,7 +35,7 @@ static struct nla_policy nss_blackhole_p - * nss_blackhole_enqueue() - * Enqueue API for nss blackhole qdisc. - */ --static int nss_blackhole_enqueue(struct sk_buff *skb, struct Qdisc *sch) -+static int nss_blackhole_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free) - { - return nss_qdisc_enqueue(skb, sch); - } -@@ -50,18 +50,6 @@ static struct sk_buff *nss_blackhole_deq - } - - /* -- * nss_blackhole_drop() -- * The following function drops a packet from HLOS queue. -- * -- * Note, this does not drop packets from queues in the NSS. We do not support that. -- */ --static unsigned int nss_blackhole_drop(struct Qdisc *sch) --{ -- nss_qdisc_info("qdisc %x dropping\n", sch->handle); -- return nss_qdisc_drop(sch); --} -- --/* - * nss_blackhole_reset() - * Resets the nss blackhole qdisc. - */ -@@ -92,7 +80,7 @@ static void nss_blackhole_destroy(struct - * nss_blackhole_change() - * Function call used to configure the parameters of the nss blackhole qdisc. - */ --static int nss_blackhole_change(struct Qdisc *sch, struct nlattr *opt) -+static int nss_blackhole_change(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) - { - struct nss_blackhole_sched_data *q; - struct tc_nssblackhole_qopt *qopt; -@@ -154,7 +142,7 @@ static int nss_blackhole_change(struct Q - * nss_blackhole_init() - * Initializes a nss blackhole qdisc. - */ --static int nss_blackhole_init(struct Qdisc *sch, struct nlattr *opt) -+static int nss_blackhole_init(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) - { - struct nss_qdisc *nq = qdisc_priv(sch); - struct tc_nssblackhole_qopt *qopt; -@@ -176,12 +164,12 @@ static int nss_blackhole_init(struct Qdi - nss_qdisc_info("qdisc %x initializing\n", sch->handle); - nss_blackhole_reset(sch); - -- if (nss_qdisc_init(sch, nq, NSS_SHAPER_NODE_TYPE_FIFO, 0, accel_mode) < 0) { -+ if (nss_qdisc_init(sch, extack, nq, NSS_SHAPER_NODE_TYPE_FIFO, 0, accel_mode) < 0) { - return -EINVAL; - } - - nss_qdisc_info("qdisc %x initialized with parent %x\n", sch->handle, sch->parent); -- if (nss_blackhole_change(sch, opt) < 0) { -+ if (nss_blackhole_change(sch, opt, NULL) < 0) { - nss_qdisc_destroy(nq); - return -EINVAL; - } -@@ -251,7 +239,6 @@ struct Qdisc_ops nss_blackhole_qdisc_ops - .enqueue = nss_blackhole_enqueue, - .dequeue = nss_blackhole_dequeue, - .peek = nss_blackhole_peek, -- .drop = nss_blackhole_drop, - .init = nss_blackhole_init, - .reset = nss_blackhole_reset, - .destroy = nss_blackhole_destroy, ---- a/nss_qdisc/nss_codel.c -+++ b/nss_qdisc/nss_codel.c -@@ -76,7 +76,7 @@ static struct nla_policy nss_codel_polic - * nss_codel_enqueue() - * Enqueue a packet into nss_codel queue in NSS firmware (bounce). - */ --static int nss_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch) -+static int nss_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free) - { - return nss_qdisc_enqueue(skb, sch); - } -@@ -91,17 +91,6 @@ static struct sk_buff *nss_codel_dequeue - } - - /* -- * nss_codel_drop() -- * Drops a packet from the bounce complete queue. -- * -- * Note: this does not drop packets from the NSS queues. -- */ --static unsigned int nss_codel_drop(struct Qdisc *sch) --{ -- return nss_qdisc_drop(sch); --} -- --/* - * nss_codel_reset() - * Resets nss_codel qdisc. - */ -@@ -234,7 +223,7 @@ static int nss_codel_mem_sz_get(struct Q - * nss_codel_change() - * Used to configure the nss_codel queue in NSS firmware. - */ --static int nss_codel_change(struct Qdisc *sch, struct nlattr *opt) -+static int nss_codel_change(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) - { - struct nss_codel_sched_data *q = qdisc_priv(sch); - struct tc_nsscodel_qopt *qopt; -@@ -381,7 +370,7 @@ fail: - * nss_codel_init() - * Initializes the nss_codel qdisc. - */ --static int nss_codel_init(struct Qdisc *sch, struct nlattr *opt) -+static int nss_codel_init(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) - { - struct nss_qdisc *nq = qdisc_priv(sch); - struct tc_nsscodel_qopt *qopt; -@@ -404,7 +393,7 @@ static int nss_codel_init(struct Qdisc * - nss_qdisc_register_configure_callback(nq, nss_codel_configure_callback); - nss_qdisc_register_stats_callback(nq, nss_codel_stats_callback); - -- if (nss_qdisc_init(sch, nq, NSS_SHAPER_NODE_TYPE_CODEL, 0, qopt->accel_mode) < 0) { -+ if (nss_qdisc_init(sch, extack, nq, NSS_SHAPER_NODE_TYPE_CODEL, 0, qopt->accel_mode) < 0) { - return -EINVAL; - } - -@@ -412,7 +401,7 @@ static int nss_codel_init(struct Qdisc * - return -EINVAL; - } - -- if (nss_codel_change(sch, opt) < 0) { -+ if (nss_codel_change(sch, opt, NULL) < 0) { - nss_qdisc_destroy(nq); - return -EINVAL; - } -@@ -511,7 +500,6 @@ struct Qdisc_ops nss_codel_qdisc_ops __r - .enqueue = nss_codel_enqueue, - .dequeue = nss_codel_dequeue, - .peek = nss_codel_peek, -- .drop = nss_codel_drop, - .init = nss_codel_init, - .reset = nss_codel_reset, - .destroy = nss_codel_destroy, -@@ -530,7 +518,6 @@ struct Qdisc_ops nss_fq_codel_qdisc_ops - .enqueue = nss_codel_enqueue, - .dequeue = nss_codel_dequeue, - .peek = nss_codel_peek, -- .drop = nss_codel_drop, - .init = nss_codel_init, - .reset = nss_codel_reset, - .destroy = nss_codel_destroy, ---- a/nss_qdisc/nss_fifo.c -+++ b/nss_qdisc/nss_fifo.c -@@ -29,7 +29,7 @@ static struct nla_policy nss_fifo_policy - [TCA_NSSFIFO_PARMS] = { .len = sizeof(struct tc_nssfifo_qopt) }, - }; - --static int nss_fifo_enqueue(struct sk_buff *skb, struct Qdisc *sch) -+static int nss_fifo_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free) - { - return nss_qdisc_enqueue(skb, sch); - } -@@ -39,12 +39,6 @@ static struct sk_buff *nss_fifo_dequeue( - return nss_qdisc_dequeue(sch); - } - --static unsigned int nss_fifo_drop(struct Qdisc *sch) --{ -- nss_qdisc_info("nss_fifo dropping"); -- return nss_qdisc_drop(sch); --} -- - static void nss_fifo_reset(struct Qdisc *sch) - { - nss_qdisc_info("nss_fifo resetting!"); -@@ -158,7 +152,7 @@ fail: - } - #endif - --static int nss_fifo_change(struct Qdisc *sch, struct nlattr *opt) -+static int nss_fifo_change(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) - { - struct nss_fifo_sched_data *q = qdisc_priv(sch); - struct nss_qdisc *nq = &q->nq; -@@ -208,7 +202,7 @@ static int nss_fifo_change(struct Qdisc - return 0; - } - --static int nss_fifo_init(struct Qdisc *sch, struct nlattr *opt) -+static int nss_fifo_init(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) - { - struct nss_qdisc *nq = qdisc_priv(sch); - struct tc_nssfifo_qopt *qopt; -@@ -226,13 +220,13 @@ static int nss_fifo_init(struct Qdisc *s - return -EINVAL; - } - -- if (nss_qdisc_init(sch, nq, NSS_SHAPER_NODE_TYPE_FIFO, 0, qopt->accel_mode) < 0) { -+ if (nss_qdisc_init(sch, extack, nq, NSS_SHAPER_NODE_TYPE_FIFO, 0, qopt->accel_mode) < 0) { - nss_qdisc_warning("Fifo %x init failed", sch->handle); - return -EINVAL; - } - - nss_qdisc_info("NSS fifo initialized - handle %x parent %x\n", sch->handle, sch->parent); -- if (nss_fifo_change(sch, opt) < 0) { -+ if (nss_fifo_change(sch, opt, NULL) < 0) { - nss_qdisc_destroy(nq); - return -EINVAL; - } -@@ -290,7 +284,6 @@ struct Qdisc_ops nss_pfifo_qdisc_ops __r - .enqueue = nss_fifo_enqueue, - .dequeue = nss_fifo_dequeue, - .peek = nss_fifo_peek, -- .drop = nss_fifo_drop, - .init = nss_fifo_init, - .reset = nss_fifo_reset, - .destroy = nss_fifo_destroy, -@@ -305,7 +298,6 @@ struct Qdisc_ops nss_bfifo_qdisc_ops __r - .enqueue = nss_fifo_enqueue, - .dequeue = nss_fifo_dequeue, - .peek = nss_fifo_peek, -- .drop = nss_fifo_drop, - .init = nss_fifo_init, - .reset = nss_fifo_reset, - .destroy = nss_fifo_destroy, ---- a/nss_qdisc/nss_htb.c -+++ b/nss_qdisc/nss_htb.c -@@ -267,7 +267,7 @@ static int nss_htb_ppe_change_class(stru - * Configures a new class. - */ - static int nss_htb_change_class(struct Qdisc *sch, u32 classid, u32 parentid, -- struct nlattr **tca, unsigned long *arg) -+ struct nlattr **tca, unsigned long *arg, struct netlink_ext_ack *extack) - { - struct nss_htb_sched_data *q = qdisc_priv(sch); - struct nss_htb_class_data *cl = (struct nss_htb_class_data *)*arg; -@@ -332,7 +332,7 @@ static int nss_htb_change_class(struct Q - * here. - */ - cl->nq.parent = nq_parent; -- if (nss_qdisc_init(sch, &cl->nq, NSS_SHAPER_NODE_TYPE_HTB_GROUP, classid, accel_mode) < 0) { -+ if (nss_qdisc_init(sch, extack, &cl->nq, NSS_SHAPER_NODE_TYPE_HTB_GROUP, classid, accel_mode) < 0) { - nss_qdisc_error("nss_init for htb class %x failed\n", classid); - goto failure; - } -@@ -478,7 +478,7 @@ static void nss_htb_destroy_class(struct - /* - * And now we destroy the child. - */ -- qdisc_destroy(cl->qdisc); -+ qdisc_put(cl->qdisc); - - /* - * Stop the stats polling timer and free class -@@ -577,7 +577,8 @@ static int nss_htb_delete_class(struct Q - * nss_htb_graft_class() - * Replaces the qdisc attached to the provided class. - */ --static int nss_htb_graft_class(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, struct Qdisc **old) -+static int nss_htb_graft_class(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, struct Qdisc **old, -+ struct netlink_ext_ack *extack) - { - struct nss_htb_class_data *cl = (struct nss_htb_class_data *)arg; - struct nss_if_msg nim_detach; -@@ -682,25 +683,6 @@ static unsigned long nss_htb_get_class(s - } - - /* -- * nss_htb_put_class() -- * Reduces reference count for this class. -- */ --static void nss_htb_put_class(struct Qdisc *sch, unsigned long arg) --{ -- struct nss_htb_class_data *cl = (struct nss_htb_class_data *)arg; -- nss_qdisc_trace("executing put on htb class %x in qdisc %x\n", -- cl->nq.qos_tag, sch->handle); -- -- /* -- * We are safe to destroy the qdisc if the reference count -- * goes down to 0. -- */ -- if (atomic_sub_return(1, &cl->nq.refcnt) == 0) { -- nss_htb_destroy_class(sch, cl); -- } --} -- --/* - * nss_htb_dump_class() - * Dumps all configurable parameters pertaining to this class. - */ -@@ -795,7 +777,7 @@ static void nss_htb_walk(struct Qdisc *s - * nss_htb_change_qdisc() - * Can be used to configure a htb qdisc. - */ --static int nss_htb_change_qdisc(struct Qdisc *sch, struct nlattr *opt) -+static int nss_htb_change_qdisc(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) - { - struct nss_htb_sched_data *q = qdisc_priv(sch); - struct tc_nsshtb_qopt *qopt; -@@ -945,7 +927,7 @@ static void nss_htb_destroy_qdisc(struct - * nss_htb_init_qdisc() - * Initializes the htb qdisc. - */ --static int nss_htb_init_qdisc(struct Qdisc *sch, struct nlattr *opt) -+static int nss_htb_init_qdisc(struct Qdisc *sch, struct nlattr *opt,struct netlink_ext_ack *extack) - { - struct nss_htb_sched_data *q = qdisc_priv(sch); - struct tc_nsshtb_qopt *qopt; -@@ -977,7 +959,7 @@ static int nss_htb_init_qdisc(struct Qdi - /* - * Initialize the NSSHTB shaper in NSS - */ -- if (nss_qdisc_init(sch, &q->nq, NSS_SHAPER_NODE_TYPE_HTB, 0, accel_mode) < 0) { -+ if (nss_qdisc_init(sch, extack, &q->nq, NSS_SHAPER_NODE_TYPE_HTB, 0, accel_mode) < 0) { - nss_qdisc_error("failed to initialize htb qdisc %x in nss", sch->handle); - return -EINVAL; - } -@@ -987,7 +969,7 @@ static int nss_htb_init_qdisc(struct Qdi - /* - * Tune HTB parameters - */ -- if (nss_htb_change_qdisc(sch, opt) < 0) { -+ if (nss_htb_change_qdisc(sch, opt, NULL) < 0) { - nss_qdisc_destroy(&q->nq); - return -EINVAL; - } -@@ -1032,7 +1014,7 @@ static int nss_htb_dump_qdisc(struct Qdi - * nss_htb_enqueue() - * Enqueues a skb to htb qdisc. - */ --static int nss_htb_enqueue(struct sk_buff *skb, struct Qdisc *sch) -+static int nss_htb_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free) - { - return nss_qdisc_enqueue(skb, sch); - } -@@ -1047,18 +1029,6 @@ static struct sk_buff *nss_htb_dequeue(s - } - - /* -- * nss_htb_drop() -- * Drops a single skb from linux queue, if not empty. -- * -- * Does not drop packets that are queued in the NSS. -- */ --static unsigned int nss_htb_drop(struct Qdisc *sch) --{ -- nss_qdisc_trace("drop called on htb qdisc %x\n", sch->handle); -- return nss_qdisc_drop(sch); --} -- --/* - * Registration structure for htb class - */ - const struct Qdisc_class_ops nss_htb_class_ops = { -@@ -1067,9 +1037,8 @@ const struct Qdisc_class_ops nss_htb_cla - .graft = nss_htb_graft_class, - .leaf = nss_htb_leaf_class, - .qlen_notify = nss_htb_qlen_notify, -- .get = nss_htb_get_class, -- .put = nss_htb_put_class, -+ .find = nss_htb_get_class, - .dump = nss_htb_dump_class, - .dump_stats = nss_htb_dump_class_stats, - .walk = nss_htb_walk - }; -@@ -1090,7 +1058,6 @@ struct Qdisc_ops nss_htb_qdisc_ops __rea - .enqueue = nss_htb_enqueue, - .dequeue = nss_htb_dequeue, - .peek = qdisc_peek_dequeued, -- .drop = nss_htb_drop, - .cl_ops = &nss_htb_class_ops, - .priv_size = sizeof(struct nss_htb_sched_data), - .owner = THIS_MODULE ---- a/nss_qdisc/nss_prio.c -+++ b/nss_qdisc/nss_prio.c -@@ -37,7 +37,7 @@ static struct nla_policy nss_prio_policy - * nss_prio_enqueue() - * Enqueues a skb to nssprio qdisc. - */ --static int nss_prio_enqueue(struct sk_buff *skb, struct Qdisc *sch) -+static int nss_prio_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free) - { - return nss_qdisc_enqueue(skb, sch); - } -@@ -52,17 +52,6 @@ static struct sk_buff *nss_prio_dequeue( - } - - /* -- * nss_prio_drop() -- * Drops a single skb from linux queue, if not empty. -- * -- * Does not drop packets that are queued in the NSS. -- */ --static unsigned int nss_prio_drop(struct Qdisc *sch) --{ -- return nss_qdisc_drop(sch); --} -- --/* - * nss_prio_peek() - * Peeks the first packet in queue for this qdisc. - */ -@@ -117,7 +106,7 @@ static void nss_prio_destroy(struct Qdis - /* - * We can now destroy it - */ -- qdisc_destroy(q->queues[i]); -+ qdisc_put(q->queues[i]); - } - - /* -@@ -157,7 +146,7 @@ static int nss_prio_get_max_bands(struct - * nss_prio_change() - * Function call to configure the nssprio parameters - */ --static int nss_prio_change(struct Qdisc *sch, struct nlattr *opt) -+static int nss_prio_change(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) - { - struct nss_prio_sched_data *q; - struct tc_nssprio_qopt *qopt; -@@ -209,7 +198,7 @@ static int nss_prio_change(struct Qdisc - * nss_prio_init() - * Initializes the nssprio qdisc - */ --static int nss_prio_init(struct Qdisc *sch, struct nlattr *opt) -+static int nss_prio_init(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) - { - struct nss_prio_sched_data *q = qdisc_priv(sch); - struct tc_nssprio_qopt *qopt; -@@ -230,14 +219,14 @@ static int nss_prio_init(struct Qdisc *s - accel_mode = qopt->accel_mode; - } - -- if (nss_qdisc_init(sch, &q->nq, NSS_SHAPER_NODE_TYPE_PRIO, 0, accel_mode) < 0) { -+ if (nss_qdisc_init(sch, extack, &q->nq, NSS_SHAPER_NODE_TYPE_PRIO, 0, accel_mode) < 0) { - return -EINVAL; - } - - nss_qdisc_info("Nssprio initialized - handle %x parent %x\n", - sch->handle, sch->parent); - -- if (nss_prio_change(sch, opt) < 0) { -+ if (nss_prio_change(sch, opt, NULL) < 0) { - nss_qdisc_destroy(&q->nq); - return -EINVAL; - } -@@ -280,7 +269,7 @@ nla_put_failure: - * Replaces existing child qdisc with the new qdisc that is passed. - */ - static int nss_prio_graft(struct Qdisc *sch, unsigned long arg, -- struct Qdisc *new, struct Qdisc **old) -+ struct Qdisc *new, struct Qdisc **old, struct netlink_ext_ack *extack) - { - struct nss_prio_sched_data *q = qdisc_priv(sch); - struct nss_qdisc *nq_new = qdisc_priv(new); -@@ -383,15 +372,6 @@ static unsigned long nss_prio_get(struct - } - - /* -- * nss_prio_put() -- * Unused API. -- */ --static void nss_prio_put(struct Qdisc *sch, unsigned long arg) --{ -- nss_qdisc_info("Inside prio put\n"); --} -- --/* - * nss_prio_walk() - * Walks the priority band. - */ -@@ -460,9 +440,8 @@ static int nss_prio_dump_class_stats(str - const struct Qdisc_class_ops nss_prio_class_ops = { - .graft = nss_prio_graft, - .leaf = nss_prio_leaf, -- .get = nss_prio_get, -- .put = nss_prio_put, -+ .find = nss_prio_get, - .walk = nss_prio_walk, - .dump = nss_prio_dump_class, - .dump_stats = nss_prio_dump_class_stats, - }; -@@ -481,7 +459,6 @@ struct Qdisc_ops nss_prio_qdisc_ops __re - .enqueue = nss_prio_enqueue, - .dequeue = nss_prio_dequeue, - .peek = nss_prio_peek, -- .drop = nss_prio_drop, - .init = nss_prio_init, - .reset = nss_prio_reset, - .destroy = nss_prio_destroy, ---- a/nss_qdisc/nss_qdisc.c -+++ b/nss_qdisc/nss_qdisc.c -@@ -929,7 +929,7 @@ static inline void nss_qdisc_add_to_tail - * We do not use the qdisc_enqueue_tail() API here in order - * to prevent stats from getting updated by the API. - */ -- __skb_queue_tail(&sch->q, skb); -+ __qdisc_enqueue_tail(skb, &sch->q); - - spin_unlock_bh(&nq->bounce_protection_lock); - }; -@@ -944,7 +944,7 @@ static inline void nss_qdisc_add_to_tail - * We do not use the qdisc_enqueue_tail() API here in order - * to prevent stats from getting updated by the API. - */ -- __skb_queue_tail(&sch->q, skb); -+ __qdisc_enqueue_tail(skb, &sch->q); - }; - - /* -@@ -966,7 +966,7 @@ static inline struct sk_buff *nss_qdisc_ - * We use __skb_dequeue() to ensure that - * stats don't get updated twice. - */ -- skb = __skb_dequeue(&sch->q); -+ skb = __qdisc_dequeue_head(&sch->q); - - spin_unlock_bh(&nq->bounce_protection_lock); - -@@ -983,7 +983,7 @@ static inline struct sk_buff *nss_qdisc_ - * We use __skb_dequeue() to ensure that - * stats don't get updated twice. - */ -- return __skb_dequeue(&sch->q); -+ return __qdisc_dequeue_head(&sch->q); - }; - - /* -@@ -1064,14 +1064,19 @@ struct Qdisc *nss_qdisc_replace(struct Q - void *nss_qdisc_qopt_get(struct nlattr *opt, struct nla_policy *policy, - uint32_t tca_max, uint32_t tca_params) - { -- struct nlattr *na[tca_max + 1]; -+ struct nlattr *na[8]; - int err; - -+ if (tca_max > 8) { -+ pr_warn("nss_qdisc_qopt_get(): Too many options!\n"); -+ return NULL; -+ } -+ - if (!opt) { - return NULL; - } - -- err = nla_parse_nested(na, tca_max, opt, policy); -+ err = nla_parse_nested_deprecated(na, tca_max, opt, policy, NULL); - if (err < 0) - return NULL; - -@@ -1104,10 +1109,10 @@ struct sk_buff *nss_qdisc_peek(struct Qd - struct sk_buff *skb; - - if (!nq->is_virtual) { -- skb = skb_peek(&sch->q); -+ skb = qdisc_peek_head(sch); - } else { - spin_lock_bh(&nq->bounce_protection_lock); -- skb = skb_peek(&sch->q); -+ skb = qdisc_peek_head(sch); - spin_unlock_bh(&nq->bounce_protection_lock); - } - -@@ -1122,15 +1127,16 @@ unsigned int nss_qdisc_drop(struct Qdisc - { - struct nss_qdisc *nq = qdisc_priv(sch); - unsigned int ret; -+ struct sk_buff *to_free = qdisc_peek_head(sch); - - if (!nq->is_virtual) { -- ret = __qdisc_queue_drop_head(sch, &sch->q); -+ ret = __qdisc_queue_drop_head(sch, &sch->q, &to_free); - } else { - spin_lock_bh(&nq->bounce_protection_lock); - /* - * This function is safe to call within locks - */ -- ret = __qdisc_queue_drop_head(sch, &sch->q); -+ ret = __qdisc_queue_drop_head(sch, &sch->q, &to_free); - spin_unlock_bh(&nq->bounce_protection_lock); - } - -@@ -1958,7 +1964,7 @@ void nss_qdisc_destroy(struct nss_qdisc - * Initializes a shaper in NSS, based on the position of this qdisc (child or root) - * and if its a normal interface or a bridge interface. - */ --int nss_qdisc_init(struct Qdisc *sch, struct nss_qdisc *nq, nss_shaper_node_type_t type, uint32_t classid, uint32_t accel_mode) -+int nss_qdisc_init(struct Qdisc *sch, struct netlink_ext_ack *extack, struct nss_qdisc *nq, nss_shaper_node_type_t type, uint32_t classid, uint32_t accel_mode) - { - struct Qdisc *root; - u32 parent; -@@ -2471,6 +2481,8 @@ static void nss_qdisc_basic_stats_callba - struct gnet_stats_queue *qstats; - struct nss_shaper_node_stats_response *response; - atomic_t *refcnt; -+ refcount_t *refcnt_new; -+ bool is_refcnt_zero = false; - - if (nim->cm.response != NSS_CMN_RESPONSE_ACK) { - nss_qdisc_warning("Qdisc %p (type %d): Receive stats FAILED - " -@@ -2494,7 +2506,7 @@ static void nss_qdisc_basic_stats_callba - } else { - bstats = &qdisc->bstats; - qstats = &qdisc->qstats; -- refcnt = &qdisc->refcnt; -+ refcnt_new = &qdisc->refcnt; - qdisc->q.qlen = response->sn_stats.qlen_packets; - } - -@@ -2533,11 +2545,20 @@ static void nss_qdisc_basic_stats_callba - * All access to nq fields below do not need lock protection. They - * do not get manipulated on different thread contexts. - */ -- if (atomic_read(refcnt) == 0) { -+ if (nq->is_class) { -+ if (atomic_read(refcnt) == 0) -+ is_refcnt_zero = true; -+ } -+ else { -+ if (refcount_read(refcnt_new) == 0) -+ is_refcnt_zero = true; -+ } -+ if (is_refcnt_zero) { - atomic_sub(1, &nq->pending_stat_requests); - wake_up(&nq->wait_queue); - return; - } -+ - - /* - * Requests for stats again, after 1 sec. -@@ -2555,9 +2576,9 @@ static void nss_qdisc_basic_stats_callba - * nss_qdisc_get_stats_timer_callback() - * Invoked periodically to get updated stats - */ --static void nss_qdisc_get_stats_timer_callback(unsigned long int data) -+static void nss_qdisc_get_stats_timer_callback(struct timer_list *arg) - { -- struct nss_qdisc *nq = (struct nss_qdisc *)data; -+ struct nss_qdisc *nq = (struct nss_qdisc *)arg->cust_data; - nss_tx_status_t rc; - struct nss_if_msg nim; - int msg_type; -@@ -2604,9 +2625,8 @@ void nss_qdisc_start_basic_stats_polling - return; - } - -- init_timer(&nq->stats_get_timer); -- nq->stats_get_timer.function = nss_qdisc_get_stats_timer_callback; -- nq->stats_get_timer.data = (unsigned long)nq; -+ timer_setup(&nq->stats_get_timer, nss_qdisc_get_stats_timer_callback, 0); -+ nq->stats_get_timer.cust_data = (unsigned long)nq; - nq->stats_get_timer.expires = jiffies + HZ; - atomic_set(&nq->pending_stat_requests, 1); - add_timer(&nq->stats_get_timer); -@@ -2650,7 +2670,7 @@ int nss_qdisc_gnet_stats_copy_basic(stru - #if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 18, 0)) - return gnet_stats_copy_basic(d, b); - #else -- return gnet_stats_copy_basic(d, NULL, b); -+ return gnet_stats_copy_basic(NULL, d, NULL, b); - #endif - } - ---- a/nss_qdisc/nss_tbl.c -+++ b/nss_qdisc/nss_tbl.c -@@ -29,7 +29,7 @@ static struct nla_policy nss_tbl_policy[ - [TCA_NSSTBL_PARMS] = { .len = sizeof(struct tc_nsstbl_qopt) }, - }; - --static int nss_tbl_enqueue(struct sk_buff *skb, struct Qdisc *sch) -+static int nss_tbl_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free) - { - return nss_qdisc_enqueue(skb, sch); - } -@@ -39,11 +39,6 @@ static struct sk_buff *nss_tbl_dequeue(s - return nss_qdisc_dequeue(sch); - } - --static unsigned int nss_tbl_drop(struct Qdisc *sch) --{ -- return nss_qdisc_drop(sch); --} -- - static struct sk_buff *nss_tbl_peek(struct Qdisc *sch) - { - return nss_qdisc_peek(sch); -@@ -77,7 +72,7 @@ static void nss_tbl_destroy(struct Qdisc - /* - * Now we can destroy our child qdisc - */ -- qdisc_destroy(q->qdisc); -+ qdisc_put(q->qdisc); - - /* - * Stop the polling of basic stats and destroy qdisc. -@@ -132,7 +127,7 @@ fail: - } - #endif - --static int nss_tbl_change(struct Qdisc *sch, struct nlattr *opt) -+static int nss_tbl_change(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) - { - struct nss_tbl_sched_data *q = qdisc_priv(sch); - struct tc_nsstbl_qopt *qopt; -@@ -216,7 +211,7 @@ static int nss_tbl_change(struct Qdisc * - return 0; - } - --static int nss_tbl_init(struct Qdisc *sch, struct nlattr *opt) -+static int nss_tbl_init(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) - { - struct nss_tbl_sched_data *q = qdisc_priv(sch); - struct tc_nsstbl_qopt *qopt; -@@ -232,10 +227,10 @@ static int nss_tbl_init(struct Qdisc *sc - return -EINVAL; - } - -- if (nss_qdisc_init(sch, &q->nq, NSS_SHAPER_NODE_TYPE_TBL, 0, qopt->accel_mode) < 0) -+ if (nss_qdisc_init(sch, extack, &q->nq, NSS_SHAPER_NODE_TYPE_TBL, 0, qopt->accel_mode) < 0) - return -EINVAL; - -- if (nss_tbl_change(sch, opt) < 0) { -+ if (nss_tbl_change(sch, opt, NULL) < 0) { - nss_qdisc_info("Failed to configure tbl\n"); - nss_qdisc_destroy(&q->nq); - return -EINVAL; -@@ -287,7 +282,7 @@ static int nss_tbl_dump_class(struct Qdi - } - - static int nss_tbl_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, -- struct Qdisc **old) -+ struct Qdisc **old, struct netlink_ext_ack *extack) - { - struct nss_tbl_sched_data *q = qdisc_priv(sch); - struct nss_qdisc *nq_new = (struct nss_qdisc *)qdisc_priv(new); -@@ -344,10 +339,6 @@ static unsigned long nss_tbl_get(struct - return 1; - } - --static void nss_tbl_put(struct Qdisc *sch, unsigned long arg) --{ --} -- - static void nss_tbl_walk(struct Qdisc *sch, struct qdisc_walker *walker) - { - nss_qdisc_info("Nsstbl walk called"); -@@ -364,9 +355,8 @@ static void nss_tbl_walk(struct Qdisc *s - const struct Qdisc_class_ops nss_tbl_class_ops = { - .graft = nss_tbl_graft, - .leaf = nss_tbl_leaf, -- .get = nss_tbl_get, -- .put = nss_tbl_put, -+ .find = nss_tbl_get, - .walk = nss_tbl_walk, - .dump = nss_tbl_dump_class, - }; - -@@ -381,7 +370,6 @@ struct Qdisc_ops nss_tbl_qdisc_ops __rea - .enqueue = nss_tbl_enqueue, - .dequeue = nss_tbl_dequeue, - .peek = nss_tbl_peek, -- .drop = nss_tbl_drop, - .init = nss_tbl_init, - .reset = nss_tbl_reset, - .destroy = nss_tbl_destroy, ---- a/nss_qdisc/nss_wred.c -+++ b/nss_qdisc/nss_wred.c -@@ -55,7 +55,7 @@ static struct nla_policy nss_wred_policy - * nss_wred_enqueue() - * Enqueue API for nsswred qdisc - */ --static int nss_wred_enqueue(struct sk_buff *skb, struct Qdisc *sch) -+static int nss_wred_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free) - { - return nss_qdisc_enqueue(skb, sch); - } -@@ -70,16 +70,6 @@ static struct sk_buff *nss_wred_dequeue( - } - - /* -- * nss_wred_drop() -- * Drops a packet from HLOS queue. -- */ --static unsigned int nss_wred_drop(struct Qdisc *sch) --{ -- nss_qdisc_info("nsswred dropping"); -- return nss_qdisc_drop(sch); --} -- --/* - * nss_wred_reset() - * Reset the nsswred qdisc - */ -@@ -171,7 +161,7 @@ fail: - * nss_wred_change() - * Function call to configure the nsswred parameters - */ --static int nss_wred_change(struct Qdisc *sch, struct nlattr *opt) -+static int nss_wred_change(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) - { - struct nss_wred_sched_data *q = qdisc_priv(sch); - struct tc_nsswred_qopt *qopt; -@@ -298,7 +288,7 @@ static int nss_wred_change(struct Qdisc - * nss_wred_init() - * Init the nsswred qdisc - */ --static int nss_wred_init(struct Qdisc *sch, struct nlattr *opt) -+static int nss_wred_init(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) - { - struct nss_qdisc *nq = qdisc_priv(sch); - struct tc_nsswred_qopt *qopt; -@@ -315,11 +305,11 @@ static int nss_wred_init(struct Qdisc *s - nss_qdisc_info("Initializing Wred - type %d\n", NSS_SHAPER_NODE_TYPE_WRED); - nss_wred_reset(sch); - -- if (nss_qdisc_init(sch, nq, NSS_SHAPER_NODE_TYPE_WRED, 0, qopt->accel_mode) < 0) -+ if (nss_qdisc_init(sch, extack, nq, NSS_SHAPER_NODE_TYPE_WRED, 0, qopt->accel_mode) < 0) - return -EINVAL; - - nss_qdisc_info("NSS wred initialized - handle %x parent %x\n", sch->handle, sch->parent); -- if (nss_wred_change(sch, opt) < 0) { -+ if (nss_wred_change(sch, opt, NULL) < 0) { - nss_qdisc_destroy(nq); - return -EINVAL; - } -@@ -405,7 +395,6 @@ struct Qdisc_ops nss_red_qdisc_ops __rea - .enqueue = nss_wred_enqueue, - .dequeue = nss_wred_dequeue, - .peek = nss_wred_peek, -- .drop = nss_wred_drop, - .init = nss_wred_init, - .reset = nss_wred_reset, - .destroy = nss_wred_destroy, -@@ -423,7 +412,6 @@ struct Qdisc_ops nss_wred_qdisc_ops __re - .enqueue = nss_wred_enqueue, - .dequeue = nss_wred_dequeue, - .peek = nss_wred_peek, -- .drop = nss_wred_drop, - .init = nss_wred_init, - .reset = nss_wred_reset, - .destroy = nss_wred_destroy, ---- a/nss_qdisc/nss_wrr.c -+++ b/nss_qdisc/nss_wrr.c -@@ -84,7 +84,7 @@ static void nss_wrr_destroy_class(struct - /* - * And now we destroy the child. - */ -- qdisc_destroy(cl->qdisc); -+ qdisc_put(cl->qdisc); - - /* - * Stop the stats polling timer and free class -@@ -219,7 +219,7 @@ static int nss_wrr_ppe_change_class(stru - #endif - - static int nss_wrr_change_class(struct Qdisc *sch, u32 classid, u32 parentid, -- struct nlattr **tca, unsigned long *arg) -+ struct nlattr **tca, unsigned long *arg, struct netlink_ext_ack *extack) - { - struct nss_wrr_sched_data *q = qdisc_priv(sch); - struct nss_wrr_class_data *cl = (struct nss_wrr_class_data *)*arg; -@@ -286,7 +286,7 @@ static int nss_wrr_change_class(struct Q - * here. - */ - cl->nq.parent = &q->nq; -- if (nss_qdisc_init(sch, &cl->nq, NSS_SHAPER_NODE_TYPE_WRR_GROUP, classid, accel_mode) < 0) { -+ if (nss_qdisc_init(sch, extack, &cl->nq, NSS_SHAPER_NODE_TYPE_WRR_GROUP, classid, accel_mode) < 0) { - nss_qdisc_error("Nss init for class %u failed\n", classid); - return -EINVAL; - } -@@ -422,7 +422,7 @@ static int nss_wrr_delete_class(struct Q - } - - static int nss_wrr_graft_class(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, -- struct Qdisc **old) -+ struct Qdisc **old, struct netlink_ext_ack *extack) - { - struct nss_wrr_sched_data *q = qdisc_priv(sch); - struct nss_wrr_class_data *cl = (struct nss_wrr_class_data *)arg; -@@ -517,20 +517,6 @@ static unsigned long nss_wrr_get_class(s - return (unsigned long)cl; - } - --static void nss_wrr_put_class(struct Qdisc *sch, unsigned long arg) --{ -- struct nss_wrr_class_data *cl = (struct nss_wrr_class_data *)arg; -- nss_qdisc_info("nss_wrr put class for %p\n", cl); -- -- /* -- * We are safe to destroy the qdisc if the reference count -- * goes down to 0. -- */ -- if (atomic_sub_return(1, &cl->nq.refcnt) == 0) { -- nss_wrr_destroy_class(sch, cl); -- } --} -- - static int nss_wrr_dump_class(struct Qdisc *sch, unsigned long arg, struct sk_buff *skb, - struct tcmsg *tcm) - { -@@ -600,7 +586,7 @@ static void nss_wrr_walk(struct Qdisc *s - } - } - --static int nss_wrr_init_qdisc(struct Qdisc *sch, struct nlattr *opt) -+static int nss_wrr_init_qdisc(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) - { - struct nss_wrr_sched_data *q = qdisc_priv(sch); - int err; -@@ -629,7 +615,7 @@ static int nss_wrr_init_qdisc(struct Qdi - /* - * Initialize the NSSWRR shaper in NSS - */ -- if (nss_qdisc_init(sch, &q->nq, NSS_SHAPER_NODE_TYPE_WRR, 0, qopt->accel_mode) < 0) { -+ if (nss_qdisc_init(sch, extack, &q->nq, NSS_SHAPER_NODE_TYPE_WRR, 0, qopt->accel_mode) < 0) { - nss_qdisc_warning("Failed init nss_wrr qdisc"); - return -EINVAL; - } -@@ -669,7 +655,7 @@ static int nss_wrr_init_qdisc(struct Qdi - return 0; - } - --static int nss_wrr_change_qdisc(struct Qdisc *sch, struct nlattr *opt) -+static int nss_wrr_change_qdisc(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) - { - struct nss_wrr_sched_data *q; - struct tc_nsswrr_qopt *qopt; -@@ -809,7 +795,7 @@ nla_put_failure: - return -EMSGSIZE; - } - --static int nss_wrr_enqueue(struct sk_buff *skb, struct Qdisc *sch) -+static int nss_wrr_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free) - { - return nss_qdisc_enqueue(skb, sch); - } -@@ -819,21 +805,14 @@ static struct sk_buff *nss_wrr_dequeue(s - return nss_qdisc_dequeue(sch); - } - --static unsigned int nss_wrr_drop(struct Qdisc *sch) --{ -- nss_qdisc_info("Nsswrr drop\n"); -- return nss_qdisc_drop(sch); --} -- - const struct Qdisc_class_ops nss_wrr_class_ops = { - .change = nss_wrr_change_class, - .delete = nss_wrr_delete_class, - .graft = nss_wrr_graft_class, - .leaf = nss_wrr_leaf_class, - .qlen_notify = nss_wrr_qlen_notify, -- .get = nss_wrr_get_class, -- .put = nss_wrr_put_class, -+ .find = nss_wrr_get_class, - .dump = nss_wrr_dump_class, - .dump_stats = nss_wrr_dump_class_stats, - .walk = nss_bf_walk - }; -@@ -851,7 +829,6 @@ struct Qdisc_ops nss_wrr_qdisc_ops __rea - .enqueue = nss_wrr_enqueue, - .dequeue = nss_wrr_dequeue, - .peek = qdisc_peek_dequeued, -- .drop = nss_wrr_drop, - .cl_ops = &nss_wrr_class_ops, - .priv_size = sizeof(struct nss_wrr_sched_data), - .owner = THIS_MODULE -@@ -863,9 +840,8 @@ const struct Qdisc_class_ops nss_wfq_cla - .graft = nss_wrr_graft_class, - .leaf = nss_wrr_leaf_class, - .qlen_notify = nss_wrr_qlen_notify, -- .get = nss_wrr_get_class, -- .put = nss_wrr_put_class, -+ .find = nss_wrr_get_class, - .dump = nss_wrr_dump_class, - .dump_stats = nss_wrr_dump_class_stats, - .walk = nss_wrr_walk - }; -@@ -883,7 +858,6 @@ struct Qdisc_ops nss_wfq_qdisc_ops __rea - .enqueue = nss_wrr_enqueue, - .dequeue = nss_wrr_dequeue, - .peek = qdisc_peek_dequeued, -- .drop = nss_wrr_drop, - .cl_ops = &nss_wrr_class_ops, - .priv_size = sizeof(struct nss_wrr_sched_data), - .owner = THIS_MODULE diff --git a/root/package/qca/nss/qca-nss-clients/patches/101-kernel-5.4-support-gre.patch b/root/package/qca/nss/qca-nss-clients/patches/101-kernel-5.4-support-gre.patch deleted file mode 100644 index 705ceabe..00000000 --- a/root/package/qca/nss/qca-nss-clients/patches/101-kernel-5.4-support-gre.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 7c89187ab2d165ccffed627742e7cb72cce375ef Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Sun, 12 Jul 2020 22:49:30 +0200 -Subject: [PATCH] kernel-5.4-support-gre - ---- - gre/nss_connmgr_gre.c | 16 +++++++--------- - gre/nss_connmgr_gre_v6.c | 4 ++-- - 2 files changed, 9 insertions(+), 11 deletions(-) - -diff --git a/gre/nss_connmgr_gre.c b/gre/nss_connmgr_gre.c -index 52203b1..6de8f6e 100644 ---- a/gre/nss_connmgr_gre.c -+++ b/gre/nss_connmgr_gre.c -@@ -88,7 +88,7 @@ static int nss_connmgr_gre_dev_init(struct net_device *dev) - u64_stats_init(&stats->syncp); - } - -- if ((dev->priv_flags & IFF_GRE_V4_TAP) || (dev->type == ARPHRD_IPGRE)) { -+ if ((dev->priv_flags_qca_ecm & IFF_QCA_ECM_GRE_V4_TAP) || (dev->type == ARPHRD_IPGRE)) { - dev->needed_headroom = sizeof(struct iphdr) + sizeof(struct ethhdr) + MAX_WIFI_HEADROOM + append; - dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr) - append; - dev->features |= NETIF_F_NETNS_LOCAL | NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA; -@@ -169,7 +169,7 @@ fail: - * nss_connmgr_gre_dev_stats64() - * Netdev ops function to retrieve stats. - */ --struct rtnl_link_stats64 *nss_connmgr_gre_dev_stats64(struct net_device *dev, -+void nss_connmgr_gre_dev_stats64(struct net_device *dev, - struct rtnl_link_stats64 *tot) - { - uint64_t rx_packets, rx_bytes, tx_packets, tx_bytes; -@@ -202,8 +202,6 @@ struct rtnl_link_stats64 *nss_connmgr_gre_dev_stats64(struct net_device *dev, - tot->rx_dropped = dev->stats.rx_dropped; - tot->tx_dropped = dev->stats.tx_dropped; - } -- -- return tot; - } - - /* -@@ -390,7 +388,7 @@ static int32_t nss_connmgr_gre_prepare_config_cmd(struct net_device *dev, - { - struct nss_gre_config_msg *cmsg = &req->msg.cmsg; - -- if ((dev->type == ARPHRD_ETHER) && (dev->priv_flags & IFF_GRE_V4_TAP)) { -+ if ((dev->type == ARPHRD_ETHER) && (dev->priv_flags_qca_ecm & IFF_QCA_ECM_GRE_V4_TAP)) { - cmsg->mode = NSS_GRE_MODE_TAP; - cmsg->ip_type = NSS_GRE_IP_IPV4; - if (enable_unalign) { -@@ -399,7 +397,7 @@ static int32_t nss_connmgr_gre_prepare_config_cmd(struct net_device *dev, - return nss_connmgr_gre_v4_get_config(dev, req, next_dev, hold); - } - -- if ((dev->type == ARPHRD_ETHER) && (dev->priv_flags & IFF_GRE_V6_TAP)) { -+ if ((dev->type == ARPHRD_ETHER) && (dev->priv_flags_qca_ecm & IFF_QCA_ECM_GRE_V6_TAP)) { - cmsg->mode = NSS_GRE_MODE_TAP; - cmsg->ip_type = NSS_GRE_IP_IPV6; - if (enable_unalign) { -@@ -605,7 +603,7 @@ static bool nss_connmgr_gre_is_gre(struct net_device *dev) - { - if ((dev->type == ARPHRD_IPGRE) || - (dev->type == ARPHRD_IP6GRE) || ((dev->type == ARPHRD_ETHER) && -- (dev->priv_flags & (IFF_GRE_V4_TAP | IFF_GRE_V6_TAP)))) { -+ (dev->priv_flags_qca_ecm & (IFF_QCA_ECM_GRE_V4_TAP | IFF_QCA_ECM_GRE_V6_TAP)))) { - return true; - } - -@@ -692,10 +690,10 @@ static struct net_device *__nss_connmgr_gre_create_interface(struct nss_connmgr_ - nss_connmgr_gre_tap_setup(dev); - - if (cfg->is_ipv6) { -- dev->priv_flags |= IFF_GRE_V6_TAP; -+ dev->priv_flags_qca_ecm |= IFF_QCA_ECM_GRE_V6_TAP; - ret = nss_connmgr_gre_v6_set_config(dev, cfg); - } else { -- dev->priv_flags |= IFF_GRE_V4_TAP; -+ dev->priv_flags_qca_ecm |= IFF_QCA_ECM_GRE_V4_TAP; - ret = nss_connmgr_gre_v4_set_config(dev, cfg); - } - break; -diff --git a/gre/nss_connmgr_gre_v6.c b/gre/nss_connmgr_gre_v6.c -index f9a8e58..e93c7e4 100644 ---- a/gre/nss_connmgr_gre_v6.c -+++ b/gre/nss_connmgr_gre_v6.c -@@ -46,7 +46,7 @@ static struct net_device *nss_connmgr_gre_v6_get_tx_dev(uint8_t *dest_ip) - struct net_device *dev; - - memcpy(ipv6_addr.s6_addr, dest_ip, 16); -- rt = rt6_lookup(&init_net, &ipv6_addr, NULL, 0, 0); -+ rt = rt6_lookup(&init_net, &ipv6_addr, NULL, 0, NULL, 0); - if (!rt) { - return NULL; - } -@@ -92,7 +92,7 @@ static int nss_connmgr_gre_v6_get_mac_address(uint8_t *src_ip, uint8_t *dest_ip, - * Find dest MAC address - */ - memcpy(ipv6_addr.s6_addr, dest_ip, 16); -- rt = rt6_lookup(&init_net, &ipv6_addr, NULL, 0, 0); -+ rt = rt6_lookup(&init_net, &ipv6_addr, NULL, 0, NULL, 0); - if (!rt) { - return GRE_ERR_NEIGH_LOOKUP; - } --- -2.27.0 - diff --git a/root/package/qca/nss/qca-nss-clients/patches/102-kernel-5.4-support-ipsec.patch b/root/package/qca/nss/qca-nss-clients/patches/102-kernel-5.4-support-ipsec.patch deleted file mode 100644 index de43b4d0..00000000 --- a/root/package/qca/nss/qca-nss-clients/patches/102-kernel-5.4-support-ipsec.patch +++ /dev/null @@ -1,29 +0,0 @@ ---- a/ipsecmgr/v1.0/nss_ipsecmgr.c -+++ b/ipsecmgr/v1.0/nss_ipsecmgr.c -@@ -377,7 +377,7 @@ free: - * nss_ipsecmgr_tunnel_stats() - * get tunnel statistics - */ --static struct rtnl_link_stats64 *nss_ipsecmgr_tunnel_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) -+void nss_ipsecmgr_tunnel_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) - { - struct nss_ipsecmgr_priv *priv = netdev_priv(dev); - -@@ -389,8 +389,6 @@ static struct rtnl_link_stats64 *nss_ips - read_lock_bh(&ipsecmgr_ctx->lock); - memcpy(stats, &priv->stats, sizeof(struct rtnl_link_stats64)); - read_unlock_bh(&ipsecmgr_ctx->lock); -- -- return stats; - } - - /* -@@ -442,7 +440,7 @@ static void nss_ipsecmgr_tunnel_setup(st - dev->header_ops = NULL; - dev->netdev_ops = &nss_ipsecmgr_tunnel_ops; - -- dev->destructor = nss_ipsecmgr_tunnel_free; -+ dev->priv_destructor = nss_ipsecmgr_tunnel_free; - - /* - * get the MAC address from the ethernet device diff --git a/root/package/qca/nss/qca-nss-clients/patches/103-kernel-5.4-support-dtls.patch b/root/package/qca/nss/qca-nss-clients/patches/103-kernel-5.4-support-dtls.patch deleted file mode 100644 index ae9c9147..00000000 --- a/root/package/qca/nss/qca-nss-clients/patches/103-kernel-5.4-support-dtls.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/dtls/v1.0/nss_connmgr_dtls_netdev.c -+++ b/dtls/v1.0/nss_connmgr_dtls_netdev.c -@@ -160,7 +160,7 @@ static void nss_dtlsmgr_dev_setup(struct - dev->ethtool_ops = NULL; - dev->header_ops = NULL; - dev->netdev_ops = &nss_dtlsmgr_session_ops; -- dev->destructor = NULL; -+ dev->priv_destructor = NULL; - - memcpy(dev->dev_addr, "\xaa\xbb\xcc\xdd\xee\xff", dev->addr_len); - memset(dev->broadcast, 0xff, dev->addr_len); diff --git a/root/package/qca/nss/qca-nss-clients/patches/104-kernel-5.4-support-l2tp.patch b/root/package/qca/nss/qca-nss-clients/patches/104-kernel-5.4-support-l2tp.patch deleted file mode 100644 index c637235c..00000000 --- a/root/package/qca/nss/qca-nss-clients/patches/104-kernel-5.4-support-l2tp.patch +++ /dev/null @@ -1,64 +0,0 @@ ---- a/l2tp/l2tpv2/nss_connmgr_l2tpv2.h -+++ b/l2tp/l2tpv2/nss_connmgr_l2tpv2.h -@@ -30,10 +30,10 @@ - - #define L2TP_V_2 2 - --#define tunnel_hold(tunnel) atomic_inc(&tunnel->ref_count) --#define tunnel_put(tunnel) atomic_dec(&tunnel->ref_count) --#define session_hold(session) atomic_inc(&session->ref_count) --#define session_put(session) atomic_dec(&session->ref_count) -+#define tunnel_hold(tunnel) refcount_inc(&tunnel->ref_count) -+#define tunnel_put(tunnel) refcount_dec(&tunnel->ref_count) -+#define session_hold(session) refcount_inc(&session->ref_count) -+#define session_put(session) refcount_dec(&session->ref_count) - - /* - * ---------------------------------------------------------------------------------- ---- a/l2tp/l2tpv2/nss_connmgr_l2tpv2.c -+++ b/l2tp/l2tpv2/nss_connmgr_l2tpv2.c -@@ -244,7 +244,7 @@ static struct nss_connmgr_l2tpv2_session - */ - data->l2tpv2.session.session_id = session->session_id; - data->l2tpv2.session.peer_session_id = session->peer_session_id; -- data->l2tpv2.session.offset = session->offset; -+ data->l2tpv2.session.offset = 0; - data->l2tpv2.session.hdr_len = session->hdr_len; - data->l2tpv2.session.reorder_timeout = session->reorder_timeout; - data->l2tpv2.session.recv_seq = session->recv_seq; -@@ -253,7 +253,7 @@ static struct nss_connmgr_l2tpv2_session - nss_connmgr_l2tpv2_info("sess %u, peer=%u nr=%u ns=%u off=%u hdr_len=%u timeout=%x" - " recv_seq=%x send_seq=%x\n", - session->session_id, session->peer_session_id, session->nr, -- session->ns, session->offset, session->hdr_len, -+ session->ns, 0, session->hdr_len, - session->reorder_timeout, session->recv_seq, - session->send_seq); - ---- a/l2tp/l2tpv2/nss_l2tpv2_stats.c -+++ b/l2tp/l2tpv2/nss_l2tpv2_stats.c -@@ -21,6 +21,7 @@ - */ - - #include -+#include - #include - #include - #include -@@ -103,14 +104,14 @@ void nss_l2tpv2_update_dev_stats(struct - /* - * Update tunnel & session stats - */ -- tunnel = l2tp_tunnel_find(dev_net(dev), data.l2tpv2.tunnel.tunnel_id); -+ tunnel = l2tp_tunnel_get(dev_net(dev), data.l2tpv2.tunnel.tunnel_id); - if (!tunnel) { - dev_put(dev); - return; - } - tunnel_hold(tunnel); - -- session = l2tp_session_find(dev_net(dev), tunnel, data.l2tpv2.session.session_id); -+ session = l2tp_session_get(dev_net(dev), data.l2tpv2.session.session_id); - if (!session) { - tunnel_put(tunnel); - dev_put(dev); diff --git a/root/package/qca/nss/qca-nss-clients/patches/200-qdisc-fix-compile-error.patch b/root/package/qca/nss/qca-nss-clients/patches/200-qdisc-fix-compile-error.patch deleted file mode 100644 index 4e147489..00000000 --- a/root/package/qca/nss/qca-nss-clients/patches/200-qdisc-fix-compile-error.patch +++ /dev/null @@ -1,14 +0,0 @@ ---- a/nss_qdisc/nss_qdisc.c -+++ b/nss_qdisc/nss_qdisc.c -@@ -2708,9 +2708,11 @@ static int nss_qdisc_if_event_cb(struct - case NETDEV_BR_JOIN: - nss_qdisc_info("Reveived NETDEV_BR_JOIN on interface %s\n", - dev->name); -+ goto fall_through; - case NETDEV_BR_LEAVE: - nss_qdisc_info("Reveived NETDEV_BR_LEAVE on interface %s\n", - dev->name); -+fall_through: - br = nss_qdisc_get_dev_master(dev); - if_num = nss_cmn_get_interface_number(nss_qdisc_ctx, dev); - diff --git a/root/package/qca/nss/qca-nss-clients/patches/202-vlanmgr-fix-compile-error.patch b/root/package/qca/nss/qca-nss-clients/patches/202-vlanmgr-fix-compile-error.patch deleted file mode 100644 index 53af3192..00000000 --- a/root/package/qca/nss/qca-nss-clients/patches/202-vlanmgr-fix-compile-error.patch +++ /dev/null @@ -1,48 +0,0 @@ ---- a/vlan/nss_vlan_mgr.c -+++ b/vlan/nss_vlan_mgr.c -@@ -820,8 +820,10 @@ static struct nss_vlan_pvt *nss_vlan_mgr - */ - static void nss_vlan_mgr_instance_free(struct nss_vlan_pvt *v) - { -+#ifdef NSS_VLAN_MGR_PPE_SUPPORT - int32_t i; - int ret = 0; -+#endif - - spin_lock(&vlan_mgr_ctx.lock); - BUG_ON(--v->refs); -@@ -979,8 +981,11 @@ static int nss_vlan_mgr_register_event(s - int ret; - #endif - uint32_t vlan_tag; -+#ifdef NSS_VLAN_MGR_PPE_SUPPORT - struct net_device *slave; -- int32_t port, port_if; -+ int32_t port; -+#endif -+ int32_t port_if; - struct vlan_dev_priv *vlan; - struct net_device *real_dev; - bool is_bond_master = false; -@@ -1354,8 +1359,10 @@ return_with_error: - int nss_vlan_mgr_join_bridge(struct net_device *dev, uint32_t bridge_vsi) - { - struct nss_vlan_pvt *v = nss_vlan_mgr_instance_find_and_ref(dev); -+#ifdef NSS_VLAN_MGR_PPE_SUPPORT - struct net_device *real_dev; - int ret; -+#endif - - if (!v) - return 0; -@@ -1415,8 +1422,10 @@ EXPORT_SYMBOL(nss_vlan_mgr_join_bridge); - int nss_vlan_mgr_leave_bridge(struct net_device *dev, uint32_t bridge_vsi) - { - struct nss_vlan_pvt *v = nss_vlan_mgr_instance_find_and_ref(dev); -+#ifdef NSS_VLAN_MGR_PPE_SUPPORT - struct net_device *real_dev; - int ret; -+#endif - - if (!v) - return 0; diff --git a/root/package/qca/nss/qca-nss-crypto/Makefile b/root/package/qca/nss/qca-nss-crypto/Makefile deleted file mode 100644 index 213e2447..00000000 --- a/root/package/qca/nss/qca-nss-crypto/Makefile +++ /dev/null @@ -1,74 +0,0 @@ -include $(TOPDIR)/rules.mk -include $(INCLUDE_DIR)/kernel.mk - -PKG_NAME:=qca-nss-crypto -PKG_RELEASE:=1 - -PKG_SOURCE_URL:=https://source.codeaurora.org/quic/qsdk/oss/lklm/nss-crypto -PKG_SOURCE_PROTO:=git -PKG_SOURCE_VERSION:=e7651c2986d30b5e8ca5ad6b9a72c47febdf3cca -PKG_MIRROR_HASH:=381ba448ccd9e0ff69fa52b3e10687b72260b7d0bf865cac10be7f159573b6c8 - -include $(INCLUDE_DIR)/package.mk - -ifeq ($(CONFIG_TARGET_ipq),y) -subtarget:=$(SUBTARGET) -else -subtarget:=$(CONFIG_TARGET_BOARD) -endif - -# v1.0 is for Akronite -# v2.0 is for Hawkeye/Cypress/Maple -ifneq (, $(findstring $(subtarget), "ipq807x" "ipq807x_64" "ipq60xx" "ipq60xx_64" "ipq50xx" "ipq50xx_64")) -NSS_CRYPTO_DIR:=v2.0 -else -NSS_CRYPTO_DIR:=v1.0 -endif - -define KernelPackage/qca-nss-crypto/Default - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Devices - DEPENDS:=@(TARGET_ipq806x||TARGET_ipq807x||TARGET_ipq50xx||TARGET_ipq60xx) +kmod-qca-nss-drv -endef - -define KernelPackage/qca-nss-crypto - $(call KernelPackage/qca-nss-crypto/Default) - TITLE:=Kernel driver for NSS crypto driver - FILES:=$(PKG_BUILD_DIR)/$(NSS_CRYPTO_DIR)/src/qca-nss-crypto.ko \ - $(PKG_BUILD_DIR)/$(NSS_CRYPTO_DIR)/tool/qca-nss-crypto-tool.ko - AUTOLOAD:=$(call AutoLoad,52,qca-nss-crypto) -endef - -define KernelPackage/qca-nss-crypto/Description -This package contains a NSS crypto driver for QCA chipset -endef - -define Build/InstallDev/qca-nss-crypto - $(INSTALL_DIR) $(1)/usr/include/qca-nss-crypto - $(CP) $(PKG_BUILD_DIR)/$(NSS_CRYPTO_DIR)/include/* $(1)/usr/include/qca-nss-crypto -endef - -define Build/InstallDev - $(call Build/InstallDev/qca-nss-crypto,$(1)) -endef - -EXTRA_CFLAGS+= \ - -DCONFIG_NSS_DEBUG_LEVEL=4 \ - -I$(STAGING_DIR)/usr/include/qca-nss-crypto \ - -I$(STAGING_DIR)/usr/include/qca-nss-drv \ - -I$(PKG_BUILD_DIR)/$(NSS_CRYPTO_DIR)/include \ - -I$(PKG_BUILD_DIR)/$(NSS_CRYPTO_DIR)/src - -define Build/Compile - $(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \ - $(KERNEL_MAKE_FLAGS) \ - $(PKG_MAKE_FLAGS) \ - M="$(PKG_BUILD_DIR)" \ - EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ - NSS_CRYPTO_DIR=$(NSS_CRYPTO_DIR) \ - SoC="$(subtarget)" \ - modules -endef - -$(eval $(call KernelPackage,qca-nss-crypto)) diff --git a/root/package/qca/nss/qca-nss-crypto/patches/100-kernel-5.4-support.patch b/root/package/qca/nss/qca-nss-crypto/patches/100-kernel-5.4-support.patch deleted file mode 100644 index b9ef6191..00000000 --- a/root/package/qca/nss/qca-nss-crypto/patches/100-kernel-5.4-support.patch +++ /dev/null @@ -1,42 +0,0 @@ ---- a/v1.0/tool/nss_crypto_bench.c -+++ b/v1.0/tool/nss_crypto_bench.c -@@ -75,8 +75,8 @@ static DECLARE_WAIT_QUEUE_HEAD(tx_comp); - static DECLARE_WAIT_QUEUE_HEAD(tx_start); - static struct task_struct *tx_thread = NULL; - --static struct timeval init_time; --static struct timeval comp_time; -+static struct timespec64 init_time; -+static struct timespec64 comp_time; - static spinlock_t op_lock; - static nss_crypto_handle_t crypto_hdl; - -@@ -782,7 +782,7 @@ static int crypto_bench_tx(void *arg) - crypto_bench_debug("#"); - - /* get start time */ -- do_gettimeofday(&init_time); -+ ktime_get_real_ts64(&init_time); - - /** - * Request submission -@@ -812,8 +812,8 @@ static int crypto_bench_tx(void *arg) - * Calculate time and output the Mbps - */ - -- init_usecs = (init_time.tv_sec * 1000 * 1000) + init_time.tv_usec; -- comp_usecs = (comp_time.tv_sec * 1000 * 1000) + comp_time.tv_usec; -+ init_usecs = (init_time.tv_sec * 1000 * 1000) + (init_time.tv_nsec / NSEC_PER_USEC); -+ comp_usecs = (comp_time.tv_sec * 1000 * 1000) + (comp_time.tv_nsec / NSEC_PER_USEC); - delta_usecs = comp_usecs - init_usecs; - - reqs_completed = param.num_reqs - atomic_read(&tx_reqs); -@@ -870,7 +870,7 @@ static void crypto_bench_done(struct nss - nss_crypto_buf_free(crypto_hdl, buf); - - if (atomic_dec_and_test(&tx_reqs)) { -- do_gettimeofday(&comp_time); -+ ktime_get_real_ts64(&comp_time); - - wake_up_interruptible(&tx_comp); - param.num_loops--; diff --git a/root/package/qca/nss/qca-nss-crypto/patches/200-fix-NULL-pointer-exception.patch b/root/package/qca/nss/qca-nss-crypto/patches/200-fix-NULL-pointer-exception.patch deleted file mode 100644 index 6bd95109..00000000 --- a/root/package/qca/nss/qca-nss-crypto/patches/200-fix-NULL-pointer-exception.patch +++ /dev/null @@ -1,57 +0,0 @@ ---- a/v1.0/src/nss_crypto_if.c -+++ b/v1.0/src/nss_crypto_if.c -@@ -370,15 +370,16 @@ void nss_crypto_transform_done(struct ne - struct nss_crypto_buf *buf = (struct nss_crypto_buf *)skb->data; - struct nss_crypto_buf_node *entry; - void *addr; -+ struct device *cdev = gbl_crypto_ctrl.eng[0].dev; - - if (likely(buf->data_in == buf->data_out)) { -- dma_unmap_single(NULL, buf->data_in, buf->data_len, DMA_BIDIRECTIONAL); -+ dma_unmap_single(cdev, buf->data_in, buf->data_len, DMA_BIDIRECTIONAL); - } else { -- dma_unmap_single(NULL, buf->data_in, buf->data_len, DMA_TO_DEVICE); -- dma_unmap_single(NULL, buf->data_out, buf->data_len, DMA_FROM_DEVICE); -+ dma_unmap_single(cdev, buf->data_in, buf->data_len, DMA_TO_DEVICE); -+ dma_unmap_single(cdev, buf->data_out, buf->data_len, DMA_FROM_DEVICE); - } - -- dma_unmap_single(NULL, buf->iv_addr, L1_CACHE_BYTES, DMA_BIDIRECTIONAL); -+ dma_unmap_single(cdev, buf->iv_addr, L1_CACHE_BYTES, DMA_BIDIRECTIONAL); - - addr = phys_to_virt(buf->iv_addr); - entry = container_of(addr, struct nss_crypto_buf_node, results); -@@ -531,6 +532,7 @@ nss_crypto_status_t nss_crypto_transform - uint32_t paddr; - void *vaddr; - size_t len; -+ struct device *cdev = gbl_crypto_ctrl.eng[0].dev; - - if (!buf->cb_fn) { - nss_crypto_warn("%p:no buffer(%p) callback present\n", crypto, buf); -@@ -544,7 +546,7 @@ nss_crypto_status_t nss_crypto_transform - */ - vaddr = (void *)buf->data_in; - len = buf->data_len; -- paddr = dma_map_single(NULL, vaddr, len, DMA_TO_DEVICE); -+ paddr = dma_map_single(cdev, vaddr, len, DMA_TO_DEVICE); - buf->data_in = paddr; - - if (vaddr == (void *)buf->data_out) { -@@ -555,14 +557,14 @@ nss_crypto_status_t nss_crypto_transform - */ - vaddr = (void *)buf->data_out; - len = buf->data_len; -- paddr = dma_map_single(NULL, vaddr, len, DMA_FROM_DEVICE); -+ paddr = dma_map_single(cdev, vaddr, len, DMA_FROM_DEVICE); - buf->data_out = paddr; - } - - /* - * We need to map the results into IV - */ -- paddr = dma_map_single(NULL, entry->results, L1_CACHE_BYTES, DMA_BIDIRECTIONAL); -+ paddr = dma_map_single(cdev, entry->results, L1_CACHE_BYTES, DMA_BIDIRECTIONAL); - buf->hash_addr = paddr; - buf->iv_addr = paddr; - diff --git a/root/package/qca/nss/qca-nss-dp/Makefile b/root/package/qca/nss/qca-nss-dp/Makefile deleted file mode 100644 index 8da7d314..00000000 --- a/root/package/qca/nss/qca-nss-dp/Makefile +++ /dev/null @@ -1,62 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=qca-nss-dp -PKG_RELEASE:=$(AUTORELEASE) - -PKG_SOURCE_URL:=https://source.codeaurora.org/quic/cc-qrdk/oss/lklm/nss-dp -PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2021-03-26 -PKG_SOURCE_VERSION:=e0c89348d5ad99559ce2fbe15d37b3b5bc66aa03 -PKG_MIRROR_HASH:=f369f0c3b33b5f4ad6d0a6ad6ac5495f63c9ecaf94e4e7fa345169f3e44fcf45 - -PKG_BUILD_PARALLEL:=1 - -include $(INCLUDE_DIR)/kernel.mk -include $(INCLUDE_DIR)/package.mk - -define KernelPackage/qca-nss-dp - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Devices - DEPENDS:=@(TARGET_ipq807x||TARGET_ipq60xx) +kmod-qca-ssdk-nohnat - TITLE:=Kernel driver for NSS data plane - FILES:=$(PKG_BUILD_DIR)/qca-nss-dp.ko - AUTOLOAD:=$(call AutoLoad,31,qca-nss-dp) -endef - -define KernelPackage/qca-nss-dp/Description -This package contains a NSS data plane driver for QCA chipset -endef - -define Build/InstallDev - mkdir -p $(1)/usr/include/qca-nss-dp - $(CP) $(PKG_BUILD_DIR)/exports/* $(1)/usr/include/qca-nss-dp/ -endef - -EXTRA_CFLAGS+= \ - -I$(STAGING_DIR)/usr/include/qca-ssdk - -NSS_DP_HAL_DIR:=$(PKG_BUILD_DIR)/hal -define Build/Configure - $(LN) $(NSS_DP_HAL_DIR)/arch/$(CONFIG_TARGET_BOARD)/nss_$(CONFIG_TARGET_BOARD).h \ - $(PKG_BUILD_DIR)/exports/nss_dp_arch.h -endef - -ifeq ($(CONFIG_TARGET_BOARD), "ipq807x") - SOC="ipq807x_64" -else ifeq ($(CONFIG_TARGET_BOARD), "ipq60xx") - SOC="ipq60xx_64" -endif - -define Build/Compile - +$(MAKE) -C "$(LINUX_DIR)" \ - CROSS_COMPILE="$(TARGET_CROSS)" \ - ARCH="$(LINUX_KARCH)" \ - M="$(PKG_BUILD_DIR)" \ - EXTRA_CFLAGS="$(EXTRA_CFLAGS)" SoC="$(SOC)" \ - $(KERNEL_MAKE_FLAGS) \ - $(PKG_JOBS) \ - modules -endef - -$(eval $(call KernelPackage,qca-nss-dp)) diff --git a/root/package/qca/nss/qca-nss-dp/patches/0001-edma_tx_rx-support-newer-kernels-time-stamping-API.patch b/root/package/qca/nss/qca-nss-dp/patches/0001-edma_tx_rx-support-newer-kernels-time-stamping-API.patch deleted file mode 100644 index 15f6caa4..00000000 --- a/root/package/qca/nss/qca-nss-dp/patches/0001-edma_tx_rx-support-newer-kernels-time-stamping-API.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 40979666b4371012405715ffa61ab5760fcdc6b3 Mon Sep 17 00:00:00 2001 -Message-Id: <40979666b4371012405715ffa61ab5760fcdc6b3.1620066716.git.baruch@tkos.co.il> -From: Baruch Siach -Date: Mon, 3 May 2021 20:07:36 +0300 -Subject: [PATCH 1/3] edma_tx_rx: support newer kernels time stamping API - ---- - hal/edma/edma_tx_rx.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - ---- a/hal/edma/edma_tx_rx.c -+++ b/hal/edma/edma_tx_rx.c -@@ -226,10 +226,16 @@ void nss_phy_tstamp_rx_buf(__attribute__ - * set to the correct PTP class value by calling ptp_classify_raw - * in drv->rxtstamp function. - */ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 6, 0)) - if (ndev && ndev->phydev && ndev->phydev->drv && - ndev->phydev->drv->rxtstamp) - if(ndev->phydev->drv->rxtstamp(ndev->phydev, skb, 0)) - return; -+#else -+ if (ndev && phy_has_rxtstamp(ndev->phydev)) -+ if (phy_rxtstamp(ndev->phydev, skb, 0)) -+ return; -+#endif - - netif_receive_skb(skb); - } -@@ -247,9 +253,14 @@ void nss_phy_tstamp_tx_buf(struct net_de - * set to the correct PTP class value by calling ptp_classify_raw - * in the drv->txtstamp function. - */ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 6, 0)) - if (ndev && ndev->phydev && ndev->phydev->drv && - ndev->phydev->drv->txtstamp) - ndev->phydev->drv->txtstamp(ndev->phydev, skb, 0); -+#else -+ if (ndev && phy_has_txtstamp(ndev->phydev)) -+ phy_rxtstamp(ndev->phydev, skb, 0); -+#endif - } - EXPORT_SYMBOL(nss_phy_tstamp_tx_buf); - diff --git a/root/package/qca/nss/qca-nss-dp/patches/0002-nss_dp_main-make-phy-mode-code-compatible-with-newer.patch b/root/package/qca/nss/qca-nss-dp/patches/0002-nss_dp_main-make-phy-mode-code-compatible-with-newer.patch deleted file mode 100644 index a3305dd3..00000000 --- a/root/package/qca/nss/qca-nss-dp/patches/0002-nss_dp_main-make-phy-mode-code-compatible-with-newer.patch +++ /dev/null @@ -1,48 +0,0 @@ -From cef7873a2d77df13ee702d902ed4e06b2248904b Mon Sep 17 00:00:00 2001 -Message-Id: -In-Reply-To: <40979666b4371012405715ffa61ab5760fcdc6b3.1620066716.git.baruch@tkos.co.il> -References: <40979666b4371012405715ffa61ab5760fcdc6b3.1620066716.git.baruch@tkos.co.il> -From: Baruch Siach -Date: Mon, 3 May 2021 20:17:22 +0300 -Subject: [PATCH 2/3] nss_dp_main: make phy mode code compatible with newer - kernels - ---- - include/nss_dp_dev.h | 4 ++-- - nss_dp_main.c | 4 ++++ - 2 files changed, 6 insertions(+), 2 deletions(-) - ---- a/include/nss_dp_dev.h -+++ b/include/nss_dp_dev.h -@@ -25,7 +25,7 @@ - #include - #include - #include --#include -+#include - - #include "nss_dp_api_if.h" - #include "nss_dp_hal_if.h" -@@ -46,7 +46,7 @@ struct nss_dp_dev { - /* Phy related stuff */ - struct phy_device *phydev; /* Phy device */ - struct mii_bus *miibus; /* MII bus */ -- uint32_t phy_mii_type; /* RGMII/SGMII/QSGMII */ -+ phy_interface_t phy_mii_type; /* RGMII/SGMII/QSGMII */ - uint32_t phy_mdio_addr; /* Mdio address */ - bool link_poll; /* Link polling enable? */ - uint32_t forced_speed; /* Forced speed? */ ---- a/nss_dp_main.c -+++ b/nss_dp_main.c -@@ -463,7 +463,11 @@ static int32_t nss_dp_of_get_pdata(struc - hal_pdata->netdev = netdev; - hal_pdata->macid = dp_priv->macid; - -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 5, 0)) - dp_priv->phy_mii_type = of_get_phy_mode(np); -+#else -+ of_get_phy_mode(np, &dp_priv->phy_mii_type); -+#endif - dp_priv->link_poll = of_property_read_bool(np, "qcom,link-poll"); - if (of_property_read_u32(np, "qcom,phy-mdio-addr", - &dp_priv->phy_mdio_addr) && dp_priv->link_poll) { diff --git a/root/package/qca/nss/qca-nss-dp/patches/0003-Drop-_nocache-variants-of-ioremap.patch b/root/package/qca/nss/qca-nss-dp/patches/0003-Drop-_nocache-variants-of-ioremap.patch deleted file mode 100644 index 3139d349..00000000 --- a/root/package/qca/nss/qca-nss-dp/patches/0003-Drop-_nocache-variants-of-ioremap.patch +++ /dev/null @@ -1,48 +0,0 @@ -From c8c52512ff48bee578901c381a42f027e79eadf9 Mon Sep 17 00:00:00 2001 -Message-Id: -In-Reply-To: <40979666b4371012405715ffa61ab5760fcdc6b3.1620066716.git.baruch@tkos.co.il> -References: <40979666b4371012405715ffa61ab5760fcdc6b3.1620066716.git.baruch@tkos.co.il> -From: Baruch Siach -Date: Mon, 3 May 2021 20:20:29 +0300 -Subject: [PATCH 3/3] Drop _nocache variants of ioremap() - -Recent kernels removed them. ---- - hal/edma/edma_data_plane.c | 2 +- - hal/gmac_hal_ops/qcom/qcom_if.c | 2 +- - hal/gmac_hal_ops/syn/xgmac/syn_if.c | 2 +- - 3 files changed, 3 insertions(+), 3 deletions(-) - ---- a/hal/edma/edma_data_plane.c -+++ b/hal/edma/edma_data_plane.c -@@ -797,7 +797,7 @@ int edma_init(void) - /* - * Remap register resource - */ -- edma_hw.reg_base = ioremap_nocache((edma_hw.reg_resource)->start, -+ edma_hw.reg_base = ioremap((edma_hw.reg_resource)->start, - resource_size(edma_hw.reg_resource)); - if (!edma_hw.reg_base) { - pr_warn("Unable to remap EDMA register memory.\n"); ---- a/hal/gmac_hal_ops/qcom/qcom_if.c -+++ b/hal/gmac_hal_ops/qcom/qcom_if.c -@@ -400,7 +400,7 @@ static void *qcom_init(struct gmac_hal_p - qhd->nghd.mac_id = gmacpdata->macid; - - /* Populate the mac base addresses */ -- qhd->nghd.mac_base = devm_ioremap_nocache(&dp_priv->pdev->dev, -+ qhd->nghd.mac_base = devm_ioremap(&dp_priv->pdev->dev, - res->start, resource_size(res)); - if (!qhd->nghd.mac_base) { - netdev_dbg(ndev, "ioremap fail.\n"); ---- a/hal/gmac_hal_ops/syn/xgmac/syn_if.c -+++ b/hal/gmac_hal_ops/syn/xgmac/syn_if.c -@@ -422,7 +422,7 @@ static void *syn_init(struct gmac_hal_pl - - /* Populate the mac base addresses */ - shd->nghd.mac_base = -- devm_ioremap_nocache(&dp_priv->pdev->dev, res->start, -+ devm_ioremap(&dp_priv->pdev->dev, res->start, - resource_size(res)); - if (!shd->nghd.mac_base) { - netdev_dbg(ndev, "ioremap fail.\n"); diff --git a/root/package/qca/nss/qca-nss-dp/patches/0004-EDMA-Fix-NAPI-packet-counting.patch b/root/package/qca/nss/qca-nss-dp/patches/0004-EDMA-Fix-NAPI-packet-counting.patch deleted file mode 100644 index eb57fe90..00000000 --- a/root/package/qca/nss/qca-nss-dp/patches/0004-EDMA-Fix-NAPI-packet-counting.patch +++ /dev/null @@ -1,31 +0,0 @@ -From d74920e2a7c413ef40eed72f9cf287cf6fbd5fb8 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Thu, 20 May 2021 14:56:46 +0200 -Subject: [PATCH 1/2] EDMA: Fix NAPI packet counting - -There is a bug in the NAPI packet counting that will -cause NAPI over budget warnings. - -Signed-off-by: Baruch Siach -Signed-off-by: Robert Marko ---- - hal/edma/edma_tx_rx.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/hal/edma/edma_tx_rx.c -+++ b/hal/edma/edma_tx_rx.c -@@ -458,12 +458,12 @@ int edma_napi(struct napi_struct *napi, - - for (i = 0; i < ehw->txcmpl_rings; i++) { - txcmpl_ring = &ehw->txcmpl_ring[i]; -- work_done += edma_clean_tx(ehw, txcmpl_ring); -+ edma_clean_tx(ehw, txcmpl_ring); - } - - for (i = 0; i < ehw->rxfill_rings; i++) { - rxfill_ring = &ehw->rxfill_ring[i]; -- work_done += edma_alloc_rx_buffer(ehw, rxfill_ring); -+ edma_alloc_rx_buffer(ehw, rxfill_ring); - } - - /* diff --git a/root/package/qca/nss/qca-nss-dp/patches/0005-EDMA-Use-NAPI_POLL_WEIGHT-as-NAPI-weight.patch b/root/package/qca/nss/qca-nss-dp/patches/0005-EDMA-Use-NAPI_POLL_WEIGHT-as-NAPI-weight.patch deleted file mode 100644 index f231c514..00000000 --- a/root/package/qca/nss/qca-nss-dp/patches/0005-EDMA-Use-NAPI_POLL_WEIGHT-as-NAPI-weight.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 44a30d94abcbb10aacc21db29be212518a6b1bf7 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Thu, 20 May 2021 14:57:46 +0200 -Subject: [PATCH] EDMA: Use NAPI_POLL_WEIGHT as NAPI weight - -Currently a weight of 100 is used by the EDMA, according -to upstream max of 64 should be used and that is used for -almost any driver. - -They also introduced NAPI_POLL_WEIGHT define which equals -to 64. - -So use NAPI_POLL_WEIGHT as the weight. - -Signed-off-by: Robert Marko ---- - hal/edma/edma_data_plane.c | 2 +- - hal/edma/edma_data_plane.h | 1 - - 2 files changed, 1 insertion(+), 2 deletions(-) - ---- a/hal/edma/edma_data_plane.c -+++ b/hal/edma/edma_data_plane.c -@@ -582,7 +582,7 @@ static int edma_register_netdevice(struc - */ - if (!edma_hw.napi_added) { - netif_napi_add(netdev, &edma_hw.napi, edma_napi, -- EDMA_NAPI_WORK); -+ NAPI_POLL_WEIGHT); - /* - * Register the interrupt handlers and enable interrupts - */ ---- a/hal/edma/edma_data_plane.h -+++ b/hal/edma/edma_data_plane.h -@@ -27,7 +27,6 @@ - #define EDMA_RX_PREHDR_SIZE (sizeof(struct edma_rx_preheader)) - #define EDMA_TX_PREHDR_SIZE (sizeof(struct edma_tx_preheader)) - #define EDMA_RING_SIZE 128 --#define EDMA_NAPI_WORK 100 - #define EDMA_START_GMACS NSS_DP_START_IFNUM - #define EDMA_MAX_GMACS NSS_DP_HAL_MAX_PORTS - #define EDMA_TX_PKT_MIN_SIZE 33 /* IPQ807x EDMA needs a minimum packet size of 33 bytes */ diff --git a/root/package/qca/nss/qca-nss-dp/patches/0006-NSS-DP-fix-of_get_mac_address.patch b/root/package/qca/nss/qca-nss-dp/patches/0006-NSS-DP-fix-of_get_mac_address.patch deleted file mode 100644 index d4965716..00000000 --- a/root/package/qca/nss/qca-nss-dp/patches/0006-NSS-DP-fix-of_get_mac_address.patch +++ /dev/null @@ -1,50 +0,0 @@ -From cadeb62a42296563141d6954eec58e34ef86778d Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Fri, 13 Aug 2021 20:12:08 +0200 -Subject: [PATCH] NSS-DP: fix of_get_mac_address() - -Recently OpenWrt backported the updated of_get_mac_address() -function which returns and error code instead. - -So, patch the SSDK to use it and fix the compilation error. - -Signed-off-by: Robert Marko ---- - nss_dp_main.c | 13 ++++--------- - 1 file changed, 4 insertions(+), 9 deletions(-) - -diff --git a/nss_dp_main.c b/nss_dp_main.c -index 5580b13..28df280 100644 ---- a/nss_dp_main.c -+++ b/nss_dp_main.c -@@ -434,9 +434,10 @@ static int32_t nss_dp_of_get_pdata(struct device_node *np, - struct net_device *netdev, - struct gmac_hal_platform_data *hal_pdata) - { -- uint8_t *maddr; -+ u8 maddr[ETH_ALEN]; - struct nss_dp_dev *dp_priv; - struct resource memres_devtree = {0}; -+ int ret; - - dp_priv = netdev_priv(netdev); - -@@ -475,14 +476,8 @@ static int32_t nss_dp_of_get_pdata(struct device_node *np, - of_property_read_u32(np, "qcom,forced-speed", &dp_priv->forced_speed); - of_property_read_u32(np, "qcom,forced-duplex", &dp_priv->forced_duplex); - -- maddr = (uint8_t *)of_get_mac_address(np); --#if (LINUX_VERSION_CODE > KERNEL_VERSION(5, 4, 0)) -- if (IS_ERR((void *)maddr)) { -- maddr = NULL; -- } --#endif -- -- if (maddr && is_valid_ether_addr(maddr)) { -+ ret = of_get_mac_address(np, maddr); -+ if (!ret && is_valid_ether_addr(maddr)) { - ether_addr_copy(netdev->dev_addr, maddr); - } else { - random_ether_addr(netdev->dev_addr); --- -2.31.1 diff --git a/root/package/qca/nss/qca-nss-dp/patches/0007-NSS-DP-implement-ethernet-IOCTL-s.patch b/root/package/qca/nss/qca-nss-dp/patches/0007-NSS-DP-implement-ethernet-IOCTL-s.patch deleted file mode 100644 index 824f1863..00000000 --- a/root/package/qca/nss/qca-nss-dp/patches/0007-NSS-DP-implement-ethernet-IOCTL-s.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 5da62ba19f554bf437752a44360fb5ae9f1a7f5e Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Tue, 8 Mar 2022 10:48:32 +0100 -Subject: [PATCH] NSS-DP: implement ethernet IOCTL-s - -Since kernel 5.15 ethernet/PHY related IOCTL-s have been split from the -generic IOCTL netdev op. -So, implement the new op instead of the generic one which is considered -for private IOCTL-s only now for 5.15+. - -Signed-off-by: Robert Marko ---- - nss_dp_main.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/nss_dp_main.c -+++ b/nss_dp_main.c -@@ -532,7 +532,11 @@ static const struct net_device_ops nss_d - .ndo_set_mac_address = nss_dp_set_mac_address, - .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = nss_dp_change_mtu, -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)) - .ndo_do_ioctl = nss_dp_do_ioctl, -+#else -+ .ndo_eth_ioctl = nss_dp_do_ioctl, -+#endif - - #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0)) - .ndo_bridge_setlink = switchdev_port_bridge_setlink, diff --git a/root/package/qca/nss/qca-nss-dp/patches/0008-switchdev-remove-the-transaction-structure.patch b/root/package/qca/nss/qca-nss-dp/patches/0008-switchdev-remove-the-transaction-structure.patch deleted file mode 100644 index 220be961..00000000 --- a/root/package/qca/nss/qca-nss-dp/patches/0008-switchdev-remove-the-transaction-structure.patch +++ /dev/null @@ -1,48 +0,0 @@ -From c9afdcdd2642485a6476906be9da2e811090fc7a Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Fri, 18 Mar 2022 18:06:03 +0100 -Subject: [PATCH] switchdev: remove the transaction structure - -Since 5.12 there is no transaction structure anymore, so drop it for -5.12 and newer. - -Signed-off-by: Robert Marko ---- - nss_dp_switchdev.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - ---- a/nss_dp_switchdev.c -+++ b/nss_dp_switchdev.c -@@ -279,13 +279,19 @@ void nss_dp_switchdev_setup(struct net_d - * Sets attributes - */ - static int nss_dp_port_attr_set(struct net_device *dev, -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0)) - const struct switchdev_attr *attr, - struct switchdev_trans *trans) -+#else -+ const struct switchdev_attr *attr) -+#endif - { - struct nss_dp_dev *dp_priv = (struct nss_dp_dev *)netdev_priv(dev); - -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0)) - if (switchdev_trans_ph_prepare(trans)) - return 0; -+#endif - - switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: -@@ -309,8 +315,12 @@ static int nss_dp_switchdev_port_attr_se - { - int err; - -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0)) - err = nss_dp_port_attr_set(netdev, port_attr_info->attr, - port_attr_info->trans); -+#else -+ err = nss_dp_port_attr_set(netdev, port_attr_info->attr); -+#endif - - port_attr_info->handled = true; - return notifier_from_errno(err); diff --git a/root/package/qca/nss/qca-nss-dp/patches/0009-switchdev-use-new-switchdev-flags.patch b/root/package/qca/nss/qca-nss-dp/patches/0009-switchdev-use-new-switchdev-flags.patch deleted file mode 100644 index 5635dd96..00000000 --- a/root/package/qca/nss/qca-nss-dp/patches/0009-switchdev-use-new-switchdev-flags.patch +++ /dev/null @@ -1,54 +0,0 @@ -From f95868d54301c0f54e968ec9d978c9caa02ee425 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Fri, 18 Mar 2022 18:24:18 +0100 -Subject: [PATCH] switchdev: use new switchdev flags - -Since kernel 5.12 switched utilizes a new way of setting the flags by -using a dedicated structure with flags and mask. - -So fix using kernels 5.12 and later. - -Signed-off-by: Robert Marko ---- - include/nss_dp_dev.h | 7 +++++++ - nss_dp_switchdev.c | 2 +- - 2 files changed, 8 insertions(+), 1 deletion(-) - ---- a/include/nss_dp_dev.h -+++ b/include/nss_dp_dev.h -@@ -24,6 +24,9 @@ - #include - #include - #include -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)) -+#include -+#endif - - #include "nss_dp_api_if.h" - #include "nss_dp_hal_if.h" -@@ -126,7 +129,11 @@ struct nss_dp_dev { - /* switchdev related attributes */ - #ifdef CONFIG_NET_SWITCHDEV - u8 stp_state; /* STP state of this physical port */ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0)) - unsigned long brport_flags; /* bridge port flags */ -+#else -+ struct switchdev_brport_flags brport_flags; /* bridge port flags */ -+#endif - #endif - uint32_t rx_page_mode; /* page mode for Rx processing */ - uint32_t rx_jumbo_mru; /* Jumbo mru value for Rx processing */ ---- a/nss_dp_switchdev.c -+++ b/nss_dp_switchdev.c -@@ -296,7 +296,11 @@ static int nss_dp_port_attr_set(struct n - switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: - dp_priv->brport_flags = attr->u.brport_flags; -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0)) - netdev_dbg(dev, "set brport_flags %lu\n", attr->u.brport_flags); -+#else -+ netdev_dbg(dev, "set brport_flags %lu\n", attr->u.brport_flags.val); -+#endif - return 0; - case SWITCHDEV_ATTR_ID_PORT_STP_STATE: - return nss_dp_stp_state_set(dp_priv, attr->u.stp_state); diff --git a/root/package/qca/nss/qca-nss-dp/patches/0010-switchdev-fix-FDB-roaming.patch b/root/package/qca/nss/qca-nss-dp/patches/0010-switchdev-fix-FDB-roaming.patch deleted file mode 100644 index 19395ac4..00000000 --- a/root/package/qca/nss/qca-nss-dp/patches/0010-switchdev-fix-FDB-roaming.patch +++ /dev/null @@ -1,110 +0,0 @@ -From d16102cad769f430144ca8094d928762b445e9b0 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Fri, 18 Mar 2022 22:02:01 +0100 -Subject: [PATCH] switchdev: fix FDB roaming - -Try and solve the roaming issue by trying to replicate what NSS bridge -module is doing, but by utilizing switchdev FDB notifiers instead of -adding new notifiers to the bridge code. - -We register a new non-blocking switchdev notifier and simply wait for -notification, and then process the SWITCHDEV_FDB_DEL_TO_DEVICE -notifications. - -Those tell us that a certain FDB entry should be removed, then a VSI ID -is fetched for the physical PPE port and using that VSI ID and the -notification provided MAC adress existing FDB entry gets removed. - -Signed-off-by: Robert Marko ---- - nss_dp_switchdev.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 61 insertions(+) - ---- a/nss_dp_switchdev.c -+++ b/nss_dp_switchdev.c -@@ -24,6 +24,8 @@ - #include "nss_dp_dev.h" - #include "fal/fal_stp.h" - #include "fal/fal_ctrlpkt.h" -+#include "fal/fal_fdb.h" -+#include "ref/ref_vsi.h" - - #define NSS_DP_SWITCH_ID 0 - #define NSS_DP_SW_ETHTYPE_PID 0 /* PPE ethtype profile ID for slow protocols */ -@@ -348,10 +350,64 @@ static int nss_dp_switchdev_event(struct - return NOTIFY_DONE; - } - -+static int nss_dp_switchdev_fdb_del_event(struct net_device *netdev, -+ struct switchdev_notifier_fdb_info *fdb_info) -+{ -+ struct nss_dp_dev *dp_priv = (struct nss_dp_dev *)netdev_priv(netdev); -+ fal_fdb_entry_t entry; -+ a_uint32_t vsi_id; -+ sw_error_t rv; -+ -+ netdev_dbg(netdev, "FDB DEL %pM port %d\n", fdb_info->addr, dp_priv->macid); -+ -+ rv = ppe_port_vsi_get(NSS_DP_SWITCH_ID, dp_priv->macid, &vsi_id); -+ if (rv) { -+ netdev_err(netdev, "cannot get VSI ID for port %d\n", dp_priv->macid); -+ return notifier_from_errno(rv); -+ } -+ -+ memset(&entry, 0, sizeof(entry)); -+ memcpy(&entry.addr, fdb_info->addr, ETH_ALEN); -+ entry.fid = vsi_id; -+ -+ rv = fal_fdb_entry_del_bymac(NSS_DP_SWITCH_ID, &entry); -+ if (rv) { -+ netdev_err(netdev, "FDB entry delete failed with MAC %pM and fid %d\n", -+ &entry.addr, entry.fid); -+ return notifier_from_errno(rv); -+ } -+ -+ return notifier_from_errno(rv); -+} -+ -+static int nss_dp_fdb_switchdev_event(struct notifier_block *nb, -+ unsigned long event, void *ptr) -+{ -+ struct net_device *dev = switchdev_notifier_info_to_dev(ptr); -+ -+ /* -+ * Handle switchdev event only for physical devices -+ */ -+ if (!nss_dp_is_phy_dev(dev)) { -+ return NOTIFY_DONE; -+ } -+ -+ switch (event) { -+ case SWITCHDEV_FDB_DEL_TO_DEVICE: -+ return nss_dp_switchdev_fdb_del_event(dev, ptr); -+ } -+ -+ return NOTIFY_DONE; -+} -+ - static struct notifier_block nss_dp_switchdev_notifier = { - .notifier_call = nss_dp_switchdev_event, - }; - -+static struct notifier_block nss_dp_switchdev_fdb_notifier = { -+ .notifier_call = nss_dp_fdb_switchdev_event, -+}; -+ - static bool switch_init_done; - - /* -@@ -366,6 +422,11 @@ void nss_dp_switchdev_setup(struct net_d - return; - } - -+ err = register_switchdev_notifier(&nss_dp_switchdev_fdb_notifier); -+ if (err) { -+ netdev_dbg(dev, "%px:Failed to register switchdev FDB notifier\n", dev); -+ } -+ - err = register_switchdev_blocking_notifier(&nss_dp_switchdev_notifier); - if (err) { - netdev_dbg(dev, "%px:Failed to register switchdev notifier\n", dev); diff --git a/root/package/qca/nss/qca-nss-dp/patches/0011-treewide-fix-confusing-printing-of-registered-netdev.patch b/root/package/qca/nss/qca-nss-dp/patches/0011-treewide-fix-confusing-printing-of-registered-netdev.patch deleted file mode 100644 index 6c3d68f7..00000000 --- a/root/package/qca/nss/qca-nss-dp/patches/0011-treewide-fix-confusing-printing-of-registered-netdev.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 7e4ae2d6285095794d73d2f2ce61404f61d4e633 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Tue, 17 May 2022 15:55:36 +0200 -Subject: [PATCH 11/11] treewide: fix confusing printing of registered netdev - -Net core implementation changed and now printing the netdev name cause -confusing printing if done before register_netdev. Move the old printing -to dbg and add an additional info log right after register_netdev to -give the user some info on correct nss-dp probe. - -Signed-off-by: Ansuel Smith ---- - nss_dp_main.c | 3 +++ - 1 files changed, 3 insertions(+), 0 deletions(-) - -diff --git a/nss_dp_main.c b/nss_dp_main.c -index c0ae9d6..441c300 100644 ---- a/nss_dp_main.c -+++ b/nss_dp_main.c -@@ -875,6 +875,9 @@ static int32_t nss_dp_probe(struct platform_device *pdev) - goto phy_setup_fail; - } - -+ netdev_info(netdev, "Registered netdev %s(qcom-id:%d)\n", -+ netdev->name, port_id); -+ - dp_global_ctx.nss_dp[dp_priv->macid - 1] = dp_priv; - dp_global_ctx.slowproto_acl_bm = 0; - --- -2.34.1 diff --git a/root/package/qca/nss/qca-nss-drv-64/Makefile b/root/package/qca/nss/qca-nss-drv-64/Makefile deleted file mode 100644 index ac73475f..00000000 --- a/root/package/qca/nss/qca-nss-drv-64/Makefile +++ /dev/null @@ -1,121 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=qca-nss-drv-64 -PKG_RELEASE:=$(AUTORELEASE) - -PKG_SOURCE_URL:=https://source.codeaurora.org/quic/qsdk/oss/lklm/nss-drv -PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2021-04-26 -PKG_SOURCE_VERSION:=1cf4bf81fd395f61648efeae78cdf1df60e954ff -PKG_MIRROR_HASH:=3dd84a548a530188021fd4dab54ca4e1eb9056ca77381b24f587365fc7c16f21 - -PKG_BUILD_PARALLEL:=1 - -include $(INCLUDE_DIR)/kernel.mk -include $(INCLUDE_DIR)/package.mk - -NSS_CLIENTS_DIR:=$(TOPDIR)/qca/src/qca-nss-clients - -define KernelPackage/qca-nss-drv-64 - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Devices - DEPENDS:=@(TARGET_ipq807x||TARGET_ipq60xx) +kmod-qca-nss-dp - TITLE:=Kernel driver for NSS (core driver) - FILES:=$(PKG_BUILD_DIR)/qca-nss-drv.ko - AUTOLOAD:=$(call AutoLoad,32,qca-nss-drv) -endef - -define KernelPackage/qca-nss-drv-64/install - $(INSTALL_DIR) $(1)/lib/debug - $(INSTALL_DIR) $(1)/etc/init.d - $(INSTALL_DIR) $(1)/etc/sysctl.d - $(INSTALL_DIR) $(1)/etc/hotplug.d/firmware - $(INSTALL_DIR) $(1)/etc/config - - $(INSTALL_BIN) ./files/qca-nss-drv.debug $(1)/lib/debug/qca-nss-drv - $(INSTALL_BIN) ./files/qca-nss-drv.init $(1)/etc/init.d/qca-nss-drv - $(INSTALL_BIN) ./files/qca-nss-drv.sysctl $(1)/etc/sysctl.d/qca-nss-drv.conf - $(INSTALL_BIN) ./files/qca-nss-drv.hotplug $(1)/etc/hotplug.d/firmware/10-qca-nss-fw - $(INSTALL_BIN) ./files/qca-nss-drv.conf $(1)/etc/config/nss - -endef - -define KernelPackage/qca-nss-drv-64/Description -This package contains a NSS driver for QCA chipset -endef - -define Build/InstallDev - mkdir -p $(1)/usr/include/qca-nss-drv - $(CP) $(PKG_BUILD_DIR)/exports/* $(1)/usr/include/qca-nss-drv/ -endef - -EXTRA_CFLAGS+= -I$(STAGING_DIR)/usr/include/qca-nss-gmac -I$(STAGING_DIR)/usr/include/qca-nss-dp -I$(STAGING_DIR)/usr/include/qca-ssdk - -ifneq (, $(findstring $(CONFIG_TARGET_BOARD), "ipq807x" "ipq60xx")) -EXTRA_CFLAGS+= -DNSS_MEM_PROFILE_MEDIUM -LOW_MEM_PROFILE_MAKE_OPTS=y -endif - -ifeq ($(CONFIG_KERNEL_SKB_FIXED_SIZE_2K),y) -EXTRA_CFLAGS+= -DNSS_SKB_FIXED_SIZE_2K -endif - -DRV_MAKE_OPTS:= -ifeq ($(LOW_MEM_PROFILE_MAKE_OPTS),y) -DRV_MAKE_OPTS+=NSS_DRV_C2C_ENABLE=n \ - NSS_DRV_CAPWAP_ENABLE=n \ - NSS_DRV_CLMAP_ENABLE=n \ - NSS_DRV_CRYPTO_ENABLE=n \ - NSS_DRV_DTLS_ENABLE=n \ - NSS_DRV_GRE_ENABLE=n \ - NSS_DRV_GRE_REDIR_ENABLE=n \ - NSS_DRV_GRE_TUNNEL_ENABLE=n \ - NSS_DRV_IGS_ENABLE=n \ - NSS_DRV_IPSEC_ENABLE=n \ - NSS_DRV_LAG_ENABLE=n \ - NSS_DRV_L2TP_ENABLE=n \ - NSS_DRV_MAPT_ENABLE=n \ - NSS_DRV_OAM_ENABLE=n \ - NSS_DRV_PPTP_ENABLE=n \ - NSS_DRV_PORTID_ENABLE=n \ - NSS_DRV_PVXLAN_ENABLE=n \ - NSS_DRV_QRFS_ENABLE=n \ - NSS_DRV_QVPN_ENABLE=n \ - NSS_DRV_RMNET_ENABLE=n \ - NSS_DRV_SHAPER_ENABLE=n \ - NSS_DRV_SJACK_ENABLE=n \ - NSS_DRV_TLS_ENABLE=n \ - NSS_DRV_TRUSTSEC_ENABLE=n \ - NSS_DRV_TSTAMP_ENABLE=n \ - NSS_DRV_TUN6RD_ENABLE=n \ - NSS_DRV_TUNIPIP6_ENABLE=n \ - NSS_DRV_VXLAN_ENABLE=n \ - NSS_DRV_MATCH_ENABLE=n \ - NSS_DRV_MIRROR_ENABLE=n -endif - -ifeq ($(CONFIG_TARGET_BOARD), "ipq807x") - SOC="ipq807x_64" -else ifeq ($(CONFIG_TARGET_BOARD), "ipq60xx") - SOC="ipq60xx_64" -endif - -define Build/Configure - $(LN) arch/nss_$(SOC).h $(PKG_BUILD_DIR)/exports/nss_arch.h - sed -i "s/define NSS_FW_VERSION_MAJOR.*/define NSS_FW_VERSION_MAJOR 11/" $(PKG_BUILD_DIR)/exports/nss_fw_version.h - sed -i "s/define NSS_FW_VERSION_MINOR.*/define NSS_FW_VERSION_MINOR 3/" $(PKG_BUILD_DIR)/exports/nss_fw_version.h -endef - -define Build/Compile - +$(MAKE) -C "$(LINUX_DIR)" $(strip $(DRV_MAKE_OPTS)) \ - CROSS_COMPILE="$(TARGET_CROSS)" \ - ARCH="$(LINUX_KARCH)" \ - M="$(PKG_BUILD_DIR)" \ - EXTRA_CFLAGS="$(EXTRA_CFLAGS)" SoC=$(SOC) \ - $(KERNEL_MAKE_FLAGS) \ - $(PKG_JOBS) \ - modules -endef - -$(eval $(call KernelPackage,qca-nss-drv-64)) diff --git a/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.conf b/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.conf deleted file mode 100644 index a8a1fbf4..00000000 --- a/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.conf +++ /dev/null @@ -1,6 +0,0 @@ -config nss_firmware 'qca_nss_0' - -config nss_firmware 'qca_nss_1' - -config general - option enable_rps '1' diff --git a/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.debug b/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.debug deleted file mode 100644 index 5d435c3a..00000000 --- a/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.debug +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh /sbin/sysdebug -# -# Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -log cat /sys/kernel/debug/qca-nss-drv/stats/pppoe -log cat /sys/kernel/debug/qca-nss-drv/stats/n2h -log cat /sys/kernel/debug/qca-nss-drv/stats/ipv6 -log cat /sys/kernel/debug/qca-nss-drv/stats/ipv4 -log cat /sys/kernel/debug/qca-nss-drv/stats/gmac -log cat /sys/kernel/debug/qca-nss-drv/stats/drv -log cat /sys/kernel/debug/qca-nss-drv/stats/wifi -log cat /sys/kernel/debug/qca-nss-drv/stats/wifi_if -log cat /sys/kernel/debug/qca-nss-drv/stats/eth_rx diff --git a/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.hotplug b/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.hotplug deleted file mode 100644 index 1e481383..00000000 --- a/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.hotplug +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -KERNEL=`uname -r` -case "${KERNEL}" in - 3.4*) - select_or_load=load_nss_fw - ;; - *) - select_or_load=select_nss_fw - ;; -esac - -load_nss_fw () { - ls -l $1 | awk ' { print $9,$5 } '> /dev/console - echo 1 > /sys/class/firmware/$DEVICENAME/loading - cat $1 > /sys/class/firmware/$DEVICENAME/data - echo 0 > /sys/class/firmware/$DEVICENAME/loading -} - -select_nss_fw () { - rm -f /lib/firmware/$DEVICENAME - ln -s $1 /lib/firmware/$DEVICENAME - ls -l /lib/firmware/$DEVICENAME | awk ' { print $9,$5 } '> /dev/console -} - -[ "$ACTION" != "add" ] && exit - -# dev name for UCI, since it doesn't let you use . or - -SDEVNAME=$(echo ${DEVICENAME} | sed s/[.-]/_/g) - -SELECTED_FW=$(uci get nss.${SDEVNAME}.firmware 2>/dev/null) -[ -e "${SELECTED_FW}" ] && { - $select_or_load ${SELECTED_FW} - exit -} - -case $DEVICENAME in - qca-nss0* | qca-nss.0*) - if [ -e /lib/firmware/qca-nss0-enterprise.bin ] ; then - $select_or_load /lib/firmware/qca-nss0-enterprise.bin - else - $select_or_load /lib/firmware/qca-nss0-retail.bin - fi - exit - ;; - qca-nss1* | qca-nss.1*) - if [ -e /lib/firmware/qca-nss1-enterprise.bin ] ; then - $select_or_load /lib/firmware/qca-nss1-enterprise.bin - else - $select_or_load /lib/firmware/qca-nss1-retail.bin - fi - exit - ;; -esac - diff --git a/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.init b/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.init deleted file mode 100644 index de12cb6d..00000000 --- a/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.init +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/sh /etc/rc.common -# -# Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -START=70 - -enable_rps() { - irq_nss_rps=`grep nss_queue1 /proc/interrupts | cut -d ':' -f 1 | tr -d ' '` - for entry in $irq_nss_rps - do - echo 2 > /proc/irq/$entry/smp_affinity - done - - irq_nss_rps=`grep nss_queue2 /proc/interrupts | cut -d ':' -f 1 | tr -d ' '` - for entry in $irq_nss_rps - do - echo 4 > /proc/irq/$entry/smp_affinity - done - - irq_nss_rps=`grep nss_queue3 /proc/interrupts | cut -d ':' -f 1 | tr -d ' '` - for entry in $irq_nss_rps - do - echo 8 > /proc/irq/$entry/smp_affinity - done - - # Enable NSS RPS - sysctl -w dev.nss.rps.enable=1 >/dev/null 2>/dev/null - -} - - -start() { - local rps_enabled="$(uci_get nss @general[0] enable_rps)" - if [ "$rps_enabled" -eq 1 ]; then - enable_rps - fi -} diff --git a/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.sysctl b/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.sysctl deleted file mode 100644 index fc36c33e..00000000 --- a/root/package/qca/nss/qca-nss-drv-64/files/qca-nss-drv.sysctl +++ /dev/null @@ -1,4 +0,0 @@ -# Default Number of connection configuration -dev.nss.ipv4cfg.ipv4_conn=4096 -dev.nss.ipv6cfg.ipv6_conn=4096 - diff --git a/root/package/qca/nss/qca-nss-drv-64/patches/0001-core-add-5.10-kernel-to-version-check.patch b/root/package/qca/nss/qca-nss-drv-64/patches/0001-core-add-5.10-kernel-to-version-check.patch deleted file mode 100644 index 3fea9b5c..00000000 --- a/root/package/qca/nss/qca-nss-drv-64/patches/0001-core-add-5.10-kernel-to-version-check.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 3885c752e12f74cad6c97888b797e5903ad1930d Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Thu, 13 May 2021 23:22:38 +0200 -Subject: [PATCH] core: add 5.10 kernel to version check - -NSS DRV has a kernel version check, so simply add -5.10 as supported. - -Signed-off-by: Robert Marko ---- - nss_core.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/nss_core.c -+++ b/nss_core.c -@@ -52,7 +52,8 @@ - (((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0)))) || \ - (((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)))) || \ - (((LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0)))) || \ --(((LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(5, 5, 0)))))) -+(((LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(5, 5, 0)))) || \ -+(((LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0)))))) - #error "Check skb recycle code in this file to match Linux version" - #endif - diff --git a/root/package/qca/nss/qca-nss-drv-64/patches/0002-nss-drv-replace-ioremap_nocache-with-ioremap.patch b/root/package/qca/nss/qca-nss-drv-64/patches/0002-nss-drv-replace-ioremap_nocache-with-ioremap.patch deleted file mode 100644 index 77155750..00000000 --- a/root/package/qca/nss/qca-nss-drv-64/patches/0002-nss-drv-replace-ioremap_nocache-with-ioremap.patch +++ /dev/null @@ -1,164 +0,0 @@ -From b5e2a7167ca3df9fce34f0d7c05468d4f5597275 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Thu, 13 May 2021 23:33:18 +0200 -Subject: [PATCH] nss-drv: replace ioremap_nocache() with ioremap() - -ioremap_nocache() does not exist anymore. - -Signed-off-by: Robert Marko ---- - nss_hal/ipq50xx/nss_hal_pvt.c | 6 +++--- - nss_hal/ipq60xx/nss_hal_pvt.c | 8 ++++---- - nss_hal/ipq806x/nss_hal_pvt.c | 4 ++-- - nss_hal/ipq807x/nss_hal_pvt.c | 6 +++--- - nss_hal/nss_hal.c | 4 ++-- - nss_meminfo.c | 2 +- - nss_ppe.c | 2 +- - 7 files changed, 16 insertions(+), 16 deletions(-) - ---- a/nss_hal/ipq50xx/nss_hal_pvt.c -+++ b/nss_hal/ipq50xx/nss_hal_pvt.c -@@ -184,13 +184,13 @@ static struct nss_platform_data *__nss_h - npd->nphys = res_nphys.start; - npd->qgic_phys = res_qgic_phys.start; - -- npd->nmap = ioremap_nocache(npd->nphys, resource_size(&res_nphys)); -+ npd->nmap = ioremap(npd->nphys, resource_size(&res_nphys)); - if (!npd->nmap) { - nss_info_always("%px: nss%d: ioremap() fail for nphys\n", nss_ctx, nss_ctx->id); - goto out; - } - -- npd->qgic_map = ioremap_nocache(npd->qgic_phys, resource_size(&res_qgic_phys)); -+ npd->qgic_map = ioremap(npd->qgic_phys, resource_size(&res_qgic_phys)); - if (!npd->qgic_map) { - nss_info_always("%px: nss%d: ioremap() fail for qgic map\n", nss_ctx, nss_ctx->id); - goto out; -@@ -348,7 +348,7 @@ static int __nss_hal_common_reset(struct - - of_node_put(cmn); - -- nss_misc_reset = ioremap_nocache(res_nss_misc_reset.start, resource_size(&res_nss_misc_reset)); -+ nss_misc_reset = ioremap(res_nss_misc_reset.start, resource_size(&res_nss_misc_reset)); - if (!nss_misc_reset) { - pr_err("%px: ioremap fail for nss_misc_reset\n", nss_dev); - return -EFAULT; ---- a/nss_hal/ipq60xx/nss_hal_pvt.c -+++ b/nss_hal/ipq60xx/nss_hal_pvt.c -@@ -207,13 +207,13 @@ static struct nss_platform_data *__nss_h - npd->nphys = res_nphys.start; - npd->qgic_phys = res_qgic_phys.start; - -- npd->nmap = ioremap_nocache(npd->nphys, resource_size(&res_nphys)); -+ npd->nmap = ioremap(npd->nphys, resource_size(&res_nphys)); - if (!npd->nmap) { - nss_info_always("%px: nss%d: ioremap() fail for nphys\n", nss_ctx, nss_ctx->id); - goto out; - } - -- npd->qgic_map = ioremap_nocache(npd->qgic_phys, resource_size(&res_qgic_phys)); -+ npd->qgic_map = ioremap(npd->qgic_phys, resource_size(&res_qgic_phys)); - if (!npd->qgic_map) { - nss_info_always("%px: nss%d: ioremap() fail for qgic map\n", nss_ctx, nss_ctx->id); - goto out; -@@ -433,13 +433,13 @@ static int __nss_hal_common_reset(struct - - of_node_put(cmn); - -- nss_misc_reset = ioremap_nocache(res_nss_misc_reset.start, resource_size(&res_nss_misc_reset)); -+ nss_misc_reset = ioremap(res_nss_misc_reset.start, resource_size(&res_nss_misc_reset)); - if (!nss_misc_reset) { - pr_err("%px: ioremap fail for nss_misc_reset\n", nss_dev); - return -EFAULT; - } - -- nss_misc_reset_flag = ioremap_nocache(res_nss_misc_reset_flag.start, resource_size(&res_nss_misc_reset_flag)); -+ nss_misc_reset_flag = ioremap(res_nss_misc_reset_flag.start, resource_size(&res_nss_misc_reset_flag)); - if (!nss_misc_reset_flag) { - pr_err("%px: ioremap fail for nss_misc_reset_flag\n", nss_dev); - return -EFAULT; ---- a/nss_hal/ipq806x/nss_hal_pvt.c -+++ b/nss_hal/ipq806x/nss_hal_pvt.c -@@ -458,7 +458,7 @@ static struct nss_platform_data *__nss_h - npd->nphys = res_nphys.start; - npd->vphys = res_vphys.start; - -- npd->nmap = ioremap_nocache(npd->nphys, resource_size(&res_nphys)); -+ npd->nmap = ioremap(npd->nphys, resource_size(&res_nphys)); - if (!npd->nmap) { - nss_info_always("%px: nss%d: ioremap() fail for nphys\n", nss_ctx, nss_ctx->id); - goto out; -@@ -711,7 +711,7 @@ static int __nss_hal_common_reset(struct - } - of_node_put(cmn); - -- fpb_base = ioremap_nocache(res_nss_fpb_base.start, resource_size(&res_nss_fpb_base)); -+ fpb_base = ioremap(res_nss_fpb_base.start, resource_size(&res_nss_fpb_base)); - if (!fpb_base) { - pr_err("%px: ioremap fail for nss_fpb_base\n", nss_dev); - return -EFAULT; ---- a/nss_hal/ipq807x/nss_hal_pvt.c -+++ b/nss_hal/ipq807x/nss_hal_pvt.c -@@ -234,7 +234,7 @@ static struct nss_platform_data *__nss_h - npd->vphys = res_vphys.start; - npd->qgic_phys = res_qgic_phys.start; - -- npd->nmap = ioremap_nocache(npd->nphys, resource_size(&res_nphys)); -+ npd->nmap = ioremap(npd->nphys, resource_size(&res_nphys)); - if (!npd->nmap) { - nss_info_always("%px: nss%d: ioremap() fail for nphys\n", nss_ctx, nss_ctx->id); - goto out; -@@ -247,7 +247,7 @@ static struct nss_platform_data *__nss_h - goto out; - } - -- npd->qgic_map = ioremap_nocache(npd->qgic_phys, resource_size(&res_qgic_phys)); -+ npd->qgic_map = ioremap(npd->qgic_phys, resource_size(&res_qgic_phys)); - if (!npd->qgic_map) { - nss_info_always("%px: nss%d: ioremap() fail for qgic map\n", nss_ctx, nss_ctx->id); - goto out; -@@ -467,7 +467,7 @@ static int __nss_hal_common_reset(struct - } - of_node_put(cmn); - -- nss_misc_reset = ioremap_nocache(res_nss_misc_reset.start, resource_size(&res_nss_misc_reset)); -+ nss_misc_reset = ioremap(res_nss_misc_reset.start, resource_size(&res_nss_misc_reset)); - if (!nss_misc_reset) { - pr_err("%px: ioremap fail for nss_misc_reset\n", nss_dev); - return -EFAULT; ---- a/nss_hal/nss_hal.c -+++ b/nss_hal/nss_hal.c -@@ -78,9 +78,9 @@ int nss_hal_firmware_load(struct nss_ctx - return rc; - } - -- load_mem = ioremap_nocache(npd->load_addr, nss_fw->size); -+ load_mem = ioremap(npd->load_addr, nss_fw->size); - if (!load_mem) { -- nss_info_always("%px: ioremap_nocache failed: %x", nss_ctx, npd->load_addr); -+ nss_info_always("%px: ioremap failed: %x", nss_ctx, npd->load_addr); - release_firmware(nss_fw); - return rc; - } ---- a/nss_meminfo.c -+++ b/nss_meminfo.c -@@ -728,7 +728,7 @@ bool nss_meminfo_init(struct nss_ctx_ins - /* - * meminfo_start is the label where the start address of meminfo map is stored. - */ -- meminfo_start = (uint32_t *)ioremap_nocache(nss_ctx->load + NSS_MEMINFO_MAP_START_OFFSET, -+ meminfo_start = (uint32_t *)ioremap(nss_ctx->load + NSS_MEMINFO_MAP_START_OFFSET, - NSS_MEMINFO_RESERVE_AREA_SIZE); - if (!meminfo_start) { - nss_info_always("%px: cannot remap meminfo start\n", nss_ctx); ---- a/nss_ppe.c -+++ b/nss_ppe.c -@@ -357,7 +357,7 @@ void nss_ppe_init(void) - /* - * Get the PPE base address - */ -- ppe_pvt.ppe_base = ioremap_nocache(PPE_BASE_ADDR, PPE_REG_SIZE); -+ ppe_pvt.ppe_base = ioremap(PPE_BASE_ADDR, PPE_REG_SIZE); - if (!ppe_pvt.ppe_base) { - nss_warning("DRV can't get PPE base address\n"); - return; diff --git a/root/package/qca/nss/qca-nss-drv-64/patches/0003-DMA-Fix-NULL-pointer-exceptions.patch b/root/package/qca/nss/qca-nss-drv-64/patches/0003-DMA-Fix-NULL-pointer-exceptions.patch deleted file mode 100644 index 0c13a788..00000000 --- a/root/package/qca/nss/qca-nss-drv-64/patches/0003-DMA-Fix-NULL-pointer-exceptions.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 62e457f262aaa0db7113ad3ccbcb7ae49d4d7ea8 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Tue, 8 Jun 2021 23:24:43 +0200 -Subject: [PATCH] DMA: Fix NULL pointer exceptions - -There are multiple instances that pass NULL instead -of device to DMA functions. -That is incorrect and will cause kernel NULL pointer -exceptions. - -So, simply pass the device structure pointers. - -Signed-off-by: Robert Marko ---- - nss_core.c | 2 +- - nss_coredump.c | 4 ++-- - 2 files changed, 3 insertions(+), 3 deletions(-) - ---- a/nss_core.c -+++ b/nss_core.c -@@ -1617,7 +1617,7 @@ static int32_t nss_core_handle_cause_que - * - */ - if (unlikely((buffer_type == N2H_BUFFER_CRYPTO_RESP))) { -- dma_unmap_single(NULL, (desc->buffer + desc->payload_offs), desc->payload_len, DMA_FROM_DEVICE); -+ dma_unmap_single(nss_ctx->dev, (desc->buffer + desc->payload_offs), desc->payload_len, DMA_FROM_DEVICE); - goto consume; - } - ---- a/nss_coredump.c -+++ b/nss_coredump.c -@@ -154,7 +154,7 @@ void nss_fw_coredump_notify(struct nss_c - dma_addr = nss_own->meminfo_ctx.logbuffer_dma; - } - -- dma_sync_single_for_cpu(NULL, dma_addr, sizeof(struct nss_log_descriptor), DMA_FROM_DEVICE); -+ dma_sync_single_for_cpu(nss_own->dev, dma_addr, sizeof(struct nss_log_descriptor), DMA_FROM_DEVICE); - - /* - * If the current entry is smaller than or equal to the number of NSS_LOG_COREDUMP_LINE_NUM, -@@ -181,7 +181,7 @@ void nss_fw_coredump_notify(struct nss_c - - offset = (index * sizeof(struct nss_log_entry)) - + offsetof(struct nss_log_descriptor, log_ring_buffer); -- dma_sync_single_for_cpu(NULL, dma_addr + offset, -+ dma_sync_single_for_cpu(nss_own->dev, dma_addr + offset, - sizeof(struct nss_log_entry), DMA_FROM_DEVICE); - nss_info_always("%px: %s\n", nss_own, nle_print->message); - nle_print++; diff --git a/root/package/qca/nss/qca-nss-drv-64/patches/0005-nss-drv-add-support-for-kernel-5.15.patch b/root/package/qca/nss/qca-nss-drv-64/patches/0005-nss-drv-add-support-for-kernel-5.15.patch deleted file mode 100644 index dfebd0d6..00000000 --- a/root/package/qca/nss/qca-nss-drv-64/patches/0005-nss-drv-add-support-for-kernel-5.15.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 6e65f6daecb09463688eaea0a234018a728196b8 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Tue, 5 Apr 2022 18:10:57 +0200 -Subject: [PATCH 5/8] nss-drv: add support for kernel 5.15 - -- Fix coredump panic notifier include change. -- Fix skb ZEROCOPY flag. -- Add skb reuse support for 5.15 kernel version. - -Signed-off-by: Ansuel Smith ---- - nss_core.c | 5 +++-- - nss_coredump.c | 4 ++++ - nss_hal/nss_hal.c | 1 + - 3 files changed, 8 insertions(+), 2 deletions(-) - -diff --git a/nss_core.c b/nss_core.c -index f9e6014..8cd1d4b 100644 ---- a/nss_core.c -+++ b/nss_core.c -@@ -53,7 +53,8 @@ - (((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)))) || \ - (((LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0)))) || \ - (((LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(5, 5, 0)))) || \ --(((LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0)))))) -+(((LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0)))) || \ -+(((LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0)))))) - #error "Check skb recycle code in this file to match Linux version" - #endif - -@@ -2623,7 +2624,11 @@ static inline bool nss_core_skb_can_reuse(struct nss_ctx_instance *nss_ctx, - if (unlikely(irqs_disabled())) - return false; - -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0)) - if (unlikely(skb_shinfo(nbuf)->tx_flags & SKBTX_DEV_ZEROCOPY)) -+#else -+ if (unlikely(skb_shinfo(nbuf)->flags & SKBFL_ZEROCOPY_ENABLE)) -+#endif - return false; - - if (unlikely(skb_is_nonlinear(nbuf))) -diff --git a/nss_coredump.c b/nss_coredump.c -index ecad659..3ecef7e 100644 ---- a/nss_coredump.c -+++ b/nss_coredump.c -@@ -23,7 +23,11 @@ - #include "nss_hal.h" - #include "nss_log.h" - #include -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0)) - #include /* for panic_notifier_list */ -+#else -+#include -+#endif - #include /* for time */ - #include "nss_tx_rx_common.h" - -diff --git a/nss_hal/nss_hal.c b/nss_hal/nss_hal.c -index 57974c1..d8c703b 100644 ---- a/nss_hal/nss_hal.c -+++ b/nss_hal/nss_hal.c -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - - #include "nss_hal.h" - #include "nss_arch.h" --- -2.34.1 - diff --git a/root/package/qca/nss/qca-nss-drv-64/patches/0005-nss-drv-use-standard-skb_skip_tc_classify-instead-of.patch b/root/package/qca/nss/qca-nss-drv-64/patches/0005-nss-drv-use-standard-skb_skip_tc_classify-instead-of.patch deleted file mode 100644 index 73c923d3..00000000 --- a/root/package/qca/nss/qca-nss-drv-64/patches/0005-nss-drv-use-standard-skb_skip_tc_classify-instead-of.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 4dd701916186803172a9f35e7e982a953613ad55 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Mon, 11 Apr 2022 21:32:41 +0200 -Subject: [PATCH 5/9] nss-drv: use standard skb_skip_tc_classify instead of - custom api - -Use skb_skip_tc_classify to skip classify for packet handled by nss -instead of custom api. - -Signed-off-by: Ansuel Smith ---- - nss_core.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/nss_core.c b/nss_core.c -index f9e6014..6ab8038 100644 ---- a/nss_core.c -+++ b/nss_core.c -@@ -1075,7 +1075,7 @@ static inline void nss_core_set_skb_classify(struct sk_buff *nbuf) - #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0)) - nbuf->tc_verd = SET_TC_NCLS_NSS(nbuf->tc_verd); - #else -- skb_set_tc_classify_offload(nbuf); -+ skb_skip_tc_classify(nbuf); - #endif - #endif - } --- -2.34.1 diff --git a/root/package/qca/nss/qca-nss-drv-64/patches/0999-treewide-hack-support-for-mismatched-firmware.patch b/root/package/qca/nss/qca-nss-drv-64/patches/0999-treewide-hack-support-for-mismatched-firmware.patch deleted file mode 100644 index 46025b82..00000000 --- a/root/package/qca/nss/qca-nss-drv-64/patches/0999-treewide-hack-support-for-mismatched-firmware.patch +++ /dev/null @@ -1,344 +0,0 @@ -From d0bffc800a50305315a0d7cf37140291ef5b1b61 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Thu, 27 May 2021 03:52:47 +0200 -Subject: [PATCH] treewide: hack support for mismatched firmware - -Make new qsdk feature configurable to support old half compatible -firmware. - -Signed-off-by: Ansuel Smith ---- - exports/nss_fw_version.h | 11 +++++++++++ - exports/nss_ipv4.h | 8 ++++++++ - exports/nss_ipv6.h | 7 +++++++ - exports/nss_wifi_vdev.h | 14 ++++++++++++++ - exports/nss_wifili_if.h | 8 ++++++++ - nss_ipv4_stats.c | 2 ++ - nss_ipv4_strings.c | 2 ++ - nss_ipv6_stats.c | 2 ++ - nss_ipv6_strings.c | 2 ++ - 9 files changed, 56 insertions(+) - create mode 100644 exports/nss_fw_version.h - -diff --git a/exports/nss_fw_version.h b/exports/nss_fw_version.h -new file mode 100644 -index 0000000..895d523 ---- /dev/null -+++ b/exports/nss_fw_version.h -@@ -0,0 +1,11 @@ -+#ifndef __NSS_FW_VERSION_H -+#define __NSS_FW_VERSION_H -+ -+#define NSS_FW_VERSION_MAJOR 11 -+#define NSS_FW_VERSION_MINOR 4 -+ -+#define NSS_FW_VERSION(a,b) (((a) << 8) + (b)) -+ -+#define NSS_FW_VERSION_CODE NSS_FW_VERSION(NSS_FW_VERSION_MAJOR, NSS_FW_VERSION_MINOR) -+ -+#endif /* __NSS_FW_VERSION_H */ -\ No newline at end of file -diff --git a/exports/nss_ipv4.h b/exports/nss_ipv4.h -index ee3a552..25c4d82 100644 ---- a/exports/nss_ipv4.h -+++ b/exports/nss_ipv4.h -@@ -26,6 +26,8 @@ - #include "nss_stats_public.h" - #endif - -+#include "nss_fw_version.h" -+ - /** - * @addtogroup nss_ipv4_subsystem - * @{ -@@ -216,12 +218,14 @@ enum nss_ipv4_stats_types { - /**< Number of IPv4 multicast connection destroy requests that missed the cache. */ - NSS_IPV4_STATS_MC_CONNECTION_FLUSHES, - /**< Number of IPv4 multicast connection flushes. */ -+#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) - NSS_IPV4_STATS_CONNECTION_CREATE_INVALID_MIRROR_IFNUM, - /**< Number of IPv4 mirror connection requests with an invalid interface number. */ - NSS_IPV4_STATS_CONNECTION_CREATE_INVALID_MIRROR_IFTYPE, - /**< Number of IPv4 mirror connection requests with an invalid interface type. */ - NSS_IPV4_STATS_MIRROR_FAILURES, - /**< Number of IPv4 mirror failures. */ -+#endif - NSS_IPV4_STATS_MAX, - /**< Maximum message type. */ - }; -@@ -609,8 +613,10 @@ struct nss_ipv4_rule_create_msg { - /**< Ingress shaping related accleration parameters. */ - struct nss_ipv4_identifier_rule identifier; - /**< Rule for adding identifier. */ -+#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) - struct nss_ipv4_mirror_rule mirror_rule; - /**< Mirror rule parameter. */ -+#endif - }; - - /** -@@ -955,6 +961,7 @@ struct nss_ipv4_node_sync { - uint32_t ipv4_mc_connection_flushes; - /**< Number of multicast connection flushes. */ - -+#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) - uint32_t ipv4_connection_create_invalid_mirror_ifnum; - /**< Number of create request failed with an invalid mirror interface number. */ - -@@ -963,6 +970,7 @@ struct nss_ipv4_node_sync { - - uint32_t ipv4_mirror_failures; - /**< Mirror packet failed. */ -+#endif - - uint32_t exception_events[NSS_IPV4_EXCEPTION_EVENT_MAX]; - /**< Number of exception events. */ -diff --git a/exports/nss_ipv6.h b/exports/nss_ipv6.h -index 930e74c..a21f939 100644 ---- a/exports/nss_ipv6.h -+++ b/exports/nss_ipv6.h -@@ -195,6 +195,8 @@ enum nss_ipv6_stats_types { - /**< Number of IPv6 multicast connection destroy requests that missed the cache. */ - NSS_IPV6_STATS_MC_CONNECTION_FLUSHES, - /**< Number of IPv6 multicast connection flushes. */ -+ -+#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) - NSS_IPV6_STATS_CONNECTION_CREATE_INVALID_MIRROR_IFNUM, - /**< Number of IPv6 mirror connection requests with an invalid interface number. */ - NSS_IPV6_STATS_CONNECTION_CREATE_INVALID_MIRROR_IFTYPE, -@@ -202,6 +204,7 @@ enum nss_ipv6_stats_types { - - NSS_IPV6_STATS_MIRROR_FAILURES, - /**< Number of IPv6 mirror failures. */ -+#endif - - NSS_IPV6_STATS_MAX, - /**< Maximum message type. */ -@@ -702,8 +705,10 @@ struct nss_ipv6_rule_create_msg { - /**< Ingress shaping related accleration parameters. */ - struct nss_ipv6_identifier_rule identifier; - /**< Rule for adding identifier. */ -+#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) - struct nss_ipv6_mirror_rule mirror_rule; - /**< Mirror rule parameter. */ -+#endif - }; - - /** -@@ -950,6 +955,7 @@ struct nss_ipv6_node_sync { - uint32_t ipv6_mc_connection_flushes; - /**< Number of multicast connection flushes. */ - -+#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) - uint32_t ipv6_connection_create_invalid_mirror_ifnum; - /**< Number of create request failed with an invalid mirror interface number. */ - -@@ -958,6 +964,7 @@ struct nss_ipv6_node_sync { - - uint32_t ipv6_mirror_failures; - /**< Mirror packet failed. */ -+#endif - - uint32_t exception_events[NSS_IPV6_EXCEPTION_EVENT_MAX]; - /**< Number of exception events. */ -diff --git a/exports/nss_wifi_vdev.h b/exports/nss_wifi_vdev.h -index 1b52f66..da91b56 100644 ---- a/exports/nss_wifi_vdev.h -+++ b/exports/nss_wifi_vdev.h -@@ -74,8 +74,10 @@ enum nss_wifi_vdev_msg_types { - NSS_WIFI_VDEV_INTERFACE_RECOVERY_RESET_MSG, - NSS_WIFI_VDEV_INTERFACE_RECOVERY_RECONF_MSG, - NSS_WIFI_VDEV_SET_GROUP_KEY, -+#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) - NSS_WIFI_VDEV_HMMC_MEMBER_ADD_MSG, - NSS_WIFI_VDEV_HMMC_MEMBER_DEL_MSG, -+#endif - NSS_WIFI_VDEV_MAX_MSG - }; - -@@ -130,6 +132,7 @@ enum nss_wifi_vdev_err_types { - NSS_WIFI_VDEV_VLAN_MODE_CONFIG_FAIL, - NSS_WIFI_VDEV_RECOVERY_RESET_FAIL, - NSS_WIFI_VDEV_RECOVERY_RECONF_FAIL, -+#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) - NSS_WIFI_VDEV_CONFIG_GROUP_KEY_FAIL, - NSS_WIFI_VDEV_MULTIPASS_NOT_ENABLED, - NSS_WIFI_VDEV_ALLOC_VLAN_MAP_FAILED, -@@ -139,6 +142,7 @@ enum nss_wifi_vdev_err_types { - NSS_WIFI_VDEV_PPE_PORT_DESTROY_FAIL, - NSS_WIFI_VDEV_PPE_VSI_ASSIGN_FAIL, - NSS_WIFI_VDEV_PPE_VSI_UNASSIGN_FAIL, -+#endif - NSS_WIFI_VDEV_EINV_MAX_CFG - }; - -@@ -161,11 +165,13 @@ enum nss_wifi_vdev_ext_data_pkt_type { - NSS_WIFI_VDEV_EXT_TX_COMPL_PKT_TYPE = 11, /**< Tx completion. */ - NSS_WIFI_VDEV_EXT_DATA_PKT_TYPE_WDS_LEARN = 12, /**< WDS source port learning command. */ - NSS_WIFI_VDEV_EXT_DATA_PPDU_INFO = 13, /**< PPDU metadata information. */ -+#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) - NSS_WIFI_VDEV_EXT_DATA_PKT_TYPE_MCBC_RX = 14, /**< Multicast/broadcast packet received. */ - NSS_WIFI_VDEV_MESH_EXT_DATA_PKT_TYPE_RX_SPL_PACKET = 15, - /**< Mesh link VAP special packet. */ - NSS_WIFI_VDEV_MESH_EXT_DATA_PKT_TYPE_RX_MCAST_EXC = 16, - /**< Mesh link VAP multicast packet. */ -+#endif - NSS_WIFI_VDEV_EXT_DATA_PKT_TYPE_MAX - }; - -@@ -201,9 +207,11 @@ enum nss_wifi_vdev_cmd { - NSS_WIFI_VDEV_ENABLE_IGMP_ME_CMD, /**< Configuration to set IGMP multicast enhancement on VAP. */ - NSS_WIFI_VDEV_CFG_WDS_BACKHAUL_CMD, - /**< Configuration to set WDS backhaul extension on VAP. */ -+#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) - NSS_WIFI_VDEV_CFG_MCBC_EXC_TO_HOST_CMD, /**< Configuration to set multicast/broadcast exception to host on VAP. */ - NSS_WIFI_VDEV_CFG_PEER_AUTHORIZE_CMD, - /**< Configuration to enable peer authorization on VAP. */ -+#endif - NSS_WIFI_VDEV_MAX_CMD - }; - -@@ -271,7 +279,9 @@ struct nss_wifi_vdev_config_msg { - uint8_t is_nss_qwrap_en; /**< VAP is configured for NSS firmware QWRAP logic. */ - uint8_t tx_per_pkt_vdev_id_check; /**< Transmit per-packet virtual device ID check. */ - uint8_t align_pad; /**< Reserved field. */ -+#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) - uint32_t vap_ext_mode; /**< Different VAP extended modes. */ -+#endif - }; - - /** -@@ -1037,8 +1047,10 @@ struct nss_wifi_vdev_stats_sync_msg { - uint32_t rx_mcast_bytes; /**< Receive multicast bytes count. */ - uint32_t rx_decrypt_err; /**< Receive decryption error */ - uint32_t rx_mic_err; /**< Receive MIC error */ -+#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) - uint32_t mcbc_exc_host_fail_cnt; - /**< Number of multicast/broadcast packets failed to send to host through exception path. */ -+#endif - }; - - /** -@@ -1070,6 +1082,7 @@ struct nss_wifi_vdev_msg { - /**< Updates a snooplist group member. */ - struct nss_wifi_vdev_me_snptbl_deny_grp_add_msg vdev_deny_member_add; - /**< Add a snooplist member to the deny list. */ -+#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) - struct nss_wifi_vdev_me_hmmc_add_msg vdev_hmmc_member_add; - /**< Adds a new member into the HMMC list. */ - struct nss_wifi_vdev_me_hmmc_del_msg vdev_hmmc_member_del; -@@ -1078,6 +1091,7 @@ struct nss_wifi_vdev_msg { - /**< Adds a new member into the deny list. */ - struct nss_wifi_vdev_me_deny_ip_del_msg vdev_deny_list_member_del; - /**< Delete a member from the deny list. */ -+#endif - struct nss_wifi_vdev_txmsg vdev_txmsgext; - /**< Transmits special data. */ - struct nss_wifi_vdev_vow_dbg_cfg_msg vdev_vow_dbg_cfg; -diff --git a/exports/nss_wifili_if.h b/exports/nss_wifili_if.h -index fce20fd..1f26d67 100644 ---- a/exports/nss_wifili_if.h -+++ b/exports/nss_wifili_if.h -@@ -62,8 +62,12 @@ - /**< Maximum number of bandwidth supported. */ - #define NSS_WIFILI_REPT_MU_MIMO 1 - #define NSS_WIFILI_REPT_MU_OFDMA_MIMO 3 -+#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) -+#define NSS_WIFILI_MAX_RESERVED_TYPE 3 -+#else - #define NSS_WIFILI_MAX_RESERVED_TYPE 2 - /**< Maximum reserved type. */ -+#endif - #define NSS_WIFILI_SOC_PER_PACKET_METADATA_SIZE 60 - /**< Metadata area total size. */ - #define NSS_WIFILI_MEC_PEER_ID 0xDEAD -@@ -1333,7 +1337,9 @@ struct nss_wifili_rx_err { - struct nss_wifili_rx_ctrl_stats { - struct nss_wifili_rx_err err; /**< Rx peer errors. */ - uint32_t multipass_rx_pkt_drop; /**< Total number of multipass packets without a VLAN header. */ -+#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) - uint32_t peer_unauth_rx_pkt_drop; /**< Number of receive packets dropped due to an authorized peer. */ -+#endif - uint32_t reserved_type[NSS_WIFILI_MAX_RESERVED_TYPE]; /**< Reserved type for future use. */ - uint32_t non_amsdu_cnt; /**< Number of MSDUs with no MSDU level aggregation. */ - uint32_t amsdu_cnt; /**< Number of MSDUs part of AMSDU. */ -@@ -1810,10 +1816,12 @@ struct nss_wifili_msg { - /**< Peer four-address event message. */ - struct nss_wifili_dbdc_repeater_loop_detection_msg wdrldm; - /**< Wifili DBDC repeater loop detection message. */ -+#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) - struct nss_wifili_peer_update_auth_flag peer_auth; - /**< Peer authentication flag message. */ - struct nss_wifili_mesh_capability_info cap_info; - /**< Mesh capability flag. */ -+#endif - } msg; /**< Message payload. */ - }; - -diff --git a/nss_ipv4_stats.c b/nss_ipv4_stats.c -index 39b162c..c875a63 100644 ---- a/nss_ipv4_stats.c -+++ b/nss_ipv4_stats.c -@@ -177,9 +177,11 @@ void nss_ipv4_stats_node_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_ - nss_ipv4_stats[NSS_IPV4_STATS_MC_CONNECTION_DESTROY_REQUESTS] += nins->ipv4_mc_connection_destroy_requests; - nss_ipv4_stats[NSS_IPV4_STATS_MC_CONNECTION_DESTROY_MISSES] += nins->ipv4_mc_connection_destroy_misses; - nss_ipv4_stats[NSS_IPV4_STATS_MC_CONNECTION_FLUSHES] += nins->ipv4_mc_connection_flushes; -+#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) - nss_ipv4_stats[NSS_IPV4_STATS_CONNECTION_CREATE_INVALID_MIRROR_IFNUM] += nins->ipv4_connection_create_invalid_mirror_ifnum; - nss_ipv4_stats[NSS_IPV4_STATS_CONNECTION_CREATE_INVALID_MIRROR_IFTYPE] += nins->ipv4_connection_create_invalid_mirror_iftype; - nss_ipv4_stats[NSS_IPV4_STATS_MIRROR_FAILURES] += nins->ipv4_mirror_failures; -+#endif - - for (i = 0; i < NSS_IPV4_EXCEPTION_EVENT_MAX; i++) { - nss_ipv4_exception_stats[i] += nins->exception_events[i]; -diff --git a/nss_ipv4_strings.c b/nss_ipv4_strings.c -index 77ff352..ce4c249 100644 ---- a/nss_ipv4_strings.c -+++ b/nss_ipv4_strings.c -@@ -137,9 +137,11 @@ struct nss_stats_info nss_ipv4_strings_stats[NSS_IPV4_STATS_MAX] = { - {"mc_destroy_requests" , NSS_STATS_TYPE_SPECIAL}, - {"mc_destroy_misses" , NSS_STATS_TYPE_SPECIAL}, - {"mc_flushes" , NSS_STATS_TYPE_SPECIAL}, -+#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) - {"mirror_invalid_ifnum_conn_create_req" , NSS_STATS_TYPE_SPECIAL}, - {"mirror_invalid_iftype_conn_create_req" , NSS_STATS_TYPE_SPECIAL}, - {"mirror_failures" , NSS_STATS_TYPE_SPECIAL}, -+#endif - }; - - /* -diff --git a/nss_ipv6_stats.c b/nss_ipv6_stats.c -index 617f55b..a492a6c 100644 ---- a/nss_ipv6_stats.c -+++ b/nss_ipv6_stats.c -@@ -180,9 +180,11 @@ void nss_ipv6_stats_node_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_ - nss_ipv6_stats[NSS_IPV6_STATS_MC_CONNECTION_DESTROY_REQUESTS] += nins->ipv6_mc_connection_destroy_requests; - nss_ipv6_stats[NSS_IPV6_STATS_MC_CONNECTION_DESTROY_MISSES] += nins->ipv6_mc_connection_destroy_misses; - nss_ipv6_stats[NSS_IPV6_STATS_MC_CONNECTION_FLUSHES] += nins->ipv6_mc_connection_flushes; -+#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) - nss_ipv6_stats[NSS_IPV6_STATS_CONNECTION_CREATE_INVALID_MIRROR_IFNUM] += nins->ipv6_connection_create_invalid_mirror_ifnum; - nss_ipv6_stats[NSS_IPV6_STATS_CONNECTION_CREATE_INVALID_MIRROR_IFTYPE] += nins->ipv6_connection_create_invalid_mirror_iftype; - nss_ipv6_stats[NSS_IPV6_STATS_MIRROR_FAILURES] += nins->ipv6_mirror_failures; -+#endif - - for (i = 0; i < NSS_IPV6_EXCEPTION_EVENT_MAX; i++) { - nss_ipv6_exception_stats[i] += nins->exception_events[i]; -diff --git a/nss_ipv6_strings.c b/nss_ipv6_strings.c -index 57b100f..29df9c9 100644 ---- a/nss_ipv6_strings.c -+++ b/nss_ipv6_strings.c -@@ -115,9 +115,11 @@ struct nss_stats_info nss_ipv6_strings_stats[NSS_IPV6_STATS_MAX] = { - {"mc_destroy_requests" ,NSS_STATS_TYPE_SPECIAL}, - {"mc_destroy_misses" ,NSS_STATS_TYPE_SPECIAL}, - {"mc_flushes" ,NSS_STATS_TYPE_SPECIAL}, -+#if (NSS_FW_VERSION_CODE > NSS_FW_VERSION(11,3)) - {"mirror_invalid_ifnum_conn_create_req" ,NSS_STATS_TYPE_SPECIAL}, - {"mirror_invalid_iftype_conn_create_req" ,NSS_STATS_TYPE_SPECIAL}, - {"mirror_failures" ,NSS_STATS_TYPE_SPECIAL}, -+#endif - }; - - /* --- -2.31.1 - diff --git a/root/package/qca/nss/qca-nss-drv/Makefile b/root/package/qca/nss/qca-nss-drv/Makefile deleted file mode 100644 index 7e695ca3..00000000 --- a/root/package/qca/nss/qca-nss-drv/Makefile +++ /dev/null @@ -1,125 +0,0 @@ -include $(TOPDIR)/rules.mk -include $(INCLUDE_DIR)/kernel.mk - -PKG_NAME:=qca-nss-drv -PKG_RELEASE:=2 - -PKG_SOURCE_URL:=https://source.codeaurora.org/quic/qsdk/oss/lklm/nss-drv -PKG_SOURCE_PROTO:=git -PKG_SOURCE_VERSION:=809a00deffe9f3d4ecd15965790a152757073437 -PKG_MIRROR_HASH:=9c4340561fe9d6ccaa094bbfc5c7f98c27867d2d9a3f1a3f9a7483bca9bbedf8 - -NSS_CLIENTS_DIR:=$(TOPDIR)/qca/src/qca-nss-clients - -include $(INCLUDE_DIR)/package.mk - -define KernelPackage/qca-nss-drv - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Devices - DEPENDS:=@TARGET_ipq806x||TARGET_ipq_ipq806x||TARGET_ipq_ipq807x||TARGET_ipq_ipq807x_64||TARGET_ipq807x||TARGET_ipq807x_64||TARGET_ipq_ipq60xx||TARGET_ipq_ipq60xx_64||TARGET_ipq_ipq50xx||TARGET_ipq_ipq50xx_64 \ - +PACKAGE_kmod-qca-nss-gmac:kmod-qca-nss-gmac @LINUX_5_4 - TITLE:=Kernel driver for NSS (core driver) - FILES:=$(PKG_BUILD_DIR)/qca-nss-drv.ko - AUTOLOAD:=$(call AutoLoad,32,qca-nss-drv) -endef - -define KernelPackage/qca-nss-drv/install - $(INSTALL_DIR) $(1)/lib/debug - $(INSTALL_DIR) $(1)/etc/init.d - $(INSTALL_DIR) $(1)/etc/sysctl.d - $(INSTALL_DIR) $(1)/etc/hotplug.d/firmware - $(INSTALL_DIR) $(1)/etc/config - $(INSTALL_DIR) $(1)/lib/firmware - - $(INSTALL_BIN) ./files/qca-nss-drv.debug $(1)/lib/debug/qca-nss-drv - $(INSTALL_BIN) ./files/qca-nss-drv.init $(1)/etc/init.d/qca-nss-drv - $(INSTALL_BIN) ./files/qca-nss-drv.sysctl $(1)/etc/sysctl.d/qca-nss-drv.conf - $(INSTALL_BIN) ./files/qca-nss-drv.hotplug $(1)/etc/hotplug.d/firmware/10-qca-nss-fw - $(INSTALL_BIN) ./files/qca-nss-drv.conf $(1)/etc/config/nss - $(INSTALL_BIN) ./files/nss-firmware/qca-nss0-retail.bin $(1)/lib/firmware/qca-nss0.bin - $(INSTALL_BIN) ./files/nss-firmware/qca-nss1-retail.bin $(1)/lib/firmware/qca-nss1.bin - -endef - -define KernelPackage/qca-nss-drv/Description -This package contains a NSS driver for QCA chipset -endef - -define Build/InstallDev - mkdir -p $(1)/usr/include/qca-nss-drv - $(CP) $(PKG_BUILD_DIR)/exports/* $(1)/usr/include/qca-nss-drv/ -ifneq (, $(findstring $(subtarget), "ipq807x" "ipq807x_64" "ipq60xx" "ipq60xx_64" "ipq50xx" "ipq50xx_64")) - $(RM) $(1)/usr/include/qca-nss-drv/nss_ipsecmgr.h - $(INSTALL_DIR) $(1)/usr/include/qca-nss-clients - $(CP) $(NSS_CLIENTS_DIR)/exports/nss_ipsecmgr.h $(1)/usr/include/qca-nss-clients/. -endif -endef - -EXTRA_CFLAGS+= -I$(STAGING_DIR)/usr/include/qca-nss-gmac - -# Keeping default as ipq806x for branches that does not have subtarget framework -ifeq ($(CONFIG_TARGET_ipq),y) -subtarget:=$(SUBTARGET) -else -subtarget:=$(CONFIG_TARGET_BOARD) -endif - -ifeq ($(CONFIG_KERNEL_IPQ_MEM_PROFILE),256) -EXTRA_CFLAGS+= -DNSS_MEM_PROFILE_LOW -endif - -ifeq ($(CONFIG_KERNEL_IPQ_MEM_PROFILE),512) -EXTRA_CFLAGS+= -DNSS_MEM_PROFILE_MEDIUM -endif - -ifeq ($(CONFIG_KERNEL_SKB_FIXED_SIZE_2K),y) -EXTRA_CFLAGS+= -DNSS_SKB_FIXED_SIZE_2K -endif - -DRV_MAKE_OPTS:= -ifeq ($(CONFIG_KERNEL_IPQ_MEM_PROFILE),256) -DRV_MAKE_OPTS+=NSS_DRV_C2C_ENABLE=n \ - NSS_DRV_CAPWAP_ENABLE=n \ - NSS_DRV_CLMAP_ENABLE=n \ - NSS_DRV_CRYPTO_ENABLE=n \ - NSS_DRV_DTLS_ENABLE=n \ - NSS_DRV_GRE_ENABLE=n \ - NSS_DRV_GRE_REDIR_ENABLE=n \ - NSS_DRV_GRE_TUNNEL_ENABLE=n \ - NSS_DRV_IGS_ENABLE=n \ - NSS_DRV_IPSEC_ENABLE=n \ - NSS_DRV_LAG_ENABLE=n \ - NSS_DRV_L2TP_ENABLE=n \ - NSS_DRV_MAPT_ENABLE=n \ - NSS_DRV_OAM_ENABLE=n \ - NSS_DRV_PPTP_ENABLE=n \ - NSS_DRV_PORTID_ENABLE=n \ - NSS_DRV_PVXLAN_ENABLE=n \ - NSS_DRV_QRFS_ENABLE=n \ - NSS_DRV_QVPN_ENABLE=n \ - NSS_DRV_RMNET_ENABLE=n \ - NSS_DRV_SHAPER_ENABLE=n \ - NSS_DRV_SJACK_ENABLE=n \ - NSS_DRV_TLS_ENABLE=n \ - NSS_DRV_TRUSTSEC_ENABLE=n \ - NSS_DRV_TSTAMP_ENABLE=n \ - NSS_DRV_TUN6RD_ENABLE=n \ - NSS_DRV_TUNIPIP6_ENABLE=n \ - NSS_DRV_VXLAN_ENABLE=n -endif - -define Build/Configure - $(LN) arch/nss_$(subtarget).h $(PKG_BUILD_DIR)/exports/nss_arch.h -endef - -define Build/Compile - $(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" $(strip $(DRV_MAKE_OPTS)) \ - $(KERNEL_MAKE_FLAGS) \ - $(PKG_MAKE_FLAGS) \ - M="$(PKG_BUILD_DIR)" \ - EXTRA_CFLAGS="$(EXTRA_CFLAGS)" SoC="$(subtarget)" \ - modules -endef - -$(eval $(call KernelPackage,qca-nss-drv)) diff --git a/root/package/qca/nss/qca-nss-drv/files/nss-firmware/LICENSE.TXT b/root/package/qca/nss/qca-nss-drv/files/nss-firmware/LICENSE.TXT deleted file mode 100644 index 41631989..00000000 --- a/root/package/qca/nss/qca-nss-drv/files/nss-firmware/LICENSE.TXT +++ /dev/null @@ -1,45 +0,0 @@ -Copyright (c) 2014 Qualcomm Atheros, Inc. - -All rights reserved. - -Redistribution and use in binary forms, without -modification, are permitted (subject to the limitations in the -disclaimer below) provided that the following conditions are met: - -*Redistributions must reproduce the above copyright - notice, this list of conditions, and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -*Neither the name of Qualcomm Atheros, Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -*No Reverse engineering, decompiling, decrypting, or disassembling of this - software is permitted. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. NO LICENSES OR OTHER RIGHTS, -WHETHER EXPRESS, IMPLIED, BASED ON ESTOPPEL OR OTHERWISE, ARE GRANTED -TO ANY PARTY'S PATENTS, PATENT APPLICATIONS, OR PATENTABLE INVENTIONS -BY VIRTUE OF THIS LICENSE OR THE DELIVERY OR PROVISION BY QUALCOMM -ATHEROS, INC. OF THE SOFTWARE. - -IN NO EVENT SHALL THE COPYRIGHT OWNER OR ANY CONTRIBUTOR BE LIABLE FOR -ANY INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND REGARDLESS OF ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -OTHERWISE) ARISING IN ANY WAY OUT OF OR RESULTING FROM THE USE OF THE -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. IN ANY -EVENT, THE TOTAL AGGREGATE LIABILITY THAT MAY BE IMPOSED ON QUALCOMM -ATHEROS, INC. FOR ANY DIRECT DAMAGES ARISING UNDER OR RESULTING FROM -THIS AGREEMENT OR IN CONNECTION WITH ANY USE OF THE SOFTWARE SHALL NOT -EXCEED A TOTAL AMOUNT OF US$5.00. - -IF ANY OF THE ABOVE PROVISIONS ARE HELD TO BE VOID, INVALID, -UNENFORCEABLE, OR ILLEGAL, THE OTHER PROVISIONS SHALL CONTINUE IN FULL -FORCE AND EFFECT. - diff --git a/root/package/qca/nss/qca-nss-drv/files/nss-firmware/NOTICE.TXT b/root/package/qca/nss/qca-nss-drv/files/nss-firmware/NOTICE.TXT deleted file mode 100644 index ab54aa01..00000000 --- a/root/package/qca/nss/qca-nss-drv/files/nss-firmware/NOTICE.TXT +++ /dev/null @@ -1,217 +0,0 @@ -============================================================================= - -This Notice.txt file contains certain notices of software components included -with the software that Qualcomm Atheros, Inc. ("Qualcomm Atheros") is required -to provide you. Except where prohibited by the open source license, the content -of this notices file is only provided to satisfy Qualcomm Atheros's attribution -and notice requirement; your use of these software components together with the -Qualcomm Atheros software (Qualcomm Atheros software hereinafter referred to as -"Software") is subject to the terms of your license from Qualcomm Atheros. -Compliance with all copyright laws and software license agreements included in -the notice section of this file are the responsibility of the user. Except as -may be granted by separate express written agreement, this file provides no -license to any Qualcomm Atheros patents, trademarks, copyrights, or other -intellectual property. - -Copyright (c) 2014 Qualcomm Atheros, Inc. All rights reserved. - -Qualcomm is a trademark of Qualcomm Incorporated, registered in the United -States and other countries. All Qualcomm Incorporated trademarks are used with -permission. Atheros is a trademark of Qualcomm Atheros, Inc., registered in the -United States and other countries. Other products and brand names may be -trademarks or registered trademarks of their respective owners. - -NOTICES: - -============================================================================= - -/* - * doprint.c - * Formatted string print support. - * - * Copyright 2001-2012 Qualcomm Atheros, Inc. All Rights Reserved. - * - * Qualcomm Atheros Confidential and Proprietary. - * - * This code originates with BSD Unix however it has been extensively - * modified. The original copyright is reproduced below: - * - * Copyright (c) 1988 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted provided - * that: (1) source distributions retain this entire copyright notice and - * comment, and (2) distributions including binaries display the following - * acknowledgement: ``This product includes software developed by the - * University of California, Berkeley and its contributors'' in the - * documentation or other materials provided with the distribution and in - * all advertising materials mentioning features or use of this software. - * Neither the name of the University nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - - -/* - * math.c - * Support for the standard C library. - * - * Copyright 2006-2012 Qualcomm Atheros, Inc. All Rights Reserved. - * - * Qualcomm Atheros Confidential and Proprietary. - * - * Software contained within this file was originally released with the - * following - * copyright and license statement: - * - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - - -/* - * stdlib.c - * Routines from stdlib.h. - * - * Copyright 2004-2012 Qualcomm Atheros, Inc. All Rights Reserved. - * - * Qualcomm Atheros Confidential and Proprietary. - * - * The code for strtol() and strtoul() are also subject to the following: - * - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -drr_alg_utils.h: -/****************************************************************************/ -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - - -shaper_list_utils.h: -/****************************************************************************/ -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - - -codel_alg_inv_sqrt.h -/****************************************************************************/ -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ diff --git a/root/package/qca/nss/qca-nss-drv/files/nss-firmware/README.md b/root/package/qca/nss/qca-nss-drv/files/nss-firmware/README.md deleted file mode 100644 index 2d0b4750..00000000 --- a/root/package/qca/nss/qca-nss-drv/files/nss-firmware/README.md +++ /dev/null @@ -1,10 +0,0 @@ -NSS FIRMWARE -============ - -This repo contains firmware files to enable the NSS MAC on QCA IPQ806x SoC. - -This product includes software developed by the University of California, -Berkeley and its contributors. - -NSS firmware extracted from Synology RT2600ac SRM 1.2 - Version: 1.2-7742-4 - diff --git a/root/package/qca/nss/qca-nss-drv/files/nss-firmware/qca-nss0-retail.bin b/root/package/qca/nss/qca-nss-drv/files/nss-firmware/qca-nss0-retail.bin deleted file mode 100644 index 08f6efe6c8d8c476a7b68c8b44e125db75276cef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 536324 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 z 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

    4|GJx3IMG;WZSS-@ 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ΠfAA56W)Al)uy*Y5hcMjv&o6EXSJ?Ho3 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

  • 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 diff --git a/root/package/qca/nss/qca-nss-drv/files/nss-firmware/qca-nss1-retail.bin b/root/package/qca/nss/qca-nss-drv/files/nss-firmware/qca-nss1-retail.bin deleted file mode 100644 index e79510f34de55c649a7fb48f1ba40c59294bb525..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 218224 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 diff --git a/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.conf b/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.conf deleted file mode 100644 index a8a1fbf4..00000000 --- a/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.conf +++ /dev/null @@ -1,6 +0,0 @@ -config nss_firmware 'qca_nss_0' - -config nss_firmware 'qca_nss_1' - -config general - option enable_rps '1' diff --git a/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.debug b/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.debug deleted file mode 100644 index 5d435c3a..00000000 --- a/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.debug +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh /sbin/sysdebug -# -# Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -log cat /sys/kernel/debug/qca-nss-drv/stats/pppoe -log cat /sys/kernel/debug/qca-nss-drv/stats/n2h -log cat /sys/kernel/debug/qca-nss-drv/stats/ipv6 -log cat /sys/kernel/debug/qca-nss-drv/stats/ipv4 -log cat /sys/kernel/debug/qca-nss-drv/stats/gmac -log cat /sys/kernel/debug/qca-nss-drv/stats/drv -log cat /sys/kernel/debug/qca-nss-drv/stats/wifi -log cat /sys/kernel/debug/qca-nss-drv/stats/wifi_if -log cat /sys/kernel/debug/qca-nss-drv/stats/eth_rx diff --git a/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.hotplug b/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.hotplug deleted file mode 100644 index 1e481383..00000000 --- a/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.hotplug +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -KERNEL=`uname -r` -case "${KERNEL}" in - 3.4*) - select_or_load=load_nss_fw - ;; - *) - select_or_load=select_nss_fw - ;; -esac - -load_nss_fw () { - ls -l $1 | awk ' { print $9,$5 } '> /dev/console - echo 1 > /sys/class/firmware/$DEVICENAME/loading - cat $1 > /sys/class/firmware/$DEVICENAME/data - echo 0 > /sys/class/firmware/$DEVICENAME/loading -} - -select_nss_fw () { - rm -f /lib/firmware/$DEVICENAME - ln -s $1 /lib/firmware/$DEVICENAME - ls -l /lib/firmware/$DEVICENAME | awk ' { print $9,$5 } '> /dev/console -} - -[ "$ACTION" != "add" ] && exit - -# dev name for UCI, since it doesn't let you use . or - -SDEVNAME=$(echo ${DEVICENAME} | sed s/[.-]/_/g) - -SELECTED_FW=$(uci get nss.${SDEVNAME}.firmware 2>/dev/null) -[ -e "${SELECTED_FW}" ] && { - $select_or_load ${SELECTED_FW} - exit -} - -case $DEVICENAME in - qca-nss0* | qca-nss.0*) - if [ -e /lib/firmware/qca-nss0-enterprise.bin ] ; then - $select_or_load /lib/firmware/qca-nss0-enterprise.bin - else - $select_or_load /lib/firmware/qca-nss0-retail.bin - fi - exit - ;; - qca-nss1* | qca-nss.1*) - if [ -e /lib/firmware/qca-nss1-enterprise.bin ] ; then - $select_or_load /lib/firmware/qca-nss1-enterprise.bin - else - $select_or_load /lib/firmware/qca-nss1-retail.bin - fi - exit - ;; -esac - diff --git a/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.init b/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.init deleted file mode 100644 index de12cb6d..00000000 --- a/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.init +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/sh /etc/rc.common -# -# Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -START=70 - -enable_rps() { - irq_nss_rps=`grep nss_queue1 /proc/interrupts | cut -d ':' -f 1 | tr -d ' '` - for entry in $irq_nss_rps - do - echo 2 > /proc/irq/$entry/smp_affinity - done - - irq_nss_rps=`grep nss_queue2 /proc/interrupts | cut -d ':' -f 1 | tr -d ' '` - for entry in $irq_nss_rps - do - echo 4 > /proc/irq/$entry/smp_affinity - done - - irq_nss_rps=`grep nss_queue3 /proc/interrupts | cut -d ':' -f 1 | tr -d ' '` - for entry in $irq_nss_rps - do - echo 8 > /proc/irq/$entry/smp_affinity - done - - # Enable NSS RPS - sysctl -w dev.nss.rps.enable=1 >/dev/null 2>/dev/null - -} - - -start() { - local rps_enabled="$(uci_get nss @general[0] enable_rps)" - if [ "$rps_enabled" -eq 1 ]; then - enable_rps - fi -} diff --git a/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.sysctl b/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.sysctl deleted file mode 100644 index fc36c33e..00000000 --- a/root/package/qca/nss/qca-nss-drv/files/qca-nss-drv.sysctl +++ /dev/null @@ -1,4 +0,0 @@ -# Default Number of connection configuration -dev.nss.ipv4cfg.ipv4_conn=4096 -dev.nss.ipv6cfg.ipv6_conn=4096 - diff --git a/root/package/qca/nss/qca-nss-drv/patches/100-kernel-5.4-support.patch b/root/package/qca/nss/qca-nss-drv/patches/100-kernel-5.4-support.patch deleted file mode 100644 index 4268225c..00000000 --- a/root/package/qca/nss/qca-nss-drv/patches/100-kernel-5.4-support.patch +++ /dev/null @@ -1,107 +0,0 @@ -diff --git a/Makefile b/Makefile -index d998548..b1a4a83 100644 ---- a/Makefile -+++ b/Makefile -@@ -161,7 +161,7 @@ endif - ccflags-y += -I$(obj)/nss_hal/include -I$(obj)/nss_data_plane/include -I$(obj)/exports -DNSS_DEBUG_LEVEL=0 -DNSS_PKT_STATS_ENABLED=1 - - ccflags-y += -DNSS_PM_DEBUG_LEVEL=0 -DNSS_SKB_REUSE_SUPPORT=1 --ccflags-y += -Werror -+# ccflags-y += -Werror - - ifneq ($(findstring 3.4, $(KERNELVERSION)),) - NSS_CCFLAGS = -DNSS_DT_SUPPORT=0 -DNSS_FW_DBG_SUPPORT=1 -DNSS_PM_SUPPORT=1 -DNSS_EMPTY_BUFFER_SIZE=1984 -diff --git a/nss_core.c b/nss_core.c -index 6c9716a..8956eb5 100644 ---- a/nss_core.c -+++ b/nss_core.c -@@ -26,6 +26,7 @@ - #include - #include - #include -+#include - #include "nss_tx_rx_common.h" - #include "nss_data_plane.h" - -@@ -45,7 +46,8 @@ - (((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0)))) || \ - (((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0)))) || \ - (((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)))) || \ --(((LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0)))))) -+(((LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0)))) || \ -+(((LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(5, 5, 0)))))) - #error "Check skb recycle code in this file to match Linux version" - #endif - -@@ -395,7 +397,11 @@ static void nss_get_ddr_info(struct nss_mmu_ddr_info *mmu, char *name) - struct device_node *node; - - si_meminfo(&vals); -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) -+ cached = global_zone_page_state(NR_FILE_PAGES); -+#else - cached = global_page_state(NR_FILE_PAGES); -+#endif /*KERNEL_VERSION(4, 14, 0)*/ - avail_ddr = (vals.totalram + cached + vals.sharedram) * vals.mem_unit; - - /* -@@ -679,7 +685,11 @@ static inline void nss_core_handle_virt_if_pkt(struct nss_ctx_instance *nss_ctx, - * Mimic Linux behavior to allow multi-queue netdev choose which queue to use - */ - if (ndev->netdev_ops->ndo_select_queue) { -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) -+ queue_offset = ndev->netdev_ops->ndo_select_queue(ndev, nbuf, NULL); -+#else - queue_offset = ndev->netdev_ops->ndo_select_queue(ndev, nbuf, NULL, NULL); -+#endif /*KERNEL_VERSION(5, 3, 0)*/ - } - - skb_set_queue_mapping(nbuf, queue_offset); -@@ -2269,7 +2279,11 @@ static inline bool nss_skb_can_reuse(struct nss_ctx_instance *nss_ctx, - * This check is added to avoid deadlock from nf_conntrack - * when ecm is trying to flush a rule. - */ -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) -+ if (unlikely(skb_nfct(nbuf))) { -+#else - if (unlikely(nbuf->nfct)) { -+#endif /*KERNEL_VERSION(4, 11, 0)*/ - return false; - } - #endif -@@ -2279,7 +2285,11 @@ static inline bool nss_skb_can_reuse(struct nss_ctx_instance *nss_ctx, - * This check is added to avoid deadlock from nf_bridge - * when ecm is trying to flush a rule. - */ -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) -+ if (unlikely(skb_ext_exist(nbuf, SKB_EXT_BRIDGE_NF))) { -+#else - if (unlikely(nbuf->nf_bridge)) { -+#endif /*KERNEL_VERSION(4, 11, 0)*/ - return false; - } - #endif -diff --git a/nss_n2h.c b/nss_n2h.c -index 781ce2b..695ac13 100644 ---- a/nss_n2h.c -+++ b/nss_n2h.c -@@ -19,6 +19,7 @@ - * NSS N2H node APIs - */ - -+#include - #include "nss_tx_rx_common.h" - #include "nss_n2h_stats.h" - - ---- a/nss_data_plane/nss_data_plane_gmac.c -+++ b/nss_data_plane/nss_data_plane_gmac.c -@@ -20,7 +20,7 @@ - #include "nss_tx_rx_common.h" - #include - --#define NSS_DP_GMAC_SUPPORTED_FEATURES (NETIF_F_HIGHDMA | NETIF_F_HW_CSUM | NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_FRAGLIST | (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_UFO)) -+#define NSS_DP_GMAC_SUPPORTED_FEATURES (NETIF_F_HIGHDMA | NETIF_F_HW_CSUM | NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_FRAGLIST | (NETIF_F_TSO | NETIF_F_TSO6)) - #define NSS_DATA_PLANE_GMAC_MAX_INTERFACES 4 - - static DEFINE_SPINLOCK(nss_data_plane_gmac_stats_lock); diff --git a/root/package/qca/nss/qca-nss-drv/patches/101-nss-drv-Control-fab-scaling-from-package-Makefile.patch b/root/package/qca/nss/qca-nss-drv/patches/101-nss-drv-Control-fab-scaling-from-package-Makefile.patch deleted file mode 100644 index b0facc85..00000000 --- a/root/package/qca/nss/qca-nss-drv/patches/101-nss-drv-Control-fab-scaling-from-package-Makefile.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 40d4b080f17883ac6b39c74a5feb1af384ab6a51 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Thu, 11 Jun 2020 16:57:39 +0200 -Subject: [PATCH] nss-drv: Control fab scaling from package Makefile - -Lets control the fab scaling from the package Makefile -instead of using kernel checks that dont work. -Fab scaling in OpenWrt is done in a external way. - -Signed-off-by: Robert Marko ---- - Makefile | 9 --------- - 1 file changed, 9 deletions(-) - -diff --git a/Makefile b/Makefile -index 20729ab..2567dd4 100644 ---- a/Makefile -+++ b/Makefile -@@ -405,15 +405,8 @@ NSS_CCFLAGS = -DNSS_DT_SUPPORT=1 -DNSS_FW_DBG_SUPPORT=0 -DNSS_PM_SUPPORT=0 - ccflags-y += -I$(obj) - endif - --# Fabric scaling is supported in 3.14 and 4.4 only --ifneq ($(findstring 3.14, $(KERNELVERSION)),) --NSS_CCFLAGS += -DNSS_FABRIC_SCALING_SUPPORT=1 --else ifneq ($(findstring 4.4, $(KERNELVERSION)),) --NSS_CCFLAGS += -DNSS_FABRIC_SCALING_SUPPORT=1 --else --NSS_CCFLAGS += -DNSS_FABRIC_SCALING_SUPPORT=0 --endif -+NSS_CCFLAGS += -DNSS_FABRIC_SCALING_SUPPORT=0 - - # Disable Frequency scaling - ifeq "$(NSS_FREQ_SCALE_DISABLE)" "y" - ccflags-y += -DNSS_FREQ_SCALE_SUPPORT=0 --- -2.26.2 - diff --git a/root/package/qca/nss/qca-nss-drv/patches/200-fix-NULL-pointer-exception.patch b/root/package/qca/nss/qca-nss-drv/patches/200-fix-NULL-pointer-exception.patch deleted file mode 100644 index 3d8bba95..00000000 --- a/root/package/qca/nss/qca-nss-drv/patches/200-fix-NULL-pointer-exception.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/nss_core.c -+++ b/nss_core.c -@@ -1599,7 +1599,7 @@ static int32_t nss_core_handle_cause_que - * - */ - if (unlikely((buffer_type == N2H_BUFFER_CRYPTO_RESP))) { -- dma_unmap_single(NULL, (desc->buffer + desc->payload_offs), desc->payload_len, DMA_FROM_DEVICE); -+ dma_unmap_single(nss_ctx->dev, (desc->buffer + desc->payload_offs), desc->payload_len, DMA_FROM_DEVICE); - goto consume; - } - diff --git a/root/package/qca/nss/qca-nss-drv/patches/201-Fix-Kernel-Panic-dma-with-NULL-dev.patch b/root/package/qca/nss/qca-nss-drv/patches/201-Fix-Kernel-Panic-dma-with-NULL-dev.patch deleted file mode 100644 index addfef1b..00000000 --- a/root/package/qca/nss/qca-nss-drv/patches/201-Fix-Kernel-Panic-dma-with-NULL-dev.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 89949decfd9a0f86427b502aae4fbc3a3ef399f0 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Tue, 23 Jun 2020 19:50:28 +0200 -Subject: [PATCH] Fix Kernel Panic dma with NULL dev - ---- - nss_coredump.c | 4 ++-- - nss_log.c | 8 +++++--- - 2 files changed, 8 insertions(+), 6 deletions(-) - -diff --git a/nss_coredump.c b/nss_coredump.c -index aa4ba82..957eca0 100644 ---- a/nss_coredump.c -+++ b/nss_coredump.c -@@ -154,7 +154,7 @@ void nss_fw_coredump_notify(struct nss_ctx_instance *nss_own, - dma_addr = nss_own->meminfo_ctx.logbuffer_dma; - } - -- dma_sync_single_for_cpu(NULL, dma_addr, sizeof(struct nss_log_descriptor), DMA_FROM_DEVICE); -+ dma_sync_single_for_cpu(nss_own->dev, dma_addr, sizeof(struct nss_log_descriptor), DMA_FROM_DEVICE); - - /* - * If the current entry is smaller than or equal to the number of NSS_LOG_COREDUMP_LINE_NUM, -@@ -181,7 +181,7 @@ void nss_fw_coredump_notify(struct nss_ctx_instance *nss_own, - - offset = (index * sizeof(struct nss_log_entry)) - + offsetof(struct nss_log_descriptor, log_ring_buffer); -- dma_sync_single_for_cpu(NULL, dma_addr + offset, -+ dma_sync_single_for_cpu(nss_own->dev, dma_addr + offset, - sizeof(struct nss_log_entry), DMA_FROM_DEVICE); - nss_info_always("%p: %s\n", nss_own, nle_print->message); - nle_print++; -diff --git a/nss_log.c b/nss_log.c -index 06ebba4..f9bd6c8 100644 ---- a/nss_log.c -+++ b/nss_log.c -@@ -44,6 +44,7 @@ struct nss_log_data { - uint32_t last_entry; /* Last known sampled entry (or index) */ - uint32_t nentries; /* Caches the total number of entries of log buffer */ - int nss_id; /* NSS Core id being used */ -+ struct device *nss_dev; - }; - - struct nss_log_ring_buffer_addr nss_rbe[NSS_MAX_CORES]; -@@ -125,6 +126,7 @@ static int nss_log_open(struct inode *inode, struct file *filp) - data->last_entry = 0; - data->nentries = nss_rbe[nss_id].nentries; - data->dma_addr = nss_rbe[nss_id].dma_addr; -+ data->nss_dev = nss_ctx->dev; - - /* - * Increment the reference count so that we don't free -@@ -207,7 +209,7 @@ static ssize_t nss_log_read(struct file *filp, char __user *buf, size_t size, lo - /* - * Get the current index - */ -- dma_sync_single_for_cpu(NULL, data->dma_addr, sizeof(struct nss_log_descriptor), DMA_FROM_DEVICE); -+ dma_sync_single_for_cpu(data->nss_dev, data->dma_addr, sizeof(struct nss_log_descriptor), DMA_FROM_DEVICE); - entry = nss_log_current_entry(desc); - - /* -@@ -251,7 +253,7 @@ static ssize_t nss_log_read(struct file *filp, char __user *buf, size_t size, lo - offset = (offset * sizeof(struct nss_log_entry)) - + offsetof(struct nss_log_descriptor, log_ring_buffer); - -- dma_sync_single_for_cpu(NULL, data->dma_addr + offset, -+ dma_sync_single_for_cpu(data->nss_dev, data->dma_addr + offset, - sizeof(struct nss_log_entry), DMA_FROM_DEVICE); - rb = &desc->log_ring_buffer[index]; - -@@ -510,7 +512,7 @@ bool nss_debug_log_buffer_alloc(uint8_t nss_id, uint32_t nentry) - return true; - - fail: -- dma_unmap_single(NULL, dma_addr, size, DMA_FROM_DEVICE); -+ dma_unmap_single(nss_ctx->dev, dma_addr, size, DMA_FROM_DEVICE); - kfree(addr); - wake_up(&nss_log_wq); - return false; --- -2.27.0 - diff --git a/root/package/qca/nss/qca-nss-drv/patches/400-Exported-set-nexthop-function.patch b/root/package/qca/nss/qca-nss-drv/patches/400-Exported-set-nexthop-function.patch deleted file mode 100644 index 8c0ffe77..00000000 --- a/root/package/qca/nss/qca-nss-drv/patches/400-Exported-set-nexthop-function.patch +++ /dev/null @@ -1,47 +0,0 @@ -From f8cf061454a3707c0c84d0fca685e84455f91362 Mon Sep 17 00:00:00 2001 -From: Suruchi Suman -Date: Tue, 3 Dec 2019 12:57:38 +0530 -Subject: [qca-nss-drv] Exported set nexhop function from drv. - -Change-Id: I3df6658bef72fe574ac9acfb7aac61785769766f -Signed-off-by: Suruchi Suman ---- - nss_phys_if.c | 9 ++++++++- - 1 file changed, 8 insertions(+), 1 deletion(-) - -diff --git a/nss_phys_if.c b/nss_phys_if.c -index 4f9b20f..0c58d95 100644 ---- a/nss_phys_if.c -+++ b/nss_phys_if.c -@@ -1,6 +1,6 @@ - /* - ************************************************************************** -- * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. -+ * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved. - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all copies. -@@ -583,6 +583,12 @@ nss_tx_status_t nss_phys_if_set_nexthop(struct nss_ctx_instance *nss_ctx, uint32 - struct nss_phys_if_msg nim; - - NSS_VERIFY_CTX_MAGIC(nss_ctx); -+ -+ if (nexthop >= NSS_MAX_NET_INTERFACES) { -+ nss_warning("%p: Invalid nexthop interface number: %d", nss_ctx, nexthop); -+ return NSS_TX_FAILURE_BAD_PARAM; -+ } -+ - nss_info("%p: Phys If nexthop will be set to %d, id:%d\n", nss_ctx, nexthop, if_num); - - nss_cmn_msg_init(&nim.cm, if_num, NSS_PHYS_IF_SET_NEXTHOP, -@@ -591,6 +597,7 @@ nss_tx_status_t nss_phys_if_set_nexthop(struct nss_ctx_instance *nss_ctx, uint32 - - return nss_phys_if_msg_sync(nss_ctx, &nim); - } -+EXPORT_SYMBOL(nss_phys_if_set_nexthop); - - /* - * nss_get_state() --- -cgit v1.1 - diff --git a/root/package/qca/nss/qca-nss-ecm-64/Makefile b/root/package/qca/nss/qca-nss-ecm-64/Makefile deleted file mode 100644 index a22d3285..00000000 --- a/root/package/qca/nss/qca-nss-ecm-64/Makefile +++ /dev/null @@ -1,96 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=qca-nss-ecm-64 -PKG_RELEASE:=$(AUTORELEASE) - -PKG_SOURCE_URL:=https://source.codeaurora.org/quic/cc-qrdk/oss/lklm/qca-nss-ecm -PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2021-04-29 -PKG_SOURCE_VERSION:=c115aec34867b582e2e5ea79fc5315971e0e953c -PKG_MIRROR_HASH:=962385b45daa2e552a15018bf2930c2df1f6f575d885375bf935a142b4255da5 - -PKG_BUILD_PARALLEL:=1 - -include $(INCLUDE_DIR)/kernel.mk -include $(INCLUDE_DIR)/package.mk - -define KernelPackage/qca-nss-ecm-64 - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Support - DEPENDS:=@(TARGET_ipq807x||TARGET_ipq60xx) \ - +kmod-qca-nss-drv-64 \ - +iptables-mod-extra \ - +kmod-ipt-conntrack \ - +kmod-ipt-physdev \ - +iptables-mod-physdev \ - +kmod-ppp \ - +kmod-pppoe - TITLE:=QCA NSS Enhanced Connection Manager (ECM) - FILES:=$(PKG_BUILD_DIR)/*.ko - KCONFIG:=CONFIG_BRIDGE_NETFILTER=y \ - CONFIG_NF_CONNTRACK_EVENTS=y \ - CONFIG_NF_CONNTRACK_CHAIN_EVENTS=y \ - CONFIG_NF_CONNTRACK_DSCPREMARK_EXT=n -endef - -define KernelPackage/qca-nss-ecm-64/Description -This package contains the QCA NSS Enhanced Connection Manager -endef - -define KernelPackage/qca-nss-ecm-64/install - $(INSTALL_DIR) $(1)/etc/firewall.d $(1)/etc/init.d $(1)/usr/bin $(1)/lib/netifd/offload $(1)/etc/config $(1)/etc/uci-defaults $(1)/etc/sysctl.d - $(INSTALL_DATA) ./files/qca-nss-ecm.firewall $(1)/etc/firewall.d/qca-nss-ecm - $(INSTALL_BIN) ./files/qca-nss-ecm.init $(1)/etc/init.d/qca-nss-ecm - $(INSTALL_BIN) ./files/ecm_dump.sh $(1)/usr/bin/ - $(INSTALL_BIN) ./files/on-demand-down $(1)/lib/netifd/offload/on-demand-down - $(INSTALL_DATA) ./files/qca-nss-ecm.uci $(1)/etc/config/ecm - $(INSTALL_DATA) ./files/qca-nss-ecm.defaults $(1)/etc/uci-defaults/99-qca-nss-ecm - $(INSTALL_BIN) ./files/qca-nss-ecm.sysctl $(1)/etc/sysctl.d/qca-nss-ecm.conf -endef - -EXTRA_CFLAGS+=-I$(STAGING_DIR)/usr/include/qca-nss-drv - -ifneq (, $(findstring $(CONFIG_TARGET_BOARD), "ipq807x" "ipq60xx")) -ECM_MAKE_OPTS+= ECM_FRONT_END_NSS_ENABLE=y \ - ECM_CLASSIFIER_HYFI_ENABLE=n \ - ECM_MULTICAST_ENABLE=n \ - ECM_INTERFACE_IPSEC_ENABLE=n \ - ECM_INTERFACE_PPTP_ENABLE=n \ - ECM_INTERFACE_L2TPV2_ENABLE=n \ - ECM_INTERFACE_GRE_TAP_ENABLE=n \ - ECM_INTERFACE_GRE_TUN_ENABLE=n \ - ECM_INTERFACE_SIT_ENABLE=n \ - ECM_INTERFACE_TUNIPIP6_ENABLE=n \ - ECM_INTERFACE_RAWIP_ENABLE=n \ - ECM_INTERFACE_VLAN_ENABLE=n \ - ECM_CLASSIFIER_MARK_ENABLE=n \ - ECM_CLASSIFIER_DSCP_ENABLE=n \ - ECM_CLASSIFIER_PCC_ENABLE=n \ - ECM_BAND_STEERING_ENABLE=n \ - ECM_INTERFACE_PPPOE_ENABLE=y -endif - -ifeq ($(CONFIG_TARGET_BOARD), "ipq807x") - SOC="ipq807x_64" -else ifeq ($(CONFIG_TARGET_BOARD), "ipq60xx") - SOC="ipq60xx_64" -endif - -define Build/InstallDev - mkdir -p $(1)/usr/include/qca-nss-ecm - $(CP) $(PKG_BUILD_DIR)/exports/* $(1)/usr/include/qca-nss-ecm -endef - -define Build/Compile - +$(MAKE) -C "$(LINUX_DIR)" $(strip $(ECM_MAKE_OPTS)) \ - CROSS_COMPILE="$(TARGET_CROSS)" \ - ARCH="$(LINUX_KARCH)" \ - M="$(PKG_BUILD_DIR)" \ - EXTRA_CFLAGS="$(EXTRA_CFLAGS)" SoC=$(SOC) \ - $(KERNEL_MAKE_FLAGS) \ - $(PKG_JOBS) \ - modules -endef - -$(eval $(call KernelPackage,qca-nss-ecm-64)) diff --git a/root/package/qca/nss/qca-nss-ecm-64/files/ecm_dump.sh b/root/package/qca/nss/qca-nss-ecm-64/files/ecm_dump.sh deleted file mode 100644 index dbf7de75..00000000 --- a/root/package/qca/nss/qca-nss-ecm-64/files/ecm_dump.sh +++ /dev/null @@ -1,95 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -ECM_MODULE=${1:-ecm_state} -MOUNT_ROOT=/dev/ecm - -# -# usage: ecm_dump.sh [module=ecm_db] -# -# with no parameters, ecm_dump.sh will attempt to mount the -# ecm_db state file and cat its contents. -# -# example with a parameter: ecm_dump.sh ecm_classifier_default -# -# this will cause ecm_dump to attempt to find and mount the state -# file for the ecm_classifier_default module, and if successful -# cat the contents. -# - -# this is one of the state files, which happens to be the -# last module started in ecm -ECM_STATE=/sys/kernel/debug/ecm/ecm_state/state_dev_major - -# tests to see if ECM is up and ready to receive commands. -# returns 0 if ECM is fully up and ready, else 1 -ecm_is_ready() { - if [ ! -e "${ECM_STATE}" ] - then - return 1 - fi - return 0 -} - -# -# module_state_mount(module_name) -# Mounts the state file of the module, if supported -# -module_state_mount() { - local module_name=$1 - local mount_dir=$2 - local state_file="/sys/kernel/debug/ecm/${module_name}/state_dev_major" - - if [ -e "${mount_dir}/${module_name}" ] - then - # already mounted - return 0 - fi - - #echo "Mount state file for $module_name ..." - if [ ! -e "$state_file" ] - then - #echo "... $module_name does not support state" - return 1 - fi - - local major="`cat $state_file`" - #echo "... Mounting state $state_file with major: $major" - mknod "${mount_dir}/${module_name}" c $major 0 -} - -# -# main -# -ecm_is_ready || { - #echo "ECM is not running" - exit 1 -} - -# all state files are mounted under MOUNT_ROOT, so make sure it exists -mkdir -p ${MOUNT_ROOT} - -# -# attempt to mount state files for the requested module and cat it -# if the mount succeeded -# -module_state_mount ${ECM_MODULE} ${MOUNT_ROOT} && { - cat ${MOUNT_ROOT}/${ECM_MODULE} - exit 0 -} - -exit 2 diff --git a/root/package/qca/nss/qca-nss-ecm-64/files/on-demand-down b/root/package/qca/nss/qca-nss-ecm-64/files/on-demand-down deleted file mode 100644 index 02d708e0..00000000 --- a/root/package/qca/nss/qca-nss-ecm-64/files/on-demand-down +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -# Copyright (c) 2016 The Linux Foundation. All rights reserved. - -[ -e "/sys/kernel/debug/ecm/ecm_db/defunct_all" ] && { - echo 1 > /sys/kernel/debug/ecm/ecm_db/defunct_all -} diff --git a/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.defaults b/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.defaults deleted file mode 100644 index 308e265c..00000000 --- a/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.defaults +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -uci -q batch << EOF - delete firewall.qcanssecm - set firewall.qcanssecm=include - set firewall.qcanssecm.type=script - set firewall.qcanssecm.path=/etc/firewall.d/qca-nss-ecm - set firewall.qcanssecm.family=any - set firewall.qcanssecm.reload=1 - commit firewall -EOF - -exit 0 diff --git a/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.firewall b/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.firewall deleted file mode 100644 index 24c64def..00000000 --- a/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.firewall +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -iptables -A FORWARD -m physdev --physdev-is-bridged -j ACCEPT diff --git a/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.init b/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.init deleted file mode 100644 index 78cf16dc..00000000 --- a/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.init +++ /dev/null @@ -1,137 +0,0 @@ -#!/bin/sh /etc/rc.common -# -# Copyright (c) 2014, 2019-2020 The Linux Foundation. All rights reserved. -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -# The shebang above has an extra space intentially to avoid having -# openwrt build scripts automatically enable this package starting -# at boot. - -START=19 - -get_front_end_mode() { - config_load "ecm" - config_get front_end global acceleration_engine "auto" - - case $front_end in - auto) - echo '0' - ;; - nss) - echo '1' - ;; - sfe) - echo '2' - ;; - *) - echo 'uci_option_acceleration_engine is invalid' - esac -} - -support_bridge() { - #NSS support bridge acceleration - [ -d /sys/kernel/debug/ecm/ecm_nss_ipv4 ] && return 0 - #SFE doesn't support bridge acceleration - [ -d /sys/kernel/debug/ecm/ecm_sfe_ipv4 ] && return 1 -} - -load_sfe() { - local kernel_version=$(uname -r) - - [ -e "/lib/modules/$kernel_version/shortcut-fe.ko" ] && { - [ -d /sys/module/shortcut_fe ] || insmod shortcut-fe - } - - [ -e "/lib/modules/$kernel_version/shortcut-fe-ipv6.ko" ] && { - [ -d /sys/module/shortcut_fe_ipv6 ] || insmod shortcut-fe-ipv6 - } - - [ -e "/lib/modules/$kernel_version/shortcut-fe-cm.ko" ] && { - [ -d /sys/module/shortcut_fe_cm ] || insmod shortcut-fe-cm - } - - [ -e "/lib/modules/$kernel_version/shortcut-fe-drv.ko" ] && { - [ -d /sys/module/shortcut_fe_drv ] || insmod shortcut-fe-drv - } -} - -load_ecm() { - [ -d /sys/module/ecm ] || { - [ ! -e /proc/device-tree/MP_256 ] && load_sfe - insmod ecm front_end_selection=$(get_front_end_mode) - } - - support_bridge && { - sysctl -w net.bridge.bridge-nf-call-ip6tables=1 - sysctl -w net.bridge.bridge-nf-call-iptables=1 - } -} - -unload_ecm() { - sysctl -w net.bridge.bridge-nf-call-ip6tables=0 - sysctl -w net.bridge.bridge-nf-call-iptables=0 - - if [ -d /sys/module/ecm ]; then - # - # Stop ECM frontends - # - echo 1 > /sys/kernel/debug/ecm/front_end_ipv4_stop - echo 1 > /sys/kernel/debug/ecm/front_end_ipv6_stop - - # - # Defunct the connections - # - echo 1 > /sys/kernel/debug/ecm/ecm_db/defunct_all - sleep 5; - - rmmod ecm - sleep 1 - fi -} - -start() { - load_ecm - - # If the acceleration engine is NSS, enable wifi redirect. - [ -d /sys/kernel/debug/ecm/ecm_nss_ipv4 ] && sysctl -w dev.nss.general.redirect=1 - - support_bridge && { - echo 'net.bridge.bridge-nf-call-ip6tables=1' >> /etc/sysctl.d/qca-nss-ecm.conf - echo 'net.bridge.bridge-nf-call-iptables=1' >> /etc/sysctl.d/qca-nss-ecm.conf - } - - if [ -d /sys/module/qca_ovsmgr ]; then - insmod ecm_ovs - fi - -} - -stop() { - # If ECM is already not loaded, just return. - if [ ! -d /sys/module/ecm ]; then - return - fi - - # If the acceleration engine is NSS, disable wifi redirect. - [ -d /sys/kernel/debug/ecm/ecm_nss_ipv4 ] && sysctl -w dev.nss.general.redirect=0 - - sed '/net.bridge.bridge-nf-call-ip6tables=1/d' -i /etc/sysctl.d/qca-nss-ecm.conf - sed '/net.bridge.bridge-nf-call-iptables=1/d' -i /etc/sysctl.d/qca-nss-ecm.conf - - if [ -d /sys/module/ecm_ovs ]; then - rmmod ecm_ovs - fi - - unload_ecm -} diff --git a/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.sysctl b/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.sysctl deleted file mode 100644 index 1a3d76b1..00000000 --- a/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.sysctl +++ /dev/null @@ -1,2 +0,0 @@ -# nf_conntrack_tcp_no_window_check is 0 by default, set it to 1 -net.netfilter.nf_conntrack_tcp_no_window_check=1 diff --git a/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.uci b/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.uci deleted file mode 100644 index 4f2de687..00000000 --- a/root/package/qca/nss/qca-nss-ecm-64/files/qca-nss-ecm.uci +++ /dev/null @@ -1,2 +0,0 @@ -config ecm 'global' - option acceleration_engine 'auto' diff --git a/root/package/qca/nss/qca-nss-ecm-64/patches/001-treewide-componentize-the-module-even-more.patch b/root/package/qca/nss/qca-nss-ecm-64/patches/001-treewide-componentize-the-module-even-more.patch deleted file mode 100644 index 4e7932c9..00000000 --- a/root/package/qca/nss/qca-nss-ecm-64/patches/001-treewide-componentize-the-module-even-more.patch +++ /dev/null @@ -1,335 +0,0 @@ -From 73345c87b28a473b35b57e673f8de963c3d73da1 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Wed, 19 May 2021 02:38:53 +0200 -Subject: [PATCH] treewide: componentize the module even more - -Signed-off-by: Ansuel Smith ---- - Makefile | 56 +++++++++++++++++++++++++------- - ecm_db/ecm_db_connection.c | 8 +++++ - ecm_db/ecm_db_node.c | 4 +++ - ecm_interface.c | 8 +++++ - frontends/ecm_front_end_common.c | 7 ++++ - 5 files changed, 72 insertions(+), 11 deletions(-) - ---- a/Makefile -+++ b/Makefile -@@ -82,10 +82,18 @@ ccflags-$(ECM_INTERFACE_BOND_ENABLE) += - # Define ECM_INTERFACE_PPPOE_ENABLE=y in order - # to enable support for PPPoE acceleration. - # ############################################################################# --ECM_INTERFACE_PPPOE_ENABLE=y -+ifndef $(ECM_INTERFACE_PPPOE_ENABLE) -+ ECM_INTERFACE_PPPOE_ENABLE=y -+endif - ccflags-$(ECM_INTERFACE_PPPOE_ENABLE) += -DECM_INTERFACE_PPPOE_ENABLE - - # ############################################################################# -+# Define ECM_INTERFACE_L2TPV2_PPTP_ENABLE=y in order -+# to enable support for l2tpv2 or PPTP detection. -+# ############################################################################# -+ccflags-$(ECM_INTERFACE_L2TPV2_PPTP_ENABLE) += -DECM_INTERFACE_L2TPV2_PPTP_ENABLE -+ -+# ############################################################################# - # Define ECM_INTERFACE_L2TPV2_ENABLE=y in order - # to enable support for l2tpv2 acceleration. - # ############################################################################# -@@ -118,6 +126,12 @@ ccflags-$(ECM_INTERFACE_PPP_ENABLE) += - - ccflags-$(ECM_INTERFACE_MAP_T_ENABLE) += -DECM_INTERFACE_MAP_T_ENABLE - - # ############################################################################# -+# Define ECM_INTERFACE_GRE_ENABLE=y in order -+# to enable support for GRE detection. -+# ############################################################################# -+ccflags-$(ECM_INTERFACE_GRE_ENABLE) += -DECM_INTERFACE_GRE_ENABLE -+ -+# ############################################################################# - # Define ECM_INTERFACE_GRE_TAP_ENABLE=y in order - # to enable support for GRE TAP interface. - # ############################################################################# -@@ -186,7 +200,9 @@ ccflags-$(ECM_INTERFACE_OVS_BRIDGE_ENABL - # ############################################################################# - # Define ECM_INTERFACE_VLAN_ENABLE=y in order to enable support for VLAN - # ############################################################################# --ECM_INTERFACE_VLAN_ENABLE=y -+ifndef $(ECM_INTERFACE_VLAN_ENABLE) -+ ECM_INTERFACE_VLAN_ENABLE=y -+endif - ccflags-$(ECM_INTERFACE_VLAN_ENABLE) += -DECM_INTERFACE_VLAN_ENABLE - - # ############################################################################# -@@ -228,7 +244,9 @@ ccflags-$(ECM_CLASSIFIER_OVS_ENABLE) += - # ############################################################################# - # Define ECM_CLASSIFIER_MARK_ENABLE=y in order to enable mark classifier. - # ############################################################################# --ECM_CLASSIFIER_MARK_ENABLE=y -+ifndef $(ECM_CLASSIFIER_MARK_ENABLE) -+ ECM_CLASSIFIER_MARK_ENABLE=y -+endif - ecm-$(ECM_CLASSIFIER_MARK_ENABLE) += ecm_classifier_mark.o - ccflags-$(ECM_CLASSIFIER_MARK_ENABLE) += -DECM_CLASSIFIER_MARK_ENABLE - -@@ -247,7 +265,9 @@ ccflags-$(ECM_CLASSIFIER_NL_ENABLE) += - - # ############################################################################# - # Define ECM_CLASSIFIER_DSCP_ENABLE=y in order to enable DSCP classifier. - # ############################################################################# --ECM_CLASSIFIER_DSCP_ENABLE=y -+ifndef $(ECM_CLASSIFIER_DSCP_ENABLE) -+ ECM_CLASSIFIER_DSCP_ENABLE=y -+endif - ecm-$(ECM_CLASSIFIER_DSCP_ENABLE) += ecm_classifier_dscp.o - ccflags-$(ECM_CLASSIFIER_DSCP_ENABLE) += -DECM_CLASSIFIER_DSCP_ENABLE - ccflags-$(ECM_CLASSIFIER_DSCP_IGS) += -DECM_CLASSIFIER_DSCP_IGS -@@ -274,7 +294,9 @@ endif - # the Parental Controls subsystem classifier in ECM. Currently disabled until - # customers require it / if they need to integrate their Parental Controls with it. - # ############################################################################# --ECM_CLASSIFIER_PCC_ENABLE=y -+ifndef $(ECM_CLASSIFIER_PCC_ENABLE) -+ ECM_CLASSIFIER_PCC_ENABLE=y -+endif - ecm-$(ECM_CLASSIFIER_PCC_ENABLE) += ecm_classifier_pcc.o - ccflags-$(ECM_CLASSIFIER_PCC_ENABLE) += -DECM_CLASSIFIER_PCC_ENABLE - -@@ -301,28 +323,36 @@ ccflags-$(ECM_NON_PORTED_SUPPORT_ENABLE) - # ############################################################################# - # Define ECM_STATE_OUTPUT_ENABLE=y to support XML state output - # ############################################################################# --ECM_STATE_OUTPUT_ENABLE=y -+ifndef $(ECM_STATE_OUTPUT_ENABLE) -+ ECM_STATE_OUTPUT_ENABLE=y -+endif - ecm-$(ECM_STATE_OUTPUT_ENABLE) += ecm_state.o - ccflags-$(ECM_STATE_OUTPUT_ENABLE) += -DECM_STATE_OUTPUT_ENABLE - - # ############################################################################# - # Define ECM_DB_ADVANCED_STATS_ENABLE to support XML state output - # ############################################################################# --ECM_DB_ADVANCED_STATS_ENABLE=y -+ifndef $(ECM_DB_ADVANCED_STATS_ENABLE) -+ ECM_DB_ADVANCED_STATS_ENABLE=y -+endif - ccflags-$(ECM_DB_ADVANCED_STATS_ENABLE) += -DECM_DB_ADVANCED_STATS_ENABLE - - # ############################################################################# - # Define ECM_DB_CONNECTION_CROSS_REFERENCING_ENABLE=y in order to enable - # the database to track relationships between objects. - # ############################################################################# --ECM_DB_CONNECTION_CROSS_REFERENCING_ENABLE=y -+ifndef $(ECM_DB_CONNECTION_CROSS_REFERENCING_ENABLE) -+ ECM_DB_CONNECTION_CROSS_REFERENCING_ENABLE=y -+endif - ccflags-$(ECM_DB_CONNECTION_CROSS_REFERENCING_ENABLE) += -DECM_DB_XREF_ENABLE - - # ############################################################################# - # Define ECM_TRACKER_DPI_SUPPORT_ENABLE=y in order to enable support for - # deep packet inspection and tracking of data with the trackers. - # ############################################################################# --ECM_TRACKER_DPI_SUPPORT_ENABLE=y -+ifndef $(ECM_TRACKER_DPI_SUPPORT_ENABLE) -+ ECM_TRACKER_DPI_SUPPORT_ENABLE=y -+endif - ccflags-$(ECM_TRACKER_DPI_SUPPORT_ENABLE) += -DECM_TRACKER_DPI_SUPPORT_ENABLE - - # ############################################################################# -@@ -330,14 +360,18 @@ ccflags-$(ECM_TRACKER_DPI_SUPPORT_ENABLE - # support for the database keeping lists of connections that are assigned - # on a per TYPE of classifier basis. - # ############################################################################# --ECM_DB_CLASSIFIER_TYPE_ASSIGNMENTS_TRACK_ENABLE=y -+ifndef $(ECM_DB_CLASSIFIER_TYPE_ASSIGNMENTS_TRACK_ENABLE) -+ ECM_DB_CLASSIFIER_TYPE_ASSIGNMENTS_TRACK_ENABLE=y -+endif - ccflags-$(ECM_DB_CLASSIFIER_TYPE_ASSIGNMENTS_TRACK_ENABLE) += -DECM_DB_CTA_TRACK_ENABLE - - # ############################################################################# - # Define ECM_BAND_STEERING_ENABLE=y in order to enable - # band steering feature. - # ############################################################################# --ECM_BAND_STEERING_ENABLE=y -+ifndef $(ECM_BAND_STEERING_ENABLE) -+ ECM_BAND_STEERING_ENABLE=y -+endif - ccflags-$(ECM_BAND_STEERING_ENABLE) += -DECM_BAND_STEERING_ENABLE - - # ############################################################################# ---- a/ecm_db/ecm_db_connection.c -+++ b/ecm_db/ecm_db_connection.c -@@ -430,7 +430,9 @@ EXPORT_SYMBOL(ecm_db_connection_make_def - */ - void ecm_db_connection_data_totals_update(struct ecm_db_connection_instance *ci, bool is_from, uint64_t size, uint64_t packets) - { -+#ifdef ECM_DB_ADVANCED_STATS_ENABLE - int32_t i; -+#endif - - DEBUG_CHECK_MAGIC(ci, ECM_DB_CONNECTION_INSTANCE_MAGIC, "%px: magic failed\n", ci); - -@@ -529,7 +531,9 @@ EXPORT_SYMBOL(ecm_db_connection_data_tot - */ - void ecm_db_connection_data_totals_update_dropped(struct ecm_db_connection_instance *ci, bool is_from, uint64_t size, uint64_t packets) - { -+#ifdef ECM_DB_ADVANCED_STATS_ENABLE - int32_t i; -+#endif - - DEBUG_CHECK_MAGIC(ci, ECM_DB_CONNECTION_INSTANCE_MAGIC, "%px: magic failed\n", ci); - -@@ -1508,6 +1512,7 @@ void ecm_db_connection_defunct_all(void) - } - EXPORT_SYMBOL(ecm_db_connection_defunct_all); - -+#ifdef ECM_INTERFACE_OVS_BRIDGE_ENABLE - /* - * ecm_db_connection_defunct_by_classifier() - * Make defunct based on masked fields -@@ -1667,6 +1672,7 @@ next_ci: - ECM_IP_ADDR_TO_OCTAL(dest_addr_mask), dest_port_mask, proto_mask, cnt); - } - } -+#endif - - /* - * ecm_db_connection_defunct_by_port() -@@ -1956,6 +1962,7 @@ struct ecm_db_node_instance *ecm_db_conn - } - EXPORT_SYMBOL(ecm_db_connection_node_get_and_ref); - -+#ifdef ECM_DB_XREF_ENABLE - /* - * ecm_db_connection_mapping_get_and_ref_next() - * Return reference to next connection in the mapping chain in the specified direction. -@@ -1997,6 +2004,7 @@ struct ecm_db_connection_instance *ecm_d - return nci; - } - EXPORT_SYMBOL(ecm_db_connection_iface_get_and_ref_next); -+#endif - - /* - * ecm_db_connection_mapping_get_and_ref() ---- a/ecm_db/ecm_db_node.c -+++ b/ecm_db/ecm_db_node.c -@@ -224,9 +224,11 @@ EXPORT_SYMBOL(ecm_db_node_get_and_ref_ne - */ - int ecm_db_node_deref(struct ecm_db_node_instance *ni) - { -+#ifdef ECM_DB_XREF_ENABLE - #if (DEBUG_LEVEL >= 1) - int dir; - #endif -+#endif - DEBUG_CHECK_MAGIC(ni, ECM_DB_NODE_INSTANCE_MAGIC, "%px: magic failed\n", ni); - - spin_lock_bh(&ecm_db_lock); -@@ -486,9 +488,11 @@ EXPORT_SYMBOL(ecm_db_node_iface_get_and_ - void ecm_db_node_add(struct ecm_db_node_instance *ni, struct ecm_db_iface_instance *ii, uint8_t *address, - ecm_db_node_final_callback_t final, void *arg) - { -+#ifdef ECM_DB_XREF_ENABLE - #if (DEBUG_LEVEL >= 1) - int dir; - #endif -+#endif - ecm_db_node_hash_t hash_index; - struct ecm_db_listener_instance *li; - ---- a/ecm_interface.c -+++ b/ecm_interface.c -@@ -1343,6 +1343,7 @@ struct neighbour *ecm_interface_ipv6_nei - */ - bool ecm_interface_is_pptp(struct sk_buff *skb, const struct net_device *out) - { -+#ifdef ECM_INTERFACE_PPTP_ENABLE - struct net_device *in; - - /* -@@ -1367,6 +1368,7 @@ bool ecm_interface_is_pptp(struct sk_buf - } - - dev_put(in); -+#endif - return false; - } - -@@ -1379,6 +1381,7 @@ bool ecm_interface_is_pptp(struct sk_buf - */ - bool ecm_interface_is_l2tp_packet_by_version(struct sk_buff *skb, const struct net_device *out, int ver) - { -+#ifdef ECM_INTERFACE_L2TPV2_PPTP_ENABLE - uint32_t flag = 0; - struct net_device *in; - -@@ -1411,6 +1414,7 @@ bool ecm_interface_is_l2tp_packet_by_ver - } - - dev_put(in); -+#endif - return false; - } - -@@ -1423,6 +1427,7 @@ bool ecm_interface_is_l2tp_packet_by_ver - */ - bool ecm_interface_is_l2tp_pptp(struct sk_buff *skb, const struct net_device *out) - { -+#ifdef ECM_INTERFACE_L2TPV2_PPTP_ENABLE - struct net_device *in; - - /* -@@ -1445,6 +1450,7 @@ bool ecm_interface_is_l2tp_pptp(struct s - } - - dev_put(in); -+#endif - return false; - } - -@@ -6630,6 +6636,7 @@ static void ecm_interface_regenerate_con - return; - } - -+#ifdef ECM_DB_XREF_ENABLE - for (dir = 0; dir < ECM_DB_OBJ_DIR_MAX; dir++) { - /* - * Re-generate all connections associated with this interface -@@ -6645,6 +6652,7 @@ static void ecm_interface_regenerate_con - ci[dir] = cin; - } - } -+#endif - - #ifdef ECM_MULTICAST_ENABLE - /* ---- a/frontends/ecm_front_end_common.c -+++ b/frontends/ecm_front_end_common.c -@@ -106,6 +106,7 @@ bool ecm_front_end_gre_proto_is_accel_al - struct nf_conntrack_tuple *tuple, - int ip_version) - { -+#ifdef ECM_INTERFACE_GRE_ENABLE - struct net_device *dev; - struct gre_base_hdr *greh; - -@@ -117,10 +118,12 @@ bool ecm_front_end_gre_proto_is_accel_al - /* - * Case 1: PPTP locally terminated - */ -+#ifdef ECM_INTERFACE_PPTP_ENABLE - if (ecm_interface_is_pptp(skb, outdev)) { - DEBUG_TRACE("%px: PPTP GRE locally terminated - allow acceleration\n", skb); - return true; - } -+#endif - - /* - * Case 2: PPTP pass through -@@ -223,6 +226,10 @@ bool ecm_front_end_gre_proto_is_accel_al - */ - DEBUG_TRACE("%px: GRE IPv%d pass through - allow acceleration\n", skb, ip_version); - return true; -+#else -+ DEBUG_TRACE("%px: GRE%d feature is disabled - do not allow acceleration\n", skb, ip_version); -+ return false; -+#endif - } - - #ifdef ECM_CLASSIFIER_DSCP_ENABLE diff --git a/root/package/qca/nss/qca-nss-ecm-64/patches/002-kernel-5.10-support.patch b/root/package/qca/nss/qca-nss-ecm-64/patches/002-kernel-5.10-support.patch deleted file mode 100644 index 107b9571..00000000 --- a/root/package/qca/nss/qca-nss-ecm-64/patches/002-kernel-5.10-support.patch +++ /dev/null @@ -1,831 +0,0 @@ -From e8b642c23af9146c973e828a7f4e0fb56cfc8d0b Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Sat, 15 May 2021 03:51:14 +0200 -Subject: [PATCH] add support for kernel 5.10 - -Signed-off-by: Ansuel Smith ---- - ecm_classifier_default.c | 24 +++--------- - ecm_classifier_dscp.c | 8 +--- - ecm_classifier_emesh.c | 16 ++------ - ecm_classifier_hyfi.c | 7 +--- - ecm_classifier_mark.c | 8 +--- - ecm_classifier_ovs.c | 8 +--- - ecm_classifier_pcc.c | 8 +--- - ecm_conntrack_notifier.c | 8 +--- - ecm_db/ecm_db_connection.c | 7 +--- - ecm_db/ecm_db_host.c | 7 +--- - ecm_db/ecm_db_iface.c | 7 +--- - ecm_db/ecm_db_mapping.c | 7 +--- - ecm_db/ecm_db_node.c | 7 +--- - ecm_interface.c | 4 +- - ecm_state.c | 14 ++----- - frontends/ecm_front_end_common.c | 4 +- - frontends/ecm_front_end_ipv4.c | 7 +--- - frontends/ecm_front_end_ipv6.c | 7 +--- - frontends/nss/ecm_nss_bond_notifier.c | 8 +--- - frontends/nss/ecm_nss_ipv4.c | 49 +++++++------------------ - frontends/nss/ecm_nss_ipv6.c | 49 +++++++------------------ - frontends/nss/ecm_nss_multicast_ipv4.c | 7 +--- - frontends/nss/ecm_nss_multicast_ipv6.c | 7 +--- - frontends/nss/ecm_nss_non_ported_ipv4.c | 7 +--- - frontends/nss/ecm_nss_non_ported_ipv6.c | 7 +--- - frontends/nss/ecm_nss_ported_ipv4.c | 8 +--- - frontends/nss/ecm_nss_ported_ipv6.c | 8 +--- - frontends/sfe/ecm_sfe_ipv4.c | 49 +++++++------------------ - frontends/sfe/ecm_sfe_ipv6.c | 49 +++++++------------------ - frontends/sfe/ecm_sfe_non_ported_ipv4.c | 7 +--- - frontends/sfe/ecm_sfe_non_ported_ipv6.c | 7 +--- - frontends/sfe/ecm_sfe_ported_ipv4.c | 8 +--- - frontends/sfe/ecm_sfe_ported_ipv6.c | 8 +--- - 33 files changed, 122 insertions(+), 314 deletions(-) - ---- a/ecm_classifier_default.c -+++ b/ecm_classifier_default.c -@@ -776,26 +776,14 @@ int ecm_classifier_default_init(struct d - return -1; - } - -- if (!debugfs_create_u32("enabled", S_IRUGO | S_IWUSR, ecm_classifier_default_dentry, -- (u32 *)&ecm_classifier_default_enabled)) { -- DEBUG_ERROR("Failed to create ecm deafult classifier enabled file in debugfs\n"); -- debugfs_remove_recursive(ecm_classifier_default_dentry); -- return -1; -- } -+ debugfs_create_u32("enabled", S_IRUGO | S_IWUSR, ecm_classifier_default_dentry, -+ (u32 *)&ecm_classifier_default_enabled); - -- if (!debugfs_create_u32("accel_mode", S_IRUGO | S_IWUSR, ecm_classifier_default_dentry, -- (u32 *)&ecm_classifier_default_accel_mode)) { -- DEBUG_ERROR("Failed to create ecm deafult classifier accel_mode file in debugfs\n"); -- debugfs_remove_recursive(ecm_classifier_default_dentry); -- return -1; -- } -+ debugfs_create_u32("accel_mode", S_IRUGO | S_IWUSR, ecm_classifier_default_dentry, -+ (u32 *)&ecm_classifier_default_accel_mode); - -- if (!debugfs_create_u32("accel_delay_pkts", S_IRUGO | S_IWUSR, ecm_classifier_default_dentry, -- (u32 *)&ecm_classifier_accel_delay_pkts)) { -- DEBUG_ERROR("Failed to create accel delay packet counts in debugfs\n"); -- debugfs_remove_recursive(ecm_classifier_default_dentry); -- return -1; -- } -+ debugfs_create_u32("accel_delay_pkts", S_IRUGO | S_IWUSR, ecm_classifier_default_dentry, -+ (u32 *)&ecm_classifier_accel_delay_pkts); - - return 0; - } ---- a/ecm_classifier_dscp.c -+++ b/ecm_classifier_dscp.c -@@ -747,12 +747,8 @@ int ecm_classifier_dscp_init(struct dent - return -1; - } - -- if (!debugfs_create_u32("enabled", S_IRUGO | S_IWUSR, ecm_classifier_dscp_dentry, -- (u32 *)&ecm_classifier_dscp_enabled)) { -- DEBUG_ERROR("Failed to create dscp enabled file in debugfs\n"); -- debugfs_remove_recursive(ecm_classifier_dscp_dentry); -- return -1; -- } -+ debugfs_create_u32("enabled", S_IRUGO | S_IWUSR, ecm_classifier_dscp_dentry, -+ (u32 *)&ecm_classifier_dscp_enabled); - - return 0; - } ---- a/ecm_classifier_emesh.c -+++ b/ecm_classifier_emesh.c -@@ -977,19 +977,11 @@ int ecm_classifier_emesh_init(struct den - return -1; - } - -- if (!debugfs_create_u32("enabled", S_IRUGO | S_IWUSR, ecm_classifier_emesh_dentry, -- (u32 *)&ecm_classifier_emesh_enabled)) { -- DEBUG_ERROR("Failed to create ecm emesh classifier enabled file in debugfs\n"); -- debugfs_remove_recursive(ecm_classifier_emesh_dentry); -- return -1; -- } -+ debugfs_create_u32("enabled", S_IRUGO | S_IWUSR, ecm_classifier_emesh_dentry, -+ (u32 *)&ecm_classifier_emesh_enabled); - -- if (!debugfs_create_u32("latency_config_enabled", S_IRUGO | S_IWUSR, ecm_classifier_emesh_dentry, -- (u32 *)&ecm_classifier_emesh_latency_config_enabled)) { -- DEBUG_ERROR("Failed to create ecm emesh classifier latency config enabled file in debugfs\n"); -- debugfs_remove_recursive(ecm_classifier_emesh_dentry); -- return -1; -- } -+ debugfs_create_u32("latency_config_enabled", S_IRUGO | S_IWUSR, ecm_classifier_emesh_dentry, -+ (u32 *)&ecm_classifier_emesh_latency_config_enabled); - - /* - * Register for service prioritization notification update. ---- a/ecm_classifier_hyfi.c -+++ b/ecm_classifier_hyfi.c -@@ -1099,11 +1099,8 @@ int ecm_classifier_hyfi_rules_init(struc - goto classifier_task_cleanup; - } - -- if (!debugfs_create_u32("enabled", S_IRUGO | S_IWUSR, ecm_classifier_hyfi_dentry, -- (u32 *)&ecm_classifier_hyfi_enabled)) { -- DEBUG_ERROR("Failed to create ecm hyfi classifier enabled file in debugfs\n"); -- goto classifier_task_cleanup; -- } -+ debugfs_create_u32("enabled", S_IRUGO | S_IWUSR, ecm_classifier_hyfi_dentry, -+ (u32 *)&ecm_classifier_hyfi_enabled); - - if (!debugfs_create_file("cmd", S_IWUSR, ecm_classifier_hyfi_dentry, - NULL, &ecm_classifier_hyfi_cmd_fops)) { ---- a/ecm_classifier_mark.c -+++ b/ecm_classifier_mark.c -@@ -753,12 +753,8 @@ int ecm_classifier_mark_init(struct dent - return -1; - } - -- if (!debugfs_create_u32("enabled", S_IRUGO | S_IWUSR, ecm_classifier_mark_dentry, -- (u32 *)&ecm_classifier_mark_enabled)) { -- DEBUG_ERROR("Failed to create mark enabled file in debugfs\n"); -- debugfs_remove_recursive(ecm_classifier_mark_dentry); -- return -1; -- } -+ debugfs_create_u32("enabled", S_IRUGO | S_IWUSR, ecm_classifier_mark_dentry, -+ (u32 *)&ecm_classifier_mark_enabled); - - return 0; - } ---- a/ecm_classifier_ovs.c -+++ b/ecm_classifier_ovs.c -@@ -2200,12 +2200,8 @@ int ecm_classifier_ovs_init(struct dentr - return -1; - } - -- if (!debugfs_create_u32("enabled", S_IRUGO | S_IWUSR, ecm_classifier_ovs_dentry, -- (u32 *)&ecm_classifier_ovs_enabled)) { -- DEBUG_ERROR("Failed to create ovs enabled file in debugfs\n"); -- debugfs_remove_recursive(ecm_classifier_ovs_dentry); -- return -1; -- } -+ debugfs_create_u32("enabled", S_IRUGO | S_IWUSR, ecm_classifier_ovs_dentry, -+ (u32 *)&ecm_classifier_ovs_enabled); - - return 0; - } ---- a/ecm_classifier_pcc.c -+++ b/ecm_classifier_pcc.c -@@ -1308,12 +1308,8 @@ int ecm_classifier_pcc_init(struct dentr - return -1; - } - -- if (!debugfs_create_u32("enabled", S_IRUGO, ecm_classifier_pcc_dentry, -- (u32 *)&ecm_classifier_pcc_enabled)) { -- DEBUG_ERROR("Failed to create pcc enabled file in debugfs\n"); -- debugfs_remove_recursive(ecm_classifier_pcc_dentry); -- return -1; -- } -+ debugfs_create_u32("enabled", S_IRUGO, ecm_classifier_pcc_dentry, -+ (u32 *)&ecm_classifier_pcc_enabled); - - return 0; - } ---- a/ecm_conntrack_notifier.c -+++ b/ecm_conntrack_notifier.c -@@ -414,12 +414,8 @@ int ecm_conntrack_notifier_init(struct d - return -1; - } - -- if (!debugfs_create_u32("stop", S_IRUGO | S_IWUSR, ecm_conntrack_notifier_dentry, -- (u32 *)&ecm_conntrack_notifier_stopped)) { -- DEBUG_ERROR("Failed to create ecm conntrack notifier stopped file in debugfs\n"); -- debugfs_remove_recursive(ecm_conntrack_notifier_dentry); -- return -1; -- } -+ debugfs_create_u32("stop", S_IRUGO | S_IWUSR, ecm_conntrack_notifier_dentry, -+ (u32 *)&ecm_conntrack_notifier_stopped); - - #ifdef CONFIG_NF_CONNTRACK_EVENTS - /* ---- a/ecm_db/ecm_db_connection.c -+++ b/ecm_db/ecm_db_connection.c -@@ -3642,11 +3642,8 @@ static struct file_operations ecm_db_con - */ - bool ecm_db_connection_init(struct dentry *dentry) - { -- if (!debugfs_create_u32("connection_count", S_IRUGO, dentry, -- (u32 *)&ecm_db_connection_count)) { -- DEBUG_ERROR("Failed to create ecm db connection count file in debugfs\n"); -- return false; -- } -+ debugfs_create_u32("connection_count", S_IRUGO, dentry, -+ (u32 *)&ecm_db_connection_count); - - if (!debugfs_create_file("connection_count_simple", S_IRUGO, dentry, - NULL, &ecm_db_connection_count_simple_fops)) { ---- a/ecm_db/ecm_db_host.c -+++ b/ecm_db/ecm_db_host.c -@@ -770,11 +770,8 @@ EXPORT_SYMBOL(ecm_db_host_alloc); - bool ecm_db_host_init(struct dentry *dentry) - { - -- if (!debugfs_create_u32("host_count", S_IRUGO, dentry, -- (u32 *)&ecm_db_host_count)) { -- DEBUG_ERROR("Failed to create ecm db host count file in debugfs\n"); -- return false;; -- } -+ debugfs_create_u32("host_count", S_IRUGO, dentry, -+ (u32 *)&ecm_db_host_count); - - ecm_db_host_table = vzalloc(sizeof(struct ecm_db_host_instance *) * ECM_DB_HOST_HASH_SLOTS); - if (!ecm_db_host_table) { ---- a/ecm_db/ecm_db_iface.c -+++ b/ecm_db/ecm_db_iface.c -@@ -3670,11 +3670,8 @@ EXPORT_SYMBOL(ecm_db_iface_alloc); - */ - bool ecm_db_iface_init(struct dentry *dentry) - { -- if (!debugfs_create_u32("iface_count", S_IRUGO, dentry, -- (u32 *)&ecm_db_iface_count)) { -- DEBUG_ERROR("Failed to create ecm db iface count file in debugfs\n"); -- return false; -- } -+ debugfs_create_u32("iface_count", S_IRUGO, dentry, -+ (u32 *)&ecm_db_iface_count); - - return true; - } ---- a/ecm_db/ecm_db_mapping.c -+++ b/ecm_db/ecm_db_mapping.c -@@ -806,11 +806,8 @@ EXPORT_SYMBOL(ecm_db_mapping_alloc); - */ - bool ecm_db_mapping_init(struct dentry *dentry) - { -- if (!debugfs_create_u32("mapping_count", S_IRUGO, dentry, -- (u32 *)&ecm_db_mapping_count)) { -- DEBUG_ERROR("Failed to create ecm db mapping count file in debugfs\n"); -- return false; -- } -+ debugfs_create_u32("mapping_count", S_IRUGO, dentry, -+ (u32 *)&ecm_db_mapping_count); - - ecm_db_mapping_table = vzalloc(sizeof(struct ecm_db_mapping_instance *) * ECM_DB_MAPPING_HASH_SLOTS); - if (!ecm_db_mapping_table) { ---- a/ecm_db/ecm_db_node.c -+++ b/ecm_db/ecm_db_node.c -@@ -1187,11 +1187,8 @@ keep_sni_conn: - */ - bool ecm_db_node_init(struct dentry *dentry) - { -- if (!debugfs_create_u32("node_count", S_IRUGO, dentry, -- (u32 *)&ecm_db_node_count)) { -- DEBUG_ERROR("Failed to create ecm db node count file in debugfs\n"); -- return false; -- } -+ debugfs_create_u32("node_count", S_IRUGO, dentry, -+ (u32 *)&ecm_db_node_count); - - ecm_db_node_table = vzalloc(sizeof(struct ecm_db_node_instance *) * ECM_DB_NODE_HASH_SLOTS); - if (!ecm_db_node_table) { ---- a/ecm_interface.c -+++ b/ecm_interface.c -@@ -332,7 +332,7 @@ static struct net_device *ecm_interface_ - struct net_device *dev; - - ECM_IP_ADDR_TO_NIN6_ADDR(addr6, addr); -- dev = (struct net_device *)ipv6_dev_find(&init_net, &addr6, 1); -+ dev = (struct net_device *)ipv6_dev_find_and_hold(&init_net, &addr6, 1); - return dev; - } - #endif -@@ -734,7 +734,7 @@ static bool ecm_interface_mac_addr_get_i - * Get the MAC address that corresponds to IP address given. - */ - ECM_IP_ADDR_TO_NIN6_ADDR(daddr, addr); -- local_dev = ipv6_dev_find(&init_net, &daddr, 1); -+ local_dev = ipv6_dev_find_and_hold(&init_net, &daddr, 1); - if (local_dev) { - DEBUG_TRACE("%pi6 is a local address\n", &daddr); - memcpy(mac_addr, dev->dev_addr, ETH_ALEN); ---- a/ecm_state.c -+++ b/ecm_state.c -@@ -899,17 +899,11 @@ int ecm_state_init(struct dentry *dentry - return -1; - } - -- if (!debugfs_create_u32("state_dev_major", S_IRUGO, ecm_state_dentry, -- (u32 *)&ecm_state_dev_major_id)) { -- DEBUG_ERROR("Failed to create ecm state dev major file in debugfs\n"); -- goto init_cleanup; -- } -+ debugfs_create_u32("state_dev_major", S_IRUGO, ecm_state_dentry, -+ (u32 *)&ecm_state_dev_major_id); - -- if (!debugfs_create_u32("state_file_output_mask", S_IRUGO | S_IWUSR, ecm_state_dentry, -- (u32 *)&ecm_state_file_output_mask)) { -- DEBUG_ERROR("Failed to create ecm state output mask file in debugfs\n"); -- goto init_cleanup; -- } -+ debugfs_create_u32("state_file_output_mask", S_IRUGO | S_IWUSR, ecm_state_dentry, -+ (u32 *)&ecm_state_file_output_mask); - - /* - * Register a char device that we will use to provide a dump of our state ---- a/frontends/ecm_front_end_common.c -+++ b/frontends/ecm_front_end_common.c -@@ -192,7 +192,7 @@ bool ecm_front_end_gre_proto_is_accel_al - return false; - } - } else { -- dev = ipv6_dev_find(&init_net, &(tuple->src.u3.in6), 1); -+ dev = ipv6_dev_find_and_hold(&init_net, &(tuple->src.u3.in6), 1); - if (dev) { - /* - * Source IP address is local -@@ -202,7 +202,7 @@ bool ecm_front_end_gre_proto_is_accel_al - return false; - } - -- dev = ipv6_dev_find(&init_net, &(tuple->dst.u3.in6), 1); -+ dev = ipv6_dev_find_and_hold(&init_net, &(tuple->dst.u3.in6), 1); - if (dev) { - /* - * Destination IP address is local ---- a/frontends/ecm_front_end_ipv4.c -+++ b/frontends/ecm_front_end_ipv4.c -@@ -376,11 +376,8 @@ void ecm_front_end_ipv4_stop(int num) - */ - int ecm_front_end_ipv4_init(struct dentry *dentry) - { -- if (!debugfs_create_u32("front_end_ipv4_stop", S_IRUGO | S_IWUSR, dentry, -- (u32 *)&ecm_front_end_ipv4_stopped)) { -- DEBUG_ERROR("Failed to create ecm front end ipv4 stop file in debugfs\n"); -- return -1; -- } -+ debugfs_create_u32("front_end_ipv4_stop", S_IRUGO | S_IWUSR, dentry, -+ (u32 *)&ecm_front_end_ipv4_stopped); - - switch (ecm_front_end_type_get()) { - case ECM_FRONT_END_TYPE_NSS: ---- a/frontends/ecm_front_end_ipv6.c -+++ b/frontends/ecm_front_end_ipv6.c -@@ -255,11 +255,8 @@ void ecm_front_end_ipv6_stop(int num) - */ - int ecm_front_end_ipv6_init(struct dentry *dentry) - { -- if (!debugfs_create_u32("front_end_ipv6_stop", S_IRUGO | S_IWUSR, dentry, -- (u32 *)&ecm_front_end_ipv6_stopped)) { -- DEBUG_ERROR("Failed to create ecm front end ipv6 stop file in debugfs\n"); -- return -1; -- } -+ debugfs_create_u32("front_end_ipv6_stop", S_IRUGO | S_IWUSR, dentry, -+ (u32 *)&ecm_front_end_ipv6_stopped); - - switch (ecm_front_end_type_get()) { - case ECM_FRONT_END_TYPE_NSS: ---- a/frontends/nss/ecm_nss_bond_notifier.c -+++ b/frontends/nss/ecm_nss_bond_notifier.c -@@ -240,12 +240,8 @@ int ecm_nss_bond_notifier_init(struct de - return -1; - } - -- if (!debugfs_create_u32("stop", S_IRUGO | S_IWUSR, ecm_nss_bond_notifier_dentry, -- (u32 *)&ecm_nss_bond_notifier_stopped)) { -- DEBUG_ERROR("Failed to create ecm bond notifier stopped file in debugfs\n"); -- debugfs_remove_recursive(ecm_nss_bond_notifier_dentry); -- return -1; -- } -+ debugfs_create_u32("stop", S_IRUGO | S_IWUSR, ecm_nss_bond_notifier_dentry, -+ (u32 *)&ecm_nss_bond_notifier_stopped); - - /* - * Register Link Aggregation callbacks with the bonding driver ---- a/frontends/nss/ecm_nss_ipv4.c -+++ b/frontends/nss/ecm_nss_ipv4.c -@@ -2802,41 +2802,23 @@ int ecm_nss_ipv4_init(struct dentry *den - return result; - } - -- if (!debugfs_create_u32("no_action_limit_default", S_IRUGO | S_IWUSR, ecm_nss_ipv4_dentry, -- (u32 *)&ecm_nss_ipv4_no_action_limit_default)) { -- DEBUG_ERROR("Failed to create ecm nss ipv4 no_action_limit_default file in debugfs\n"); -- goto task_cleanup; -- } -+ debugfs_create_u32("no_action_limit_default", S_IRUGO | S_IWUSR, ecm_nss_ipv4_dentry, -+ (u32 *)&ecm_nss_ipv4_no_action_limit_default); - -- if (!debugfs_create_u32("driver_fail_limit_default", S_IRUGO | S_IWUSR, ecm_nss_ipv4_dentry, -- (u32 *)&ecm_nss_ipv4_driver_fail_limit_default)) { -- DEBUG_ERROR("Failed to create ecm nss ipv4 driver_fail_limit_default file in debugfs\n"); -- goto task_cleanup; -- } -+ debugfs_create_u32("driver_fail_limit_default", S_IRUGO | S_IWUSR, ecm_nss_ipv4_dentry, -+ (u32 *)&ecm_nss_ipv4_driver_fail_limit_default); - -- if (!debugfs_create_u32("nack_limit_default", S_IRUGO | S_IWUSR, ecm_nss_ipv4_dentry, -- (u32 *)&ecm_nss_ipv4_nack_limit_default)) { -- DEBUG_ERROR("Failed to create ecm nss ipv4 nack_limit_default file in debugfs\n"); -- goto task_cleanup; -- } -+ debugfs_create_u32("nack_limit_default", S_IRUGO | S_IWUSR, ecm_nss_ipv4_dentry, -+ (u32 *)&ecm_nss_ipv4_nack_limit_default); - -- if (!debugfs_create_u32("accelerated_count", S_IRUGO, ecm_nss_ipv4_dentry, -- (u32 *)&ecm_nss_ipv4_accelerated_count)) { -- DEBUG_ERROR("Failed to create ecm nss ipv4 accelerated_count file in debugfs\n"); -- goto task_cleanup; -- } -+ debugfs_create_u32("accelerated_count", S_IRUGO, ecm_nss_ipv4_dentry, -+ (u32 *)&ecm_nss_ipv4_accelerated_count); - -- if (!debugfs_create_u32("pending_accel_count", S_IRUGO, ecm_nss_ipv4_dentry, -- (u32 *)&ecm_nss_ipv4_pending_accel_count)) { -- DEBUG_ERROR("Failed to create ecm nss ipv4 pending_accel_count file in debugfs\n"); -- goto task_cleanup; -- } -+ debugfs_create_u32("pending_accel_count", S_IRUGO, ecm_nss_ipv4_dentry, -+ (u32 *)&ecm_nss_ipv4_pending_accel_count); - -- if (!debugfs_create_u32("pending_decel_count", S_IRUGO, ecm_nss_ipv4_dentry, -- (u32 *)&ecm_nss_ipv4_pending_decel_count)) { -- DEBUG_ERROR("Failed to create ecm nss ipv4 pending_decel_count file in debugfs\n"); -- goto task_cleanup; -- } -+ debugfs_create_u32("pending_decel_count", S_IRUGO, ecm_nss_ipv4_dentry, -+ (u32 *)&ecm_nss_ipv4_pending_decel_count); - - if (!debugfs_create_file("accel_limit_mode", S_IRUGO | S_IWUSR, ecm_nss_ipv4_dentry, - NULL, &ecm_nss_ipv4_accel_limit_mode_fops)) { -@@ -2867,11 +2849,8 @@ int ecm_nss_ipv4_init(struct dentry *den - goto task_cleanup; - } - -- if (!debugfs_create_u32("vlan_passthrough_set", S_IRUGO | S_IWUSR, ecm_nss_ipv4_dentry, -- (u32 *)&ecm_nss_ipv4_vlan_passthrough_enable)) { -- DEBUG_ERROR("Failed to create ecm nss ipv4 vlan passthrough file in debugfs\n"); -- goto task_cleanup; -- } -+ debugfs_create_u32("vlan_passthrough_set", S_IRUGO | S_IWUSR, ecm_nss_ipv4_dentry, -+ (u32 *)&ecm_nss_ipv4_vlan_passthrough_enable); - - #ifdef ECM_NON_PORTED_SUPPORT_ENABLE - if (!ecm_nss_non_ported_ipv4_debugfs_init(ecm_nss_ipv4_dentry)) { ---- a/frontends/nss/ecm_nss_ipv6.c -+++ b/frontends/nss/ecm_nss_ipv6.c -@@ -2542,41 +2542,23 @@ int ecm_nss_ipv6_init(struct dentry *den - return result; - } - -- if (!debugfs_create_u32("no_action_limit_default", S_IRUGO | S_IWUSR, ecm_nss_ipv6_dentry, -- (u32 *)&ecm_nss_ipv6_no_action_limit_default)) { -- DEBUG_ERROR("Failed to create ecm nss ipv6 no_action_limit_default file in debugfs\n"); -- goto task_cleanup; -- } -+ debugfs_create_u32("no_action_limit_default", S_IRUGO | S_IWUSR, ecm_nss_ipv6_dentry, -+ (u32 *)&ecm_nss_ipv6_no_action_limit_default); - -- if (!debugfs_create_u32("driver_fail_limit_default", S_IRUGO | S_IWUSR, ecm_nss_ipv6_dentry, -- (u32 *)&ecm_nss_ipv6_driver_fail_limit_default)) { -- DEBUG_ERROR("Failed to create ecm nss ipv6 driver_fail_limit_default file in debugfs\n"); -- goto task_cleanup; -- } -+ debugfs_create_u32("driver_fail_limit_default", S_IRUGO | S_IWUSR, ecm_nss_ipv6_dentry, -+ (u32 *)&ecm_nss_ipv6_driver_fail_limit_default); - -- if (!debugfs_create_u32("nack_limit_default", S_IRUGO | S_IWUSR, ecm_nss_ipv6_dentry, -- (u32 *)&ecm_nss_ipv6_nack_limit_default)) { -- DEBUG_ERROR("Failed to create ecm nss ipv6 nack_limit_default file in debugfs\n"); -- goto task_cleanup; -- } -+ debugfs_create_u32("nack_limit_default", S_IRUGO | S_IWUSR, ecm_nss_ipv6_dentry, -+ (u32 *)&ecm_nss_ipv6_nack_limit_default); - -- if (!debugfs_create_u32("accelerated_count", S_IRUGO, ecm_nss_ipv6_dentry, -- (u32 *)&ecm_nss_ipv6_accelerated_count)) { -- DEBUG_ERROR("Failed to create ecm nss ipv6 accelerated_count file in debugfs\n"); -- goto task_cleanup; -- } -+ debugfs_create_u32("accelerated_count", S_IRUGO, ecm_nss_ipv6_dentry, -+ (u32 *)&ecm_nss_ipv6_accelerated_count); - -- if (!debugfs_create_u32("pending_accel_count", S_IRUGO, ecm_nss_ipv6_dentry, -- (u32 *)&ecm_nss_ipv6_pending_accel_count)) { -- DEBUG_ERROR("Failed to create ecm nss ipv6 pending_accel_count file in debugfs\n"); -- goto task_cleanup; -- } -+ debugfs_create_u32("pending_accel_count", S_IRUGO, ecm_nss_ipv6_dentry, -+ (u32 *)&ecm_nss_ipv6_pending_accel_count); - -- if (!debugfs_create_u32("pending_decel_count", S_IRUGO, ecm_nss_ipv6_dentry, -- (u32 *)&ecm_nss_ipv6_pending_decel_count)) { -- DEBUG_ERROR("Failed to create ecm nss ipv6 pending_decel_count file in debugfs\n"); -- goto task_cleanup; -- } -+ debugfs_create_u32("pending_decel_count", S_IRUGO, ecm_nss_ipv6_dentry, -+ (u32 *)&ecm_nss_ipv6_pending_decel_count); - - if (!debugfs_create_file("accel_limit_mode", S_IRUGO | S_IWUSR, ecm_nss_ipv6_dentry, - NULL, &ecm_nss_ipv6_accel_limit_mode_fops)) { -@@ -2607,11 +2589,8 @@ int ecm_nss_ipv6_init(struct dentry *den - goto task_cleanup; - } - -- if (!debugfs_create_u32("vlan_passthrough_set", S_IRUGO | S_IWUSR, ecm_nss_ipv6_dentry, -- (u32 *)&ecm_nss_ipv6_vlan_passthrough_enable)) { -- DEBUG_ERROR("Failed to create ecm nss ipv6 vlan passthrough file in debugfs\n"); -- goto task_cleanup; -- } -+ debugfs_create_u32("vlan_passthrough_set", S_IRUGO | S_IWUSR, ecm_nss_ipv6_dentry, -+ (u32 *)&ecm_nss_ipv6_vlan_passthrough_enable); - - #ifdef ECM_NON_PORTED_SUPPORT_ENABLE - if (!ecm_nss_non_ported_ipv6_debugfs_init(ecm_nss_ipv6_dentry)) { ---- a/frontends/nss/ecm_nss_multicast_ipv4.c -+++ b/frontends/nss/ecm_nss_multicast_ipv4.c -@@ -4139,11 +4139,8 @@ void ecm_nss_multicast_ipv4_stop(int num - */ - int ecm_nss_multicast_ipv4_init(struct dentry *dentry) - { -- if (!debugfs_create_u32("ecm_nss_multicast_ipv4_stop", S_IRUGO | S_IWUSR, dentry, -- (u32 *)&ecm_front_end_ipv4_mc_stopped)) { -- DEBUG_ERROR("Failed to create ecm front end ipv4 mc stop file in debugfs\n"); -- return -1; -- } -+ debugfs_create_u32("ecm_nss_multicast_ipv4_stop", S_IRUGO | S_IWUSR, dentry, -+ (u32 *)&ecm_front_end_ipv4_mc_stopped); - - /* - * Register multicast update callback to MCS snooper ---- a/frontends/nss/ecm_nss_multicast_ipv6.c -+++ b/frontends/nss/ecm_nss_multicast_ipv6.c -@@ -3939,11 +3939,8 @@ void ecm_nss_multicast_ipv6_stop(int num - */ - int ecm_nss_multicast_ipv6_init(struct dentry *dentry) - { -- if (!debugfs_create_u32("ecm_nss_multicast_ipv6_stop", S_IRUGO | S_IWUSR, dentry, -- (u32 *)&ecm_front_end_ipv6_mc_stopped)) { -- DEBUG_ERROR("Failed to create ecm front end ipv6 mc stop file in debugfs\n"); -- return -1; -- } -+ debugfs_create_u32("ecm_nss_multicast_ipv6_stop", S_IRUGO | S_IWUSR, dentry, -+ (u32 *)&ecm_front_end_ipv6_mc_stopped); - - /* - * Register multicast update callback to MCS snooper ---- a/frontends/nss/ecm_nss_non_ported_ipv4.c -+++ b/frontends/nss/ecm_nss_non_ported_ipv4.c -@@ -2615,11 +2615,8 @@ done: - */ - bool ecm_nss_non_ported_ipv4_debugfs_init(struct dentry *dentry) - { -- if (!debugfs_create_u32("non_ported_accelerated_count", S_IRUGO, dentry, -- (u32 *)&ecm_nss_non_ported_ipv4_accelerated_count)) { -- DEBUG_ERROR("Failed to create ecm nss ipv4 non_ported_accelerated_count file in debugfs\n"); -- return false; -- } -+ debugfs_create_u32("non_ported_accelerated_count", S_IRUGO, dentry, -+ (u32 *)&ecm_nss_non_ported_ipv4_accelerated_count); - - return true; - } ---- a/frontends/nss/ecm_nss_non_ported_ipv6.c -+++ b/frontends/nss/ecm_nss_non_ported_ipv6.c -@@ -2329,11 +2329,8 @@ done: - */ - bool ecm_nss_non_ported_ipv6_debugfs_init(struct dentry *dentry) - { -- if (!debugfs_create_u32("non_ported_accelerated_count", S_IRUGO, dentry, -- (u32 *)&ecm_nss_non_ported_ipv6_accelerated_count)) { -- DEBUG_ERROR("Failed to create ecm nss ipv6 non_ported_accelerated_count file in debugfs\n"); -- return false; -- } -+ debugfs_create_u32("non_ported_accelerated_count", S_IRUGO, dentry, -+ (u32 *)&ecm_nss_non_ported_ipv6_accelerated_count); - - return true; - } ---- a/frontends/nss/ecm_nss_ported_ipv4.c -+++ b/frontends/nss/ecm_nss_ported_ipv4.c -@@ -2944,12 +2944,8 @@ bool ecm_nss_ported_ipv4_debugfs_init(st - return false; - } - -- if (!debugfs_create_u32("tcp_accelerated_count", S_IRUGO, dentry, -- &ecm_nss_ported_ipv4_accelerated_count[ECM_NSS_PORTED_IPV4_PROTO_TCP])) { -- DEBUG_ERROR("Failed to create ecm nss ipv4 tcp_accelerated_count file in debugfs\n"); -- debugfs_remove(udp_dentry); -- return false; -- } -+ debugfs_create_u32("tcp_accelerated_count", S_IRUGO, dentry, -+ &ecm_nss_ported_ipv4_accelerated_count[ECM_NSS_PORTED_IPV4_PROTO_TCP]); - - return true; - } ---- a/frontends/nss/ecm_nss_ported_ipv6.c -+++ b/frontends/nss/ecm_nss_ported_ipv6.c -@@ -2732,12 +2732,8 @@ bool ecm_nss_ported_ipv6_debugfs_init(st - return false; - } - -- if (!debugfs_create_u32("tcp_accelerated_count", S_IRUGO, dentry, -- &ecm_nss_ported_ipv6_accelerated_count[ECM_NSS_PORTED_IPV6_PROTO_TCP])) { -- DEBUG_ERROR("Failed to create ecm nss ipv6 tcp_accelerated_count file in debugfs\n"); -- debugfs_remove(udp_dentry); -- return false; -- } -+ debugfs_create_u32("tcp_accelerated_count", S_IRUGO, dentry, -+ &ecm_nss_ported_ipv6_accelerated_count[ECM_NSS_PORTED_IPV6_PROTO_TCP]); - - return true; - } ---- a/frontends/sfe/ecm_sfe_ipv4.c -+++ b/frontends/sfe/ecm_sfe_ipv4.c -@@ -1808,48 +1808,27 @@ int ecm_sfe_ipv4_init(struct dentry *den - } - - #ifdef CONFIG_XFRM -- if (!debugfs_create_u32("reject_acceleration_for_ipsec", S_IRUGO | S_IWUSR, ecm_sfe_ipv4_dentry, -- (u32 *)&ecm_sfe_ipv4_reject_acceleration_for_ipsec)) { -- DEBUG_ERROR("Failed to create ecm sfe ipv4 reject_acceleration_for_ipsec file in debugfs\n"); -- goto task_cleanup; -- } -+ debugfs_create_u32("reject_acceleration_for_ipsec", S_IRUGO | S_IWUSR, ecm_sfe_ipv4_dentry, -+ (u32 *)&ecm_sfe_ipv4_reject_acceleration_for_ipsec); - #endif - -- if (!debugfs_create_u32("no_action_limit_default", S_IRUGO | S_IWUSR, ecm_sfe_ipv4_dentry, -- (u32 *)&ecm_sfe_ipv4_no_action_limit_default)) { -- DEBUG_ERROR("Failed to create ecm sfe ipv4 no_action_limit_default file in debugfs\n"); -- goto task_cleanup; -- } -+ debugfs_create_u32("no_action_limit_default", S_IRUGO | S_IWUSR, ecm_sfe_ipv4_dentry, -+ (u32 *)&ecm_sfe_ipv4_no_action_limit_default); - -- if (!debugfs_create_u32("driver_fail_limit_default", S_IRUGO | S_IWUSR, ecm_sfe_ipv4_dentry, -- (u32 *)&ecm_sfe_ipv4_driver_fail_limit_default)) { -- DEBUG_ERROR("Failed to create ecm sfe ipv4 driver_fail_limit_default file in debugfs\n"); -- goto task_cleanup; -- } -+ debugfs_create_u32("driver_fail_limit_default", S_IRUGO | S_IWUSR, ecm_sfe_ipv4_dentry, -+ (u32 *)&ecm_sfe_ipv4_driver_fail_limit_default); - -- if (!debugfs_create_u32("nack_limit_default", S_IRUGO | S_IWUSR, ecm_sfe_ipv4_dentry, -- (u32 *)&ecm_sfe_ipv4_nack_limit_default)) { -- DEBUG_ERROR("Failed to create ecm sfe ipv4 nack_limit_default file in debugfs\n"); -- goto task_cleanup; -- } -+ debugfs_create_u32("nack_limit_default", S_IRUGO | S_IWUSR, ecm_sfe_ipv4_dentry, -+ (u32 *)&ecm_sfe_ipv4_nack_limit_default); - -- if (!debugfs_create_u32("accelerated_count", S_IRUGO, ecm_sfe_ipv4_dentry, -- (u32 *)&ecm_sfe_ipv4_accelerated_count)) { -- DEBUG_ERROR("Failed to create ecm sfe ipv4 accelerated_count file in debugfs\n"); -- goto task_cleanup; -- } -+ debugfs_create_u32("accelerated_count", S_IRUGO, ecm_sfe_ipv4_dentry, -+ (u32 *)&ecm_sfe_ipv4_accelerated_count); - -- if (!debugfs_create_u32("pending_accel_count", S_IRUGO, ecm_sfe_ipv4_dentry, -- (u32 *)&ecm_sfe_ipv4_pending_accel_count)) { -- DEBUG_ERROR("Failed to create ecm sfe ipv4 pending_accel_count file in debugfs\n"); -- goto task_cleanup; -- } -+ debugfs_create_u32("pending_accel_count", S_IRUGO, ecm_sfe_ipv4_dentry, -+ (u32 *)&ecm_sfe_ipv4_pending_accel_count); - -- if (!debugfs_create_u32("pending_decel_count", S_IRUGO, ecm_sfe_ipv4_dentry, -- (u32 *)&ecm_sfe_ipv4_pending_decel_count)) { -- DEBUG_ERROR("Failed to create ecm sfe ipv4 pending_decel_count file in debugfs\n"); -- goto task_cleanup; -- } -+ debugfs_create_u32("pending_decel_count", S_IRUGO, ecm_sfe_ipv4_dentry, -+ (u32 *)&ecm_sfe_ipv4_pending_decel_count); - - if (!debugfs_create_file("accel_limit_mode", S_IRUGO | S_IWUSR, ecm_sfe_ipv4_dentry, - NULL, &ecm_sfe_ipv4_accel_limit_mode_fops)) { ---- a/frontends/sfe/ecm_sfe_ipv6.c -+++ b/frontends/sfe/ecm_sfe_ipv6.c -@@ -1532,48 +1532,27 @@ int ecm_sfe_ipv6_init(struct dentry *den - } - - #ifdef CONFIG_XFRM -- if (!debugfs_create_u32("reject_acceleration_for_ipsec", S_IRUGO | S_IWUSR, ecm_sfe_ipv6_dentry, -- (u32 *)&ecm_sfe_ipv6_reject_acceleration_for_ipsec)) { -- DEBUG_ERROR("Failed to create ecm sfe ipv6 reject_acceleration_for_ipsec file in debugfs\n"); -- goto task_cleanup; -- } -+ debugfs_create_u32("reject_acceleration_for_ipsec", S_IRUGO | S_IWUSR, ecm_sfe_ipv6_dentry, -+ (u32 *)&ecm_sfe_ipv6_reject_acceleration_for_ipsec); - #endif - -- if (!debugfs_create_u32("no_action_limit_default", S_IRUGO | S_IWUSR, ecm_sfe_ipv6_dentry, -- (u32 *)&ecm_sfe_ipv6_no_action_limit_default)) { -- DEBUG_ERROR("Failed to create ecm sfe ipv6 no_action_limit_default file in debugfs\n"); -- goto task_cleanup; -- } -+ debugfs_create_u32("no_action_limit_default", S_IRUGO | S_IWUSR, ecm_sfe_ipv6_dentry, -+ (u32 *)&ecm_sfe_ipv6_no_action_limit_default); - -- if (!debugfs_create_u32("driver_fail_limit_default", S_IRUGO | S_IWUSR, ecm_sfe_ipv6_dentry, -- (u32 *)&ecm_sfe_ipv6_driver_fail_limit_default)) { -- DEBUG_ERROR("Failed to create ecm sfe ipv6 driver_fail_limit_default file in debugfs\n"); -- goto task_cleanup; -- } -+ debugfs_create_u32("driver_fail_limit_default", S_IRUGO | S_IWUSR, ecm_sfe_ipv6_dentry, -+ (u32 *)&ecm_sfe_ipv6_driver_fail_limit_default); - -- if (!debugfs_create_u32("nack_limit_default", S_IRUGO | S_IWUSR, ecm_sfe_ipv6_dentry, -- (u32 *)&ecm_sfe_ipv6_nack_limit_default)) { -- DEBUG_ERROR("Failed to create ecm sfe ipv6 nack_limit_default file in debugfs\n"); -- goto task_cleanup; -- } -+ debugfs_create_u32("nack_limit_default", S_IRUGO | S_IWUSR, ecm_sfe_ipv6_dentry, -+ (u32 *)&ecm_sfe_ipv6_nack_limit_default); - -- if (!debugfs_create_u32("accelerated_count", S_IRUGO, ecm_sfe_ipv6_dentry, -- (u32 *)&ecm_sfe_ipv6_accelerated_count)) { -- DEBUG_ERROR("Failed to create ecm sfe ipv6 accelerated_count file in debugfs\n"); -- goto task_cleanup; -- } -+ debugfs_create_u32("accelerated_count", S_IRUGO, ecm_sfe_ipv6_dentry, -+ (u32 *)&ecm_sfe_ipv6_accelerated_count); - -- if (!debugfs_create_u32("pending_accel_count", S_IRUGO, ecm_sfe_ipv6_dentry, -- (u32 *)&ecm_sfe_ipv6_pending_accel_count)) { -- DEBUG_ERROR("Failed to create ecm sfe ipv6 pending_accel_count file in debugfs\n"); -- goto task_cleanup; -- } -+ debugfs_create_u32("pending_accel_count", S_IRUGO, ecm_sfe_ipv6_dentry, -+ (u32 *)&ecm_sfe_ipv6_pending_accel_count); - -- if (!debugfs_create_u32("pending_decel_count", S_IRUGO, ecm_sfe_ipv6_dentry, -- (u32 *)&ecm_sfe_ipv6_pending_decel_count)) { -- DEBUG_ERROR("Failed to create ecm sfe ipv6 pending_decel_count file in debugfs\n"); -- goto task_cleanup; -- } -+ debugfs_create_u32("pending_decel_count", S_IRUGO, ecm_sfe_ipv6_dentry, -+ (u32 *)&ecm_sfe_ipv6_pending_decel_count); - - if (!debugfs_create_file("accel_limit_mode", S_IRUGO | S_IWUSR, ecm_sfe_ipv6_dentry, - NULL, &ecm_sfe_ipv6_accel_limit_mode_fops)) { ---- a/frontends/sfe/ecm_sfe_non_ported_ipv4.c -+++ b/frontends/sfe/ecm_sfe_non_ported_ipv4.c -@@ -2284,11 +2284,8 @@ done: - */ - bool ecm_sfe_non_ported_ipv4_debugfs_init(struct dentry *dentry) - { -- if (!debugfs_create_u32("non_ported_accelerated_count", S_IRUGO, dentry, -- (u32 *)&ecm_sfe_non_ported_ipv4_accelerated_count)) { -- DEBUG_ERROR("Failed to create ecm sfe ipv4 non_ported_accelerated_count file in debugfs\n"); -- return false; -- } -+ debugfs_create_u32("non_ported_accelerated_count", S_IRUGO, dentry, -+ (u32 *)&ecm_sfe_non_ported_ipv4_accelerated_count); - - return true; - } ---- a/frontends/sfe/ecm_sfe_non_ported_ipv6.c -+++ b/frontends/sfe/ecm_sfe_non_ported_ipv6.c -@@ -2083,11 +2083,8 @@ done: - */ - bool ecm_sfe_non_ported_ipv6_debugfs_init(struct dentry *dentry) - { -- if (!debugfs_create_u32("non_ported_accelerated_count", S_IRUGO, dentry, -- (u32 *)&ecm_sfe_non_ported_ipv6_accelerated_count)) { -- DEBUG_ERROR("Failed to create ecm sfe ipv6 non_ported_accelerated_count file in debugfs\n"); -- return false; -- } -+ debugfs_create_u32("non_ported_accelerated_count", S_IRUGO, dentry, -+ (u32 *)&ecm_sfe_non_ported_ipv6_accelerated_count); - - return true; - } ---- a/frontends/sfe/ecm_sfe_ported_ipv4.c -+++ b/frontends/sfe/ecm_sfe_ported_ipv4.c -@@ -2528,12 +2528,8 @@ bool ecm_sfe_ported_ipv4_debugfs_init(st - return false; - } - -- if (!debugfs_create_u32("tcp_accelerated_count", S_IRUGO, dentry, -- &ecm_sfe_ported_ipv4_accelerated_count[ECM_SFE_PORTED_IPV4_PROTO_TCP])) { -- DEBUG_ERROR("Failed to create ecm sfe ipv4 tcp_accelerated_count file in debugfs\n"); -- debugfs_remove(udp_dentry); -- return false; -- } -+ debugfs_create_u32("tcp_accelerated_count", S_IRUGO, dentry, -+ &ecm_sfe_ported_ipv4_accelerated_count[ECM_SFE_PORTED_IPV4_PROTO_TCP]); - - return true; - } ---- a/frontends/sfe/ecm_sfe_ported_ipv6.c -+++ b/frontends/sfe/ecm_sfe_ported_ipv6.c -@@ -2374,12 +2374,8 @@ bool ecm_sfe_ported_ipv6_debugfs_init(st - return false; - } - -- if (!debugfs_create_u32("tcp_accelerated_count", S_IRUGO, dentry, -- &ecm_sfe_ported_ipv6_accelerated_count[ECM_SFE_PORTED_IPV6_PROTO_TCP])) { -- DEBUG_ERROR("Failed to create ecm sfe ipv6 tcp_accelerated_count file in debugfs\n"); -- debugfs_remove(udp_dentry); -- return false; -- } -+ debugfs_create_u32("tcp_accelerated_count", S_IRUGO, dentry, -+ &ecm_sfe_ported_ipv6_accelerated_count[ECM_SFE_PORTED_IPV6_PROTO_TCP]); - - return true; - } diff --git a/root/package/qca/nss/qca-nss-ecm-64/patches/003-rework-nfct-notification.patch b/root/package/qca/nss/qca-nss-ecm-64/patches/003-rework-nfct-notification.patch deleted file mode 100644 index 72005cd7..00000000 --- a/root/package/qca/nss/qca-nss-ecm-64/patches/003-rework-nfct-notification.patch +++ /dev/null @@ -1,25 +0,0 @@ ---- a/ecm_conntrack_notifier.c -+++ b/ecm_conntrack_notifier.c -@@ -421,7 +421,11 @@ int ecm_conntrack_notifier_init(struct d - /* - * Eventing subsystem is available so we register a notifier hook to get fast notifications of expired connections - */ -+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS -+ result = nf_conntrack_register_chain_notifier(&init_net, &ecm_conntrack_notifier); -+#else - result = nf_conntrack_register_notifier(&init_net, &ecm_conntrack_notifier); -+#endif - if (result < 0) { - DEBUG_ERROR("Can't register nf notifier hook.\n"); - debugfs_remove_recursive(ecm_conntrack_notifier_dentry); -@@ -439,7 +443,9 @@ EXPORT_SYMBOL(ecm_conntrack_notifier_ini - void ecm_conntrack_notifier_exit(void) - { - DEBUG_INFO("ECM Conntrack Notifier exit\n"); --#ifdef CONFIG_NF_CONNTRACK_EVENTS -+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS -+ nf_conntrack_unregister_chain_notifier(&init_net, &ecm_conntrack_notifier); -+#else - nf_conntrack_unregister_notifier(&init_net, &ecm_conntrack_notifier); - #endif - /* diff --git a/root/package/qca/nss/qca-nss-ecm-64/patches/004-More-compile-fixes.patch b/root/package/qca/nss/qca-nss-ecm-64/patches/004-More-compile-fixes.patch deleted file mode 100644 index a998d829..00000000 --- a/root/package/qca/nss/qca-nss-ecm-64/patches/004-More-compile-fixes.patch +++ /dev/null @@ -1,58 +0,0 @@ -From e6d701c0d454d841366c556b2ef07a5203ffb35d Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Fri, 21 May 2021 21:41:31 +0200 -Subject: [PATCH] More compile fixes - -More runtime compile fixes. - -Signed-off-by: Robert Marko ---- - frontends/nss/ecm_nss_ported_ipv4.c | 12 +++--------- - frontends/nss/ecm_nss_ported_ipv6.c | 12 +++--------- - 2 files changed, 6 insertions(+), 18 deletions(-) - -diff --git a/frontends/nss/ecm_nss_ported_ipv4.c b/frontends/nss/ecm_nss_ported_ipv4.c -index 3522f0f..7f5fcd1 100644 ---- a/frontends/nss/ecm_nss_ported_ipv4.c -+++ b/frontends/nss/ecm_nss_ported_ipv4.c -@@ -2935,14 +2935,8 @@ done: - */ - bool ecm_nss_ported_ipv4_debugfs_init(struct dentry *dentry) - { -- struct dentry *udp_dentry; -- -- udp_dentry = debugfs_create_u32("udp_accelerated_count", S_IRUGO, dentry, -+ debugfs_create_u32("udp_accelerated_count", S_IRUGO, dentry, - &ecm_nss_ported_ipv4_accelerated_count[ECM_NSS_PORTED_IPV4_PROTO_UDP]); -- if (!udp_dentry) { -- DEBUG_ERROR("Failed to create ecm nss ipv4 udp_accelerated_count file in debugfs\n"); -- return false; -- } - - debugfs_create_u32("tcp_accelerated_count", S_IRUGO, dentry, - &ecm_nss_ported_ipv4_accelerated_count[ECM_NSS_PORTED_IPV4_PROTO_TCP]); -diff --git a/frontends/nss/ecm_nss_ported_ipv6.c b/frontends/nss/ecm_nss_ported_ipv6.c -index f43ac95..e0f779c 100644 ---- a/frontends/nss/ecm_nss_ported_ipv6.c -+++ b/frontends/nss/ecm_nss_ported_ipv6.c - /* - * ecm_nss_ported_ipv6_connection_callback() -@@ -2723,14 +2723,8 @@ done: - */ - bool ecm_nss_ported_ipv6_debugfs_init(struct dentry *dentry) - { -- struct dentry *udp_dentry; -- -- udp_dentry = debugfs_create_u32("udp_accelerated_count", S_IRUGO, dentry, -+ debugfs_create_u32("udp_accelerated_count", S_IRUGO, dentry, - &ecm_nss_ported_ipv6_accelerated_count[ECM_NSS_PORTED_IPV6_PROTO_UDP]); -- if (!udp_dentry) { -- DEBUG_ERROR("Failed to create ecm nss ipv6 udp_accelerated_count file in debugfs\n"); -- return false; -- } - - debugfs_create_u32("tcp_accelerated_count", S_IRUGO, dentry, - &ecm_nss_ported_ipv6_accelerated_count[ECM_NSS_PORTED_IPV6_PROTO_TCP]); --- -2.31.1 - diff --git a/root/package/qca/nss/qca-nss-ecm-64/patches/005-resolve-high-load.patch b/root/package/qca/nss/qca-nss-ecm-64/patches/005-resolve-high-load.patch deleted file mode 100644 index f4106a35..00000000 --- a/root/package/qca/nss/qca-nss-ecm-64/patches/005-resolve-high-load.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 6924b71ed809b37fffd74d6428a8ca83e5919746 Mon Sep 17 00:00:00 2001 -From: Dirk Buchwalder -Date: Sun, 27 Jun 2021 16:52:39 +0200 -Subject: [PATCH] qca-nss-ecm: resolve the cpu high load regarding ecm - -If using ECM, cpu load goes up (around 1.0) and stucks there. -This is due to using uninterruptible sleep function, -the patch changes this to interruptible sleep function. - -Signed-off-by: Dirk Buchwalder buchwalder@posteo.de ---- - frontends/nss/ecm_nss_ipv4.c | 4 ++-- - frontends/nss/ecm_nss_ipv6.c | 4 ++-- - 2 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/frontends/nss/ecm_nss_ipv4.c b/frontends/nss/ecm_nss_ipv4.c -index e00553c..94b39cd 100644 ---- a/frontends/nss/ecm_nss_ipv4.c -+++ b/frontends/nss/ecm_nss_ipv4.c -@@ -2471,7 +2471,7 @@ static void ecm_nss_ipv4_stats_sync_req_work(struct work_struct *work) - } - spin_unlock_bh(&ecm_nss_ipv4_lock); - -- usleep_range(ECM_NSS_IPV4_STATS_SYNC_UDELAY - 100, ECM_NSS_IPV4_STATS_SYNC_UDELAY); -+ msleep_interruptible(ECM_NSS_IPV4_STATS_SYNC_UDELAY / 1000); - - /* - * If index is 0, we are starting a new round, but if we still have time remain -@@ -2485,7 +2485,7 @@ static void ecm_nss_ipv4_stats_sync_req_work(struct work_struct *work) - } - - if (time_after(ecm_nss_ipv4_next_req_time, current_jiffies)) { -- msleep(jiffies_to_msecs(ecm_nss_ipv4_next_req_time - current_jiffies)); -+ msleep_interruptible(jiffies_to_msecs(ecm_nss_ipv4_next_req_time - current_jiffies)); - } - ecm_nss_ipv4_roll_check_jiffies = jiffies; - ecm_nss_ipv4_next_req_time = ecm_nss_ipv4_roll_check_jiffies + ECM_NSS_IPV4_STATS_SYNC_PERIOD; -diff --git a/frontends/nss/ecm_nss_ipv6.c b/frontends/nss/ecm_nss_ipv6.c -index 82e739f..30af050 100644 ---- a/frontends/nss/ecm_nss_ipv6.c -+++ b/frontends/nss/ecm_nss_ipv6.c -@@ -2210,7 +2210,7 @@ static void ecm_nss_ipv6_stats_sync_req_work(struct work_struct *work) - } - spin_unlock_bh(&ecm_nss_ipv6_lock); - -- usleep_range(ECM_NSS_IPV6_STATS_SYNC_UDELAY - 100, ECM_NSS_IPV6_STATS_SYNC_UDELAY); -+ msleep_interruptible(ECM_NSS_IPV6_STATS_SYNC_UDELAY / 1000); - - /* - * If index is 0, we are starting a new round, but if we still have time remain -@@ -2224,7 +2224,7 @@ static void ecm_nss_ipv6_stats_sync_req_work(struct work_struct *work) - } - - if (time_after(ecm_nss_ipv6_next_req_time, current_jiffies)) { -- msleep(jiffies_to_msecs(ecm_nss_ipv6_next_req_time - current_jiffies)); -+ msleep_interruptible(jiffies_to_msecs(ecm_nss_ipv6_next_req_time - current_jiffies)); - } - ecm_nss_ipv6_roll_check_jiffies = jiffies; - ecm_nss_ipv6_next_req_time = ecm_nss_ipv6_roll_check_jiffies + ECM_NSS_IPV6_STATS_SYNC_PERIOD; --- -2.31.1 diff --git a/root/package/qca/nss/qca-nss-ecm-64/patches/006-ecm_interface-switch-to-kernel_recvmsg-api.patch b/root/package/qca/nss/qca-nss-ecm-64/patches/006-ecm_interface-switch-to-kernel_recvmsg-api.patch deleted file mode 100644 index caa591ab..00000000 --- a/root/package/qca/nss/qca-nss-ecm-64/patches/006-ecm_interface-switch-to-kernel_recvmsg-api.patch +++ /dev/null @@ -1,40 +0,0 @@ -diff --git a/ecm_interface.c b/ecm_interface.c -index b461456..6be872a 100644 ---- a/ecm_interface.c -+++ b/ecm_interface.c -@@ -7493,9 +7493,13 @@ - static int ecm_interface_wifi_event_rx(struct socket *sock, struct sockaddr_nl *addr, unsigned char *buf, int len) - { - struct msghdr msg; -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)) - struct iovec iov; - mm_segment_t oldfs; - int size; -+#else -+ struct kvec iov; -+#endif - - iov.iov_base = buf; - iov.iov_len = len; -@@ -7505,9 +7509,10 @@ - msg.msg_namelen = sizeof(struct sockaddr_nl); - msg.msg_control = NULL; - msg.msg_controllen = 0; -- iov_iter_init(&msg.msg_iter, READ, &iov, 1, 1); -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)) - oldfs = get_fs(); - set_fs(KERNEL_DS); -+ iov_iter_init(&msg.msg_iter, READ, &iov, 1, 1); - #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0)) - size = sock_recvmsg(sock, &msg, len, msg.msg_flags); - #else -@@ -7516,6 +7521,9 @@ - set_fs(oldfs); - - return size; -+#else -+ return kernel_recvmsg(sock, &msg, &iov, 1, iov.iov_len, 0); -+#endif - } - - /* diff --git a/root/package/qca/nss/qca-nss-ecm-64/patches/007-treewide-rework-notifier-changes-for-5.15.patch b/root/package/qca/nss/qca-nss-ecm-64/patches/007-treewide-rework-notifier-changes-for-5.15.patch deleted file mode 100644 index 262a8fb8..00000000 --- a/root/package/qca/nss/qca-nss-ecm-64/patches/007-treewide-rework-notifier-changes-for-5.15.patch +++ /dev/null @@ -1,72 +0,0 @@ -From e9073363a50a25bddd96e808f04bcf56c45da4ac Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Sun, 8 May 2022 18:19:47 +0200 -Subject: [PATCH 07/12] treewide: rework notifier changes for 5.15 - -Rework notifier changes for 5.15 conntrack new implementation. - -Signed-off-by: Ansuel Smith ---- - ecm_conntrack_notifier.c | 16 +++++++++++++++- - 1 file changed, 15 insertions(+), 1 deletion(-) - -diff --git a/ecm_conntrack_notifier.c b/ecm_conntrack_notifier.c -index 9c8a45e..9f2cdae 100644 ---- a/ecm_conntrack_notifier.c -+++ b/ecm_conntrack_notifier.c -@@ -322,7 +322,7 @@ EXPORT_SYMBOL(ecm_conntrack_ipv4_event); - #ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS - static int ecm_conntrack_event(struct notifier_block *this, unsigned long events, void *ptr) - #else --static int ecm_conntrack_event(unsigned int events, struct nf_ct_event *item) -+static int ecm_conntrack_event(unsigned int events, const struct nf_ct_event *item) - #endif - { - #ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS -@@ -388,7 +388,11 @@ static struct notifier_block ecm_conntrack_notifier = { - * Netfilter conntrack event system to monitor connection tracking changes - */ - static struct nf_ct_event_notifier ecm_conntrack_notifier = { -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)) - .fcn = ecm_conntrack_event, -+#else -+ .ct_event = ecm_conntrack_event, -+#endif - }; - #endif - #endif -@@ -426,13 +430,19 @@ int ecm_conntrack_notifier_init(struct dentry *dentry) - #ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS - result = nf_conntrack_register_chain_notifier(&init_net, &ecm_conntrack_notifier); - #else -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)) - result = nf_conntrack_register_notifier(&init_net, &ecm_conntrack_notifier); -+#else -+ nf_conntrack_register_notifier(&init_net, &ecm_conntrack_notifier); -+#endif - #endif -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)) - if (result < 0) { - DEBUG_ERROR("Can't register nf notifier hook.\n"); - debugfs_remove_recursive(ecm_conntrack_notifier_dentry); - return result; - } -+#endif - #endif - - return 0; -@@ -448,7 +458,11 @@ void ecm_conntrack_notifier_exit(void) - #ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS - nf_conntrack_unregister_chain_notifier(&init_net, &ecm_conntrack_notifier); - #else -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)) - nf_conntrack_unregister_notifier(&init_net, &ecm_conntrack_notifier); -+#else -+ nf_conntrack_unregister_notifier(&init_net); -+#endif - #endif - /* - * Remove the debugfs files recursively. --- -2.34.1 - diff --git a/root/package/qca/nss/qca-nss-ecm-64/patches/008-frontends-drop-use-of-static-be_liberal-and-no_windo.patch b/root/package/qca/nss/qca-nss-ecm-64/patches/008-frontends-drop-use-of-static-be_liberal-and-no_windo.patch deleted file mode 100644 index c5989cc1..00000000 --- a/root/package/qca/nss/qca-nss-ecm-64/patches/008-frontends-drop-use-of-static-be_liberal-and-no_windo.patch +++ /dev/null @@ -1,156 +0,0 @@ ---- a/frontends/nss/ecm_nss_ported_ipv4.c -+++ b/frontends/nss/ecm_nss_ported_ipv4.c -@@ -125,6 +125,7 @@ - static int ecm_nss_ported_ipv4_accelerated_count[ECM_NSS_PORTED_IPV4_PROTO_MAX] = {0}; - /* Array of Number of TCP and UDP connections currently offloaded */ - -+ #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0) - /* - * Expose what should be a static flag in the TCP connection tracker. - */ -@@ -132,6 +133,7 @@ - extern int nf_ct_tcp_no_window_check; - #endif - extern int nf_ct_tcp_be_liberal; -+#endif - - /* - * ecm_nss_ported_ipv4_connection_callback() -@@ -372,6 +374,10 @@ - uint8_t dest_mac_xlate[ETH_ALEN]; - ecm_db_direction_t ecm_dir; - ecm_front_end_acceleration_mode_t result_mode; -+#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 12, 0) -+ struct net *net = nf_ct_net(ct); -+ struct nf_tcp_net *tn = nf_tcp_pernet(net); -+#endif - - DEBUG_CHECK_MAGIC(npci, ECM_NSS_PORTED_IPV4_CONNECTION_INSTANCE_MAGIC, "%px: magic failed", npci); - -@@ -1236,9 +1242,17 @@ - nircm->tcp_rule.return_end = ct->proto.tcp.seen[return_dir].td_end; - nircm->tcp_rule.return_max_end = ct->proto.tcp.seen[return_dir].td_maxend; - #ifdef ECM_OPENWRT_SUPPORT -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0) - if (nf_ct_tcp_be_liberal || nf_ct_tcp_no_window_check - #else -+ if (tn->tcp_be_liberal || tn->tcp_no_window_check -+#endif -+#else -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0) - if (nf_ct_tcp_be_liberal -+#else -+ if (tn->tcp_be_liberal -+#endif - #endif - || (ct->proto.tcp.seen[flow_dir].flags & IP_CT_TCP_FLAG_BE_LIBERAL) - || (ct->proto.tcp.seen[return_dir].flags & IP_CT_TCP_FLAG_BE_LIBERAL)) { ---- a/frontends/nss/ecm_nss_ported_ipv6.c -+++ b/frontends/nss/ecm_nss_ported_ipv6.c -@@ -125,6 +125,7 @@ - static int ecm_nss_ported_ipv6_accelerated_count[ECM_NSS_PORTED_IPV6_PROTO_MAX] = {0}; - /* Array of Number of TCP and UDP connections currently offloaded */ - -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0) - /* - * Expose what should be a static flag in the TCP connection tracker. - */ -@@ -132,6 +133,7 @@ - extern int nf_ct_tcp_no_window_check; - #endif - extern int nf_ct_tcp_be_liberal; -+#endif - - /* - * ecm_nss_ported_ipv6_connection_callback() -@@ -376,6 +378,10 @@ - ip_addr_t src_ip; - ip_addr_t dest_ip; - ecm_front_end_acceleration_mode_t result_mode; -+#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 12, 0) -+ struct net *net = nf_ct_net(ct); -+ struct nf_tcp_net *tn = nf_tcp_pernet(net); -+#endif - - DEBUG_CHECK_MAGIC(npci, ECM_NSS_PORTED_IPV6_CONNECTION_INSTANCE_MAGIC, "%px: magic failed", npci); - -@@ -1162,9 +1168,17 @@ - nircm->tcp_rule.return_end = ct->proto.tcp.seen[return_dir].td_end; - nircm->tcp_rule.return_max_end = ct->proto.tcp.seen[return_dir].td_maxend; - #ifdef ECM_OPENWRT_SUPPORT -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0) - if (nf_ct_tcp_be_liberal || nf_ct_tcp_no_window_check - #else -+ if (tn->tcp_be_liberal || tn->tcp_no_window_check -+#endif -+#else -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0) - if (nf_ct_tcp_be_liberal -+#else -+ if (tn->tcp_be_liberal -+#endif - #endif - || (ct->proto.tcp.seen[flow_dir].flags & IP_CT_TCP_FLAG_BE_LIBERAL) - || (ct->proto.tcp.seen[return_dir].flags & IP_CT_TCP_FLAG_BE_LIBERAL)) { ---- a/frontends/sfe/ecm_sfe_ported_ipv4.c -+++ b/frontends/sfe/ecm_sfe_ported_ipv4.c -@@ -422,6 +422,10 @@ - int32_t interface_type_counts[ECM_DB_IFACE_TYPE_COUNT]; - bool rule_invalid; - ecm_db_direction_t ecm_dir; -+#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 12, 0) -+ struct net *net = nf_ct_net(ct); -+ struct nf_tcp_net *tn = nf_tcp_pernet(net); -+#endif - ecm_front_end_acceleration_mode_t result_mode; - - DEBUG_CHECK_MAGIC(npci, ECM_SFE_PORTED_IPV4_CONNECTION_INSTANCE_MAGIC, "%px: magic failed", npci); -@@ -1333,9 +1337,17 @@ - nircm->tcp_rule.return_end = ct->proto.tcp.seen[return_dir].td_end; - nircm->tcp_rule.return_max_end = ct->proto.tcp.seen[return_dir].td_maxend; - #ifdef ECM_OPENWRT_SUPPORT -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0) - if (nf_ct_tcp_be_liberal || nf_ct_tcp_no_window_check - #else -+ if (tn->tcp_be_liberal || tn->tcp_no_window_check) -+#endif -+#else -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0) - if (nf_ct_tcp_be_liberal -+#else -+ if (tn->tcp_be_liberal) -+#endif - #endif - || (ct->proto.tcp.seen[flow_dir].flags & IP_CT_TCP_FLAG_BE_LIBERAL) - || (ct->proto.tcp.seen[return_dir].flags & IP_CT_TCP_FLAG_BE_LIBERAL)) { ---- a/frontends/sfe/ecm_sfe_ported_ipv6.c -+++ b/frontends/sfe/ecm_sfe_ported_ipv6.c -@@ -426,6 +426,10 @@ - int32_t interface_type_counts[ECM_DB_IFACE_TYPE_COUNT]; - bool rule_invalid; - ip_addr_t src_ip; -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0) -+ struct net *net = nf_ct_net(ct); -+ struct nf_tcp_net *tn = nf_tcp_pernet(net); -+#endif - ip_addr_t dest_ip; - ecm_front_end_acceleration_mode_t result_mode; - -@@ -1293,9 +1297,17 @@ - nircm->tcp_rule.return_end = ct->proto.tcp.seen[return_dir].td_end; - nircm->tcp_rule.return_max_end = ct->proto.tcp.seen[return_dir].td_maxend; - #ifdef ECM_OPENWRT_SUPPORT -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0) - if (nf_ct_tcp_be_liberal || nf_ct_tcp_no_window_check - #else -+ if (tn->tcp_be_liberal || tn->tcp_no_window_check) -+#endif -+#else -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0) - if (nf_ct_tcp_be_liberal -+#else -+ if (tn->tcp_be_liberal) -+#endif - #endif - || (ct->proto.tcp.seen[flow_dir].flags & IP_CT_TCP_FLAG_BE_LIBERAL) - || (ct->proto.tcp.seen[return_dir].flags & IP_CT_TCP_FLAG_BE_LIBERAL)) { diff --git a/root/package/qca/nss/qca-nss-ecm-64/patches/009-ecm_tracker_datagram-drop-static-for-EXPORT_SYMBOL.patch b/root/package/qca/nss/qca-nss-ecm-64/patches/009-ecm_tracker_datagram-drop-static-for-EXPORT_SYMBOL.patch deleted file mode 100644 index 1bcaa12e..00000000 --- a/root/package/qca/nss/qca-nss-ecm-64/patches/009-ecm_tracker_datagram-drop-static-for-EXPORT_SYMBOL.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 9827d8597545ecfee17eba7b08d48dbcdf55c614 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Sun, 8 May 2022 18:39:39 +0200 -Subject: [PATCH 09/12] ecm_tracker_datagram: drop static for EXPORT_SYMBOL - -EXPORT_SYMBOL should NOT be static - -Signed-off-by: Ansuel Smith ---- - ecm_tracker_datagram.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/ecm_tracker_datagram.c b/ecm_tracker_datagram.c -index 9c04d73..ae14146 100644 ---- a/ecm_tracker_datagram.c -+++ b/ecm_tracker_datagram.c -@@ -203,7 +203,7 @@ static void ecm_tracker_datagram_datagram_discard(struct ecm_tracker_datagram_in - * ecm_tracker_datagram_discard_all() - * Discard all tracked data - */ --static void ecm_tracker_datagram_discard_all(struct ecm_tracker_datagram_internal_instance *dtii) -+void ecm_tracker_datagram_discard_all(struct ecm_tracker_datagram_internal_instance *dtii) - { - int32_t src_count; - int32_t dest_count; -@@ -364,7 +364,7 @@ static void ecm_tracker_datagram_datagram_discard_callback(struct ecm_tracker_in - * ecm_tracker_datagram_datagram_size_get() - * Return size in bytes of datagram at index i that was sent to the target - */ --static int32_t ecm_tracker_datagram_datagram_size_get(struct ecm_tracker_datagram_instance *uti, ecm_tracker_sender_type_t sender, int32_t i) -+int32_t ecm_tracker_datagram_datagram_size_get(struct ecm_tracker_datagram_instance *uti, ecm_tracker_sender_type_t sender, int32_t i) - { - struct ecm_tracker_datagram_internal_instance *dtii = (struct ecm_tracker_datagram_internal_instance *)uti; - -@@ -412,7 +412,7 @@ static int32_t ecm_tracker_datagram_datagram_size_get_callback(struct ecm_tracke - * ecm_tracker_datagram_datagram_read() - * Read size bytes from datagram at index i into the buffer - */ --static int ecm_tracker_datagram_datagram_read(struct ecm_tracker_datagram_instance *uti, ecm_tracker_sender_type_t sender, int32_t i, int32_t offset, int32_t size, void *buffer) -+int ecm_tracker_datagram_datagram_read(struct ecm_tracker_datagram_instance *uti, ecm_tracker_sender_type_t sender, int32_t i, int32_t offset, int32_t size, void *buffer) - { - struct ecm_tracker_datagram_internal_instance *dtii = (struct ecm_tracker_datagram_internal_instance *)uti; - int res; -@@ -466,7 +466,7 @@ static int ecm_tracker_datagram_datagram_read_callback(struct ecm_tracker_instan - * ecm_tracker_datagram_datagram_add() - * Append the datagram onto the tracker queue for the given target - */ --static bool ecm_tracker_datagram_datagram_add(struct ecm_tracker_datagram_instance *uti, ecm_tracker_sender_type_t sender, struct sk_buff *skb) -+bool ecm_tracker_datagram_datagram_add(struct ecm_tracker_datagram_instance *uti, ecm_tracker_sender_type_t sender, struct sk_buff *skb) - { - struct ecm_tracker_datagram_internal_instance *dtii = (struct ecm_tracker_datagram_internal_instance *)uti; - struct sk_buff *skbc; --- -2.34.1 - diff --git a/root/package/qca/nss/qca-nss-ecm-64/patches/010-frontends-drop-udp_get_timeouts-and-use-standard-ups.patch b/root/package/qca/nss/qca-nss-ecm-64/patches/010-frontends-drop-udp_get_timeouts-and-use-standard-ups.patch deleted file mode 100644 index da88eea4..00000000 --- a/root/package/qca/nss/qca-nss-ecm-64/patches/010-frontends-drop-udp_get_timeouts-and-use-standard-ups.patch +++ /dev/null @@ -1,74 +0,0 @@ -From ef638a84405c9f6556a9d7c257ccbba74efd228e Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Sat, 14 May 2022 20:15:10 +0200 -Subject: [PATCH 10/12] frontends: drop udp_get_timeouts and use standard - upstream api - -Drop udp_get_timeouts and use nf_udp_pernet and ->timeoutrs -instead or relying on a downstream api not present upstream. ---- - frontends/nss/ecm_nss_ipv4.c | 3 ++- - frontends/nss/ecm_nss_ipv6.c | 3 ++- - frontends/sfe/ecm_sfe_ipv4.c | 3 ++- - frontends/sfe/ecm_sfe_ipv6.c | 3 ++- - 4 files changed, 8 insertions(+), 4 deletions(-) - -diff --git a/frontends/nss/ecm_nss_ipv4.c b/frontends/nss/ecm_nss_ipv4.c -index 719a747..558819a 100644 ---- a/frontends/nss/ecm_nss_ipv4.c -+++ b/frontends/nss/ecm_nss_ipv4.c -@@ -607,7 +607,8 @@ sync_conntrack: - #else - timeouts = nf_ct_timeout_lookup(ct); - if (!timeouts) { -- timeouts = udp_get_timeouts(nf_ct_net(ct)); -+ struct nf_udp_net *un = nf_udp_pernet(nf_ct_net(ct)); -+ timeouts = un->timeouts; - } - - spin_lock_bh(&ct->lock); -diff --git a/frontends/nss/ecm_nss_ipv6.c b/frontends/nss/ecm_nss_ipv6.c -index 67ee364..51eb069 100644 ---- a/frontends/nss/ecm_nss_ipv6.c -+++ b/frontends/nss/ecm_nss_ipv6.c -@@ -586,7 +586,8 @@ sync_conntrack: - #else - timeouts = nf_ct_timeout_lookup(ct); - if (!timeouts) { -- timeouts = udp_get_timeouts(nf_ct_net(ct)); -+ struct nf_udp_net *un = nf_udp_pernet(nf_ct_net(ct)); -+ timeouts = un->timeouts; - } - - spin_lock_bh(&ct->lock); -diff --git a/frontends/sfe/ecm_sfe_ipv4.c b/frontends/sfe/ecm_sfe_ipv4.c -index 3f30821..931af5d 100644 ---- a/frontends/sfe/ecm_sfe_ipv4.c -+++ b/frontends/sfe/ecm_sfe_ipv4.c -@@ -527,7 +527,8 @@ sync_conntrack: - #else - timeouts = nf_ct_timeout_lookup(ct); - if (!timeouts) { -- timeouts = udp_get_timeouts(nf_ct_net(ct)); -+ struct nf_udp_net *un = nf_udp_pernet(nf_ct_net(ct)); -+ timeouts = un->timeouts; - } - - spin_lock_bh(&ct->lock); -diff --git a/frontends/sfe/ecm_sfe_ipv6.c b/frontends/sfe/ecm_sfe_ipv6.c -index 54fdbf3..63d8888 100644 ---- a/frontends/sfe/ecm_sfe_ipv6.c -+++ b/frontends/sfe/ecm_sfe_ipv6.c -@@ -516,7 +516,8 @@ sync_conntrack: - #else - timeouts = nf_ct_timeout_lookup(ct); - if (!timeouts) { -- timeouts = udp_get_timeouts(nf_ct_net(ct)); -+ struct nf_udp_net *un = nf_udp_pernet(nf_ct_net(ct)); -+ timeouts = un->timeouts; - } - - spin_lock_bh(&ct->lock); --- -2.34.1 - diff --git a/root/package/qca/nss/qca-nss-ecm-64/patches/901-qca-nss-ecm-fix-a-memcpy-overflow-in-ecm_db.patch b/root/package/qca/nss/qca-nss-ecm-64/patches/901-qca-nss-ecm-fix-a-memcpy-overflow-in-ecm_db.patch deleted file mode 100644 index 491cbedc..00000000 --- a/root/package/qca/nss/qca-nss-ecm-64/patches/901-qca-nss-ecm-fix-a-memcpy-overflow-in-ecm_db.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 1958e34c4c1b8b4fb62eba693fbd7693536947b9 Mon Sep 17 00:00:00 2001 -From: flebourse -Date: Thu, 23 Dec 2021 16:11:06 +0100 -Subject: [PATCH] qca-nss-ecm: fix a memcpy overflow in ecm_db - -Calls to ipv6_addr_prefix() trigger a memcpy overflow if the prefix len -argument is greater than 128, cap it at this value. - -stack bactrace: -detected buffer overflow in memcpy -Kernel BUG at fortify_panic+0x20/0x24 -Internal error: Oops - BUG: 0 [#1] SMP -CPU: 2 PID: 2592 Comm: netifd Not tainted 5.10.80 #0 -Hardware name: Xiaomi AX9000 (DT) -Call trace: - fortify_panic+0x20/0x24 - ecm_db_exit+0x42c/0x49c [ecm] - ecm_db_exit+0x464/0x49c [ecm] - atomic_notifier_call_chain+0x5c/0x90 - ip6_route_add+0x13c/0x1a4 - inet6_rtm_newroute+0x98/0xa0 - rtnetlink_rcv_msg+0x10c/0x34c - netlink_rcv_skb+0x5c/0x130 - rtnetlink_rcv+0x1c/0x2c - netlink_unicast+0x1ec/0x2e0 - netlink_sendmsg+0x1a4/0x394 - ____sys_sendmsg+0x270/0x2b4 - ___sys_sendmsg+0x7c/0xc0 - __sys_sendmsg+0x5c/0xb0 - __arm64_sys_sendmsg+0x28/0x34 - el0_svc_common.constprop.0+0x88/0x190 - do_el0_svc+0x74/0x94 - el0_svc+0x14/0x20 - el0_sync_handler+0xa8/0x130 - el0_sync+0x184/0x1c0 -Code: aa0003e1 912b4040 910003fd 97fff56c (d4210000) - -Signed-off-By: Francis Le Bourse ---- - ecm_db/ecm_db.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/ecm_db/ecm_db.c b/ecm_db/ecm_db.c -index c6f408d..df04afd 100644 ---- a/ecm_db/ecm_db.c -+++ b/ecm_db/ecm_db.c -@@ -298,7 +298,7 @@ static int ecm_db_ipv6_route_table_update_event(struct notifier_block *nb, - * Compute ECM connection's prefix destination address by masking it with the - * route config's destination address prefix length. - */ -- ipv6_addr_prefix(&prefix_addr, &ecm_in6, cfg->fc_dst_len); -+ ipv6_addr_prefix(&prefix_addr, &ecm_in6, min(128, cfg->fc_dst_len)); - - DEBUG_TRACE("dest addr prefix: %pI6 prefix_len: %d ecm_in6: %pI6\n", &prefix_addr, cfg->fc_dst_len, &ecm_in6); - -@@ -326,7 +326,7 @@ static int ecm_db_ipv6_route_table_update_event(struct notifier_block *nb, - * Compute ECM connection's prefix source address by masking it with the - * route config's destination address prefix length. - */ -- ipv6_addr_prefix(&prefix_addr, &ecm_in6, cfg->fc_dst_len); -+ ipv6_addr_prefix(&prefix_addr, &ecm_in6, min(128, cfg->fc_dst_len)); - - DEBUG_TRACE("src addr prefix: %pI6 prefix_len: %d ecm_in6: %pI6\n", &prefix_addr, cfg->fc_dst_len, &ecm_in6); - --- -2.1.4 - diff --git a/root/package/qca/nss/qca-nss-ecm/Makefile b/root/package/qca/nss/qca-nss-ecm/Makefile deleted file mode 100644 index 0053ff12..00000000 --- a/root/package/qca/nss/qca-nss-ecm/Makefile +++ /dev/null @@ -1,278 +0,0 @@ -include $(TOPDIR)/rules.mk -include $(INCLUDE_DIR)/kernel.mk - -PKG_NAME:=qca-nss-ecm -PKG_RELEASE:=1 - -PKG_SOURCE_URL:=https://source.codeaurora.org/quic/qsdk/oss/lklm/qca-nss-ecm -PKG_SOURCE_PROTO:=git -PKG_SOURCE_VERSION:=9228212b4238c0d8c296f795948ede8f2ca0242e -PKG_MIRROR_HASH:=02fe4c86c8c88fb15704b1b253ab756a2658f24ce5db64a7909cb60bf9c1cdff - -LOCAL_VARIANT=$(patsubst qca-nss-ecm-%,%,$(patsubst qca-nss-ecm-%,%,$(BUILD_VARIANT))) -include $(INCLUDE_DIR)/package.mk - -ifeq ($(CONFIG_QCA_NSS_ECM_EXAMPLES_PCC),y) - FILES_EXAMPLES=$(PKG_BUILD_DIR)/examples/ecm_pcc_test.ko -endif - -ifeq ($(CONFIG_QCA_NSS_ECM_EXAMPLES_MARK),y) - FILES_EXAMPLES+=$(PKG_BUILD_DIR)/examples/ecm_mark_test.ko -endif - -#Explicitly enable OVS external module, if ovsmgr is enabled. -ifneq ($(CONFIG_PACKAGE_kmod-qca-ovsmgr),) -CONFIG_QCA_NSS_ECM_OVS=y -endif - -ifeq ($(CONFIG_QCA_NSS_ECM_OVS),y) - FILES_EXAMPLES+=$(PKG_BUILD_DIR)/examples/ecm_ovs.ko -endif - -define KernelPackage/qca-nss-ecm/Default - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Support - DEPENDS:=+TARGET_ipq806x:kmod-qca-nss-drv \ - +TARGET_ipq_ipq806x:kmod-qca-nss-drv \ - +TARGET_ipq_ipq807x:kmod-qca-nss-drv \ - +TARGET_ipq_ipq807x_64:kmod-qca-nss-drv \ - +TARGET_ipq807x:kmod-qca-nss-drv \ - +TARGET_ipq807x_64:kmod-qca-nss-drv \ - +TARGET_ipq_ipq60xx:kmod-qca-nss-drv \ - +TARGET_ipq_ipq60xx_64:kmod-qca-nss-drv \ - +TARGET_ipq_ipq50xx:kmod-qca-nss-drv \ - +TARGET_ipq_ipq50xx_64:kmod-qca-nss-drv \ - +iptables-mod-extra +kmod-ipt-conntrack \ - +kmod-pppoe @LINUX_5_4 \ - +kmod-ipsec - TITLE:=QCA NSS Enhanced Connection Manager (ECM) - FILES:=$(PKG_BUILD_DIR)/*.ko $(FILES_EXAMPLES) - KCONFIG:=CONFIG_BRIDGE_NETFILTER=y \ - CONFIG_NF_CONNTRACK_EVENTS=y \ - CONFIG_NF_CONNTRACK_CHAIN_EVENTS=y \ - CONFIG_NF_CONNTRACK_DSCPREMARK_EXT=y - MENU:=1 - PROVIDES:=kmod-qca-nss-ecm -endef - -define KernelPackage/qca-nss-ecm/Description/Default -This package contains the QCA NSS Enhanced Connection Manager -endef - -define KernelPackage/qca-nss-ecm/Default/install - $(INSTALL_DIR) $(1)/etc/firewall.d $(1)/etc/init.d $(1)/usr/bin $(1)/lib/netifd/offload $(1)/etc/config $(1)/etc/uci-defaults $(1)/etc/sysctl.d - $(INSTALL_DATA) ./files/qca-nss-ecm.firewall $(1)/etc/firewall.d/qca-nss-ecm - $(INSTALL_BIN) ./files/qca-nss-ecm.init $(1)/etc/init.d/qca-nss-ecm - $(INSTALL_BIN) ./files/ecm_dump.sh $(1)/usr/bin/ - $(INSTALL_BIN) ./files/on-demand-down $(1)/lib/netifd/offload/on-demand-down - $(INSTALL_DATA) ./files/qca-nss-ecm.uci $(1)/etc/config/ecm - $(INSTALL_DATA) ./files/qca-nss-ecm.defaults $(1)/etc/uci-defaults/99-qca-nss-ecm - $(INSTALL_BIN) ./files/qca-nss-ecm.sysctl $(1)/etc/sysctl.d/qca-nss-ecm.conf -ifeq ($(CONFIG_KERNEL_IPQ_MEM_PROFILE),256) - echo 'net.netfilter.nf_conntrack_max=2048' >> $(1)/etc/sysctl.d/qca-nss-ecm.conf -endif -ifeq ($(CONFIG_KERNEL_IPQ_MEM_PROFILE),512) - echo 'net.netfilter.nf_conntrack_max=8192' >> $(1)/etc/sysctl.d/qca-nss-ecm.conf -endif -endef - -define KernelPackage/qca-nss-ecm-standard - $(call KernelPackage/qca-nss-ecm/Default) - VARIANT:=standard - DEPENDS+=+PACKAGE_kmod-qca-mcs:kmod-qca-mcs -endef - -define KernelPackage/qca-nss-ecm-standard/Description - $(call KernelPackage/qca-nss-ecm/Description/Default) -endef - -define KernelPackage/qca-nss-ecm-standard/install -$(call KernelPackage/qca-nss-ecm/Default/install, $(1)) -endef - -# Variant with additional features enabled for premium profile -define KernelPackage/qca-nss-ecm-premium/Default -$(call KernelPackage/qca-nss-ecm/Default) - TITLE+= (with premium features) - VARIANT:=premium - DEPENDS+=+kmod-nat46 \ - +kmod-l2tp +kmod-pppol2tp +kmod-pptp \ - +kmod-bonding -endef - -define KernelPackage/qca-nss-ecm-premium/Description/Default -$(call KernelPackage/qca-nss-ecm/Description/Default) -with the premium features enabled -endef - -define KernelPackage/qca-nss-ecm-premium/Default/install -$(call KernelPackage/qca-nss-ecm/install) -endef - -define KernelPackage/qca-nss-ecm-premium -$(call KernelPackage/qca-nss-ecm-premium/Default) -endef - -define KernelPackage/qca-nss-ecm-premium/Description -$(call KernelPackage/qca-nss-ecm-premium/Description/Default) -endef - -define KernelPackage/qca-nss-ecm-premium/install -$(call KernelPackage/qca-nss-ecm-standard/install, $(1)) -endef - -# Variant with additional features enabled for noload profile -define KernelPackage/qca-nss-ecm-noload - $(call KernelPackage/qca-nss-ecm/Default) - TITLE+= (with noload features) - PROVIDES:=kmod-qca-nss-ecm - VARIANT:=noload - DEPENDS+=+kmod-l2tp +kmod-pppol2tp +kmod-pptp \ - +kmod-bonding -endef - -define KernelPackage/qca-nss-ecm-noload/Description - $(call KernelPackage/qca-nss-ecm/Description/Default) - When selected, this package installs the driver but does not load it at init. -endef - -define KernelPackage/qca-nss-ecm-noload/install -$(call KernelPackage/qca-nss-ecm/Default/install, $(1)) - # - # Remove the START line from the init script, so that the symlink - # in the /etc/rc.d directory is not created. - # - sed -i '/START=/d' $(1)/etc/init.d/qca-nss-ecm -endef - -define KernelPackage/qca-nss-ecm-premium-noload - $(call KernelPackage/qca-nss-ecm-premium/Default) - PROVIDES:=kmod-qca-nss-ecm-premium -endef - -define KernelPackage/qca-nss-ecm-premium-noload/Description - $(call KernelPackage/qca-nss-ecm-premium/Description/Default) - When selected, this package installs the driver but does not load it at init. -endef - -define KernelPackage/qca-nss-ecm-premium-noload/install -$(call KernelPackage/qca-nss-ecm-premium/Default/install, $(1)) -endef - -define Build/InstallDev/qca-nss-ecm - $(INSTALL_DIR) $(1)/usr/include/qca-nss-ecm - $(CP) $(PKG_BUILD_DIR)/exports/* $(1)/usr/include/qca-nss-ecm/ -endef - -define Build/InstallDev - $(call Build/InstallDev/qca-nss-ecm,$(1)) -endef - -EXTRA_CFLAGS+= \ - -I$(STAGING_DIR)/usr/include/hyfibr \ - -I$(STAGING_DIR)/usr/include/qca-mcs \ - -I$(STAGING_DIR)/usr/include/qca-nss-drv \ - -I$(STAGING_DIR)/usr/include/shortcut-fe \ - -I$(STAGING_DIR)/usr/include/nat46 - -ECM_MAKE_OPTS:=ECM_CLASSIFIER_HYFI_ENABLE=y -ifneq ($(LOCAL_VARIANT),standard) -ECM_MAKE_OPTS+=ECM_MULTICAST_ENABLE=y \ - ECM_INTERFACE_IPSEC_ENABLE=y \ - # ECM_INTERFACE_PPTP_ENABLE=y \ - ECM_INTERFACE_L2TPV2_ENABLE=y \ - ECM_INTERFACE_GRE_TAP_ENABLE=y \ - ECM_INTERFACE_GRE_TUN_ENABLE=y \ - ECM_INTERFACE_SIT_ENABLE=y \ - ECM_INTERFACE_TUNIPIP6_ENABLE=y \ - ECM_INTERFACE_RAWIP_ENABLE=y - -ifeq ($(CONFIG_TARGET_ipq_ipq40xx)$(CONFIG_TARGET_ipq40xx),) -ECM_MAKE_OPTS+=ECM_INTERFACE_BOND_ENABLE=y -endif -endif - -ifeq ($(filter $(CONFIG_KERNEL_IPQ_MEM_PROFILE), 256),) -ECM_MAKE_OPTS+=ECM_XFRM_ENABLE=y -endif - -# ifneq ($(CONFIG_PACKAGE_kmod-nat46),) -# ECM_MAKE_OPTS+=ECM_INTERFACE_MAP_T_ENABLE=y -# endif - -ifneq ($(CONFIG_PACKAGE_kmod-qca-mcs),) -ECM_MAKE_OPTS+=ECM_MULTICAST_ENABLE=y -endif - -ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-ovpn-link),) -ECM_MAKE_OPTS+=ECM_INTERFACE_OVPN_ENABLE=y -endif - -ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-drv-vxlanmgr),) -ECM_MAKE_OPTS+=ECM_INTERFACE_VXLAN_ENABLE=y -endif - -ifneq ($(CONFIG_PACKAGE_kmod-qca-ovsmgr),) -ECM_MAKE_OPTS+=ECM_INTERFACE_OVS_BRIDGE_ENABLE=y \ - ECM_CLASSIFIER_OVS_ENABLE=y -EXTRA_CFLAGS+= -I$(STAGING_DIR)/usr/include/qca-ovsmgr -endif - -# Keeping default as ipq806x for branches that does not have subtarget framework -ifeq ($(CONFIG_TARGET_ipq),y) -subtarget:=$(SUBTARGET) -else -subtarget:=$(CONFIG_TARGET_BOARD) -endif - -define Build/InstallDev - $(INSTALL_DIR) $(1)/usr/include/qca-nss-ecm - $(CP) $(PKG_BUILD_DIR)/exports/* $(1)/usr/include/qca-nss-ecm -endef - -define Build/Compile - $(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" $(strip $(ECM_MAKE_OPTS)) \ - $(KERNEL_MAKE_FLAGS) \ - $(PKG_MAKE_FLAGS) \ - M="$(PKG_BUILD_DIR)" \ - EXTRA_CFLAGS="$(EXTRA_CFLAGS)" SoC="$(subtarget)" \ - EXAMPLES_BUILD_PCC="$(CONFIG_QCA_NSS_ECM_EXAMPLES_PCC)" \ - EXAMPLES_BUILD_MARK="$(CONFIG_QCA_NSS_ECM_EXAMPLES_MARK)" \ - EXAMPLES_BUILD_OVS="$(CONFIG_QCA_NSS_ECM_OVS)" \ - ECM_FRONT_END_SFE_ENABLE="$(CONFIG_QCA_ECM_SFE_SUPPORT)" \ - modules -endef - -define KernelPackage/qca-nss-ecm-premium/config -menu "ECM Configuration" - depends on PACKAGE_kmod_qca-nss-ecm-premium - - config QCA_NSS_ECM_EXAMPLES_PCC - bool "Build PCC usage example" - help - Selecting this will build the PCC classifier usage example module. - default n - - config QCA_NSS_ECM_EXAMPLES_MARK - bool "Build Mark classifier usage example" - help - Selecting this will build the Mark classifier usage example module. - default n - - config QCA_NSS_ECM_OVS - bool "Build OVS classifier external module" - help - Selecting this will build the OVS classifier external module. - default n - - config QCA_ECM_SFE_SUPPORT - bool "Add SFE support to ECM driver" - default n -endmenu -endef - -$(eval $(call KernelPackage,qca-nss-ecm-noload)) -$(eval $(call KernelPackage,qca-nss-ecm-standard)) -$(eval $(call KernelPackage,qca-nss-ecm-premium-noload)) -$(eval $(call KernelPackage,qca-nss-ecm-premium)) diff --git a/root/package/qca/nss/qca-nss-ecm/files/ecm_dump.sh b/root/package/qca/nss/qca-nss-ecm/files/ecm_dump.sh deleted file mode 100644 index dbf7de75..00000000 --- a/root/package/qca/nss/qca-nss-ecm/files/ecm_dump.sh +++ /dev/null @@ -1,95 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -ECM_MODULE=${1:-ecm_state} -MOUNT_ROOT=/dev/ecm - -# -# usage: ecm_dump.sh [module=ecm_db] -# -# with no parameters, ecm_dump.sh will attempt to mount the -# ecm_db state file and cat its contents. -# -# example with a parameter: ecm_dump.sh ecm_classifier_default -# -# this will cause ecm_dump to attempt to find and mount the state -# file for the ecm_classifier_default module, and if successful -# cat the contents. -# - -# this is one of the state files, which happens to be the -# last module started in ecm -ECM_STATE=/sys/kernel/debug/ecm/ecm_state/state_dev_major - -# tests to see if ECM is up and ready to receive commands. -# returns 0 if ECM is fully up and ready, else 1 -ecm_is_ready() { - if [ ! -e "${ECM_STATE}" ] - then - return 1 - fi - return 0 -} - -# -# module_state_mount(module_name) -# Mounts the state file of the module, if supported -# -module_state_mount() { - local module_name=$1 - local mount_dir=$2 - local state_file="/sys/kernel/debug/ecm/${module_name}/state_dev_major" - - if [ -e "${mount_dir}/${module_name}" ] - then - # already mounted - return 0 - fi - - #echo "Mount state file for $module_name ..." - if [ ! -e "$state_file" ] - then - #echo "... $module_name does not support state" - return 1 - fi - - local major="`cat $state_file`" - #echo "... Mounting state $state_file with major: $major" - mknod "${mount_dir}/${module_name}" c $major 0 -} - -# -# main -# -ecm_is_ready || { - #echo "ECM is not running" - exit 1 -} - -# all state files are mounted under MOUNT_ROOT, so make sure it exists -mkdir -p ${MOUNT_ROOT} - -# -# attempt to mount state files for the requested module and cat it -# if the mount succeeded -# -module_state_mount ${ECM_MODULE} ${MOUNT_ROOT} && { - cat ${MOUNT_ROOT}/${ECM_MODULE} - exit 0 -} - -exit 2 diff --git a/root/package/qca/nss/qca-nss-ecm/files/on-demand-down b/root/package/qca/nss/qca-nss-ecm/files/on-demand-down deleted file mode 100644 index 02d708e0..00000000 --- a/root/package/qca/nss/qca-nss-ecm/files/on-demand-down +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -# Copyright (c) 2016 The Linux Foundation. All rights reserved. - -[ -e "/sys/kernel/debug/ecm/ecm_db/defunct_all" ] && { - echo 1 > /sys/kernel/debug/ecm/ecm_db/defunct_all -} diff --git a/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.defaults b/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.defaults deleted file mode 100644 index 308e265c..00000000 --- a/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.defaults +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -uci -q batch << EOF - delete firewall.qcanssecm - set firewall.qcanssecm=include - set firewall.qcanssecm.type=script - set firewall.qcanssecm.path=/etc/firewall.d/qca-nss-ecm - set firewall.qcanssecm.family=any - set firewall.qcanssecm.reload=1 - commit firewall -EOF - -exit 0 diff --git a/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.firewall b/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.firewall deleted file mode 100644 index 24c64def..00000000 --- a/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.firewall +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -iptables -A FORWARD -m physdev --physdev-is-bridged -j ACCEPT diff --git a/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.init b/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.init deleted file mode 100644 index 0d58c359..00000000 --- a/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.init +++ /dev/null @@ -1,133 +0,0 @@ -#!/bin/sh /etc/rc.common -# -# Copyright (c) 2014, 2019 The Linux Foundation. All rights reserved. -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -# The shebang above has an extra space intentially to avoid having -# openwrt build scripts automatically enable this package starting -# at boot. - -START=19 - -get_front_end_mode() { - config_load "ecm" - config_get front_end global acceleration_engine "auto" - - case $front_end in - auto) - echo '0' - ;; - nss) - echo '1' - ;; - sfe) - echo '2' - ;; - *) - echo 'uci_option_acceleration_engine is invalid' - esac -} - -support_bridge() { - #NSS support bridge acceleration - [ -d /sys/kernel/debug/ecm/ecm_nss_ipv4 ] && return 0 - #SFE doesn't support bridge acceleration - [ -d /sys/kernel/debug/ecm/ecm_sfe_ipv4 ] && return 1 -} - -load_sfe() { - local kernel_version=$(uname -r) - - [ -e "/lib/modules/$kernel_version/shortcut-fe.ko" ] && { - [ -d /sys/module/shortcut_fe ] || insmod shortcut-fe - } - - [ -e "/lib/modules/$kernel_version/shortcut-fe-ipv6.ko" ] && { - [ -d /sys/module/shortcut_fe_ipv6 ] || insmod shortcut-fe-ipv6 - } - - [ -e "/lib/modules/$kernel_version/shortcut-fe-cm.ko" ] && { - [ -d /sys/module/shortcut_fe_cm ] || insmod shortcut-fe-cm - } - - [ -e "/lib/modules/$kernel_version/shortcut-fe-drv.ko" ] && { - [ -d /sys/module/shortcut_fe_drv ] || insmod shortcut-fe-drv - } - -} - -load_ecm() { - [ -d /sys/module/ecm ] || { - [ ! -e /proc/device-tree/MP_256 ] && load_sfe - insmod ecm front_end_selection=$(get_front_end_mode) - } - - support_bridge && { - sysctl -w net.bridge.bridge-nf-call-ip6tables=1 - sysctl -w net.bridge.bridge-nf-call-iptables=1 - } -} - -unload_ecm() { - sysctl -w net.bridge.bridge-nf-call-ip6tables=0 - sysctl -w net.bridge.bridge-nf-call-iptables=0 - - if [ -d /sys/module/ecm ]; then - # - # Stop ECM frontends - # - echo 1 > /sys/kernel/debug/ecm/front_end_ipv4_stop - echo 1 > /sys/kernel/debug/ecm/front_end_ipv6_stop - - # - # Defunct the connections - # - echo 1 > /sys/kernel/debug/ecm/ecm_db/defunct_all - sleep 5; - - rmmod ecm - sleep 1 - fi -} - -start() { - load_ecm - - # If the acceleration engine is NSS, enable wifi redirect. - [ -d /sys/kernel/debug/ecm/ecm_nss_ipv4 ] && sysctl -w dev.nss.general.redirect=1 - - support_bridge && { - echo 'net.bridge.bridge-nf-call-ip6tables=1' >> /etc/sysctl.d/qca-nss-ecm.conf - echo 'net.bridge.bridge-nf-call-iptables=1' >> /etc/sysctl.d/qca-nss-ecm.conf - } - - if [ -d /sys/module/qca_ovsmgr ]; then - insmod ecm_ovs - fi - -} - -stop() { - # If the acceleration engine is NSS, disable wifi redirect. - [ -d /sys/kernel/debug/ecm/ecm_nss_ipv4 ] && sysctl -w dev.nss.general.redirect=0 - - sed '/net.bridge.bridge-nf-call-ip6tables=1/d' -i /etc/sysctl.d/qca-nss-ecm.conf - sed '/net.bridge.bridge-nf-call-iptables=1/d' -i /etc/sysctl.d/qca-nss-ecm.conf - - if [ -d /sys/module/ecm_ovs ]; then - rmmod ecm_ovs - fi - - unload_ecm -} diff --git a/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.sysctl b/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.sysctl deleted file mode 100644 index 1a3d76b1..00000000 --- a/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.sysctl +++ /dev/null @@ -1,2 +0,0 @@ -# nf_conntrack_tcp_no_window_check is 0 by default, set it to 1 -net.netfilter.nf_conntrack_tcp_no_window_check=1 diff --git a/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.uci b/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.uci deleted file mode 100644 index 4f2de687..00000000 --- a/root/package/qca/nss/qca-nss-ecm/files/qca-nss-ecm.uci +++ /dev/null @@ -1,2 +0,0 @@ -config ecm 'global' - option acceleration_engine 'auto' diff --git a/root/package/qca/nss/qca-nss-ecm/patches/001-Drop_SFE_from_ecm.patch b/root/package/qca/nss/qca-nss-ecm/patches/001-Drop_SFE_from_ecm.patch deleted file mode 100644 index b1cd2b7b..00000000 --- a/root/package/qca/nss/qca-nss-ecm/patches/001-Drop_SFE_from_ecm.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- a/Makefile -+++ b/Makefile -@@ -66,8 +66,7 @@ endif - # Define ECM_FRONT_END_SFE_ENABLE=y in order to select - # sfe as ECM's front end. - # ############################################################################# --ifeq ($(SoC),$(filter $(SoC),ipq806x ipq40xx)) --ECM_FRONT_END_SFE_ENABLE=y -+ifeq ($(ECM_FRONT_END_SFE_ENABLE), y) - ecm-$(ECM_FRONT_END_SFE_ENABLE) += frontends/sfe/ecm_sfe_ipv4.o - ecm-$(ECM_FRONT_END_SFE_ENABLE) += frontends/sfe/ecm_sfe_ported_ipv4.o - ccflags-$(ECM_FRONT_END_SFE_ENABLE) += -DECM_FRONT_END_SFE_ENABLE diff --git a/root/package/qca/nss/qca-nss-ecm/patches/100-kernel-5.4-support.patch b/root/package/qca/nss/qca-nss-ecm/patches/100-kernel-5.4-support.patch deleted file mode 100644 index b863ad7e..00000000 --- a/root/package/qca/nss/qca-nss-ecm/patches/100-kernel-5.4-support.patch +++ /dev/null @@ -1,1276 +0,0 @@ ---- a/ecm_classifier_default.c -+++ b/ecm_classifier_default.c -@@ -42,7 +42,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/ecm_classifier_dscp.c -+++ b/ecm_classifier_dscp.c -@@ -41,7 +41,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/ecm_classifier_hyfi.c -+++ b/ecm_classifier_hyfi.c -@@ -41,7 +41,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/ecm_classifier_nl.c -+++ b/ecm_classifier_nl.c -@@ -41,7 +41,6 @@ - #include - #include - #include --#include - #if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 2, 0)) - #include - #else -@@ -146,12 +145,42 @@ static struct genl_multicast_group ecm_c - }, - }; - -+static int ecm_classifier_nl_genl_msg_ACCEL(struct sk_buff *skb, struct genl_info *info); -+static int ecm_classifier_nl_genl_msg_DUMP(struct sk_buff *skb, struct netlink_callback *cb); -+ -+/* -+ * Generic Netlink message-to-handler mapping -+ */ -+static struct genl_ops ecm_cl_nl_genl_ops[] = { -+ { -+ .cmd = ECM_CL_NL_GENL_CMD_ACCEL, -+ .flags = 0, -+ .doit = ecm_classifier_nl_genl_msg_ACCEL, -+ .dumpit = NULL, -+ }, -+ { -+ .cmd = ECM_CL_NL_GENL_CMD_ACCEL_OK, -+ .flags = 0, -+ .doit = NULL, -+ .dumpit = ecm_classifier_nl_genl_msg_DUMP, -+ }, -+ { -+ .cmd = ECM_CL_NL_GENL_CMD_CONNECTION_CLOSED, -+ .flags = 0, -+ .doit = NULL, -+ .dumpit = ecm_classifier_nl_genl_msg_DUMP, -+ }, -+}; -+ - static struct genl_family ecm_cl_nl_genl_family = { -- .id = GENL_ID_GENERATE, - .hdrsize = 0, - .name = ECM_CL_NL_GENL_NAME, - .version = ECM_CL_NL_GENL_VERSION, - .maxattr = ECM_CL_NL_GENL_ATTR_MAX, -+ .ops = ecm_cl_nl_genl_ops, -+ .n_ops = ARRAY_SIZE(ecm_cl_nl_genl_ops), -+ .mcgrps = ecm_cl_nl_genl_mcgrp, -+ .n_mcgrps = ARRAY_SIZE(ecm_cl_nl_genl_mcgrp), - }; - - /* -@@ -215,12 +244,7 @@ ecm_classifier_nl_send_genl_msg(enum ECM - return ret; - } - -- ret = genlmsg_end(skb, msg_head); -- if (ret < 0) { -- DEBUG_WARN("failed to finalize genl msg: %d\n", ret); -- nlmsg_free(skb); -- return ret; -- } -+ genlmsg_end(skb, msg_head); - - /* genlmsg_multicast frees the skb in both success and error cases */ - #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) -@@ -1377,85 +1401,14 @@ static struct file_operations ecm_classi - .write = ecm_classifier_nl_set_command, - }; - --/* -- * Generic Netlink attr checking policies -- */ --static struct nla_policy --ecm_cl_nl_genl_policy[ECM_CL_NL_GENL_ATTR_COUNT] = { -- [ECM_CL_NL_GENL_ATTR_TUPLE] = { -- .type = NLA_UNSPEC, -- .len = sizeof(struct ecm_cl_nl_genl_attr_tuple), }, --}; -- --/* -- * Generic Netlink message-to-handler mapping -- */ --static struct genl_ops ecm_cl_nl_genl_ops[] = { -- { -- .cmd = ECM_CL_NL_GENL_CMD_ACCEL, -- .flags = 0, -- .policy = ecm_cl_nl_genl_policy, -- .doit = ecm_classifier_nl_genl_msg_ACCEL, -- .dumpit = NULL, -- }, -- { -- .cmd = ECM_CL_NL_GENL_CMD_ACCEL_OK, -- .flags = 0, -- .policy = ecm_cl_nl_genl_policy, -- .doit = NULL, -- .dumpit = ecm_classifier_nl_genl_msg_DUMP, -- }, -- { -- .cmd = ECM_CL_NL_GENL_CMD_CONNECTION_CLOSED, -- .flags = 0, -- .policy = ecm_cl_nl_genl_policy, -- .doit = NULL, -- .dumpit = ecm_classifier_nl_genl_msg_DUMP, -- }, --}; -- - static int ecm_classifier_nl_register_genl(void) - { - int result; - --#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) -- result = genl_register_family_with_ops_groups(&ecm_cl_nl_genl_family, -- ecm_cl_nl_genl_ops, -- ecm_cl_nl_genl_mcgrp); -- if (result != 0) { -- DEBUG_ERROR("failed to register genl ops: %d\n", result); -- return result; -- } --#else - result = genl_register_family(&ecm_cl_nl_genl_family); -- if (result != 0) { -+ if (result != 0) - DEBUG_ERROR("failed to register genl family: %d\n", result); -- goto err1; -- } -- -- result = genl_register_ops(&ecm_cl_nl_genl_family, -- ecm_cl_nl_genl_ops); -- if (result != 0) { -- DEBUG_ERROR("failed to register genl ops: %d\n", result); -- goto err2; -- } -- -- result = genl_register_mc_group(&ecm_cl_nl_genl_family, -- ecm_cl_nl_genl_mcgrp); -- if (result != 0) { -- DEBUG_ERROR("failed to register genl multicast group: %d\n", -- result); -- goto err3; -- } -- -- return 0; - --err3: -- genl_unregister_ops(&ecm_cl_nl_genl_family, ecm_cl_nl_genl_ops); --err2: -- genl_unregister_family(&ecm_cl_nl_genl_family); --err1: --#endif - return result; - } - ---- a/ecm_classifier_pcc.c -+++ b/ecm_classifier_pcc.c -@@ -49,7 +49,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/ecm_conntrack_notifier.c -+++ b/ecm_conntrack_notifier.c -@@ -51,7 +51,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -345,14 +344,6 @@ static int ecm_conntrack_event(unsigned - return NOTIFY_DONE; - } - -- /* -- * Special untracked connection is not monitored -- */ -- if (ct == &nf_conntrack_untracked) { -- DEBUG_TRACE("Fake connection event - ignoring\n"); -- return NOTIFY_DONE; -- } -- - /* - * Only interested if this is IPv4 or IPv6. - */ ---- a/ecm_db/ecm_db.c -+++ b/ecm_db/ecm_db.c -@@ -42,7 +42,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/ecm_db/ecm_db_connection.c -+++ b/ecm_db/ecm_db_connection.c -@@ -41,7 +41,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/ecm_db/ecm_db_host.c -+++ b/ecm_db/ecm_db_host.c -@@ -41,7 +41,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/ecm_db/ecm_db_iface.c -+++ b/ecm_db/ecm_db_iface.c -@@ -41,7 +41,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/ecm_db/ecm_db_listener.c -+++ b/ecm_db/ecm_db_listener.c -@@ -41,7 +41,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/ecm_db/ecm_db_mapping.c -+++ b/ecm_db/ecm_db_mapping.c -@@ -41,7 +41,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/ecm_db/ecm_db_multicast.c -+++ b/ecm_db/ecm_db_multicast.c -@@ -42,7 +42,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/ecm_db/ecm_db_node.c -+++ b/ecm_db/ecm_db_node.c -@@ -41,7 +41,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/ecm_db/ecm_db_timer.c -+++ b/ecm_db/ecm_db_timer.c -@@ -42,7 +42,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -387,7 +386,7 @@ EXPORT_SYMBOL(ecm_db_time_get); - * Manage expiration of connections - * NOTE: This is softirq context - */ --static void ecm_db_timer_callback(unsigned long data) -+static void ecm_db_timer_callback(struct timer_list *arg) - { - uint32_t timer; - -@@ -425,9 +424,7 @@ void ecm_db_timer_init(void) - /* - * Set a timer to manage cleanup of expired connections - */ -- init_timer(&ecm_db_timer); -- ecm_db_timer.function = ecm_db_timer_callback; -- ecm_db_timer.data = 0; -+ timer_setup(&ecm_db_timer, ecm_db_timer_callback, 0); - ecm_db_timer.expires = jiffies + HZ; - add_timer(&ecm_db_timer); - ---- a/ecm_interface.c -+++ b/ecm_interface.c -@@ -66,7 +66,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -537,7 +536,7 @@ static bool ecm_interface_find_gateway_ipv4(ip_addr_t addr, ip_addr_t gw_addr) - return false; - } - -- ECM_NIN4_ADDR_TO_IP_ADDR(gw_addr, rt->rt_gateway) -+ ECM_NIN4_ADDR_TO_IP_ADDR(gw_addr, rt->rt_gw4) - ecm_interface_route_release(&ecm_rt); - return true; - } -@@ -596,7 +595,7 @@ static bool ecm_interface_mac_addr_get_ipv4(ip_addr_t addr, uint8_t *mac_addr, b - if (rt->rt_uses_gateway || (rt->rt_flags & RTF_GATEWAY)) { - #endif - *on_link = false; -- ECM_NIN4_ADDR_TO_IP_ADDR(gw_addr, rt->rt_gateway) -+ ECM_NIN4_ADDR_TO_IP_ADDR(gw_addr, rt->rt_gw4) - } else { - *on_link = true; - } -@@ -1003,7 +1002,7 @@ static bool ecm_interface_find_route_by_addr_ipv6(ip_addr_t addr, struct ecm_int - * Get a route to the given IP address, this will allow us to also find the interface - * it is using to communicate with that IP address. - */ -- ecm_rt->rt.rtv6 = rt6_lookup(&init_net, &naddr, NULL, 0, 0); -+ ecm_rt->rt.rtv6 = rt6_lookup(&init_net, &naddr, NULL, 0, NULL, 0); - if (!ecm_rt->rt.rtv6) { - DEBUG_TRACE("No output route to: " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(addr)); - return NULL; -@@ -1077,7 +1076,7 @@ void ecm_interface_send_neighbour_solicitation(struct net_device *dev, ip_addr_t - /* - * Find the route entry - */ -- rt6i = rt6_lookup(netf, &dst_addr, NULL, 0, 0); -+ rt6i = rt6_lookup(netf, &dst_addr, NULL, 0, NULL, 0); - if (!rt6i) { - DEBUG_TRACE("IPv6 Route lookup failure for destination IPv6 address " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(addr)); - return; -@@ -1104,7 +1103,7 @@ void ecm_interface_send_neighbour_solicitation(struct net_device *dev, ip_addr_t - #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)) - ndisc_send_ns(dev, neigh, &dst_addr, &mc_dst_addr, &src_addr); - #else -- ndisc_send_ns(dev, &dst_addr, &mc_dst_addr, &src_addr); -+ ndisc_send_ns(dev, &dst_addr, &mc_dst_addr, &src_addr, 0); - #endif - neigh_release(neigh); - dst_release(&rt6i->dst); -@@ -1194,7 +1193,7 @@ struct neighbour *ecm_interface_ipv6_neigh_get(ip_addr_t addr) - struct in6_addr ipv6_addr; - - ECM_IP_ADDR_TO_NIN6_ADDR(ipv6_addr, addr); -- rt = rt6_lookup(&init_net, &ipv6_addr, NULL, 0, 0); -+ rt = rt6_lookup(&init_net, &ipv6_addr, NULL, 0, NULL, 0); - if (!rt) { - return NULL; - } -@@ -1220,7 +1219,7 @@ bool ecm_interface_is_pptp(struct sk_buff *skb, const struct net_device *out) - * skip first pass of l2tp/pptp tunnel encapsulated traffic - */ - if (out->type == ARPHRD_PPP) { -- if (out->priv_flags & IFF_PPP_PPTP) { -+ if (out->priv_flags_qca_ecm & IFF_QCA_ECM_PPP_PPTP) { - return true; - } - } -@@ -1231,7 +1230,7 @@ bool ecm_interface_is_pptp(struct sk_buff *skb, const struct net_device *out) - } - - if (in->type == ARPHRD_PPP) { -- if (in->priv_flags & IFF_PPP_PPTP) { -+ if (in->priv_flags_qca_ecm & IFF_QCA_ECM_PPP_PPTP) { - dev_put(in); - return true; - } -@@ -1256,10 +1255,10 @@ bool ecm_interface_is_l2tp_packet_by_version(struct sk_buff *skb, const struct n - - switch (ver) { - case 2: -- flag = IFF_PPP_L2TPV2; -+ flag = IFF_QCA_ECM_PPP_L2TPV2; - break; - case 3: -- flag = IFF_PPP_L2TPV3; -+ flag = IFF_QCA_ECM_PPP_L2TPV3; - break; - default: - break; -@@ -1268,10 +1267,8 @@ bool ecm_interface_is_l2tp_packet_by_version(struct sk_buff *skb, const struct n - /* - * skip first pass of l2tp/pptp tunnel encapsulated traffic - */ -- if (out->type == ARPHRD_PPP) { -- if (out->priv_flags & flag) { -- return true; -- } -+ if (out->priv_flags_qca_ecm & flag) { -+ return true; - } - - in = dev_get_by_index(&init_net, skb->skb_iif); -@@ -1279,11 +1276,9 @@ bool ecm_interface_is_l2tp_packet_by_version(struct sk_buff *skb, const struct n - return true; - } - -- if (in->type == ARPHRD_PPP) { -- if (in->priv_flags & flag) { -- dev_put(in); -- return true; -- } -+ if (out->priv_flags_qca_ecm & flag) { -+ dev_put(in); -+ return true; - } - - dev_put(in); -@@ -1304,11 +1299,9 @@ bool ecm_interface_is_l2tp_pptp(struct sk_buff *skb, const struct net_device *ou - /* - * skip first pass of l2tp/pptp tunnel encapsulated traffic - */ -- if (out->type == ARPHRD_PPP) { -- if (out->priv_flags & (IFF_PPP_L2TPV2 | IFF_PPP_L2TPV3 | -- IFF_PPP_PPTP)) { -- return true; -- } -+ if (out->priv_flags_qca_ecm & (IFF_QCA_ECM_PPP_L2TPV2 | IFF_QCA_ECM_PPP_L2TPV3 | -+ IFF_QCA_ECM_PPP_PPTP)) { -+ return true; - } - - in = dev_get_by_index(&init_net, skb->skb_iif); -@@ -1316,12 +1309,10 @@ bool ecm_interface_is_l2tp_pptp(struct sk_buff *skb, const struct net_device *ou - return true; - } - -- if (in->type == ARPHRD_PPP) { -- if (in->priv_flags & (IFF_PPP_L2TPV2 | IFF_PPP_L2TPV3 | -- IFF_PPP_PPTP)) { -- dev_put(in); -- return true; -- } -+ if (out->priv_flags_qca_ecm & (IFF_QCA_ECM_PPP_L2TPV2 | IFF_QCA_ECM_PPP_L2TPV3 | -+ IFF_QCA_ECM_PPP_PPTP)) { -+ dev_put(in); -+ return true; - } - - dev_put(in); -@@ -2416,7 +2407,7 @@ struct ecm_db_iface_instance *ecm_interface_establish_and_ref(struct ecm_front_e - /* - * GRE TAP? - */ -- if (dev->priv_flags & (IFF_GRE_V4_TAP | IFF_GRE_V6_TAP)) { -+ if (dev->priv_flags_qca_ecm & (IFF_QCA_ECM_GRE_V4_TAP | IFF_QCA_ECM_GRE_V6_TAP)) { - interface_type = feci->ae_interface_type_get(feci, dev); - ae_interface_num = feci->ae_interface_number_by_dev_type_get(dev, interface_type); - -@@ -2680,7 +2671,7 @@ identifier_update: - /* - * OVPN Tunnel? - */ -- if ((dev_type == ARPHRD_NONE) && (dev->priv_flags & IFF_TUN_TAP)) { -+ if ((dev_type == ARPHRD_NONE) && (dev->priv_flags_qca_ecm & IFF_QCA_ECM_TUN_TAP)) { - struct net_device *tun_dev = NULL; - ip_addr_t saddr, daddr; - -@@ -2746,7 +2737,7 @@ identifier_update: - * ppp_is_multilink() and ppp_hold_channels() which acquire same lock - */ - -- if ((dev->priv_flags & IFF_PPP_L2TPV2) && ppp_is_xmit_locked(dev)) { -+ if ((dev->priv_flags_qca_ecm & IFF_QCA_ECM_PPP_L2TPV2) && ppp_is_xmit_locked(dev)) { - if (skb && (skb->skb_iif == dev->ifindex)) { - struct pppol2tp_common_addr info; - -@@ -2804,7 +2795,7 @@ identifier_update: - #endif - - #ifdef ECM_INTERFACE_PPTP_ENABLE -- if ((protocol == IPPROTO_GRE) && skb && v4_hdr && (dev->priv_flags & IFF_PPP_PPTP)) { -+ if ((protocol == IPPROTO_GRE) && skb && v4_hdr && (dev->priv_flags_qca_ecm & IFF_QCA_ECM_PPP_PPTP)) { - struct gre_hdr_pptp *gre_hdr; - uint16_t proto; - int ret; -@@ -3972,7 +3963,7 @@ int32_t ecm_interface_heirarchy_construct(struct ecm_front_end_connection_instan - if (((ip_version == 4) && (protocol == IPPROTO_IPV6)) || - ((ip_version == 6) && (protocol == IPPROTO_IPIP)) || - (protocol == IPPROTO_GRE) || -- ((given_dest_dev->type == ARPHRD_NONE) && (given_dest_dev->priv_flags & IFF_TUN_TAP))) { -+ ((given_dest_dev->type == ARPHRD_NONE) && (given_dest_dev->priv_flags_qca_ecm & IFF_QCA_ECM_TUN_TAP))) { - dev_put(dest_dev); - dest_dev = given_dest_dev; - if (dest_dev) { -@@ -3991,7 +3982,7 @@ int32_t ecm_interface_heirarchy_construct(struct ecm_front_end_connection_instan - /* - * if the address is a local address and indev=l2tp. - */ -- if ((given_src_dev->type == ARPHRD_PPP) && (given_src_dev->priv_flags & IFF_PPP_L2TPV2) && ppp_is_xmit_locked(given_src_dev)) { -+ if ((given_src_dev->type == ARPHRD_PPP) && (given_src_dev->priv_flags_qca_ecm & IFF_QCA_ECM_PPP_L2TPV2) && ppp_is_xmit_locked(given_src_dev)) { - dev_put(dest_dev); - dest_dev = given_dest_dev; - if (dest_dev) { -@@ -4005,7 +3996,7 @@ int32_t ecm_interface_heirarchy_construct(struct ecm_front_end_connection_instan - /* - * if the address is a local address and indev=PPTP. - */ -- if (protocol == IPPROTO_GRE && given_dest_dev && (given_dest_dev->priv_flags & IFF_PPP_PPTP)){ -+ if (protocol == IPPROTO_GRE && given_dest_dev && (given_dest_dev->priv_flags_qca_ecm & IFF_QCA_ECM_PPP_PPTP)){ - dev_put(dest_dev); - dest_dev = given_dest_dev; - if (dest_dev) { -@@ -4054,7 +4045,7 @@ int32_t ecm_interface_heirarchy_construct(struct ecm_front_end_connection_instan - if (((ip_version == 4) && (protocol == IPPROTO_IPV6)) || - ((ip_version == 6) && (protocol == IPPROTO_IPIP)) || - (protocol == IPPROTO_GRE) || -- ((given_src_dev->type == ARPHRD_NONE) && (given_src_dev->priv_flags & IFF_TUN_TAP))) { -+ ((given_src_dev->type == ARPHRD_NONE) && (given_src_dev->priv_flags_qca_ecm & IFF_QCA_ECM_TUN_TAP))) { - dev_put(src_dev); - src_dev = given_src_dev; - if (src_dev) { -@@ -4504,7 +4495,7 @@ lag_success: - /* - * OVPN ? - */ -- if ((dest_dev_type == ARPHRD_NONE) && (dest_dev->priv_flags & IFF_TUN_TAP)) { -+ if ((dest_dev_type == ARPHRD_NONE) && (dest_dev->priv_flags_qca_ecm & IFF_QCA_ECM_TUN_TAP)) { - DEBUG_TRACE("Net device: %p is OVPN, device name: %s\n", dest_dev, dest_dev->name); - break; - } -@@ -4523,7 +4514,7 @@ lag_success: - DEBUG_TRACE("%p: Net device: %p is PPP\n", feci, dest_dev); - - #ifdef ECM_INTERFACE_L2TPV2_ENABLE -- if ((given_src_dev->priv_flags & IFF_PPP_L2TPV2) && ppp_is_xmit_locked(given_src_dev)) { -+ if ((given_src_dev->priv_flags_qca_ecm & IFF_QCA_ECM_PPP_L2TPV2) && ppp_is_xmit_locked(given_src_dev)) { - if (skb->skb_iif == dest_dev->ifindex) { - DEBUG_TRACE("%p: Net device: %p PPP channel is PPPoL2TPV2\n", feci, dest_dev); - break; -@@ -4532,7 +4523,7 @@ lag_success: - #endif - - #ifdef ECM_INTERFACE_PPTP_ENABLE -- if (protocol == IPPROTO_GRE && dest_dev && (dest_dev->priv_flags & IFF_PPP_PPTP)) { -+ if (protocol == IPPROTO_GRE && dest_dev && (dest_dev->priv_flags_qca_ecm & IFF_QCA_ECM_PPP_PPTP)) { - DEBUG_TRACE("%p: Net device: %p PPP channel is PPTP\n", feci, dest_dev); - break; - } -@@ -4798,7 +4789,7 @@ int32_t ecm_interface_multicast_from_heirarchy_construct(struct ecm_front_end_co - /* - * if the address is a local address and indev=l2tp. - */ -- if ((given_src_dev->type == ARPHRD_PPP) && (given_src_dev->priv_flags & IFF_PPP_L2TPV2) && ppp_is_xmit_locked(given_src_dev)) { -+ if ((given_src_dev->type == ARPHRD_PPP) && (given_src_dev->priv_flags_qca_ecm & IFF_QCA_ECM_PPP_L2TPV2) && ppp_is_xmit_locked(given_src_dev)) { - dev_put(dest_dev); - dest_dev = given_dest_dev; - if (dest_dev) { -@@ -5265,7 +5256,7 @@ int32_t ecm_interface_multicast_from_heirarchy_construct(struct ecm_front_end_co - DEBUG_TRACE("Net device: %p is PPP\n", dest_dev); - - #ifdef ECM_INTERFACE_L2TPV2_ENABLE -- if ((given_src_dev->priv_flags & IFF_PPP_L2TPV2) && ppp_is_xmit_locked(given_src_dev)) { -+ if ((given_src_dev->priv_flags_qca_ecm & IFF_QCA_ECM_PPP_L2TPV2) && ppp_is_xmit_locked(given_src_dev)) { - if (skb->skb_iif == dest_dev->ifindex) { - DEBUG_TRACE("Net device: %p PPP channel is PPPoL2TPV2\n", dest_dev); - break; -@@ -6520,7 +6511,7 @@ static int ecm_interface_wifi_event_rx(struct socket *sock, struct sockaddr_nl * - #endif - oldfs = get_fs(); - set_fs(KERNEL_DS); -- size = sock_recvmsg(sock, &msg, len, msg.msg_flags); -+ size = sock_recvmsg(sock, &msg, msg.msg_flags); - set_fs(oldfs); - - return size; -@@ -6609,7 +6600,7 @@ int ecm_interface_wifi_event_stop(void) - } - - DEBUG_INFO("kill ecm_interface_wifi_event thread\n"); -- force_sig(SIGKILL, __ewn.thread); -+ send_sig(SIGKILL, __ewn.thread, 1); - err = kthread_stop(__ewn.thread); - __ewn.thread = NULL; - ---- a/ecm_tracker.c -+++ b/ecm_tracker.c -@@ -43,7 +43,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/ecm_tracker_datagram.c -+++ b/ecm_tracker_datagram.c -@@ -43,7 +43,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/ecm_tracker_tcp.c -+++ b/ecm_tracker_tcp.c -@@ -43,7 +43,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -1143,7 +1142,7 @@ static bool ecm_tracker_tcp_extract_mss( - const u8 *hash_location; - tcp_parse_options(skb, &opt_rx, &hash_location, 0); - #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) -- tcp_parse_options(skb, &opt_rx, 0, NULL); -+ tcp_parse_options(&init_net, skb, &opt_rx, 0, NULL); - #else - #error "Unsupported kernel version for tcp_parse_options()" - #endif ---- a/ecm_tracker_udp.c -+++ b/ecm_tracker_udp.c -@@ -43,7 +43,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/frontends/ecm_front_end_ipv4.c -+++ b/frontends/ecm_front_end_ipv4.c -@@ -215,7 +215,7 @@ bool ecm_front_end_ipv4_interface_constr - * behind a gateway. - */ - DEBUG_TRACE("Gateway address will be looked up overwrite the rt_dst_addr\n"); -- ECM_NIN4_ADDR_TO_IP_ADDR(rt_dst_addr, rt->rt_gateway) -+ ECM_NIN4_ADDR_TO_IP_ADDR(rt_dst_addr, rt->rt_gw4) - gateway = true; - } - ---- a/frontends/include/ecm_front_end_common.h -+++ b/frontends/include/ecm_front_end_common.h -@@ -98,13 +98,6 @@ static inline bool ecm_front_end_acceler - return false; - } - -- if (unlikely(nf_ct_is_untracked(ct))) { -- /* -- * Untracked traffic certainly can't be accelerated. -- */ -- return true; -- } -- - #if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 6, 0)) - acct = nf_conn_acct_find(ct); - #else ---- a/frontends/nss/ecm_nss_bond_notifier.c -+++ b/frontends/nss/ecm_nss_bond_notifier.c -@@ -52,7 +52,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/frontends/nss/ecm_nss_common.h -+++ b/frontends/nss/ecm_nss_common.h -@@ -144,7 +144,7 @@ static inline int32_t ecm_nss_common_get_interface_type(struct ecm_front_end_con - /* - * If device is not GRETAP then return NONE. - */ -- if (!(dev->priv_flags & (IFF_GRE_V4_TAP | IFF_GRE_V6_TAP))) { -+ if (!(dev->priv_flags_qca_ecm & (IFF_QCA_ECM_GRE_V4_TAP | IFF_QCA_ECM_GRE_V6_TAP))) { - break; - } - #endif ---- a/frontends/nss/ecm_nss_ipv4.c -+++ b/frontends/nss/ecm_nss_ipv4.c -@@ -48,7 +48,6 @@ - #include - #include - #include --#include - #if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 2, 0)) - #include - #else -@@ -1053,7 +1052,7 @@ static unsigned int ecm_nss_ipv4_ip_process(struct net_device *out_dev, struct n - * If any of the input or output interface is a GRE V4 TAP/TUN interface - * we can continue to accelerate it. - */ -- if ((in_dev->priv_flags & IFF_GRE_V4_TAP) || (out_dev->priv_flags & IFF_GRE_V4_TAP)) { -+ if ((in_dev->priv_flags_qca_ecm & IFF_QCA_ECM_GRE_V4_TAP) || (out_dev->priv_flags_qca_ecm & IFF_QCA_ECM_GRE_V4_TAP)) { - #ifndef ECM_INTERFACE_GRE_TAP_ENABLE - DEBUG_TRACE("GRE TAP acceleration is disabled\n"); - return NF_ACCEPT; -@@ -1082,7 +1081,7 @@ static unsigned int ecm_nss_ipv4_ip_process(struct net_device *out_dev, struct n - reply_tuple.dst.u3.ip = orig_tuple.src.u3.ip; - sender = ECM_TRACKER_SENDER_TYPE_SRC; - } else { -- if (unlikely(ct == &nf_conntrack_untracked)) { -+ if (unlikely(ctinfo == IP_CT_UNTRACKED)) { - DEBUG_TRACE("%p: ct: untracked\n", skb); - return NF_ACCEPT; - } -@@ -2097,7 +2096,6 @@ sync_conntrack: - } - - ct = nf_ct_tuplehash_to_ctrack(h); -- NF_CT_ASSERT(ct->timeout.data == (unsigned long)ct); - DEBUG_TRACE("%p: NSS Sync: conntrack connection\n", ct); - - ecm_front_end_flow_and_return_directions_get(ct, flow_ip, 4, &flow_dir, &return_dir); -@@ -2108,7 +2106,7 @@ sync_conntrack: - */ - if (!test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) { - spin_lock_bh(&ct->lock); -- ct->timeout.expires += delta_jiffies; -+ ct->timeout += delta_jiffies; - spin_unlock_bh(&ct->lock); - } - -@@ -2166,17 +2164,15 @@ sync_conntrack: - u_int64_t reply_pkts = atomic64_read(&acct[IP_CT_DIR_REPLY].packets); - - if (reply_pkts != 0) { -- struct nf_conntrack_l4proto *l4proto; - unsigned int *timeouts; - - set_bit(IPS_SEEN_REPLY_BIT, &ct->status); - set_bit(IPS_ASSURED_BIT, &ct->status); - -- l4proto = __nf_ct_l4proto_find(AF_INET, IPPROTO_UDP); -- timeouts = nf_ct_timeout_lookup(&init_net, ct, l4proto); -+ timeouts = nf_ct_timeout_lookup(ct); - - spin_lock_bh(&ct->lock); -- ct->timeout.expires = jiffies + timeouts[UDP_CT_REPLIED]; -+ ct->timeout = jiffies + timeouts[UDP_CT_REPLIED]; - spin_unlock_bh(&ct->lock); - } - } -@@ -2690,7 +2686,8 @@ int ecm_nss_ipv4_init(struct dentry *dentry) - /* - * Register netfilter hooks - */ -- result = nf_register_hooks(ecm_nss_ipv4_netfilter_hooks, ARRAY_SIZE(ecm_nss_ipv4_netfilter_hooks)); -+ result = nf_register_net_hooks(&init_net, ecm_nss_ipv4_netfilter_hooks, \ -+ ARRAY_SIZE(ecm_nss_ipv4_netfilter_hooks)); - if (result < 0) { - DEBUG_ERROR("Can't register netfilter hooks.\n"); - nss_ipv4_notify_unregister(); -@@ -2702,8 +2699,8 @@ int ecm_nss_ipv4_init(struct dentry *dentry) - if (result < 0) { - DEBUG_ERROR("Failed to init ecm ipv4 multicast frontend\n"); - nss_ipv4_notify_unregister(); -- nf_unregister_hooks(ecm_nss_ipv4_netfilter_hooks, -- ARRAY_SIZE(ecm_nss_ipv4_netfilter_hooks)); -+ nf_unregister_net_hooks(&init_net, ecm_nss_ipv4_netfilter_hooks, -+ ARRAY_SIZE(ecm_nss_ipv4_netfilter_hooks)); - goto task_cleanup; - } - #endif -@@ -2714,8 +2711,8 @@ int ecm_nss_ipv4_init(struct dentry *dentry) - #ifdef ECM_MULTICAST_ENABLE - ecm_nss_multicast_ipv4_exit(); - #endif -- nf_unregister_hooks(ecm_nss_ipv4_netfilter_hooks, -- ARRAY_SIZE(ecm_nss_ipv4_netfilter_hooks)); -+ nf_unregister_net_hooks(&init_net, ecm_nss_ipv4_netfilter_hooks, -+ ARRAY_SIZE(ecm_nss_ipv4_netfilter_hooks)); - goto task_cleanup; - } - -@@ -2742,8 +2739,8 @@ void ecm_nss_ipv4_exit(void) - /* - * Stop the network stack hooks - */ -- nf_unregister_hooks(ecm_nss_ipv4_netfilter_hooks, -- ARRAY_SIZE(ecm_nss_ipv4_netfilter_hooks)); -+ nf_unregister_net_hooks(&init_net, ecm_nss_ipv4_netfilter_hooks, -+ ARRAY_SIZE(ecm_nss_ipv4_netfilter_hooks)); - - /* - * Unregister from the Linux NSS Network driver ---- a/frontends/nss/ecm_nss_ipv6.c -+++ b/frontends/nss/ecm_nss_ipv6.c -@@ -51,7 +51,6 @@ - #include - #include - #include --#include - #if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 2, 0)) - #include - #else -@@ -1035,7 +1034,7 @@ static unsigned int ecm_nss_ipv6_ip_process(struct net_device *out_dev, struct n - * If any of the input or output interface is a GRE V4 TAP/TUN interface - * we can continue to accelerate it. - */ -- if ((in_dev->priv_flags & IFF_GRE_V4_TAP) || (out_dev->priv_flags & IFF_GRE_V4_TAP)) { -+ if ((in_dev->priv_flags_qca_ecm & IFF_QCA_ECM_GRE_V4_TAP) || (out_dev->priv_flags_qca_ecm & IFF_QCA_ECM_GRE_V4_TAP)) { - #ifndef ECM_INTERFACE_GRE_TAP_ENABLE - DEBUG_TRACE("GRE TAP acceleration is disabled\n"); - return NF_ACCEPT; -@@ -1064,7 +1063,7 @@ static unsigned int ecm_nss_ipv6_ip_process(struct net_device *out_dev, struct n - ECM_IP_ADDR_TO_NIN6_ADDR(reply_tuple.dst.u3.in6, ip_hdr.src_addr); - sender = ECM_TRACKER_SENDER_TYPE_SRC; - } else { -- if (unlikely(ct == &nf_conntrack_untracked)) { -+ if (unlikely(ctinfo == IP_CT_UNTRACKED)) { - DEBUG_TRACE("%p: ct: untracked\n", skb); - return NF_ACCEPT; - } -@@ -1809,7 +1808,6 @@ sync_conntrack: - } - - ct = nf_ct_tuplehash_to_ctrack(h); -- NF_CT_ASSERT(ct->timeout.data == (unsigned long)ct); - DEBUG_TRACE("%p: NSS Sync: conntrack connection\n", ct); - - ecm_front_end_flow_and_return_directions_get(ct, flow_ip, 6, &flow_dir, &return_dir); -@@ -1820,7 +1818,7 @@ sync_conntrack: - */ - if (!test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) { - spin_lock_bh(&ct->lock); -- ct->timeout.expires += delta_jiffies; -+ ct->timeout += delta_jiffies; - spin_unlock_bh(&ct->lock); - } - -@@ -1878,17 +1876,15 @@ sync_conntrack: - u_int64_t reply_pkts = atomic64_read(&acct[IP_CT_DIR_REPLY].packets); - - if (reply_pkts != 0) { -- struct nf_conntrack_l4proto *l4proto; - unsigned int *timeouts; - - set_bit(IPS_SEEN_REPLY_BIT, &ct->status); - set_bit(IPS_ASSURED_BIT, &ct->status); - -- l4proto = __nf_ct_l4proto_find(AF_INET6, IPPROTO_UDP); -- timeouts = nf_ct_timeout_lookup(&init_net, ct, l4proto); -+ timeouts = nf_ct_timeout_lookup(ct); - - spin_lock_bh(&ct->lock); -- ct->timeout.expires = jiffies + timeouts[UDP_CT_REPLIED]; -+ ct->timeout = jiffies + timeouts[UDP_CT_REPLIED]; - spin_unlock_bh(&ct->lock); - } - } -@@ -2402,7 +2398,7 @@ int ecm_nss_ipv6_init(struct dentry *dentry) - /* - * Register netfilter hooks - */ -- result = nf_register_hooks(ecm_nss_ipv6_netfilter_hooks, ARRAY_SIZE(ecm_nss_ipv6_netfilter_hooks)); -+ result = nf_register_net_hooks(&init_net, ecm_nss_ipv6_netfilter_hooks, ARRAY_SIZE(ecm_nss_ipv6_netfilter_hooks)); - if (result < 0) { - DEBUG_ERROR("Can't register netfilter hooks.\n"); - nss_ipv6_notify_unregister(); -@@ -2414,8 +2410,8 @@ int ecm_nss_ipv6_init(struct dentry *dentry) - if (result < 0) { - DEBUG_ERROR("Failed to init ecm ipv6 multicast frontend\n"); - nss_ipv6_notify_unregister(); -- nf_unregister_hooks(ecm_nss_ipv6_netfilter_hooks, -- ARRAY_SIZE(ecm_nss_ipv6_netfilter_hooks)); -+ nf_unregister_net_hooks(&init_net, ecm_nss_ipv6_netfilter_hooks, -+ ARRAY_SIZE(ecm_nss_ipv6_netfilter_hooks)); - goto task_cleanup; - } - #endif -@@ -2426,8 +2422,8 @@ int ecm_nss_ipv6_init(struct dentry *dentry) - #ifdef ECM_MULTICAST_ENABLE - ecm_nss_multicast_ipv6_exit(); - #endif -- nf_unregister_hooks(ecm_nss_ipv6_netfilter_hooks, -- ARRAY_SIZE(ecm_nss_ipv6_netfilter_hooks)); -+ nf_unregister_net_hooks(&init_net, ecm_nss_ipv6_netfilter_hooks, -+ ARRAY_SIZE(ecm_nss_ipv6_netfilter_hooks)); - goto task_cleanup; - } - -@@ -2453,8 +2449,8 @@ void ecm_nss_ipv6_exit(void) - /* - * Stop the network stack hooks - */ -- nf_unregister_hooks(ecm_nss_ipv6_netfilter_hooks, -- ARRAY_SIZE(ecm_nss_ipv6_netfilter_hooks)); -+ nf_unregister_net_hooks(&init_net, ecm_nss_ipv6_netfilter_hooks, -+ ARRAY_SIZE(ecm_nss_ipv6_netfilter_hooks)); - - /* - * Unregister from the Linux NSS Network driver ---- a/frontends/nss/ecm_nss_multicast_ipv4.c -+++ b/frontends/nss/ecm_nss_multicast_ipv4.c -@@ -50,7 +50,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/frontends/nss/ecm_nss_multicast_ipv6.c -+++ b/frontends/nss/ecm_nss_multicast_ipv6.c -@@ -51,7 +51,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/frontends/nss/ecm_nss_non_ported_ipv4.c -+++ b/frontends/nss/ecm_nss_non_ported_ipv4.c -@@ -47,7 +47,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -640,7 +639,7 @@ static void ecm_nss_non_ported_ipv4_connection_accelerate(struct ecm_front_end_c - #ifdef ECM_INTERFACE_GRE_TAP_ENABLE - dev = dev_get_by_index(&init_net, ecm_db_iface_interface_identifier_get(ii)); - if (dev) { -- if (dev->priv_flags & IFF_GRE_V4_TAP) { -+ if (dev->priv_flags_qca_ecm & IFF_QCA_ECM_GRE_V4_TAP) { - /* - * Clear QOS_VALID to prevent outer rule from overwriting - * inner flow's QoS classification. ---- a/frontends/nss/ecm_nss_non_ported_ipv6.c -+++ b/frontends/nss/ecm_nss_non_ported_ipv6.c -@@ -47,7 +47,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -548,7 +547,7 @@ static void ecm_nss_non_ported_ipv6_connection_accelerate(struct ecm_front_end_c - #ifdef ECM_INTERFACE_GRE_TAP_ENABLE - dev = dev_get_by_index(&init_net, ecm_db_iface_interface_identifier_get(ii)); - if (dev) { -- if (dev->priv_flags & IFF_GRE_V6_TAP) { -+ if (dev->priv_flags_qca_ecm & IFF_QCA_ECM_GRE_V6_TAP) { - /* - * Clear QOS_VALID to prevent outer rule from overwriting - * inner flow's QoS classification. ---- a/frontends/nss/ecm_nss_ported_ipv4.c -+++ b/frontends/nss/ecm_nss_ported_ipv4.c -@@ -47,7 +47,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/frontends/nss/ecm_nss_ported_ipv6.c -+++ b/frontends/nss/ecm_nss_ported_ipv6.c -@@ -47,7 +47,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -1996,7 +1995,7 @@ unsigned int ecm_nss_ported_ipv6_process - /* - * Deny acceleration for L2TP-over-UDP tunnel - */ -- if ((in_dev->priv_flags & IFF_PPP_L2TPV2) && ppp_is_xmit_locked(in_dev)) { -+ if ((in_dev->priv_flags_qca_ecm & IFF_QCA_ECM_PPP_L2TPV2) && ppp_is_xmit_locked(in_dev)) { - DEBUG_TRACE("Skip packets for L2TP tunnel in skb %p\n", skb); - can_accel = false; - } ---- a/frontends/sfe/ecm_sfe_ipv4.c -+++ b/frontends/sfe/ecm_sfe_ipv4.c -@@ -47,7 +47,6 @@ - #include - #include - #include --#include - #if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 2, 0)) - #include - #else -@@ -746,7 +745,8 @@ static unsigned int ecm_sfe_ipv4_ip_proc - * If skb_dst(skb)->xfrm is not null, packet is to be encrypted by ipsec, we can't accelerate it. - * If skb->sp is not null, packet is decrypted by ipsec. We only accelerate it when configuration didn't reject ipsec. - */ -- if (unlikely((skb_dst(skb) && skb_dst(skb)->xfrm) || (ecm_sfe_ipv4_reject_acceleration_for_ipsec && skb->sp))) { -+ if (unlikely((skb_dst(skb) && skb_dst(skb)->xfrm) || \ -+ (ecm_sfe_ipv4_reject_acceleration_for_ipsec && skb_ext_exist(skb, SKB_EXT_SEC_PATH)))) { - DEBUG_TRACE("skip local ipsec flows\n"); - return NF_ACCEPT; - } -@@ -762,7 +762,7 @@ static unsigned int ecm_sfe_ipv4_ip_process(struct net_device *out_dev, struct n - reply_tuple.dst.u3.ip = orig_tuple.src.u3.ip; - sender = ECM_TRACKER_SENDER_TYPE_SRC; - } else { -- if (unlikely(ct == &nf_conntrack_untracked)) { -+ if (unlikely(ctinfo == IP_CT_UNTRACKED)) { - DEBUG_TRACE("%p: ct: untracked\n", skb); - return NF_ACCEPT; - } -@@ -1531,7 +1526,6 @@ sync_conntrack: - } - - ct = nf_ct_tuplehash_to_ctrack(h); -- NF_CT_ASSERT(ct->timeout.data == (unsigned long)ct); - DEBUG_TRACE("%p: SFE Sync: conntrack connection\n", ct); - - ecm_front_end_flow_and_return_directions_get(ct, flow_ip, 4, &flow_dir, &return_dir); -@@ -1551,7 +1545,7 @@ sync_conntrack: - delta_jiffies = ((sync->inc_ticks * HZ) + (MSEC_PER_SEC / 2)) / MSEC_PER_SEC; - - spin_lock_bh(&ct->lock); -- ct->timeout.expires += delta_jiffies; -+ ct->timeout += delta_jiffies; - spin_unlock_bh(&ct->lock); - } - -@@ -1609,17 +1603,15 @@ sync_conntrack: - u_int64_t reply_pkts = atomic64_read(&acct[IP_CT_DIR_REPLY].packets); - - if (reply_pkts != 0) { -- struct nf_conntrack_l4proto *l4proto; - unsigned int *timeouts; - - set_bit(IPS_SEEN_REPLY_BIT, &ct->status); - set_bit(IPS_ASSURED_BIT, &ct->status); - -- l4proto = __nf_ct_l4proto_find(AF_INET, IPPROTO_UDP); -- timeouts = nf_ct_timeout_lookup(&init_net, ct, l4proto); -+ timeouts = nf_ct_timeout_lookup(ct); - - spin_lock_bh(&ct->lock); -- ct->timeout.expires = jiffies + timeouts[UDP_CT_REPLIED]; -+ ct->timeout = jiffies + timeouts[UDP_CT_REPLIED]; - spin_unlock_bh(&ct->lock); - } - } -@@ -1901,7 +1893,7 @@ int ecm_sfe_ipv4_init(struct dentry *den - /* - * Register netfilter hooks - */ -- result = nf_register_hooks(ecm_sfe_ipv4_netfilter_hooks, ARRAY_SIZE(ecm_sfe_ipv4_netfilter_hooks)); -+ result = nf_register_net_hooks(&init_net, ecm_sfe_ipv4_netfilter_hooks, ARRAY_SIZE(ecm_sfe_ipv4_netfilter_hooks)); - if (result < 0) { - DEBUG_ERROR("Can't register netfilter hooks.\n"); - sfe_drv_ipv4_notify_unregister(); -@@ -1934,8 +1926,8 @@ void ecm_sfe_ipv4_exit(void) - /* - * Stop the network stack hooks - */ -- nf_unregister_hooks(ecm_sfe_ipv4_netfilter_hooks, -- ARRAY_SIZE(ecm_sfe_ipv4_netfilter_hooks)); -+ nf_unregister_net_hooks(&init_net, ecm_sfe_ipv4_netfilter_hooks, -+ ARRAY_SIZE(ecm_sfe_ipv4_netfilter_hooks)); - - /* - * Unregister from the simulated sfe driver ---- a/frontends/sfe/ecm_sfe_ipv6.c -+++ b/frontends/sfe/ecm_sfe_ipv6.c -@@ -51,7 +51,6 @@ - #include - #include - #include --#include - #if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 2, 0)) - #include - #else -@@ -714,7 +713,8 @@ static unsigned int ecm_sfe_ipv6_ip_proc - * If skb_dst(skb)->xfrm is not null, packet is to be encrypted by ipsec, we can't accelerate it. - * If skb->sp is not null, packet is decrypted by ipsec. We only accelerate it when configuration didn't reject ipsec. - */ -- if (unlikely((skb_dst(skb) && skb_dst(skb)->xfrm) || (ecm_sfe_ipv6_reject_acceleration_for_ipsec && skb->sp))) { -+ if (unlikely((skb_dst(skb) && skb_dst(skb)->xfrm) || \ -+ (ecm_sfe_ipv6_reject_acceleration_for_ipsec && skb_ext_exist(skb, SKB_EXT_SEC_PATH)))) { - DEBUG_TRACE("skip local ipsec flows\n"); - return NF_ACCEPT; - } -@@ -733,7 +733,7 @@ static unsigned int ecm_sfe_ipv6_ip_proc - ECM_IP_ADDR_TO_NIN6_ADDR(reply_tuple.dst.u3.in6, ip_hdr.src_addr); - sender = ECM_TRACKER_SENDER_TYPE_SRC; - } else { -- if (unlikely(ct == &nf_conntrack_untracked)) { -+ if (unlikely(ctinfo == IP_CT_UNTRACKED)) { - DEBUG_TRACE("%p: ct: untracked\n", skb); - return NF_ACCEPT; - } -@@ -1255,7 +1255,6 @@ sync_conntrack: - } - - ct = nf_ct_tuplehash_to_ctrack(h); -- NF_CT_ASSERT(ct->timeout.data == (unsigned long)ct); - DEBUG_TRACE("%p: SFE Sync: conntrack connection\n", ct); - - ecm_front_end_flow_and_return_directions_get(ct, flow_ip, 6, &flow_dir, &return_dir); -@@ -1275,7 +1274,7 @@ sync_conntrack: - delta_jiffies = ((sync->inc_ticks * HZ) + (MSEC_PER_SEC / 2)) / MSEC_PER_SEC; - - spin_lock_bh(&ct->lock); -- ct->timeout.expires += delta_jiffies; -+ ct->timeout += delta_jiffies; - spin_unlock_bh(&ct->lock); - } - #if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,6,0)) -@@ -1332,17 +1331,15 @@ sync_conntrack: - u_int64_t reply_pkts = atomic64_read(&acct[IP_CT_DIR_REPLY].packets); - - if (reply_pkts != 0) { -- struct nf_conntrack_l4proto *l4proto; - unsigned int *timeouts; - - set_bit(IPS_SEEN_REPLY_BIT, &ct->status); - set_bit(IPS_ASSURED_BIT, &ct->status); - -- l4proto = __nf_ct_l4proto_find(AF_INET6, IPPROTO_UDP); -- timeouts = nf_ct_timeout_lookup(&init_net, ct, l4proto); -+ timeouts = nf_ct_timeout_lookup(ct); - - spin_lock_bh(&ct->lock); -- ct->timeout.expires = jiffies + timeouts[UDP_CT_REPLIED]; -+ ct->timeout = jiffies + timeouts[UDP_CT_REPLIED]; - spin_unlock_bh(&ct->lock); - } - } -@@ -1624,7 +1621,7 @@ int ecm_sfe_ipv6_init(struct dentry *den - /* - * Register netfilter hooks - */ -- result = nf_register_hooks(ecm_sfe_ipv6_netfilter_hooks, ARRAY_SIZE(ecm_sfe_ipv6_netfilter_hooks)); -+ result = nf_register_net_hooks(&init_net, ecm_sfe_ipv6_netfilter_hooks, ARRAY_SIZE(ecm_sfe_ipv6_netfilter_hooks)); - if (result < 0) { - DEBUG_ERROR("Can't register netfilter hooks.\n"); - sfe_drv_ipv6_notify_unregister(); -@@ -1656,8 +1653,8 @@ void ecm_sfe_ipv6_exit(void) - /* - * Stop the network stack hooks - */ -- nf_unregister_hooks(ecm_sfe_ipv6_netfilter_hooks, -- ARRAY_SIZE(ecm_sfe_ipv6_netfilter_hooks)); -+ nf_unregister_net_hooks(&init_net, ecm_sfe_ipv6_netfilter_hooks, -+ ARRAY_SIZE(ecm_sfe_ipv6_netfilter_hooks)); - - /* - * Unregister from the Linux SFE Network driver ---- a/frontends/sfe/ecm_sfe_non_ported_ipv4.c -+++ b/frontends/sfe/ecm_sfe_non_ported_ipv4.c -@@ -46,7 +46,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -1829,7 +1828,7 @@ unsigned int ecm_sfe_non_ported_ipv4_pro - /* - * Packet has been decrypted by ipsec, mark it in connection. - */ -- if (unlikely(skb->sp)) { -+ if (unlikely(skb_ext_exist(skb, SKB_EXT_SEC_PATH))) { - ((struct ecm_sfe_non_ported_ipv4_connection_instance *)feci)->flow_ipsec_state = ECM_SFE_IPSEC_STATE_WAS_DECRYPTED; - ((struct ecm_sfe_non_ported_ipv4_connection_instance *)feci)->return_ipsec_state = ECM_SFE_IPSEC_STATE_TO_ENCRYPT; - } ---- a/frontends/sfe/ecm_sfe_non_ported_ipv6.c -+++ b/frontends/sfe/ecm_sfe_non_ported_ipv6.c -@@ -47,7 +47,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -1710,7 +1709,7 @@ unsigned int ecm_sfe_non_ported_ipv6_pro - /* - * Packet has been decrypted by ipsec, mark it in connection. - */ -- if (unlikely(skb->sp)) { -+ if (unlikely(skb_ext_exist(skb, SKB_EXT_SEC_PATH))) { - ((struct ecm_sfe_non_ported_ipv6_connection_instance *)feci)->flow_ipsec_state = ECM_SFE_IPSEC_STATE_WAS_DECRYPTED; - ((struct ecm_sfe_non_ported_ipv6_connection_instance *)feci)->return_ipsec_state = ECM_SFE_IPSEC_STATE_TO_ENCRYPT; - } ---- a/frontends/sfe/ecm_sfe_ported_ipv4.c -+++ b/frontends/sfe/ecm_sfe_ported_ipv4.c -@@ -46,7 +46,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -2053,7 +2052,7 @@ unsigned int ecm_sfe_ported_ipv4_process - /* - * Packet has been decrypted by ipsec, mark it in connection. - */ -- if (unlikely(skb->sp)) { -+ if (unlikely(skb_ext_exist(skb, SKB_EXT_SEC_PATH))) { - ((struct ecm_sfe_ported_ipv4_connection_instance *)feci)->flow_ipsec_state = ECM_SFE_IPSEC_STATE_WAS_DECRYPTED; - ((struct ecm_sfe_ported_ipv4_connection_instance *)feci)->return_ipsec_state = ECM_SFE_IPSEC_STATE_TO_ENCRYPT; - } ---- a/frontends/sfe/ecm_sfe_ported_ipv6.c -+++ b/frontends/sfe/ecm_sfe_ported_ipv6.c -@@ -47,7 +47,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -1826,7 +1825,7 @@ unsigned int ecm_sfe_ported_ipv6_process - /* - * Deny acceleration for L2TP-over-UDP tunnel - */ -- if ((in_dev->priv_flags & IFF_PPP_L2TPV2) && ppp_is_xmit_locked(in_dev)) { -+ if ((in_dev->priv_flags_qca_ecm & IFF_QCA_ECM_PPP_L2TPV2) && ppp_is_xmit_locked(in_dev)) { - DEBUG_TRACE("Skip packets for L2TP tunnel in skb %p\n", skb); - can_accel = false; - } -@@ -1958,7 +1957,7 @@ unsigned int ecm_sfe_ported_ipv6_process - /* - * Packet has been decrypted by ipsec, mark it in connection. - */ -- if (unlikely(skb->sp)) { -+ if (unlikely(skb_ext_exist(skb, SKB_EXT_SEC_PATH))) { - ((struct ecm_sfe_ported_ipv6_connection_instance *)feci)->flow_ipsec_state = ECM_SFE_IPSEC_STATE_WAS_DECRYPTED; - ((struct ecm_sfe_ported_ipv6_connection_instance *)feci)->return_ipsec_state = ECM_SFE_IPSEC_STATE_TO_ENCRYPT; - } diff --git a/root/package/qca/nss/qca-nss-ecm/patches/101-Fix_Kern_Panic_on_UDP_CONNTRACK.patch b/root/package/qca/nss/qca-nss-ecm/patches/101-Fix_Kern_Panic_on_UDP_CONNTRACK.patch deleted file mode 100644 index 6633f72b..00000000 --- a/root/package/qca/nss/qca-nss-ecm/patches/101-Fix_Kern_Panic_on_UDP_CONNTRACK.patch +++ /dev/null @@ -1,60 +0,0 @@ -diff --git a/frontends/nss/ecm_nss_ipv4.c b/frontends/nss/ecm_nss_ipv4.c -index 1ce4b61..29e70ba 100644 ---- a/frontends/nss/ecm_nss_ipv4.c -+++ b/frontends/nss/ecm_nss_ipv4.c -@@ -2171,6 +2171,10 @@ sync_conntrack: - - timeouts = nf_ct_timeout_lookup(ct); - -+ /* Copy of udp_get_timeouts in kernel */ -+ if (!timeouts) -+ timeouts = nf_udp_pernet(nf_ct_net(ct))->timeouts; -+ - spin_lock_bh(&ct->lock); - ct->timeout = jiffies + timeouts[UDP_CT_REPLIED]; - spin_unlock_bh(&ct->lock); -diff --git a/frontends/nss/ecm_nss_ipv6.c b/frontends/nss/ecm_nss_ipv6.c -index 2adc5ec..08253b6 100644 ---- a/frontends/nss/ecm_nss_ipv6.c -+++ b/frontends/nss/ecm_nss_ipv6.c -@@ -1883,6 +1883,10 @@ sync_conntrack: - - timeouts = nf_ct_timeout_lookup(ct); - -+ /* Copy of udp_get_timeouts in kernel */ -+ if (!timeouts) -+ timeouts = nf_udp_pernet(nf_ct_net(ct))->timeouts; -+ - spin_lock_bh(&ct->lock); - ct->timeout = jiffies + timeouts[UDP_CT_REPLIED]; - spin_unlock_bh(&ct->lock); -diff --git a/frontends/sfe/ecm_sfe_ipv4.c b/frontends/sfe/ecm_sfe_ipv4.c -index 7cfe4fc..8f525ee 100644 ---- a/frontends/sfe/ecm_sfe_ipv4.c -+++ b/frontends/sfe/ecm_sfe_ipv4.c -@@ -1608,6 +1608,10 @@ sync_conntrack: - - timeouts = nf_ct_timeout_lookup(ct); - -+ /* Copy of udp_get_timeouts in kernel */ -+ if (!timeouts) -+ timeouts = nf_udp_pernet(nf_ct_net(ct))->timeouts; -+ - spin_lock_bh(&ct->lock); - ct->timeout = jiffies + timeouts[UDP_CT_REPLIED]; - spin_unlock_bh(&ct->lock); -diff --git a/frontends/sfe/ecm_sfe_ipv6.c b/frontends/sfe/ecm_sfe_ipv6.c -index dfde309..47c531a 100644 ---- a/frontends/sfe/ecm_sfe_ipv6.c -+++ b/frontends/sfe/ecm_sfe_ipv6.c -@@ -1321,6 +1321,10 @@ sync_conntrack: - - timeouts = nf_ct_timeout_lookup(ct); - -+ /* Copy of udp_get_timeouts in kernel */ -+ if (!timeouts) -+ timeouts = nf_udp_pernet(nf_ct_net(ct))->timeouts; -+ - spin_lock_bh(&ct->lock); - ct->timeout = jiffies + timeouts[UDP_CT_REPLIED]; - spin_unlock_bh(&ct->lock); diff --git a/root/package/qca/nss/qca-nss-ecm/patches/200-resolve-high-load.patch b/root/package/qca/nss/qca-nss-ecm/patches/200-resolve-high-load.patch deleted file mode 100644 index 2f39d277..00000000 --- a/root/package/qca/nss/qca-nss-ecm/patches/200-resolve-high-load.patch +++ /dev/null @@ -1,44 +0,0 @@ -The sync update work queue tasks is calling uninterruptible sleep function, which is -causing high CPU load. Changed to interruptible sleep function. The stats update -task should be interruptible. - ---- a/frontends/nss/ecm_nss_ipv4.c -+++ b.frontends/nss/ecm_nss_ipv4.c -@@ -2411,7 +2411,7 @@ static void ecm_nss_ipv4_stats_sync_req_ - } - spin_unlock_bh(&ecm_nss_ipv4_lock); - -- usleep_range(ECM_NSS_IPV4_STATS_SYNC_UDELAY - 100, ECM_NSS_IPV4_STATS_SYNC_UDELAY); -+ msleep_interruptible(ECM_NSS_IPV4_STATS_SYNC_UDELAY / 1000); - - /* - * If index is 0, we are starting a new round, but if we still have time remain -@@ -2425,7 +2425,7 @@ static void ecm_nss_ipv4_stats_sync_req_ - } - - if (ecm_nss_ipv4_next_req_time > current_jiffies) { -- msleep(jiffies_to_msecs(ecm_nss_ipv4_next_req_time - current_jiffies)); -+ msleep_interruptible(jiffies_to_msecs(ecm_nss_ipv4_next_req_time - current_jiffies)); - } - ecm_nss_ipv4_roll_check_jiffies = jiffies; - ecm_nss_ipv4_next_req_time = ecm_nss_ipv4_roll_check_jiffies + ECM_NSS_IPV4_STATS_SYNC_PERIOD; ---- a/frontends/nss/ecm_nss_ipv6.c -+++ b.frontends/nss/ecm_nss_ipv6.c -@@ -2128,7 +2128,7 @@ static void ecm_nss_ipv6_stats_sync_req_ - } - spin_unlock_bh(&ecm_nss_ipv6_lock); - -- usleep_range(ECM_NSS_IPV6_STATS_SYNC_UDELAY - 100, ECM_NSS_IPV6_STATS_SYNC_UDELAY); -+ msleep_interruptible(ECM_NSS_IPV6_STATS_SYNC_UDELAY / 1000); - - /* - * If index is 0, we are starting a new round, but if we still have time remain -@@ -2142,7 +2142,7 @@ static void ecm_nss_ipv6_stats_sync_req_ - } - - if (ecm_nss_ipv6_next_req_time > current_jiffies) { -- msleep(jiffies_to_msecs(ecm_nss_ipv6_next_req_time - current_jiffies)); -+ msleep_interruptible(jiffies_to_msecs(ecm_nss_ipv6_next_req_time - current_jiffies)); - } - ecm_nss_ipv6_roll_check_jiffies = jiffies; - ecm_nss_ipv6_next_req_time = ecm_nss_ipv6_roll_check_jiffies + ECM_NSS_IPV6_STATS_SYNC_PERIOD; diff --git a/root/package/qca/nss/qca-nss-ecm/patches/203-rework-nfct-notification.patch b/root/package/qca/nss/qca-nss-ecm/patches/203-rework-nfct-notification.patch deleted file mode 100644 index a0e09c1f..00000000 --- a/root/package/qca/nss/qca-nss-ecm/patches/203-rework-nfct-notification.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- a/ecm_conntrack_notifier.c -+++ b/ecm_conntrack_notifier.c -@@ -411,7 +411,7 @@ int ecm_conntrack_notifier_init(struct d - /* - * Eventing subsystem is available so we register a notifier hook to get fast notifications of expired connections - */ -- result = nf_conntrack_register_notifier(&init_net, &ecm_conntrack_notifier); -+ result = nf_conntrack_register_chain_notifier(&init_net, &ecm_conntrack_notifier); - if (result < 0) { - DEBUG_ERROR("Can't register nf notifier hook.\n"); - debugfs_remove_recursive(ecm_conntrack_notifier_dentry); -@@ -430,7 +430,7 @@ void ecm_conntrack_notifier_exit(void) - { - DEBUG_INFO("ECM Conntrack Notifier exit\n"); - #ifdef CONFIG_NF_CONNTRACK_EVENTS -- nf_conntrack_unregister_notifier(&init_net, &ecm_conntrack_notifier); -+ nf_conntrack_unregister_chain_notifier(&init_net, &ecm_conntrack_notifier); - #endif - /* - * Remove the debugfs files recursively. diff --git a/root/package/qca/nss/qca-nss-ecm/patches/400-Check-TCP_UDP-conntrack-state-earlier.patch b/root/package/qca/nss/qca-nss-ecm/patches/400-Check-TCP_UDP-conntrack-state-earlier.patch deleted file mode 100644 index b7882c1b..00000000 --- a/root/package/qca/nss/qca-nss-ecm/patches/400-Check-TCP_UDP-conntrack-state-earlier.patch +++ /dev/null @@ -1,236 +0,0 @@ -From 90cace88a342e77ee8ca1e961cf7b7a7930d4c89 Mon Sep 17 00:00:00 2001 -From: Murat Sezgin -Date: Mon, 9 Mar 2020 12:51:03 -0700 -Subject: [qca-nss-ecm] Check TCP/UDP conntrack state earlier - -Check the conntrack state before processing the flow -and adding it to the database. The unconfirmed -connections can be changed after the confirmation. - -Changed the TCP tracker connection state matrix to set the -state of the connection as ESTABLISHED when any of the src or -dest side is set as ESTABLISHED. With this change ECM will not -handle the SYN and SYN-ACK packets of the TCP handshake. Only the -ACK and FIN flaged packets will be used during the creation and -closing the connection respectively. - -Signed-off-by: Murat Sezgin -Change-Id: I3e0a58d604df4c6a85478ca9c05f24d50cd8c894 ---- - ecm_classifier_default.c | 36 ++++++++---------------------------- - ecm_tracker_tcp.c | 4 ++-- - frontends/nss/ecm_nss_ported_ipv4.c | 17 +++++++++++++++++ - frontends/nss/ecm_nss_ported_ipv6.c | 17 +++++++++++++++++ - frontends/sfe/ecm_sfe_ported_ipv4.c | 17 +++++++++++++++++ - frontends/sfe/ecm_sfe_ported_ipv6.c | 17 +++++++++++++++++ - 6 files changed, 78 insertions(+), 30 deletions(-) - -diff --git a/ecm_classifier_default.c b/ecm_classifier_default.c -index 22c4bec..d04cdfa 100644 ---- a/ecm_classifier_default.c -+++ b/ecm_classifier_default.c -@@ -1,6 +1,6 @@ - /* - ************************************************************************** -- * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. -+ * Copyright (c) 2014-2016, 2020, The Linux Foundation. All rights reserved. - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all copies. -@@ -285,12 +285,12 @@ static void ecm_classifier_default_process(struct ecm_classifier_instance *aci, - } - - /* -- * Check the TCP connection state. -+ * Check the TCP connection state, when the ct is NULL. -+ * ct valid case was already checked in the ecm_nss{sfe}_ported_ipv4{6}_process functions. - * If we are not established then we deny acceleration. -- * Take lead from conntrack if exists. - */ - ct = nf_ct_get(skb, &ctinfo); -- if (ct == NULL) { -+ if (!ct) { - DEBUG_TRACE("%p: No Conntrack found for packet, using ECM tracker state\n", cdii); - if (unlikely(prevailing_state != ECM_TRACKER_CONNECTION_STATE_ESTABLISHED)) { - cdii->process_response.accel_mode = ECM_CLASSIFIER_ACCELERATION_MODE_NO; -@@ -298,29 +298,10 @@ static void ecm_classifier_default_process(struct ecm_classifier_instance *aci, - } - } else { - /* -- * Unconfirmed connection may be dropped by Linux at the final step, -- * So we don't allow acceleration for the unconfirmed connections. -- */ -- if (!nf_ct_is_confirmed(ct)) { -- DEBUG_TRACE("%p: Unconfirmed connection\n", ct); -- cdii->process_response.accel_mode = ECM_CLASSIFIER_ACCELERATION_MODE_NO; -- goto return_response; -- } -- -- /* -- * Don't try to manage a non-established connection. -- */ -- if (!test_bit(IPS_ASSURED_BIT, &ct->status)) { -- DEBUG_TRACE("%p: Non-established connection\n", ct); -- cdii->process_response.accel_mode = ECM_CLASSIFIER_ACCELERATION_MODE_NO; -- goto return_response; -- } -- -- /* -- * If the connection is shutting down do not manage it. -- * state can not be SYN_SENT, SYN_RECV because connection is assured -- * Not managed states: FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE. -- */ -+ * If the connection is shutting down do not manage it. -+ * state can not be SYN_SENT, SYN_RECV because connection is assured -+ * Not managed states: FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE. -+ */ - spin_lock_bh(&ct->lock); - if (ct->proto.tcp.state != TCP_CONNTRACK_ESTABLISHED) { - spin_unlock_bh(&ct->lock); -@@ -333,7 +314,6 @@ static void ecm_classifier_default_process(struct ecm_classifier_instance *aci, - - return_response: - ; -- - /* - * Return the process response - */ -diff --git a/ecm_tracker_tcp.c b/ecm_tracker_tcp.c -index f073c36..e5b327a 100644 ---- a/ecm_tracker_tcp.c -+++ b/ecm_tracker_tcp.c -@@ -257,9 +257,9 @@ static DEFINE_SPINLOCK(ecm_tracker_tcp_lock); /* Global lock for the tracker gl - */ - static ecm_tracker_connection_state_t ecm_tracker_tcp_connection_state_matrix[ECM_TRACKER_SENDER_STATE_MAX][ECM_TRACKER_SENDER_STATE_MAX] = - { /* Unknown Establishing Established Closing Closed Fault */ -- /* Unknown */ {ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT}, -+ /* Unknown */ {ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_ESTABLISHED, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT}, - /* Establishing */ {ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT}, -- /* Established */ {ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_ESTABLISHED, ECM_TRACKER_CONNECTION_STATE_CLOSING, ECM_TRACKER_CONNECTION_STATE_CLOSING, ECM_TRACKER_CONNECTION_STATE_FAULT}, -+ /* Established */ {ECM_TRACKER_CONNECTION_STATE_ESTABLISHED, ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_ESTABLISHED, ECM_TRACKER_CONNECTION_STATE_CLOSING, ECM_TRACKER_CONNECTION_STATE_CLOSING, ECM_TRACKER_CONNECTION_STATE_FAULT}, - /* Closing */ {ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_CLOSING, ECM_TRACKER_CONNECTION_STATE_CLOSING, ECM_TRACKER_CONNECTION_STATE_CLOSING, ECM_TRACKER_CONNECTION_STATE_FAULT}, - /* Closed */ {ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_CLOSING, ECM_TRACKER_CONNECTION_STATE_CLOSING, ECM_TRACKER_CONNECTION_STATE_CLOSED, ECM_TRACKER_CONNECTION_STATE_FAULT}, - /* Fault */ {ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT}, -diff --git a/frontends/nss/ecm_nss_ported_ipv4.c b/frontends/nss/ecm_nss_ported_ipv4.c -index 1435ec0..34c056f 100644 ---- a/frontends/nss/ecm_nss_ported_ipv4.c -+++ b/frontends/nss/ecm_nss_ported_ipv4.c -@@ -2002,8 +2002,25 @@ unsigned int ecm_nss_ported_ipv4_process(struct net_device *out_dev, struct net_ - int protocol = (int)orig_tuple->dst.protonum; - __be16 *layer4hdr = NULL; - -+ /* -+ * Unconfirmed connection may be dropped by Linux at the final step, -+ * So we don't allow acceleration for the unconfirmed connections. -+ */ -+ if (likely(ct) && !nf_ct_is_confirmed(ct)) { -+ DEBUG_WARN("%p: Unconfirmed connection\n", ct); -+ return NF_ACCEPT; -+ } -+ - if (protocol == IPPROTO_TCP) { - /* -+ * Don't try to manage a non-established connection. -+ */ -+ if (likely(ct) && !test_bit(IPS_ASSURED_BIT, &ct->status)) { -+ DEBUG_WARN("%p: Non-established TCP connection\n", ct); -+ return NF_ACCEPT; -+ } -+ -+ /* - * Extract TCP header to obtain port information - */ - tcp_hdr = ecm_tracker_tcp_check_header_and_read(skb, iph, &tcp_hdr_buff); -diff --git a/frontends/nss/ecm_nss_ported_ipv6.c b/frontends/nss/ecm_nss_ported_ipv6.c -index 4c154a6..bd6349b 100644 ---- a/frontends/nss/ecm_nss_ported_ipv6.c -+++ b/frontends/nss/ecm_nss_ported_ipv6.c -@@ -1914,8 +1914,25 @@ unsigned int ecm_nss_ported_ipv6_process(struct net_device *out_dev, - int protocol = (int)orig_tuple->dst.protonum; - __be16 *layer4hdr = NULL; - -+ /* -+ * Unconfirmed connection may be dropped by Linux at the final step, -+ * So we don't allow acceleration for the unconfirmed connections. -+ */ -+ if (likely(ct) && !nf_ct_is_confirmed(ct)) { -+ DEBUG_WARN("%p: Unconfirmed connection\n", ct); -+ return NF_ACCEPT; -+ } -+ - if (protocol == IPPROTO_TCP) { - /* -+ * Don't try to manage a non-established connection. -+ */ -+ if (likely(ct) && !test_bit(IPS_ASSURED_BIT, &ct->status)) { -+ DEBUG_WARN("%p: Non-established TCP connection\n", ct); -+ return NF_ACCEPT; -+ } -+ -+ /* - * Extract TCP header to obtain port information - */ - tcp_hdr = ecm_tracker_tcp_check_header_and_read(skb, iph, &tcp_hdr_buff); -diff --git a/frontends/sfe/ecm_sfe_ported_ipv4.c b/frontends/sfe/ecm_sfe_ported_ipv4.c -index e034cde..df1ce57 100644 ---- a/frontends/sfe/ecm_sfe_ported_ipv4.c -+++ b/frontends/sfe/ecm_sfe_ported_ipv4.c -@@ -1805,8 +1805,25 @@ unsigned int ecm_sfe_ported_ipv4_process(struct net_device *out_dev, struct net_ - int protocol = (int)orig_tuple->dst.protonum; - __be16 *layer4hdr = NULL; - -+ /* -+ * Unconfirmed connection may be dropped by Linux at the final step, -+ * So we don't allow acceleration for the unconfirmed connections. -+ */ -+ if (likely(ct) && !nf_ct_is_confirmed(ct)) { -+ DEBUG_WARN("%p: Unconfirmed connection\n", ct); -+ return NF_ACCEPT; -+ } -+ - if (protocol == IPPROTO_TCP) { - /* -+ * Don't try to manage a non-established connection. -+ */ -+ if (likely(ct) && !test_bit(IPS_ASSURED_BIT, &ct->status)) { -+ DEBUG_WARN("%p: Non-established TCP connection\n", ct); -+ return NF_ACCEPT; -+ } -+ -+ /* - * Extract TCP header to obtain port information - */ - tcp_hdr = ecm_tracker_tcp_check_header_and_read(skb, iph, &tcp_hdr_buff); -diff --git a/frontends/sfe/ecm_sfe_ported_ipv6.c b/frontends/sfe/ecm_sfe_ported_ipv6.c -index 6ac05ad..657a1c7 100644 ---- a/frontends/sfe/ecm_sfe_ported_ipv6.c -+++ b/frontends/sfe/ecm_sfe_ported_ipv6.c -@@ -1746,8 +1746,25 @@ unsigned int ecm_sfe_ported_ipv6_process(struct net_device *out_dev, - int protocol = (int)orig_tuple->dst.protonum; - __be16 *layer4hdr = NULL; - -+ /* -+ * Unconfirmed connection may be dropped by Linux at the final step, -+ * So we don't allow acceleration for the unconfirmed connections. -+ */ -+ if (likely(ct) && !nf_ct_is_confirmed(ct)) { -+ DEBUG_WARN("%p: Unconfirmed connection\n", ct); -+ return NF_ACCEPT; -+ } -+ - if (protocol == IPPROTO_TCP) { - /* -+ * Don't try to manage a non-established connection. -+ */ -+ if (likely(ct) && !test_bit(IPS_ASSURED_BIT, &ct->status)) { -+ DEBUG_WARN("%p: Non-established TCP connection\n", ct); -+ return NF_ACCEPT; -+ } -+ -+ /* - * Extract TCP header to obtain port information - */ - tcp_hdr = ecm_tracker_tcp_check_header_and_read(skb, iph, &tcp_hdr_buff); --- -cgit v1.1 - diff --git a/root/package/qca/nss/qca-nss-ecm/patches/401-Fix-NSS-stats-request-roll-over-issue.patch b/root/package/qca/nss/qca-nss-ecm/patches/401-Fix-NSS-stats-request-roll-over-issue.patch deleted file mode 100644 index 217054bb..00000000 --- a/root/package/qca/nss/qca-nss-ecm/patches/401-Fix-NSS-stats-request-roll-over-issue.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 9ad19ffdcfdf77baf3abd4fcc933fd3dc8e791a5 Mon Sep 17 00:00:00 2001 -From: Murat Sezgin -Date: Sat, 20 Jun 2020 09:41:01 -0700 -Subject: [qca-nss-ecm] Fix NSS stats request roll over issue - -Use the correct timer API to check the next request time -when jiffies wrap happens. - -Signed-off-by: Murat Sezgin -Change-Id: I18646d28df7e17daeff2986dfe4bd73866d47668 ---- - frontends/nss/ecm_nss_ipv4.c | 4 ++-- - frontends/nss/ecm_nss_ipv6.c | 4 ++-- - 2 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/frontends/nss/ecm_nss_ipv4.c b/frontends/nss/ecm_nss_ipv4.c -index 3eaf5d8..80e1aee 100644 ---- a/frontends/nss/ecm_nss_ipv4.c -+++ b/frontends/nss/ecm_nss_ipv4.c -@@ -2421,10 +2421,10 @@ static void ecm_nss_ipv4_stats_sync_req_work(struct work_struct *work) - current_jiffies = jiffies; - - if (time_is_after_jiffies(ecm_nss_ipv4_roll_check_jiffies)) { -- ecm_nss_ipv4_next_req_time = 0; -+ ecm_nss_ipv4_next_req_time = jiffies + ECM_NSS_IPV4_STATS_SYNC_PERIOD; - } - -- if (ecm_nss_ipv4_next_req_time > current_jiffies) { -+ if (time_after(ecm_nss_ipv4_next_req_time, current_jiffies)) { - msleep_interruptible(jiffies_to_msecs(ecm_nss_ipv4_next_req_time - current_jiffies)); - } - ecm_nss_ipv4_roll_check_jiffies = jiffies; -diff --git a/frontends/nss/ecm_nss_ipv6.c b/frontends/nss/ecm_nss_ipv6.c -index 288dc55..483421e 100644 ---- a/frontends/nss/ecm_nss_ipv6.c -+++ b/frontends/nss/ecm_nss_ipv6.c -@@ -2135,10 +2135,10 @@ static void ecm_nss_ipv6_stats_sync_req_work(struct work_struct *work) - current_jiffies = jiffies; - - if (time_is_after_jiffies(ecm_nss_ipv6_roll_check_jiffies)) { -- ecm_nss_ipv6_next_req_time = 0; -+ ecm_nss_ipv6_next_req_time = jiffies + ECM_NSS_IPV6_STATS_SYNC_PERIOD; - } - -- if (ecm_nss_ipv6_next_req_time > current_jiffies) { -+ if (time_after(ecm_nss_ipv6_next_req_time, current_jiffies)) { - msleep_interruptible(jiffies_to_msecs(ecm_nss_ipv6_next_req_time - current_jiffies)); - } - ecm_nss_ipv6_roll_check_jiffies = jiffies; --- -cgit v1.1 - diff --git a/root/package/qca/nss/qca-nss-ecm/patches/401-Fix-for-ref-leak-during-multicast.patch b/root/package/qca/nss/qca-nss-ecm/patches/401-Fix-for-ref-leak-during-multicast.patch deleted file mode 100644 index e1df653b..00000000 --- a/root/package/qca/nss/qca-nss-ecm/patches/401-Fix-for-ref-leak-during-multicast.patch +++ /dev/null @@ -1,112 +0,0 @@ -From 4b41703a181b7187d9ff8cb744eb96d09997387c Mon Sep 17 00:00:00 2001 -From: Suman Ghosh -Date: Wed, 19 Feb 2020 15:09:19 +0530 -Subject: [qca-nss-ecm] Fix for ref leak during multicast 'to' hierarchy - creation - -Change-Id: I89df9dbe5ea054cf3b87d55ce68a751cb1d6c24f -Signed-off-by: Suman Ghosh ---- - ecm_interface.c | 34 ++++++++++++++++++++++++++++++---- - 1 file changed, 30 insertions(+), 4 deletions(-) - -diff --git a/ecm_interface.c b/ecm_interface.c -index 4f7a886..2a0ca5b 100644 ---- a/ecm_interface.c -+++ b/ecm_interface.c -@@ -3885,13 +3885,13 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ - dest_dev = dev_get_by_index(&init_net, *dst_if_index); - if (!dest_dev) { - if (!src_dev_is_bridge) { -- int i; -- - /* - * If already constructed any interface heirarchies before hitting - * this error condition then Deref all interface heirarchies. - */ - if (valid_if > 0) { -+ int i; -+ - for (i = 0; i < valid_if; i++) { - ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i); - ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces); -@@ -3902,11 +3902,14 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ - /* - * If valid netdev not found, Return 0 - */ -+ if (br_dev_src) { -+ dev_put(br_dev_src); -+ } -+ - return 0; - } - - dest_dev = br_dev_src; -- - } - - dest_dev_type = dest_dev->type; -@@ -3945,6 +3948,10 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ - } - } - -+ if (br_dev_src && (dest_dev != br_dev_src)) { -+ dev_put(br_dev_src); -+ } -+ - dev_put(dest_dev); - return 0; - } -@@ -3972,6 +3979,10 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ - ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]); - } - -+ if (br_dev_src && (dest_dev != br_dev_src)) { -+ dev_put(br_dev_src); -+ } -+ - dev_put(dest_dev); - dev_put(mc_br_slave_dev); - return 0; -@@ -3997,6 +4008,10 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ - } - } - -+ if (br_dev_src && (dest_dev != br_dev_src)) { -+ dev_put(br_dev_src); -+ } -+ - dev_put(dest_dev); - dev_put(mc_br_slave_dev); - return 0; -@@ -4032,6 +4047,10 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ - } - } - -+ if (br_dev_src && (dest_dev != br_dev_src)) { -+ dev_put(br_dev_src); -+ } -+ - dev_put(dest_dev); - return 0; - } -@@ -4042,8 +4061,15 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ - valid_if++; - } - -- dev_put(dest_dev); -+ if (dest_dev != br_dev_src) { -+ dev_put(dest_dev); -+ } - } -+ -+ if (br_dev_src) { -+ dev_put(br_dev_src); -+ } -+ - return total_ii_count; - } - EXPORT_SYMBOL(ecm_interface_multicast_heirarchy_construct_routed); --- -cgit v1.1 - diff --git a/root/package/qca/nss/qca-nss-ecm/patches/401-Fix-neighbour-solicitation-send-function.patch b/root/package/qca/nss/qca-nss-ecm/patches/401-Fix-neighbour-solicitation-send-function.patch deleted file mode 100644 index 7d32d6fd..00000000 --- a/root/package/qca/nss/qca-nss-ecm/patches/401-Fix-neighbour-solicitation-send-function.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 72e3ae508906553e7bc982bf3c0d99bb1cbe9008 Mon Sep 17 00:00:00 2001 -From: Murat Sezgin -Date: Wed, 20 Nov 2019 16:23:06 -0800 -Subject: [qca-nss-ecm] Fix neighbour solicitation send function. - -dst_ops->neigh_lookup function pointer is set to the -ip6_neigh_lookup function. This function returns an -error pointer with the ERR_PTR() macro. So, we should -check the return value of this function pointer with -the IS_ERR() macro. - -Change-Id: I188a6e53278faaa68f1854524f612efc1f7451fe -Signed-off-by: Murat Sezgin ---- - ecm_interface.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ecm_interface.c b/ecm_interface.c -index 3f8554b..36509f0 100644 ---- a/ecm_interface.c -+++ b/ecm_interface.c -@@ -1100,7 +1100,7 @@ void ecm_interface_send_neighbour_solicitation(struct net_device *dev, ip_addr_t - #else - neigh = rt6i->dst.ops->neigh_lookup(&rt6i->dst, NULL, &dst_addr); - #endif -- if (neigh == NULL) { -+ if (IS_ERR(neigh)) { - DEBUG_TRACE("Neighbour lookup failure for destination IPv6 address " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(addr)); - dst_release(&rt6i->dst); - return; --- -cgit v1.1 - diff --git a/root/package/qca/nss/qca-nss-ecm/patches/402-Reference-leak-during-multicast_PPPoE-bridge.patch b/root/package/qca/nss/qca-nss-ecm/patches/402-Reference-leak-during-multicast_PPPoE-bridge.patch deleted file mode 100644 index 97ce7a7e..00000000 --- a/root/package/qca/nss/qca-nss-ecm/patches/402-Reference-leak-during-multicast_PPPoE-bridge.patch +++ /dev/null @@ -1,260 +0,0 @@ -From 7c0610828b835b2aab96dd50ec841a3a28689112 Mon Sep 17 00:00:00 2001 -From: Suman Ghosh -Date: Mon, 16 Mar 2020 15:22:18 +0530 -Subject: [qca-nss-ecm] Reference leak during multicast + PPPoE bridge - -Signed-off-by: Suman Ghosh -Change-Id: I4472035f1bbb087e637169762ae2648c0fda792a ---- - ecm_interface.c | 136 +++++++++++++++++++++++++------------------------------- - 1 file changed, 60 insertions(+), 76 deletions(-) - -diff --git a/ecm_interface.c b/ecm_interface.c -index 1614336..c0d2357 100644 ---- a/ecm_interface.c -+++ b/ecm_interface.c -@@ -3796,6 +3796,25 @@ fail: - } - - /* -+ * ecm_interface_hierarchy_delete() -+ * Delete hierarchy of the requested interfaces. -+ */ -+static inline void ecm_interface_hierarchy_delete(struct ecm_db_iface_instance *interfaces, -+ uint32_t *interface_first_base, -+ int valid_if) -+{ -+ struct ecm_db_iface_instance *to_list_single[ECM_DB_IFACE_HEIRARCHY_MAX]; -+ struct ecm_db_iface_instance *ifaces; -+ int i; -+ -+ for (i = 0; i < valid_if; i++) { -+ ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i); -+ ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces); -+ ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]); -+ } -+} -+ -+/* - * ecm_interface_multicast_heirarchy_construct_routed() - * Create destination interface heirarchy for a routed multicast connectiona - * -@@ -3816,7 +3835,6 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ - uint32_t *interface_first_base, bool mfc_update, - __be16 *layer4hdr, struct sk_buff *skb) - { -- struct ecm_db_iface_instance *to_list_single[ECM_DB_IFACE_HEIRARCHY_MAX]; - struct ecm_db_iface_instance *ifaces; - struct net_device *dest_dev = NULL; - struct net_device *br_dev_src = NULL; -@@ -3829,7 +3847,7 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ - int if_index; - int ii_cnt; - int total_ii_count = 0; -- bool src_dev_is_bridge = false; -+ bool src_dev_is_bridge = false, dest_dev_is_br_dev_src = false; - - DEBUG_TRACE("Construct interface heirarchy for dest_addr: " ECM_IP_ADDR_DOT_FMT " src_addr: " ECM_IP_ADDR_DOT_FMT "total destination ifs %d\n", - ECM_IP_ADDR_TO_DOT(packet_dest_addr), ECM_IP_ADDR_TO_DOT(packet_src_addr), max_if); -@@ -3876,6 +3894,7 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ - continue; - } - -+ dest_dev_is_br_dev_src = false; - dest_dev = dev_get_by_index(&init_net, *dst_if_index); - if (!dest_dev) { - if (!src_dev_is_bridge) { -@@ -3884,26 +3903,23 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ - * this error condition then Deref all interface heirarchies. - */ - if (valid_if > 0) { -- int i; -- -- for (i = 0; i < valid_if; i++) { -- ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i); -- ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces); -- ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]); -- } -+ ecm_interface_hierarchy_delete(interfaces, interface_first_base, valid_if); - } - -- /* -- * If valid netdev not found, Return 0 -- */ -- if (br_dev_src) { -- dev_put(br_dev_src); -- } -- -- return 0; -+ goto fail1; - } - - dest_dev = br_dev_src; -+ -+ /* -+ * In some cases when WAN interface is added to bridge and traffic is downstream, -+ * the bridge device is part of the destination list from MFC, and at the same time -+ * 'src_dev_is_bridge' will be true as well. In such cases we will need to release -+ * the hold on the bridge device separately for dest_dev and br_dev_src. -+ * Setting this flag to true indicates that this is not the case, -+ * and that releasing the hold once is enough -+ */ -+ dest_dev_is_br_dev_src = true; - } - - dest_dev_type = dest_dev->type; -@@ -3927,7 +3943,6 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ - } - - if ((if_num < 0) || (if_num > ECM_DB_MULTICAST_IF_MAX)) { -- int i; - DEBUG_WARN("MCS is not ready\n"); - - /* -@@ -3935,19 +3950,10 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ - * this error condition then Deref all interface heirarchies. - */ - if (valid_if > 0) { -- for (i = 0; i < valid_if; i++) { -- ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i); -- ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces); -- ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]); -- } -+ ecm_interface_hierarchy_delete(interfaces, interface_first_base, valid_if); - } - -- if (br_dev_src && (dest_dev != br_dev_src)) { -- dev_put(br_dev_src); -- } -- -- dev_put(dest_dev); -- return 0; -+ goto fail2; - } - - if (in_dev && !mfc_update) { -@@ -3955,34 +3961,20 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ - } - - for (br_if = 0; br_if < if_num; br_if++) { -+ int total_if = valid_if + br_if; -+ - mc_br_slave_dev = dev_get_by_index(&init_net, mc_dst_if_index[br_if]); - if (!mc_br_slave_dev) { - continue; - } - -- if ((valid_if + br_if) > ECM_DB_MULTICAST_IF_MAX) { -- int i; -- -- /* -- * If already constructed any interface heirarchies before hitting -- * this error condition then Deref all interface heirarchies. -- */ -- for (i = 0; i < (valid_if + br_if); i++) { -- ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i); -- ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces); -- ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]); -- } -- -- if (br_dev_src && (dest_dev != br_dev_src)) { -- dev_put(br_dev_src); -- } -- -- dev_put(dest_dev); -+ if (total_if > ECM_DB_MULTICAST_IF_MAX) { -+ ecm_interface_hierarchy_delete(interfaces, interface_first_base, total_if); - dev_put(mc_br_slave_dev); -- return 0; -+ goto fail2; - } - -- ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, valid_if + br_if); -+ ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, total_if); - /* - * Construct a single interface heirarchy of a multicast dev. - */ -@@ -3993,25 +3985,15 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ - * If already constructed any interface heirarchies before hitting - * this error condition then Deref all interface heirarchies. - */ -- if ((valid_if + br_if) > 0) { -- int i; -- for (i = 0; i < (valid_if + br_if); i++) { -- ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i); -- ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces); -- ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]); -- } -- } -- -- if (br_dev_src && (dest_dev != br_dev_src)) { -- dev_put(br_dev_src); -+ if (total_if > 0) { -+ ecm_interface_hierarchy_delete(interfaces, interface_first_base, total_if); - } - -- dev_put(dest_dev); - dev_put(mc_br_slave_dev); -- return 0; -+ goto fail2; - } - -- interface_first = ecm_db_multicast_if_first_get_at_index(interface_first_base, (valid_if + br_if)); -+ interface_first = ecm_db_multicast_if_first_get_at_index(interface_first_base, total_if); - *interface_first = ii_cnt; - total_ii_count += ii_cnt; - dev_put(mc_br_slave_dev); -@@ -4033,20 +4015,10 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ - * this error condition then Deref all interface heirarchies. - */ - if (valid_if > 0) { -- int i; -- for (i = 0; i < valid_if; i++) { -- ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i); -- ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces); -- ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]); -- } -- } -- -- if (br_dev_src && (dest_dev != br_dev_src)) { -- dev_put(br_dev_src); -+ ecm_interface_hierarchy_delete(interfaces, interface_first_base, valid_if); - } - -- dev_put(dest_dev); -- return 0; -+ goto fail2; - } - - interface_first = ecm_db_multicast_if_first_get_at_index(interface_first_base, valid_if); -@@ -4055,7 +4027,7 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ - valid_if++; - } - -- if (dest_dev != br_dev_src) { -+ if (!dest_dev_is_br_dev_src) { - dev_put(dest_dev); - } - } -@@ -4065,6 +4037,18 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_ - } - - return total_ii_count; -+ -+fail2: -+ if (!dest_dev_is_br_dev_src) { -+ dev_put(dest_dev); -+ } -+ -+fail1: -+ if (br_dev_src) { -+ dev_put(br_dev_src); -+ } -+ -+ return 0; - } - EXPORT_SYMBOL(ecm_interface_multicast_heirarchy_construct_routed); - --- -cgit v1.1 - diff --git a/root/package/qca/nss/qca-nss-ecm/patches/403-Access-global-accelerated-count-under-lock.patch b/root/package/qca/nss/qca-nss-ecm/patches/403-Access-global-accelerated-count-under-lock.patch deleted file mode 100644 index d458e113..00000000 --- a/root/package/qca/nss/qca-nss-ecm/patches/403-Access-global-accelerated-count-under-lock.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 65a49ebd1bd12b9952dfa214de0a2da43ba2abed Mon Sep 17 00:00:00 2001 -From: Bhaskar Valaboju -Date: Tue, 13 Aug 2019 14:21:03 +0530 -Subject: [qca-nss-ecm]: Access global ipv4/ipv6 accelerated count under lock - -Flow accelerated count maintained as global variables are accessed -in multiple kernel contexts. These counters are updated under lock, -but read without lock. Read is in kernel thread context (workqueue) -and sometimes it is taking stale entry (0) and doesn't change. -Lock is added to read correct value. - -Change-Id: I74cf27fe5097c6ae7dfcc06319762a8a322d79a3 -Signed-off-by: Bhaskar Valaboju ---- - frontends/nss/ecm_nss_ipv4.c | 3 +++ - frontends/nss/ecm_nss_ipv6.c | 3 +++ - 2 files changed, 6 insertions(+) - -(limited to 'frontends') - -diff --git a/frontends/nss/ecm_nss_ipv4.c b/frontends/nss/ecm_nss_ipv4.c -index afd660e..4e66cdf 100644 ---- a/frontends/nss/ecm_nss_ipv4.c -+++ b/frontends/nss/ecm_nss_ipv4.c -@@ -2288,10 +2288,13 @@ static void ecm_nss_ipv4_stats_sync_req_work(struct work_struct *work) - int retry = 3; - unsigned long int current_jiffies; - -+ spin_lock_bh(&ecm_nss_ipv4_lock); - if (ecm_nss_ipv4_accelerated_count == 0) { -+ spin_unlock_bh(&ecm_nss_ipv4_lock); - DEBUG_TRACE("There is no accelerated IPv4 connection\n"); - goto reschedule; - } -+ spin_unlock_bh(&ecm_nss_ipv4_lock); - - usleep_range(ECM_NSS_IPV4_STATS_SYNC_UDELAY - 100, ECM_NSS_IPV4_STATS_SYNC_UDELAY); - -diff --git a/frontends/nss/ecm_nss_ipv6.c b/frontends/nss/ecm_nss_ipv6.c -index 1f7f51e..55849e7 100644 ---- a/frontends/nss/ecm_nss_ipv6.c -+++ b/frontends/nss/ecm_nss_ipv6.c -@@ -1998,10 +1998,13 @@ static void ecm_nss_ipv6_stats_sync_req_work(struct work_struct *work) - int retry = 3; - unsigned long int current_jiffies; - -+ spin_lock_bh(&ecm_nss_ipv6_lock); - if (ecm_nss_ipv6_accelerated_count == 0) { -+ spin_unlock_bh(&ecm_nss_ipv6_lock); - DEBUG_TRACE("There is no accelerated IPv6 connection\n"); - goto reschedule; - } -+ spin_unlock_bh(&ecm_nss_ipv6_lock); - - usleep_range(ECM_NSS_IPV6_STATS_SYNC_UDELAY - 100, ECM_NSS_IPV6_STATS_SYNC_UDELAY); - --- -cgit v1.1 - diff --git a/root/package/qca/nss/qca-nss-ecm/patches/403-Fix-IPv6-neighbor-solicitation-request.patch b/root/package/qca/nss/qca-nss-ecm/patches/403-Fix-IPv6-neighbor-solicitation-request.patch deleted file mode 100644 index 7639b88a..00000000 --- a/root/package/qca/nss/qca-nss-ecm/patches/403-Fix-IPv6-neighbor-solicitation-request.patch +++ /dev/null @@ -1,83 +0,0 @@ -From b96002061178f399c1e58a9ad821e5096a64f788 Mon Sep 17 00:00:00 2001 -From: Murat Sezgin -Date: Mon, 23 Mar 2020 10:59:39 -0700 -Subject: [qca-nss-ecm] Fix IPv6 neighbor solicitation request - -Send the solicitation request to the GW address, when -a GW address is found, while establishing the node instance. - -Signed-off-by: Murat Sezgin -Change-Id: I2187569bcfd05b0d091cf8c79171ee3c41c39cb9 ---- - frontends/nss/ecm_nss_ipv6.c | 7 ++++--- - frontends/nss/ecm_nss_multicast_ipv6.c | 9 +++++++++ - frontends/sfe/ecm_sfe_ipv6.c | 7 ++++--- - 3 files changed, 17 insertions(+), 6 deletions(-) - -diff --git a/frontends/nss/ecm_nss_ipv6.c b/frontends/nss/ecm_nss_ipv6.c -index c7dd37f..9011e18 100644 ---- a/frontends/nss/ecm_nss_ipv6.c -+++ b/frontends/nss/ecm_nss_ipv6.c -@@ -527,13 +527,14 @@ struct ecm_db_node_instance *ecm_nss_ipv6_node_establish_and_ref(struct ecm_fron - struct net_device *master; - master = ecm_interface_get_and_hold_dev_master(dev); - DEBUG_ASSERT(master, "Expected a master\n"); -- ecm_interface_send_neighbour_solicitation(master, addr); -+ ecm_interface_send_neighbour_solicitation(master, gw_addr); - dev_put(master); - } else { -- ecm_interface_send_neighbour_solicitation(dev, addr); -+ ecm_interface_send_neighbour_solicitation(dev, gw_addr); - } - -- DEBUG_TRACE("Failed to obtain mac for host " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(addr)); -+ DEBUG_TRACE("Failed to obtain mac for host " ECM_IP_ADDR_OCTAL_FMT " gw: " ECM_IP_ADDR_OCTAL_FMT "\n", -+ ECM_IP_ADDR_TO_OCTAL(addr), ECM_IP_ADDR_TO_OCTAL(gw_addr)); - return NULL; - } - done: -diff --git a/frontends/nss/ecm_nss_multicast_ipv6.c b/frontends/nss/ecm_nss_multicast_ipv6.c -index a361eec..38fde95 100644 ---- a/frontends/nss/ecm_nss_multicast_ipv6.c -+++ b/frontends/nss/ecm_nss_multicast_ipv6.c -@@ -2558,6 +2558,15 @@ static struct ecm_db_node_instance *ecm_nss_multicast_ipv6_node_establish_and_re - #endif - if (!ecm_interface_mac_addr_get(addr, node_addr, &on_link, gw_addr)) { - DEBUG_TRACE("Failed to obtain mac for host " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(addr)); -+ -+ /* -+ * If there is a gw_addr found during the lookup, use that address -+ * for neighbour solicitation request. -+ */ -+ if (!ECM_IP_ADDR_IS_NULL(gw_addr)) { -+ ECM_IP_ADDR_COPY(addr, gw_addr); -+ } -+ - if (ecm_front_end_is_bridge_port(dev)) { - struct net_device *master; - master = ecm_interface_get_and_hold_dev_master(dev); -diff --git a/frontends/sfe/ecm_sfe_ipv6.c b/frontends/sfe/ecm_sfe_ipv6.c -index 3fd5d46..51a9ccb 100644 ---- a/frontends/sfe/ecm_sfe_ipv6.c -+++ b/frontends/sfe/ecm_sfe_ipv6.c -@@ -256,13 +256,14 @@ struct ecm_db_node_instance *ecm_sfe_ipv6_node_establish_and_ref(struct ecm_fron - struct net_device *master; - master = ecm_interface_get_and_hold_dev_master(dev); - DEBUG_ASSERT(master, "Expected a master\n"); -- ecm_interface_send_neighbour_solicitation(master, addr); -+ ecm_interface_send_neighbour_solicitation(master, gw_addr); - dev_put(master); - } else { -- ecm_interface_send_neighbour_solicitation(dev, addr); -+ ecm_interface_send_neighbour_solicitation(dev, gw_addr); - } - -- DEBUG_TRACE("Failed to obtain mac for host " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(addr)); -+ DEBUG_TRACE("Failed to obtain mac for host " ECM_IP_ADDR_OCTAL_FMT " gw: " ECM_IP_ADDR_OCTAL_FMT "\n", -+ ECM_IP_ADDR_TO_OCTAL(addr), ECM_IP_ADDR_TO_OCTAL(gw_addr)); - return NULL; - } - done: --- -cgit v1.1 - diff --git a/root/package/qca/nss/qca-nss-ecm/patches/404-IPv6-solicitation-fix-with-zero-gateway-address.patch b/root/package/qca/nss/qca-nss-ecm/patches/404-IPv6-solicitation-fix-with-zero-gateway-address.patch deleted file mode 100644 index bdedff44..00000000 --- a/root/package/qca/nss/qca-nss-ecm/patches/404-IPv6-solicitation-fix-with-zero-gateway-address.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 5b51ae2f1eca61c6f68e40a05333da5a362ff327 Mon Sep 17 00:00:00 2001 -From: Murat Sezgin -Date: Mon, 13 Apr 2020 09:01:48 -0700 -Subject: [qca-nss-ecm] IPv6 solicitation fix with zero gateway address - -The ECM function can find a zero gateway address for -a host IP address. In this case, we need to use the -host IP address while sending the solicitation request. - -Signed-off-by: Murat Sezgin -Change-Id: I1979834088ddfe1843566f51f64348f79e2df0fc ---- - frontends/nss/ecm_nss_ipv6.c | 11 ++++++++++- - frontends/sfe/ecm_sfe_ipv6.c | 11 ++++++++++- - 2 files changed, 20 insertions(+), 2 deletions(-) - -diff --git a/frontends/nss/ecm_nss_ipv6.c b/frontends/nss/ecm_nss_ipv6.c -index a05781b..9eb591c 100644 ---- a/frontends/nss/ecm_nss_ipv6.c -+++ b/frontends/nss/ecm_nss_ipv6.c -@@ -516,7 +516,16 @@ struct ecm_db_node_instance *ecm_nss_ipv6_node_establish_and_ref(struct ecm_fron - return NULL; - } - -- DEBUG_TRACE("Have a gw address " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(gw_addr)); -+ /* -+ * The found gateway address can be all zeros, -+ * so in this case use the host address. -+ */ -+ if (ECM_IP_ADDR_IS_NULL(gw_addr)) { -+ DEBUG_TRACE("GW address is found as zeros, so use host IP\n"); -+ ECM_IP_ADDR_COPY(gw_addr, addr); -+ } else { -+ DEBUG_TRACE("Have a gw address " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(gw_addr)); -+ } - - if (ecm_interface_mac_addr_get_no_route(dev, gw_addr, node_addr)) { - DEBUG_TRACE("Found the mac address for gateway\n"); -diff --git a/frontends/sfe/ecm_sfe_ipv6.c b/frontends/sfe/ecm_sfe_ipv6.c -index 51a9ccb..e609df7 100644 ---- a/frontends/sfe/ecm_sfe_ipv6.c -+++ b/frontends/sfe/ecm_sfe_ipv6.c -@@ -245,7 +245,16 @@ struct ecm_db_node_instance *ecm_sfe_ipv6_node_establish_and_ref(struct ecm_fron - return NULL; - } - -- DEBUG_TRACE("Have a gw address " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(gw_addr)); -+ /* -+ * The found gateway address can be all zeros, -+ * so in this case use the host address. -+ */ -+ if (ECM_IP_ADDR_IS_NULL(gw_addr)) { -+ DEBUG_TRACE("GW address is found as zeros, so use host IP\n"); -+ ECM_IP_ADDR_COPY(gw_addr, addr); -+ } else { -+ DEBUG_TRACE("Have a gw address " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(gw_addr)); -+ } - - if (ecm_interface_mac_addr_get_no_route(dev, gw_addr, node_addr)) { - DEBUG_TRACE("Found the mac address for gateway\n"); --- -cgit v1.1 - diff --git a/root/package/qca/nss/qca-nss-ecm/patches/405-Allow-egress-on-same-port-when-bridge-hairpin-is-enabled.patch b/root/package/qca/nss/qca-nss-ecm/patches/405-Allow-egress-on-same-port-when-bridge-hairpin-is-enabled.patch deleted file mode 100644 index a236fb75..00000000 --- a/root/package/qca/nss/qca-nss-ecm/patches/405-Allow-egress-on-same-port-when-bridge-hairpin-is-enabled.patch +++ /dev/null @@ -1,126 +0,0 @@ -From e23eabd570eabde1d1fc803127a97fd101642467 Mon Sep 17 00:00:00 2001 -From: Varsha Mishra -Date: Fri, 12 Jun 2020 01:06:58 +0530 -Subject: [qca-nss-ecm] Allow egress on same port when bridge hairpin is - enabled. - -When bridge hairpin is enabled, allow egress on same port. Wi-Fi intrabss -frames are getting exceptioned to stack. Bridge gets to make the decision -whether these frames need to be forwarded or dropped. - -Signed-off-by: Varsha Mishra -Change-Id: Ibdd72264d8887330ba0297ed12cbcfc390065bff ---- - frontends/nss/ecm_nss_ipv4.c | 28 ++++++++++++++++++++++------ - frontends/nss/ecm_nss_ipv6.c | 28 ++++++++++++++++++++++------ - 2 files changed, 44 insertions(+), 12 deletions(-) - -diff --git a/frontends/nss/ecm_nss_ipv4.c b/frontends/nss/ecm_nss_ipv4.c -index 60f799b..51c9ebf 100644 ---- a/frontends/nss/ecm_nss_ipv4.c -+++ b/frontends/nss/ecm_nss_ipv4.c -@@ -1756,7 +1756,9 @@ static unsigned int ecm_nss_ipv4_bridge_post_routing_hook(void *priv, - * Case 2: - * For routed packets the skb will have the src mac matching the bridge mac. - * Case 3: -- * If the packet was not local (case 1) or routed (case 2) then we process. -+ * If the packet was not local (case 1) or routed (case 2) then -+ * we process. There is an exception to case 2: when hairpin mode -+ * is enabled, we process. - */ - - /* -@@ -1768,14 +1770,28 @@ static unsigned int ecm_nss_ipv4_bridge_post_routing_hook(void *priv, - dev_put(bridge); - return NF_ACCEPT; - } -+ -+ /* -+ * This flag needs to be checked in slave port(eth0/ath0) -+ * and not on master interface(br-lan). Hairpin flag can be -+ * enabled/disabled for ports individually. -+ */ - if (in == out) { -- DEBUG_TRACE("skb: %p, bridge: %p (%s), port bounce on %p (%s)\n", skb, bridge, bridge->name, out, out->name); -- dev_put(in); -- dev_put(bridge); -- return NF_ACCEPT; -+ if (!br_is_hairpin_enabled(in)) { -+ DEBUG_TRACE("skb: %p, bridge: %p (%s), ignoring" -+ "the packet, hairpin not enabled" -+ "on port %p (%s)\n", skb, bridge, -+ bridge->name, out, out->name); -+ dev_put(in); -+ dev_put(bridge); -+ return NF_ACCEPT; -+ } -+ DEBUG_TRACE("skb: %p, bridge: %p (%s), hairpin enabled on port" -+ "%p (%s)\n", skb, bridge, bridge->name, out, out->name); - } -+ -+ /* -+ * Case 2: Routed trafffic would be handled by the INET post routing. -+ */ - if (!ecm_mac_addr_equal(skb_eth_hdr->h_source, bridge->dev_addr)) { -- /* -- * Case 2: Routed trafffic would be handled by the INET post routing. -- */ - DEBUG_TRACE("skb: %p, Ignoring routed packet to bridge: %p (%s)\n", skb, bridge, bridge->name); - goto skip_ipv4_bridge_flow; - } -diff --git a/frontends/nss/ecm_nss_ipv6.c b/frontends/nss/ecm_nss_ipv6.c -index 6ad425e..160c94c 100644 ---- a/frontends/nss/ecm_nss_ipv6.c -+++ b/frontends/nss/ecm_nss_ipv6.c -@@ -1498,7 +1498,9 @@ static unsigned int ecm_nss_ipv6_bridge_post_routing_hook(void *priv, - * Case 2: - * For routed packets the skb will have the src mac matching the bridge mac. - * Case 3: -- * If the packet was not local (case 1) or routed (case 2) then we process. -+ * If the packet was not local (case 1) or routed (case 2) then -+ * we process. There is an exception to case 2: when hairpin mode -+ * is enabled, we process. - */ - - /* -@@ -1510,14 +1512,28 @@ static unsigned int ecm_nss_ipv6_bridge_post_routing_hook(void *priv, - dev_put(bridge); - return NF_ACCEPT; - } -+ -+ /* -+ * This flag needs to be checked in slave port(eth0/ath0) -+ * and not on master interface(br-lan). Hairpin flag can be -+ * enabled/disabled for ports individually. -+ */ - if (in == out) { -- DEBUG_TRACE("skb: %p, bridge: %p (%s), port bounce on %p (%s)\n", skb, bridge, bridge->name, out, out->name); -- dev_put(in); -- dev_put(bridge); -- return NF_ACCEPT; -+ if (!br_is_hairpin_enabled(in)) { -+ DEBUG_TRACE("skb: %p, bridge: %p (%s), ignoring" -+ "the packet, hairpin not enabled" -+ "on port %p (%s)\n", skb, bridge, -+ bridge->name, out, out->name); -+ dev_put(in); -+ dev_put(bridge); -+ return NF_ACCEPT; -+ } -+ DEBUG_TRACE("skb: %p, bridge: %p (%s), hairpin enabled on port" -+ "%p (%s)\n", skb, bridge, bridge->name, out, out->name); - } -+ -+ /* -+ * Case 2: Routed trafffic would be handled by the INET post routing. -+ */ - if (!ecm_mac_addr_equal(skb_eth_hdr->h_source, bridge->dev_addr)) { -- /* -- * Case 2: Routed trafffic would be handled by the INET post routing. -- */ - DEBUG_TRACE("skb: %p, Ignoring routed packet to bridge: %p (%s)\n", skb, bridge, bridge->name); - goto skip_ipv6_bridge_flow; - } --- -cgit v1.1 - diff --git a/root/package/qca/nss/qca-nss-gmac/Makefile b/root/package/qca/nss/qca-nss-gmac/Makefile deleted file mode 100644 index 8b39f043..00000000 --- a/root/package/qca/nss/qca-nss-gmac/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -include $(TOPDIR)/rules.mk -include $(INCLUDE_DIR)/kernel.mk - -PKG_NAME:=qca-nss-gmac -PKG_RELEASE:=1 - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://source.codeaurora.org/quic/qsdk/oss/lklm/nss-gmac -PKG_SOURCE_VERSION:=9b74deef2816d91e58926e6fab7a6ff931eb3b22 -PKG_MIRROR_HASH:=a1939caa638414323e60f7d29f797ea831c6036e424b8e7bd6cf2d3d874de064 - -include $(INCLUDE_DIR)/package.mk - -define KernelPackage/qca-nss-gmac - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Devices - DEPENDS:=@TARGET_ipq806x @LINUX_5_4 - TITLE:=Kernel driver for NSS gmac - FILES:=$(PKG_BUILD_DIR)/ipq806x/qca-nss-gmac.ko - AUTOLOAD:=$(call AutoLoad,31,qca-nss-gmac) -endef - -define KernelPackage/qca-nss-gmac/Description -This package contains a NSS driver for QCA chipset -endef - -define Build/InstallDev - mkdir -p $(1)/usr/include/qca-nss-gmac - $(CP) $(PKG_BUILD_DIR)/ipq806x/exports/* $(1)/usr/include/qca-nss-gmac/ -endef - -EXTRA_CFLAGS+= \ - -DCONFIG_NSS_DEBUG_LEVEL=4 \ - -I$(PKG_BUILD_DIR)/nss_hal/include \ - -I$(PKG_BUILD_DIR)/nss_hal/$(BOARD) - -define Build/Compile - $(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \ - $(KERNEL_MAKE_FLAGS) \ - $(PKG_MAKE_FLAGS) \ - M="$(PKG_BUILD_DIR)" \ - EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ - modules -endef - -$(eval $(call KernelPackage,qca-nss-gmac)) diff --git a/root/package/qca/nss/qca-nss-gmac/patches/100-kernel-5.4-support.patch b/root/package/qca/nss/qca-nss-gmac/patches/100-kernel-5.4-support.patch deleted file mode 100644 index f3b91abc..00000000 --- a/root/package/qca/nss/qca-nss-gmac/patches/100-kernel-5.4-support.patch +++ /dev/null @@ -1,279 +0,0 @@ ---- a/ipq806x/nss_gmac_ctrl.c -+++ b/ipq806x/nss_gmac_ctrl.c -@@ -322,16 +322,15 @@ void nss_gmac_tx_rx_desc_init(struct nss - * (for example "ifconfig eth0"). - * @param[in] pointer to net_device structure. - * @param[in] pointer to net_device_stats64 structure. -- * @return Returns pointer to net_device_stats64 structure. - */ --struct rtnl_link_stats64 *nss_gmac_get_stats64(struct net_device *netdev, -+void nss_gmac_get_stats64(struct net_device *netdev, - struct rtnl_link_stats64 *stats) - { - struct nss_gmac_dev *gmacdev = (struct nss_gmac_dev *)netdev_priv(netdev); - BUG_ON(gmacdev == NULL); - - if (!gmacdev->data_plane_ops) -- return stats; -+ return; - - spin_lock_bh(&gmacdev->stats_lock); - gmacdev->data_plane_ops->get_stats(gmacdev->data_plane_ctx, &gmacdev->nss_stats); -@@ -354,8 +353,6 @@ struct rtnl_link_stats64 *nss_gmac_get_s - stats->tx_fifo_errors = gmacdev->nss_stats.tx_underflow_errors; - stats->tx_window_errors = gmacdev->nss_stats.tx_late_collision_errors; - spin_unlock_bh(&gmacdev->stats_lock); -- -- return stats; - } - - -@@ -439,7 +436,7 @@ static int nss_gmac_mtnp_show(struct dev - static int nss_gmac_tstamp_show(struct device *dev, struct device_attribute *attr, char *buf) - { - struct nss_gmac_dev *gmacdev = (struct nss_gmac_dev *)netdev_priv(to_net_dev(dev)); -- struct timeval tv; -+ struct timespec64 ts64; - uint32_t ret, timeout; - uint32_t ts_hi, ts_lo; - -@@ -459,11 +456,12 @@ static int nss_gmac_tstamp_show(struct d - return -1; - } - -- do_gettimeofday(&tv); -+ ktime_get_real_ts64(&ts64); - - ret = snprintf( - buf, PAGE_SIZE, -- "sec:%u nsec:%u time-of-day: %12d.%06d \n", ts_hi, ts_lo, (int)tv.tv_sec, (int)tv.tv_usec); -+ "sec:%u nsec:%u time-of-day: %12d.%06d \n", \ -+ ts_hi, ts_lo, (int)ts64.tv_sec, (int)(ts64.tv_nsec / NSEC_PER_USEC)); - - return ret; - } -@@ -951,7 +949,7 @@ static const struct net_device_ops nss_g - * @param[in] pointer to advertised features - * @return void - */ --static void nss_gmac_update_features(uint32_t *supp, uint32_t *adv) -+static void nss_gmac_update_features(long unsigned int *supp, long unsigned int *adv) - { - *supp |= NSS_GMAC_SUPPORTED_FEATURES; - *adv |= NSS_GMAC_ADVERTISED_FEATURES; -@@ -1409,8 +1407,8 @@ static int32_t nss_gmac_probe(struct pla - goto nss_gmac_phy_attach_fail; - } - -- nss_gmac_update_features(&(gmacdev->phydev->supported), -- &(gmacdev->phydev->advertising)); -+ nss_gmac_update_features(gmacdev->phydev->supported, -+ gmacdev->phydev->advertising); - gmacdev->phydev->irq = PHY_POLL; - netdev_dbg(netdev, "PHY %s attach OK\n", phy_id); - -@@ -1440,6 +1438,8 @@ static int32_t nss_gmac_probe(struct pla - netdev_dbg(netdev, "%s MII_PHYSID2 - 0x%04x\n", netdev->name, - nss_gmac_mii_rd_reg(gmacdev, gmacdev->phy_base, MII_PHYSID2)); - } else if (gmacdev->phy_base != NSS_GMAC_NO_MDIO_PHY) { -+ SET_NETDEV_DEV(netdev, gmacdev->miibus->parent); -+ - /* - * Issue a phy_attach for the interface connected to a switch - */ ---- a/ipq806x/nss_gmac_ethtool.c -+++ b/ipq806x/nss_gmac_ethtool.c -@@ -143,9 +143,9 @@ static const struct nss_gmac_ethtool_sta - /** - * @brief Array of strings describing private flag names - */ --static const char *gmac_strings_priv_flags[] = { -- "linkpoll", -- "tstamp", -+static const char *gmac_strings_priv_flags[][ETH_GSTRING_LEN] = { -+ {"linkpoll"}, -+ {"tstamp"}, - }; - - #define NSS_GMAC_STATS_LEN ARRAY_SIZE(gmac_gstrings_stats) -@@ -292,6 +292,7 @@ static int nss_gmac_set_pauseparam(struc - { - struct nss_gmac_dev *gmacdev = (struct nss_gmac_dev *)netdev_priv(netdev); - struct phy_device *phydev; -+ long unsigned int *advertising; - - BUG_ON(gmacdev == NULL); - BUG_ON(gmacdev->netdev != netdev); -@@ -327,14 +328,15 @@ static int nss_gmac_set_pauseparam(struc - phydev = gmacdev->phydev; - - /* Update flow control advertisment */ -- phydev->advertising &= ~(ADVERTISED_Pause | ADVERTISED_Asym_Pause); -+ advertising = phydev->advertising; -+ *advertising &= ~(ADVERTISED_Pause | ADVERTISED_Asym_Pause); - - if (gmacdev->pause & FLOW_CTRL_RX) -- phydev->advertising |= -+ *advertising |= - (ADVERTISED_Pause | ADVERTISED_Asym_Pause); - - if (gmacdev->pause & FLOW_CTRL_TX) -- phydev->advertising |= ADVERTISED_Asym_Pause; -+ *advertising |= ADVERTISED_Asym_Pause; - - genphy_config_aneg(gmacdev->phydev); - -@@ -396,12 +398,13 @@ static uint32_t nss_gmac_get_msglevel(st - * @param[in] pointer to struct net_device. - * @param[in] pointer to struct ethtool_cmd. - */ --static int32_t nss_gmac_get_settings(struct net_device *netdev, -- struct ethtool_cmd *ecmd) -+static int nss_gmac_get_settings(struct net_device *netdev, -+ struct ethtool_link_ksettings *elk) - { - struct nss_gmac_dev *gmacdev = (struct nss_gmac_dev *)netdev_priv(netdev); - struct phy_device *phydev = NULL; - uint16_t phyreg; -+ u32 lp_advertising = 0; - - BUG_ON(gmacdev == NULL); - -@@ -413,10 +416,10 @@ static int32_t nss_gmac_get_settings(str - */ - if (!test_bit(__NSS_GMAC_LINKPOLL, &gmacdev->flags)) { - if (gmacdev->forced_speed != SPEED_UNKNOWN) { -- ethtool_cmd_speed_set(ecmd, gmacdev->forced_speed); -- ecmd->duplex = gmacdev->forced_duplex; -- ecmd->mdio_support = 0; -- ecmd->lp_advertising = 0; -+ elk->base.speed = gmacdev->forced_speed; -+ elk->base.duplex = gmacdev->forced_duplex; -+ elk->base.mdio_support = 0; -+ ethtool_convert_legacy_u32_to_link_mode(elk->link_modes.lp_advertising, 0); - return 0; - } else { - /* Non-link polled interfaced must have a forced -@@ -429,63 +429,59 @@ static int32_t nss_gmac_get_settings(struct net_device *netdev, - - /* update PHY status */ - if (phydev->is_c45 == true) { -- ecmd->mdio_support = ETH_MDIO_SUPPORTS_C45; -+ elk->base.mdio_support = ETH_MDIO_SUPPORTS_C45; - } else { - if (genphy_read_status(phydev) != 0) { - return -EIO; - } -- ecmd->mdio_support = ETH_MDIO_SUPPORTS_C22; -+ elk->base.mdio_support = ETH_MDIO_SUPPORTS_C22; - } - - /* Populate capabilities advertised by self */ -- ecmd->advertising = phydev->advertising; -+ bitmap_copy(elk->link_modes.advertising, phydev->advertising, __ETHTOOL_LINK_MODE_MASK_NBITS); - -- ecmd->autoneg = phydev->autoneg; -- -- if (gmacdev->link_state == LINKDOWN) { -- ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN); -- ecmd->duplex = DUPLEX_UNKNOWN; -- } else { -- ethtool_cmd_speed_set(ecmd, phydev->speed); -- ecmd->duplex = phydev->duplex; -- } -- -- ecmd->port = PORT_TP; -- ecmd->phy_address = gmacdev->phy_base; -- ecmd->transceiver = XCVR_EXTERNAL; -+ elk->base.autoneg = phydev->autoneg; -+ elk->base.speed = phydev->speed; -+ elk->base.duplex = phydev->duplex; -+ elk->base.port = PORT_TP; -+ elk->base.phy_address = gmacdev->phy_base; -+ elk->base.transceiver = XCVR_EXTERNAL; - - /* Populate supported capabilities */ -- ecmd->supported = phydev->supported; -+ bitmap_copy(elk->link_modes.supported, phydev->supported, __ETHTOOL_LINK_MODE_MASK_NBITS); - - if (phydev->is_c45 == true) - return 0; - - /* Populate capabilities advertised by link partner */ -+ ethtool_convert_link_mode_to_legacy_u32(&lp_advertising, elk->link_modes.lp_advertising); - phyreg = nss_gmac_mii_rd_reg(gmacdev, gmacdev->phy_base, MII_LPA); - if (phyreg & LPA_10HALF) -- ecmd->lp_advertising |= ADVERTISED_10baseT_Half; -+ lp_advertising |= ADVERTISED_10baseT_Half; - - if (phyreg & LPA_10FULL) -- ecmd->lp_advertising |= ADVERTISED_10baseT_Full; -+ lp_advertising |= ADVERTISED_10baseT_Full; - - if (phyreg & LPA_100HALF) -- ecmd->lp_advertising |= ADVERTISED_100baseT_Half; -+ lp_advertising |= ADVERTISED_100baseT_Half; - - if (phyreg & LPA_100FULL) -- ecmd->lp_advertising |= ADVERTISED_100baseT_Full; -+ lp_advertising |= ADVERTISED_100baseT_Full; - - if (phyreg & LPA_PAUSE_CAP) -- ecmd->lp_advertising |= ADVERTISED_Pause; -+ lp_advertising |= ADVERTISED_Pause; - - if (phyreg & LPA_PAUSE_ASYM) -- ecmd->lp_advertising |= ADVERTISED_Asym_Pause; -+ lp_advertising |= ADVERTISED_Asym_Pause; - - phyreg = nss_gmac_mii_rd_reg(gmacdev, gmacdev->phy_base, MII_STAT1000); - if (phyreg & LPA_1000HALF) -- ecmd->lp_advertising |= ADVERTISED_1000baseT_Half; -+ lp_advertising |= ADVERTISED_1000baseT_Half; - - if (phyreg & LPA_1000FULL) -- ecmd->lp_advertising |= ADVERTISED_1000baseT_Full; -+ lp_advertising |= ADVERTISED_1000baseT_Full; -+ -+ ethtool_convert_legacy_u32_to_link_mode(elk->link_modes.lp_advertising, lp_advertising); - - return 0; - } -@@ -489,8 +495,8 @@ static int32_t nss_gmac_get_settings(str - * @param[in] pointer to struct net_device. - * @param[in] pointer to struct ethtool_cmd. - */ --static int32_t nss_gmac_set_settings(struct net_device *netdev, -- struct ethtool_cmd *ecmd) -+static int nss_gmac_set_settings(struct net_device *netdev, -+ const struct ethtool_link_ksettings *elk) - { - struct nss_gmac_dev *gmacdev = (struct nss_gmac_dev *)netdev_priv(netdev); - struct phy_device *phydev = NULL; -@@ -512,13 +518,13 @@ static int32_t nss_gmac_set_settings(str - return -EPERM; - } - -- if (ecmd->autoneg == AUTONEG_ENABLE) { -+ if (elk->base.autoneg == AUTONEG_ENABLE) { - set_bit(__NSS_GMAC_AUTONEG, &gmacdev->flags); - } else { - clear_bit(__NSS_GMAC_AUTONEG, &gmacdev->flags); - } - -- return phy_ethtool_sset(phydev, ecmd); -+ return phy_ethtool_ksettings_set(phydev, elk); - } - - /** -@@ -580,8 +586,8 @@ struct ethtool_ops nss_gmac_ethtool_ops - .set_pauseparam = &nss_gmac_set_pauseparam, - .nway_reset = &nss_gmac_nway_reset, - .get_wol = &nss_gmac_get_wol, -- .get_settings = &nss_gmac_get_settings, -- .set_settings = &nss_gmac_set_settings, -+ .get_link_ksettings = &nss_gmac_get_settings, -+ .set_link_ksettings = &nss_gmac_set_settings, - .get_strings = &nss_gmac_get_strings, - .get_sset_count = &nss_gmac_get_strset_count, - .get_ethtool_stats = &nss_gmac_get_ethtool_stats, diff --git a/root/package/qca/nss/qca-nss-gmac/patches/101-nss-gmac-test-ptr.patch b/root/package/qca/nss/qca-nss-gmac/patches/101-nss-gmac-test-ptr.patch deleted file mode 100644 index a5bff16b..00000000 --- a/root/package/qca/nss/qca-nss-gmac/patches/101-nss-gmac-test-ptr.patch +++ /dev/null @@ -1,25 +0,0 @@ ---- a/ipq806x/nss_gmac_ctrl.c -+++ b/ipq806x/nss_gmac_ctrl.c -@@ -957,7 +957,8 @@ static int32_t nss_gmac_of_get_pdata(struct device_node *np, - struct net_device *netdev, - struct msm_nss_gmac_platform_data *gmaccfg) - { -- uint8_t *maddr = NULL; -+ int ret; -+ u8 maddr[ETH_ALEN]; - struct nss_gmac_dev *gmacdev = (struct nss_gmac_dev *)netdev_priv(netdev); - struct resource memres_devtree = {0}; - -@@ -991,9 +992,9 @@ static int32_t nss_gmac_of_get_pdata(struct device_node *np, - pr_err("%s: Can't map interrupt\n", np->name); - return -EFAULT; - } -- maddr = (uint8_t *)of_get_mac_address(np); -- if (maddr) -- memcpy(gmaccfg->mac_addr, maddr, ETH_ALEN); -+ ret = of_get_mac_address(np, maddr); -+ if (!ret && is_valid_ether_addr(maddr)) -+ ether_addr_copy(gmaccfg->mac_addr, maddr); - - if (of_address_to_resource(np, 0, &memres_devtree) != 0) - return -EFAULT; diff --git a/root/package/qca/nss/qca-nss-gmac/patches/200-work-around-interface-close-warning.patch b/root/package/qca/nss/qca-nss-gmac/patches/200-work-around-interface-close-warning.patch deleted file mode 100644 index 7cb6d6fa..00000000 --- a/root/package/qca/nss/qca-nss-gmac/patches/200-work-around-interface-close-warning.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- a/ipq806x/nss_gmac_tx_rx_offload.c -+++ b/ipq806x/nss_gmac_tx_rx_offload.c -@@ -1027,8 +1027,10 @@ int nss_gmac_close(struct net_device *ne - nss_gmac_disable_interrupt_all(gmacdev); - gmacdev->data_plane_ops->link_state(gmacdev->data_plane_ctx, 0); - -- if (!IS_ERR(gmacdev->phydev)) -- phy_stop(gmacdev->phydev); -+ if (!IS_ERR(gmacdev->phydev)) { -+ if (test_bit(__NSS_GMAC_LINKPOLL, &gmacdev->flags)) -+ phy_stop(gmacdev->phydev); -+ } - - clear_bit(__NSS_GMAC_UP, &gmacdev->flags); - clear_bit(__NSS_GMAC_CLOSING, &gmacdev->flags); diff --git a/root/package/qca/qca-mcs/Makefile b/root/package/qca/qca-mcs/Makefile deleted file mode 100644 index af9372d8..00000000 --- a/root/package/qca/qca-mcs/Makefile +++ /dev/null @@ -1,54 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=qca-mcs -PKG_RELEASE:=1 - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2021-10-28 -PKG_SOURCE_URL:=https://source.codeaurora.org/quic/qsdk/oss/lklm/qca-mcs -PKG_SOURCE_VERSION:=31f5cd4b83da5a7c0fdca240b4e72677e4523b6e -PKG_MIRROR_HASH:=3e2e25025dc2e771aafe7d8b12f26ac831d123b34bdd7b7e84bd39c1e933491d - -include $(INCLUDE_DIR)/kernel.mk -include $(INCLUDE_DIR)/package.mk - -define KernelPackage/qca-mcs - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Support - TITLE:=QCA Multicast Snooping Support - DEPENDS:=@(TARGET_ipq806x||TARGET_ipq807x) - KCONFIG:= \ - CONFIG_NETFILTER=y \ - CONFIG_BRIDGE_NETFILTER=y - FILES:=$(PKG_BUILD_DIR)/qca-mcs.ko - AUTOLOAD:=$(call AutoLoad,52,qca-mcs) -endef - -define KernelPackage/qca-mcs/description - This package installs the IGMP/MLD Snooping Module -endef - -QCA_MC_SNOOPING_HEADERS= \ - $(PKG_BUILD_DIR)/mc_api.h \ - $(PKG_BUILD_DIR)/mc_ecm.h \ - -define Build/InstallDev - $(INSTALL_DIR) $(1)/usr/include/qca-mcs - $(foreach header_file,$(QCA_MC_SNOOPING_HEADERS), $(CP) $(header_file) $(1)/usr/include/qca-mcs;) - $(foreach header_file,$(QCA_MC_SNOOPING_HEADERS), $(CP) $(header_file) $(1)/usr/include/;) -endef - -QCA_MC_SNOOPING_MAKE_OPTS:= \ - $(KERNEL_MAKE_FLAGS) \ - CONFIG_SUPPORT_MLD=y \ - MDIR=$(PKG_BUILD_DIR) \ - KBUILDPATH=$(LINUX_DIR) \ - KERNELPATH=$(LINUX_SRC_DIR) \ - KERNELRELEASE=$(LINUX_RELEASE) - -define Build/Compile - $(MAKE) -C $(LINUX_DIR) M=$(PKG_BUILD_DIR) $(strip $(QCA_MC_SNOOPING_MAKE_OPTS)) -endef - -$(eval $(call KernelPackage,qca-mcs)) diff --git a/root/package/qca/qca-rfs/Makefile b/root/package/qca/qca-rfs/Makefile deleted file mode 100644 index 7831e4d3..00000000 --- a/root/package/qca/qca-rfs/Makefile +++ /dev/null @@ -1,51 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=qca-rfs -PKG_RELEASE:=1 - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://source.codeaurora.org/quic/qsdk/oss/lklm/qca-rfs -PKG_SOURCE_DATE:=2021-03-17 -PKG_SOURCE_VERSION:=75197c386f477c7b3a6f02489d9903a9409fd5cc -PKG_MIRROR_HASH:=90f1c3ec2e984cf8efa79c85d715ebd8a21e347ab57adbd9695de23e64eea1ec - -include $(INCLUDE_DIR)/kernel.mk -include $(INCLUDE_DIR)/package.mk - -define KernelPackage/qca-rfs - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Support - DEPENDS:=@TARGET_ipq40xx +kmod-ipt-conntrack - TITLE:=Kernel module for QCA Receiving Flow Steering - FILES:=$(PKG_BUILD_DIR)/qrfs.ko - KCONFIG:=\ - CONFIG_NF_CONNTRACK_EVENTS=y \ - CONFIG_NF_CONNTRACK_CHAIN_EVENTS=y - AUTOLOAD:=$(call AutoLoad,29,qrfs) -endef - -define KernelPackage/qca-rfs/Description -QCA-RFS is a kernel module for ESS Receive Flow Steering. -endef - -define Build/Compile - $(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \ - $(KERNEL_MAKE_FLAGS) \ - $(PKG_MAKE_FLAGS) \ - M="$(PKG_BUILD_DIR)" \ - EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ - modules -endef - -define Build/InstallDev - $(INSTALL_DIR) $(1)/usr/include/qca-rfs - $(CP) -rf $(PKG_BUILD_DIR)/rfs_dev.h $(1)/usr/include/qca-rfs -endef - -define KernelPackage/qca-rfs/install - $(INSTALL_DIR) $(1)/etc/init.d - $(INSTALL_BIN) ./files/qrfs.init $(1)/etc/init.d/qrfs -endef - -$(eval $(call KernelPackage,qca-rfs)) diff --git a/root/package/qca/qca-rfs/files/qrfs.init b/root/package/qca/qca-rfs/files/qrfs.init deleted file mode 100644 index f3f8a38c..00000000 --- a/root/package/qca/qca-rfs/files/qrfs.init +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/sh /etc/rc.common -# -# Copyright (c) 2015 The Linux Foundation. All rights reserved. -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -START=70 - -start() { - echo "1" > /proc/qrfs/enable - ip neigh flush all -} - -stop() { - echo "0" > /proc/qrfs/enable -} diff --git a/root/package/qca/qca-rfs/patches/100-add-kernel-5.4-support.patch b/root/package/qca/qca-rfs/patches/100-add-kernel-5.4-support.patch deleted file mode 100644 index b7b2db55..00000000 --- a/root/package/qca/qca-rfs/patches/100-add-kernel-5.4-support.patch +++ /dev/null @@ -1,57 +0,0 @@ ---- a/rfs_cm.c -+++ b/rfs_cm.c -@@ -462,14 +462,6 @@ static int rfs_cm_conntrack_event(unsign - } - - /* -- * If this is an untracked connection then we can't have any state either. -- */ -- if (unlikely(ct == &nf_conntrack_untracked)) { -- RFS_TRACE("ignoring untracked conn\n"); -- return NOTIFY_DONE; -- } -- -- /* - * Ignore anything other than IPv4 connections. - */ - if (unlikely(nf_ct_l3num(ct) != AF_INET)) { ---- a/rfs_rule.c -+++ b/rfs_rule.c -@@ -702,7 +702,7 @@ int rfs_rule_init(void) - - RFS_DEBUG("RFS Rule init\n"); - spin_lock_init(&rr->hash_lock); -- memset(&rr->hash, 0, RFS_RULE_HASH_SIZE); -+ memset(&rr->hash, 0, sizeof(rr->hash)); - - rr->proc_rule = proc_create("rule", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, - rfs_proc_entry, &rule_proc_fops); -@@ -717,7 +717,7 @@ void rfs_rule_exit(void) - struct rfs_rule *rr = &__rr; - - RFS_DEBUG("RFS Rule exit\n"); -- if (rr->proc_rule); -+ if (rr->proc_rule) - remove_proc_entry("rule", rfs_proc_entry); - rfs_rule_destroy_all(); - } ---- a/rfs_wxt.c -+++ b/rfs_wxt.c -@@ -422,7 +422,7 @@ static int rfs_wxt_rx(struct socket *soc - #else - iov_iter_init(&msg.msg_iter, READ, &iov, 1, len); - #endif -- size = sock_recvmsg(sock, &msg, len, msg.msg_flags); -+ size = sock_recvmsg(sock, &msg, msg.msg_flags); - set_fs(oldfs); - - return size; -@@ -510,7 +510,7 @@ int rfs_wxt_stop(void) - } - - RFS_DEBUG("kill rfs_wxt thread"); -- force_sig(SIGKILL, __rwn.thread); -+ send_sig(SIGKILL, __rwn.thread, 1); - if (__rwn.thread) - err = kthread_stop(__rwn.thread); - __rwn.thread = NULL; diff --git a/root/package/qca/qca-rfs/patches/200-rework-nfct-notification.patch b/root/package/qca/qca-rfs/patches/200-rework-nfct-notification.patch deleted file mode 100644 index 81e608c0..00000000 --- a/root/package/qca/qca-rfs/patches/200-rework-nfct-notification.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- a/rfs_cm.c -+++ b/rfs_cm.c -@@ -709,7 +709,7 @@ int rfs_cm_start(void) - - RFS_DEBUG("RFS cm start\n"); - #ifdef CONFIG_NF_CONNTRACK_EVENTS -- ret = nf_conntrack_register_notifier(&init_net, &rfs_cm_conntrack_notifier); -+ ret = nf_conntrack_register_chain_notifier(&init_net, &rfs_cm_conntrack_notifier); - if (ret < 0) { - RFS_ERROR("can't register nf notifier hook: %d\n", ret); - return -1; -@@ -740,7 +740,7 @@ int rfs_cm_stop(void) - #endif - - #ifdef CONFIG_NF_CONNTRACK_EVENTS -- nf_conntrack_unregister_notifier(&init_net, &rfs_cm_conntrack_notifier); -+ nf_conntrack_unregister_chain_notifier(&init_net, &rfs_cm_conntrack_notifier); - #endif - - rfs_cm_connection_destroy_all(); diff --git a/root/package/qca/qca-ssdk-shell/Makefile b/root/package/qca/qca-ssdk-shell/Makefile deleted file mode 100644 index 90e2c2e6..00000000 --- a/root/package/qca/qca-ssdk-shell/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=qca-ssdk-shell -PKG_RELEASE:=1 - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://source.codeaurora.org/quic/qsdk/oss/ssdk-shell -PKG_SOURCE_DATE:=2021-01-27 -PKG_SOURCE_VERSION:=5661366d471a78314bc7010f985ad8cc15be832a -PKG_MIRROR_HASH:=73111e09e896f0abbe3ee1c358aea7ec14fe5e668ce8753b8968e03c78f9599b - -include $(INCLUDE_DIR)/kernel.mk -include $(INCLUDE_DIR)/package.mk - -define Package/qca-ssdk-shell - SECTION:=utils - CATEGORY:=Utilities - TITLE:=Shell application for QCA SSDK - DEPENDS:=@(TARGET_ipq40xx||TARGET_ipq806x||TARGET_ipq807x) -endef - -define Package/qca-ssdk-shell/Description - This package contains a qca-ssdk shell application for QCA chipset -endef - -ifndef CONFIG_TOOLCHAIN_BIN_PATH -CONFIG_TOOLCHAIN_BIN_PATH=$(TOOLCHAIN_DIR)/bin -endif - -QCASSDK_CONFIG_OPTS+= \ - TOOL_PATH=$(CONFIG_TOOLCHAIN_BIN_PATH) \ - SYS_PATH=$(LINUX_DIR) \ - TOOLPREFIX=$(TARGET_CROSS) \ - KVER=$(LINUX_VERSION) \ - CFLAGS="$(TARGET_CFLAGS)" \ - LDFLAGS="$(TARGET_LDFLAGS)" \ - ARCH=$(LINUX_KARCH) - -define Build/Compile - $(MAKE) -C $(PKG_BUILD_DIR) $(strip $(QCASSDK_CONFIG_OPTS)) -endef - -define Package/qca-ssdk-shell/install - $(INSTALL_DIR) $(1)/usr/sbin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/build/bin/ssdk_sh $(1)/usr/sbin/ -endef - -$(eval $(call BuildPackage,qca-ssdk-shell)) diff --git a/root/package/qca/qca-ssdk/Makefile b/root/package/qca/qca-ssdk/Makefile deleted file mode 100644 index 487117bb..00000000 --- a/root/package/qca/qca-ssdk/Makefile +++ /dev/null @@ -1,125 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=qca-ssdk -PKG_RELEASE:=1 - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://source.codeaurora.org/quic/qsdk/oss/lklm/qca-ssdk -PKG_SOURCE_DATE:=2021-04-28 -PKG_SOURCE_VERSION:=c9bc3bc34eaaac78083573524097356e2dcc1b66 -PKG_MIRROR_HASH:=29db78529be32427b8b96fcbfec22a016a243676781ec96d9d65b810944fa405 - -LOCAL_VARIANT=$(patsubst qca-ssdk-%,%,$(patsubst qca-ssdk-%,%,$(BUILD_VARIANT))) - -include $(INCLUDE_DIR)/kernel.mk -include $(INCLUDE_DIR)/package.mk - -define KernelPackage/qca-ssdk/default-nohnat - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Devices - TITLE:=Kernel driver for QCA SSDK - FILES:=$(PKG_BUILD_DIR)/build/bin/qca-ssdk.ko - AUTOLOAD:=$(call AutoLoad,30,qca-ssdk) - PROVIDES:=qca-ssdk -endef - -define KernelPackage/qca-ssdk-nohnat -$(call KernelPackage/qca-ssdk/default-nohnat) - DEPENDS:=@(TARGET_ipq806x||TARGET_ipq807x||TARGET_ipq60xx) - VARIANT:=nohnat -endef - -define KernelPackage/qca-ssdk-nohnat/Description -This package contains a qca-ssdk driver for QCA chipset -endef - -define KernelPackage/qca-ssdk-hnat -$(call KernelPackage/qca-ssdk/default-nohnat) - DEPENDS:=@TARGET_ipq40xx +kmod-ipt-extra +kmod-ipt-filter \ - +kmod-ppp +TARGET_ipq40xx:kmod-qca-rfs - TITLE+= (hnat) - VARIANT:=hnat -endef - -define KernelPackage/qca-ssdk-hnat/Description -This package contains a qca-ssdk-hnat driver for QCA chipset -endef - -ifdef CONFIG_TOOLCHAIN_BIN_PATH -TOOLCHAIN_BIN_PATH=$(CONFIG_TOOLCHAIN_BIN_PATH) -else -TOOLCHAIN_BIN_PATH=$(TOOLCHAIN_DIR)/bin -endif - -QCASSDK_CONFIG_OPTS+= \ - $(KERNEL_MAKE_FLAGS) \ - KVER=$(LINUX_VERSION) \ - SYS_PATH=$(LINUX_DIR) \ - GCC_VERSION=$(GCC_VERSION) \ - TOOLPREFIX=$(TARGET_CROSS) \ - TOOL_PATH=$(TOOLCHAIN_BIN_PATH) \ - TARGET_SUFFIX=$(CONFIG_TARGET_SUFFIX) \ - EXTRA_CFLAGS=-fno-stack-protector -I$(STAGING_DIR)/usr/include - -ifeq ($(LOCAL_VARIANT),hnat) - QCASSDK_CONFIG_OPTS+= HNAT_FEATURE=enable -ifeq ($(BOARD),ipq40xx) - QCASSDK_CONFIG_OPTS+= RFS_FEATURE=enable -endif -endif - -ifeq ($(BOARD),ipq60xx) - QCASSDK_CONFIG_OPTS+= CHIP_TYPE=CPPE -else ifeq ($(BOARD),ipq807x) - QCASSDK_CONFIG_OPTS+= CHIP_TYPE=HPPE -else - QCASSDK_CONFIG_OPTS+= HK_CHIP=enable -endif - -ifneq (, $(findstring $(BOARD), ipq60xx ipq807x)) - QCASSDK_CONFIG_OPTS+= PTP_FEATURE=disable SWCONFIG_FEATURE=disable -endif - -define Build/Compile - $(MAKE) -C $(PKG_BUILD_DIR) $(strip $(QCASSDK_CONFIG_OPTS)) -endef - -define Build/InstallDev - $(INSTALL_DIR) $(1)/usr/include/qca-ssdk - $(INSTALL_DIR) $(1)/usr/include/qca-ssdk/api - $(INSTALL_DIR) $(1)/usr/include/qca-ssdk/ref - $(INSTALL_DIR) $(1)/usr/include/qca-ssdk/fal - $(INSTALL_DIR) $(1)/usr/include/qca-ssdk/sal - $(INSTALL_DIR) $(1)/usr/include/qca-ssdk/init - $(CP) -rf $(PKG_BUILD_DIR)/include/api/sw_ioctl.h $(1)/usr/include/qca-ssdk/api - if [ -f $(PKG_BUILD_DIR)/include/ref/ref_vsi.h ]; then \ - $(CP) -rf $(PKG_BUILD_DIR)/include/ref/ref_vsi.h $(1)/usr/include/qca-ssdk/ref/; \ - fi - if [ -f $(PKG_BUILD_DIR)/include/ref/ref_fdb.h ]; then \ - $(CP) -rf $(PKG_BUILD_DIR)/include/ref/ref_fdb.h $(1)/usr/include/qca-ssdk/ref/; \ - fi - if [ -f $(PKG_BUILD_DIR)/include/ref/ref_port_ctrl.h ]; then \ - $(CP) -rf $(PKG_BUILD_DIR)/include/ref/ref_port_ctrl.h $(1)/usr/include/qca-ssdk/ref/; \ - fi - if [ -f $(PKG_BUILD_DIR)/include/init/ssdk_init.h ]; then \ - $(CP) -rf $(PKG_BUILD_DIR)/include/init/ssdk_init.h $(1)/usr/include/qca-ssdk/init/; \ - fi - $(CP) -rf $(PKG_BUILD_DIR)/include/fal $(1)/usr/include/qca-ssdk - $(CP) -rf $(PKG_BUILD_DIR)/include/common/*.h $(1)/usr/include/qca-ssdk - $(CP) -rf $(PKG_BUILD_DIR)/include/sal/os/linux/*.h $(1)/usr/include/qca-ssdk - $(CP) -rf $(PKG_BUILD_DIR)/include/sal/os/*.h $(1)/usr/include/qca-ssdk -endef - -define KernelPackage/qca-ssdk-nohnat/install - $(INSTALL_DIR) $(1)/etc/init.d - $(INSTALL_BIN) ./files/qca-ssdk $(1)/etc/init.d/qca-ssdk -endef - -define KernelPackage/qca-ssdk-hnat/install - $(INSTALL_DIR) $(1)/etc/init.d - $(INSTALL_BIN) ./files/qca-ssdk $(1)/etc/init.d/qca-ssdk -endef - -$(eval $(call KernelPackage,qca-ssdk-nohnat)) -$(eval $(call KernelPackage,qca-ssdk-hnat)) diff --git a/root/package/qca/qca-ssdk/files/qca-ssdk b/root/package/qca/qca-ssdk/files/qca-ssdk deleted file mode 100644 index 389279c0..00000000 --- a/root/package/qca/qca-ssdk/files/qca-ssdk +++ /dev/null @@ -1,206 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (c) 2018, The Linux Foundation. All rights reserved. -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -START=16 - -#!/bin/sh -ruletype="ip4 ip6" -side="wan lan" -qwan="1 3 2 0 5 7 6 4" -qlan="0 1 2 3 4 5 6 7" - -function create_war_acl_rules(){ - for lw in $side - do - #echo $lw - if [ "$lw" == "wan" ];then - listid=254 - queue=$qwan - portmap=0x20 - else - listid=255 - queue=$qlan - portmap=0x1e - fi - #echo $queue - #echo "creating list $listid" - ssdk_sh acl list create $listid 255 - ruleid=0 - for rt in $ruletype - do - for qid in $queue - do - cmd="ssdk_sh acl rule add $listid $ruleid 1 n 0 0" - #echo $cmd - if [ "$rt" == "ip4" ];then - cmd="$cmd ip4 n n n n n n n n n n n n n n n n n n n n n n n n n n n n n" - #echo $cmd - else - cmd="$cmd ip6 n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n" - #echo $cmd - fi - if [ $ruleid -le 3 ];then - #non-zero dscp - cmd="$cmd y 0x0 0xff" - elif [ $ruleid -le 7 ];then - #zero dscp - cmd="$cmd n" - elif [ $ruleid -le 11 ];then - #non-zero dscp - cmd="$cmd y 0x0 0xff" - else - #zero dscp - cmd="$cmd n" - fi - p=$((ruleid/2)) - cmd="$cmd y mask $((ruleid%2)) 0x1 y mask $((p%2)) 0x1 n n n n n n n n n n n n n n n y n n n n n n n y $qid n n 0 0 n n n n n n n n n n n n n n n n n n n n 0" - #echo $cmd - $cmd - ruleid=`expr $ruleid + 1` - done - done - ssdk_sh acl list bind $listid 0 1 $portmap - done -} - -function create_war_cosmap(){ - ssdk_sh cosmap pri2q set 0 0 - ssdk_sh cosmap pri2q set 1 0 - ssdk_sh cosmap pri2q set 2 0 - ssdk_sh cosmap pri2q set 3 0 - ssdk_sh cosmap pri2q set 4 1 - ssdk_sh cosmap pri2q set 5 1 - ssdk_sh cosmap pri2q set 6 1 - ssdk_sh cosmap pri2q set 7 1 - ssdk_sh cosmap pri2ehq set 0 0 - ssdk_sh cosmap pri2ehq set 1 0 - ssdk_sh cosmap pri2ehq set 2 0 - ssdk_sh cosmap pri2ehq set 3 0 - ssdk_sh cosmap pri2ehq set 4 1 - ssdk_sh cosmap pri2ehq set 5 1 - ssdk_sh cosmap pri2ehq set 6 1 - ssdk_sh cosmap pri2ehq set 7 1 -} - -function create_acl_byp_egstp_rules(){ - ssdk_sh debug module_func set servcode 0xf 0x0 0x0 - ssdk_sh servcode config set 1 n 0 0xfffefc7f 0xffbdff 0 0 0 0 0 0 - ssdk_sh debug module_func set servcode 0x0 0x0 0x0 - ssdk_sh acl list create 56 48 - ssdk_sh acl rule add 56 0 1 n 0 0 mac n n n n n y 01-80-c2-00-00-00 ff-ff-ff-ff-ff-ff n n n n n n n n n n n n n n n n n n n n n n n y n n n n n n n n n n 0 0 n n n n n n n n n n n n n y n n n n n n n n n n n n y n n n n n n n n n n n n 0 - ssdk_sh acl rule add 56 1 1 n 0 0 mac n n n n n n n yes 0x8809 0xffff n n n n n n n n n n n n n n n n n n n n n y n n n n n n n n n n 0 0 n n n n n n n n n n n n n y n n n n n n n n n n n n y n n n n n n n n n n n n 0 - ssdk_sh acl rule add 56 2 1 n 0 0 mac n n n n n n n yes 0x888e 0xffff n n n n n n n n n n n n n n n n n n n n n y n n n n n n n n n n 0 0 n n n n n n n n n n n n n y n n n n n n n n n n n n y n n n n n n n n n n n n 0 - ssdk_sh acl list bind 56 0 2 1 -} - -function delete_war_acl_rules(){ - for lw in $side - do - #echo $lw - if [ "$lw" == "wan" ];then - listid=254 - queue=$qwan - portmap=0x20 - else - listid=255 - queue=$qlan - portmap=0x1e - fi - ssdk_sh acl list unbind $listid 0 1 $portmap - for rt in $ruletype - do - for qid in $queue - do - cmd="ssdk_sh acl rule del $listid 0 1" - echo $cmd - $cmd - done - done - #echo "deleting list $listid" - ssdk_sh acl list destroy $listid - done -} - -function delete_war_cosmap(){ - ssdk_sh cosmap pri2q set 0 0 - ssdk_sh cosmap pri2q set 1 0 - ssdk_sh cosmap pri2q set 2 1 - ssdk_sh cosmap pri2q set 3 1 - ssdk_sh cosmap pri2q set 4 2 - ssdk_sh cosmap pri2q set 5 2 - ssdk_sh cosmap pri2q set 6 3 - ssdk_sh cosmap pri2q set 7 3 - ssdk_sh cosmap pri2ehq set 0 1 - ssdk_sh cosmap pri2ehq set 1 0 - ssdk_sh cosmap pri2ehq set 2 2 - ssdk_sh cosmap pri2ehq set 3 2 - ssdk_sh cosmap pri2ehq set 4 3 - ssdk_sh cosmap pri2ehq set 5 3 - ssdk_sh cosmap pri2ehq set 6 4 - ssdk_sh cosmap pri2ehq set 7 5 -} - -function delete_acl_byp_egstp_rules(){ - ssdk_sh debug module_func set servcode 0xf 0x0 0x0 - ssdk_sh servcode config set 1 n 0 0xfffefcff 0xffbfff 0 0 0 0 0 0 - ssdk_sh debug module_func set servcode 0x0 0x0 0x0 - ssdk_sh acl list unbind 56 0 2 1 - ssdk_sh acl rule del 56 0 1 - ssdk_sh acl rule del 56 1 1 - ssdk_sh acl rule del 56 2 1 - ssdk_sh acl list destroy 56 -} - -function edma_war_config_add(){ - create_war_cosmap - ssdk_sh acl status set enable - create_war_acl_rules -} - -function edma_war_config_del(){ - delete_war_acl_rules - delete_war_cosmap -} - -start() { - chip_ver=`ssdk_sh debug reg get 0 4 | grep Data | tr -d 'SSDK Init OK![Data]:'` - #The following commands should be uncommented to enable EDMA WAR - if [ "$chip_ver" = "0x1401" ]; then - #edma_war_config_add - echo '' - fi - #The following commands should be uncommented to add acl egress stp bypass rules - if [ "$chip_ver" = "0x1500" ] || [ "$chip_ver" = "0x1501" ]; then - #create_acl_byp_egstp_rules - echo '' - fi - echo starting -} - -stop() { - chip_ver=`ssdk_sh debug reg get 0 4 | grep Data | tr -d 'SSDK Init OK![Data]:'` - #The following commands should be uncommented to disable EDMA WAR - if [ "$chip_ver" = "0x1401" ]; then - #edma_war_config_del - echo '' - fi - #The following commands should be uncommented to delete acl egress stp bypass rules - if [ "$chip_ver" = "0x1500" ] || [ "$chip_ver" = "0x1501" ]; then - #delete_acl_byp_egstp_rules - echo '' - fi - echo stoping -} diff --git a/root/package/qca/qca-ssdk/patches/0001-SSDK-config-add-kernel-5.10-5.15.patch b/root/package/qca/qca-ssdk/patches/0001-SSDK-config-add-kernel-5.10-5.15.patch deleted file mode 100644 index 057652e4..00000000 --- a/root/package/qca/qca-ssdk/patches/0001-SSDK-config-add-kernel-5.10-5.15.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 472c0c8132784608312c80c4b02c03ea7c132235 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Wed, 12 May 2021 13:41:12 +0200 -Subject: [PATCH] SSDK: config: add kernel 5.10 - -This is purely to identify it and be able to set -flags correctly. - -Signed-off-by: Robert Marko ---- - config | 6 +++++- - make/linux_opt.mk | 4 ++-- - 2 files changed, 7 insertions(+), 3 deletions(-) - ---- a/config -+++ b/config -@@ -22,6 +22,14 @@ ifeq ($(KVER),$(filter 5.4%,$(KVER))) - OS_VER=5_4 - endif - -+ifeq ($(KVER),$(filter 5.10%,$(KVER))) -+OS_VER=5_10 -+endif -+ -+ifeq ($(KVER),$(filter 5.15%,$(KVER))) -+OS_VER=5_15 -+endif -+ - ifeq ($(KVER), 3.4.0) - OS_VER=3_4 - endif -@@ -123,7 +127,7 @@ endif - endif - - ifeq ($(ARCH), arm64) --ifeq ($(KVER),$(filter 4.1% 4.4% 4.9% 5.4%,$(KVER))) -+ifeq ($(KVER),$(filter 4.1% 4.4% 4.9% 5.4% 5.10% 5.15%,$(KVER))) - CPU_CFLAG= -DMODULE -Os -pipe -march=armv8-a -mcpu=cortex-a53+crypto -fno-caller-saves -fno-strict-aliasing -Werror -fno-common -Wno-format-security -Wno-pointer-sign -Wno-unused-but-set-variable -Wno-error=unused-result -mcmodel=large - endif - endif ---- a/make/linux_opt.mk -+++ b/make/linux_opt.mk -@@ -388,7 +388,7 @@ ifeq (KSLIB, $(MODULE_TYPE)) - KASAN_SHADOW_SCALE_SHIFT := 3 - endif - -- ifeq (5_4, $(OS_VER)) -+ ifeq ($(OS_VER),$(filter 5_4 5_10 5_15, $(OS_VER))) - ifeq ($(ARCH), arm64) - KASAN_OPTION += -DKASAN_SHADOW_SCALE_SHIFT=$(KASAN_SHADOW_SCALE_SHIFT) - endif -@@ -419,7 +419,7 @@ ifeq (KSLIB, $(MODULE_TYPE)) - - endif - -- ifeq ($(OS_VER),$(filter 4_4 5_4, $(OS_VER))) -+ ifeq ($(OS_VER),$(filter 4_4 5_4 5_10 5_15, $(OS_VER))) - MODULE_CFLAG += -DKVER34 - MODULE_CFLAG += -DKVER32 - MODULE_CFLAG += -DLNX26_22 diff --git a/root/package/qca/qca-ssdk/patches/0002-SSDK-replace-ioremap_nocache-with-ioremap.patch b/root/package/qca/qca-ssdk/patches/0002-SSDK-replace-ioremap_nocache-with-ioremap.patch deleted file mode 100644 index b293ad29..00000000 --- a/root/package/qca/qca-ssdk/patches/0002-SSDK-replace-ioremap_nocache-with-ioremap.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 784f2cfdfaf3bdf44917924e157049230a0ef5f8 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Wed, 12 May 2021 13:45:45 +0200 -Subject: [PATCH] SSDK: replace ioremap_nocache with ioremap - -ioremap_nocache was dropped upstream, simply use the -generic variety. - -Signed-off-by: Robert Marko ---- - src/init/ssdk_clk.c | 10 +++++----- - src/init/ssdk_init.c | 2 +- - src/init/ssdk_plat.c | 6 +++--- - 3 files changed, 9 insertions(+), 9 deletions(-) - ---- a/src/init/ssdk_clk.c -+++ b/src/init/ssdk_clk.c -@@ -623,7 +623,7 @@ ssdk_mp_tcsr_get(a_uint32_t tcsr_offset, - { - void __iomem *tcsr_base = NULL; - -- tcsr_base = ioremap_nocache(TCSR_ETH_ADDR, TCSR_ETH_SIZE); -+ tcsr_base = ioremap(TCSR_ETH_ADDR, TCSR_ETH_SIZE); - if (!tcsr_base) - { - SSDK_ERROR("Failed to map tcsr eth address!\n"); -@@ -640,7 +640,7 @@ ssdk_mp_tcsr_set(a_uint32_t tcsr_offset, - { - void __iomem *tcsr_base = NULL; - -- tcsr_base = ioremap_nocache(TCSR_ETH_ADDR, TCSR_ETH_SIZE); -+ tcsr_base = ioremap(TCSR_ETH_ADDR, TCSR_ETH_SIZE); - if (!tcsr_base) - { - SSDK_ERROR("Failed to map tcsr eth address!\n"); -@@ -688,7 +688,7 @@ ssdk_mp_cmnblk_stable_check(void) - a_uint32_t reg_val; - int i, loops = 20; - -- pll_lock = ioremap_nocache(CMN_PLL_LOCKED_ADDR, CMN_PLL_LOCKED_SIZE); -+ pll_lock = ioremap(CMN_PLL_LOCKED_ADDR, CMN_PLL_LOCKED_SIZE); - if (!pll_lock) { - SSDK_ERROR("Failed to map CMN PLL LOCK register!\n"); - return A_FALSE; -@@ -745,7 +745,7 @@ static void ssdk_cmnblk_pll_src_set(enum - void __iomem *cmn_pll_src_base = NULL; - a_uint32_t reg_val; - -- cmn_pll_src_base = ioremap_nocache(CMN_BLK_PLL_SRC_ADDR, CMN_BLK_SIZE); -+ cmn_pll_src_base = ioremap(CMN_BLK_PLL_SRC_ADDR, CMN_BLK_SIZE); - if (!cmn_pll_src_base) { - SSDK_ERROR("Failed to map cmn pll source address!\n"); - return; -@@ -766,7 +766,7 @@ static void ssdk_cmnblk_init(enum cmnblk - void __iomem *gcc_pll_base = NULL; - a_uint32_t reg_val; - -- gcc_pll_base = ioremap_nocache(CMN_BLK_ADDR, CMN_BLK_SIZE); -+ gcc_pll_base = ioremap(CMN_BLK_ADDR, CMN_BLK_SIZE); - if (!gcc_pll_base) { - SSDK_ERROR("Failed to map gcc pll address!\n"); - return; ---- a/src/init/ssdk_init.c -+++ b/src/init/ssdk_init.c -@@ -2770,7 +2770,7 @@ static int ssdk_dess_mac_mode_init(a_uin - (a_uint8_t *)®_value, 4); - mdelay(10); - /*softreset psgmii, fixme*/ -- gcc_addr = ioremap_nocache(0x1812000, 0x200); -+ gcc_addr = ioremap(0x1812000, 0x200); - if (!gcc_addr) { - SSDK_ERROR("gcc map fail!\n"); - return 0; ---- a/src/init/ssdk_plat.c -+++ b/src/init/ssdk_plat.c -@@ -1312,7 +1312,7 @@ ssdk_plat_init(ssdk_init_cfg *cfg, a_uin - reg_mode = ssdk_uniphy_reg_access_mode_get(dev_id); - if(reg_mode == HSL_REG_LOCAL_BUS) { - ssdk_uniphy_reg_map_info_get(dev_id, &map); -- qca_phy_priv_global[dev_id]->uniphy_hw_addr = ioremap_nocache(map.base_addr, -+ qca_phy_priv_global[dev_id]->uniphy_hw_addr = ioremap(map.base_addr, - map.size); - if (!qca_phy_priv_global[dev_id]->uniphy_hw_addr) { - SSDK_ERROR("%s ioremap fail.", __func__); -@@ -1327,7 +1327,7 @@ ssdk_plat_init(ssdk_init_cfg *cfg, a_uin - reg_mode = ssdk_switch_reg_access_mode_get(dev_id); - if(reg_mode == HSL_REG_LOCAL_BUS) { - ssdk_switch_reg_map_info_get(dev_id, &map); -- qca_phy_priv_global[dev_id]->hw_addr = ioremap_nocache(map.base_addr, -+ qca_phy_priv_global[dev_id]->hw_addr = ioremap(map.base_addr, - map.size); - if (!qca_phy_priv_global[dev_id]->hw_addr) { - SSDK_ERROR("%s ioremap fail.", __func__); -@@ -1358,7 +1358,7 @@ ssdk_plat_init(ssdk_init_cfg *cfg, a_uin - return -1; - } - -- qca_phy_priv_global[dev_id]->psgmii_hw_addr = ioremap_nocache(map.base_addr, -+ qca_phy_priv_global[dev_id]->psgmii_hw_addr = ioremap(map.base_addr, - map.size); - if (!qca_phy_priv_global[dev_id]->psgmii_hw_addr) { - SSDK_ERROR("%s ioremap fail.", __func__); diff --git a/root/package/qca/qca-ssdk/patches/0004-platform-use-of_mdio_find_bus-to-get-MDIO-bus.patch b/root/package/qca/qca-ssdk/patches/0004-platform-use-of_mdio_find_bus-to-get-MDIO-bus.patch deleted file mode 100644 index 3bcbcccf..00000000 --- a/root/package/qca/qca-ssdk/patches/0004-platform-use-of_mdio_find_bus-to-get-MDIO-bus.patch +++ /dev/null @@ -1,40 +0,0 @@ -From b6190ca46287d01a895c7cc14de30410c09ff1b8 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Wed, 12 May 2021 17:15:46 +0200 -Subject: [PATCH] SSDK: platform: use of_mdio_find_bus() to get MDIO bus - -Kernel has a generic of_mdio_find_bus() which can get the appropriate -MDIO bus based on the DT node. -So, drop the getting MDIO from platform data, which no longer works -in 5.4 and later and use of_mdio_find_bus(). - -Signed-off-by: Baruch Siach -Signed-off-by: Robert Marko ---- - src/init/ssdk_plat.c | 8 +------- - 1 file changed, 1 insertion(+), 7 deletions(-) - ---- a/src/init/ssdk_plat.c -+++ b/src/init/ssdk_plat.c -@@ -551,7 +551,6 @@ static int miibus_get(a_uint32_t dev_id) - struct device_node *mdio_node = NULL; - struct device_node *switch_node = NULL; - struct platform_device *mdio_plat = NULL; -- struct ipq40xx_mdio_data *mdio_data = NULL; - struct qca_phy_priv *priv; - hsl_reg_mode reg_mode = HSL_REG_LOCAL_BUS; - priv = qca_phy_priv_global[dev_id]; -@@ -584,12 +583,7 @@ static int miibus_get(a_uint32_t dev_id) - - if(reg_mode == HSL_REG_LOCAL_BUS) - { -- mdio_data = dev_get_drvdata(&mdio_plat->dev); -- if (!mdio_data) { -- SSDK_ERROR("cannot get mdio_data reference from device data\n"); -- return 1; -- } -- priv->miibus = mdio_data->mii_bus; -+ priv->miibus = of_mdio_find_bus(mdio_node); - } - else - priv->miibus = dev_get_drvdata(&mdio_plat->dev); diff --git a/root/package/qca/qca-ssdk/patches/0005-add-kernel-5.4-support.patch b/root/package/qca/qca-ssdk/patches/0005-add-kernel-5.4-support.patch deleted file mode 100644 index 6b08b05a..00000000 --- a/root/package/qca/qca-ssdk/patches/0005-add-kernel-5.4-support.patch +++ /dev/null @@ -1,108 +0,0 @@ ---- a/app/nathelper/linux/lib/nat_helper_dt.c -+++ b/app/nathelper/linux/lib/nat_helper_dt.c -@@ -721,7 +721,7 @@ napt_ct_counter_sync(a_uint32_t hw_index) - } - - if (!test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) { -- ct->timeout.expires += delta_jiffies; -+ ct->timeout += delta_jiffies; - } - - if((cct != NULL) && (napt_hw_get_by_index(&napt, hw_index) == 0)) -@@ -770,7 +770,7 @@ napt_ct_timer_update(a_uint32_t hw_index) - } - - if (!test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) { -- ct->timeout.expires += delta_jiffies; -+ ct->timeout += delta_jiffies; - } - - return 0; ---- a/app/nathelper/linux/napt_helper.c -+++ b/app/nathelper/linux/napt_helper.c -@@ -64,11 +64,6 @@ napt_ct_aging_disable(uint32_t ct_addr) - } - - ct = (struct nf_conn *)ct_addr; -- -- if (timer_pending(&ct->timeout)) -- { -- del_timer(&ct->timeout); -- } - } - - int -@@ -85,7 +80,7 @@ napt_ct_aging_is_enable(uint32_t ct_addr) - - ct = (struct nf_conn *)ct_addr; - -- return timer_pending(&(((struct nf_conn *)ct)->timeout)); -+ return (nf_ct_is_expired(ct)); - } - - void -@@ -111,18 +106,17 @@ napt_ct_aging_enable(uint32_t ct_addr) - l3num = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; - protonum = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum; - -- ct->timeout.expires = jiffies+10*HZ; -+ ct->timeout = jiffies+10*HZ; - - if ((l3num == AF_INET) && (protonum == IPPROTO_TCP)) - { - if (ct->proto.tcp.state == TCP_CONNTRACK_ESTABLISHED) - { -- ct->timeout.expires = jiffies+(5*24*60*60*HZ); -+ ct->timeout = jiffies+(5*24*60*60*HZ); - } - } - - HNAT_PRINTK(" ct:[%x] add timeout again\n", ct_addr); -- add_timer(&ct->timeout); - } - - void -@@ -339,7 +333,6 @@ napt_ct_list_unlock(void) - uint32_t - napt_ct_list_iterate(uint32_t *hash, uint32_t *iterate) - { -- struct net *net = &init_net; - struct nf_conntrack_tuple_hash *h = NULL; - struct nf_conn *ct = NULL; - struct hlist_nulls_node *pos = (struct hlist_nulls_node *) (*iterate); -@@ -349,7 +342,7 @@ napt_ct_list_iterate(uint32_t *hash, uint32_t *iterate) - if(pos == 0) - { - /*get head for list*/ -- pos = rcu_dereference((&net->ct.hash[*hash])->first); -+ pos = rcu_dereference(hlist_nulls_first_rcu(&nf_conntrack_hash[*hash])); - } - - hlist_nulls_for_each_entry_from(h, pos, hnnode) ---- a/app/nathelper/linux/nat_ipt_helper.c -+++ b/app/nathelper/linux/nat_ipt_helper.c -@@ -534,10 +534,10 @@ nat_ipt_data_init(void) - memset(&old_replace, 0, sizeof (old_replace)); - - /*record ipt rule(SNAT) sequence for hw nat*/ -- memset(hw_nat_ipt_seq, 0, NAT_HW_NUM); -+ memset(hw_nat_ipt_seq, 0, sizeof(hw_nat_ipt_seq)); - - /*record ipt rule(SNAT) pubip index for hw nat*/ -- memset(hw_nat_pip_idx, 0, NAT_HW_NUM); -+ memset(hw_nat_pip_idx, 0, sizeof(hw_nat_pip_idx)); - } - - static void ---- a/make/linux_opt.mk -+++ b/make/linux_opt.mk -@@ -449,9 +449,6 @@ ifeq (KSLIB, $(MODULE_TYPE)) - else ifeq ($(ARCH), arm) - MODULE_INC += -I$(SYS_PATH) \ - -I$(TOOL_PATH)/../lib/gcc/$(TARGET_NAME)/$(GCC_VERSION)/include/ \ -- -I$(TOOL_PATH)/../lib/gcc/$(TARGET_NAME)/7.5.0/include/ \ -- -I$(TOOL_PATH)/../../lib/armv7a-vfp-neon-rdk-linux-gnueabi/gcc/arm-rdk-linux-gnueabi/4.8.4/include/ \ -- -I$(TOOL_PATH)/../../lib/arm-rdk-linux-musleabi/gcc/arm-rdk-linux-musleabi/6.4.0/include/ \ - -I$(SYS_PATH)/include \ - -I$(SYS_PATH)/source \ - -I$(SYS_PATH)/source/include \ diff --git a/root/package/qca/qca-ssdk/patches/0006-fix-mdio-probe-on-ipq806x.patch b/root/package/qca/qca-ssdk/patches/0006-fix-mdio-probe-on-ipq806x.patch deleted file mode 100644 index 8e802fe2..00000000 --- a/root/package/qca/qca-ssdk/patches/0006-fix-mdio-probe-on-ipq806x.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/src/init/ssdk_plat.c -+++ b/src/init/ssdk_plat.c -@@ -568,7 +568,7 @@ static int miibus_get(a_uint32_t dev_id) - if(reg_mode == HSL_REG_LOCAL_BUS) - mdio_node = of_find_compatible_node(NULL, NULL, "qcom,ipq40xx-mdio"); - else -- mdio_node = of_find_compatible_node(NULL, NULL, "virtual,mdio-gpio"); -+ mdio_node = of_find_compatible_node(NULL, NULL, "qcom,ipq8064-mdio"); - - if (!mdio_node) { - SSDK_ERROR("No MDIO node found in DTS!\n"); diff --git a/root/package/qca/qca-ssdk/patches/0007-SSDK-dts-fix-of_get_mac_address.patch b/root/package/qca/qca-ssdk/patches/0007-SSDK-dts-fix-of_get_mac_address.patch deleted file mode 100644 index 29be9312..00000000 --- a/root/package/qca/qca-ssdk/patches/0007-SSDK-dts-fix-of_get_mac_address.patch +++ /dev/null @@ -1,42 +0,0 @@ -From f3a7b93137c1a6a1b8010b86296242178eed5d9e Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Fri, 13 Aug 2021 20:03:21 +0200 -Subject: [PATCH] SSDK: dts: fix of_get_mac_address() - -Recently OpenWrt backported the updated of_get_mac_address() -function which returns and error code instead. - -So, patch the SSDK to use it and fix the compilation error. - -Signed-off-by: Robert Marko ---- - src/init/ssdk_dts.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - ---- a/src/init/ssdk_dts.c -+++ b/src/init/ssdk_dts.c -@@ -779,8 +779,9 @@ static void ssdk_dt_parse_intf_mac(void) - { - struct device_node *dp_node = NULL; - a_uint32_t dp = 0; -- a_uint8_t *maddr = NULL; -+ u8 maddr[ETH_ALEN]; - char dp_name[8] = {0}; -+ int ret; - - for (dp = 1; dp <= SSDK_MAX_NR_ETH; dp++) { - snprintf(dp_name, sizeof(dp_name), "dp%d", dp); -@@ -788,11 +789,11 @@ static void ssdk_dt_parse_intf_mac(void) - if (!dp_node) { - continue; - } -- maddr = (a_uint8_t *)of_get_mac_address(dp_node); -+ ret = of_get_mac_address(dp_node, maddr); - #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)) - if (maddr && is_valid_ether_addr(maddr)) { - #else -- if (!IS_ERR(maddr) && is_valid_ether_addr(maddr)) { -+ if (!ret && is_valid_ether_addr(maddr)) { - #endif - ssdk_dt_global.num_intf_mac++; - ether_addr_copy(ssdk_dt_global.intf_mac[dp-1].uc, maddr); diff --git a/root/package/qca/qca-ssdk/patches/0008-add-aquantia-phy-id-113CB0.patch b/root/package/qca/qca-ssdk/patches/0008-add-aquantia-phy-id-113CB0.patch deleted file mode 100644 index fba52635..00000000 --- a/root/package/qca/qca-ssdk/patches/0008-add-aquantia-phy-id-113CB0.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 440ab349813e5aa9dbeddab4d82ab64ff5347c5f Mon Sep 17 00:00:00 2001 -From: Dirk Buchwalder -Date: Sat, 30 Oct 2021 19:51:06 +0200 -Subject: [PATCH] add aquantia phy id 113CB0 / 0x31c31C12 - -This adds support for the AQR113C with the id -"113CB0 / 0x31c31C12" to the ssdk. - -This is used in the QNAP 301w - -Signed-off-by: Dirk Buchwalder - ---- - include/hsl/phy/hsl_phy.h | 1 + - src/hsl/phy/hsl_phy.c | 1 + - 2 files changed, 2 insertions(+) - ---- a/include/hsl/phy/hsl_phy.h -+++ b/include/hsl/phy/hsl_phy.h -@@ -579,6 +579,7 @@ typedef struct { - #define AQUANTIA_PHY_112 0x03a1b660 - #define AQUANTIA_PHY_113C_A0 0x31c31C10 - #define AQUANTIA_PHY_113C_A1 0x31c31C11 -+#define AQUANTIA_PHY_113C_B0 0x31c31C12 - #define AQUANTIA_PHY_112C 0x03a1b792 - - #define PHY_805XV2 0x004DD082 ---- a/src/hsl/phy/hsl_phy.c -+++ b/src/hsl/phy/hsl_phy.c -@@ -235,6 +235,7 @@ phy_type_t hsl_phytype_get_by_phyid(a_ui - case AQUANTIA_PHY_112: - case AQUANTIA_PHY_113C_A0: - case AQUANTIA_PHY_113C_A1: -+ case AQUANTIA_PHY_113C_B0: - case AQUANTIA_PHY_112C: - phytype = AQUANTIA_PHY_CHIP; - break; diff --git a/root/package/qca/qca-ssdk/patches/0009-qca8081-convert-to-5.11-IRQ-model.patch b/root/package/qca/qca-ssdk/patches/0009-qca8081-convert-to-5.11-IRQ-model.patch deleted file mode 100644 index b0c272b1..00000000 --- a/root/package/qca/qca-ssdk/patches/0009-qca8081-convert-to-5.11-IRQ-model.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 25ff0ae02accadd7b05f1dae788505f833d5c019 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Fri, 24 Dec 2021 20:02:32 +0100 -Subject: [PATCH] qca8081: convert to 5.11 IRQ model - -Kernel 5.11 introduced new IRQ handling model for PHY-s, -so provide those if 5.11 or later is used. - -Signed-off-by: Robert Marko ---- - src/hsl/phy/qca808x.c | 46 +++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 46 insertions(+) - ---- a/src/hsl/phy/qca808x.c -+++ b/src/hsl/phy/qca808x.c -@@ -238,6 +238,7 @@ static int qca808x_config_intr(struct ph - return err; - } - -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0)) - static int qca808x_ack_interrupt(struct phy_device *phydev) - { - int err; -@@ -257,6 +258,47 @@ static int qca808x_ack_interrupt(struct - - return (err < 0) ? err : 0; - } -+#endif -+ -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(5, 11, 0)) -+static irqreturn_t qca808x_handle_interrupt(struct phy_device *phydev) -+{ -+ a_uint16_t irq_status, int_enabled; -+ a_uint32_t dev_id = 0, phy_id = 0; -+ qca808x_priv *priv = phydev->priv; -+ const struct qca808x_phy_info *pdata = priv->phy_info; -+ -+ if (!pdata) { -+ return SW_FAIL; -+ } -+ -+ dev_id = pdata->dev_id; -+ phy_id = pdata->phy_addr; -+ -+ irq_status = qca808x_phy_reg_read(dev_id, phy_id, -+ QCA808X_PHY_INTR_STATUS); -+ if (irq_status < 0) { -+ phy_error(phydev); -+ return IRQ_NONE; -+ } -+ -+ /* Read the current enabled interrupts */ -+ int_enabled = qca808x_phy_reg_read(dev_id, phy_id, -+ QCA808X_PHY_INTR_MASK); -+ if (int_enabled < 0) { -+ phy_error(phydev); -+ return IRQ_NONE; -+ } -+ -+ /* See if this was one of our enabled interrupts */ -+ if (!(irq_status & int_enabled)) -+ return IRQ_NONE; -+ -+ phy_trigger_machine(phydev); -+ -+ return IRQ_HANDLED; -+} -+#endif - - /* switch linux negtiation capability to fal avariable */ - #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)) -@@ -559,7 +601,11 @@ struct phy_driver qca808x_phy_driver = { - .config_intr = qca808x_config_intr, - .config_aneg = qca808x_config_aneg, - .aneg_done = qca808x_aneg_done, -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0)) - .ack_interrupt = qca808x_ack_interrupt, -+#else -+ .handle_interrupt = qca808x_handle_interrupt, -+#endif - .read_status = qca808x_read_status, - .suspend = qca808x_suspend, - .resume = qca808x_resume, diff --git a/root/package/qca/qca-ssdk/patches/0012-include-fix-compilation-error-for-parse_uci_option.patch b/root/package/qca/qca-ssdk/patches/0012-include-fix-compilation-error-for-parse_uci_option.patch deleted file mode 100644 index 01b8deda..00000000 --- a/root/package/qca/qca-ssdk/patches/0012-include-fix-compilation-error-for-parse_uci_option.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 8e3500df074625b3eb3a8ed4e8e0b1b116f13d0c Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Sat, 7 May 2022 19:03:55 +0200 -Subject: [PATCH] include: fix compilation error for parse_uci_option - -Fix missing include for parse_uci_option - -Signed-off-by: Ansuel Smith ---- - include/ref/ref_uci.h | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/include/ref/ref_uci.h b/include/ref/ref_uci.h -index a42ea153..0906c5ba 100755 ---- a/include/ref/ref_uci.h -+++ b/include/ref/ref_uci.h -@@ -19,6 +19,7 @@ - extern "C" { - #endif /* __cplusplus */ - -+#include - - #if defined(IN_SWCONFIG) - int --- -2.34.1 - From 1ae305bc132d11c5fad8681de911d12a2b1c7dcd Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Wed, 23 Nov 2022 13:45:15 +0800 Subject: [PATCH 055/102] Update build.sh --- build.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/build.sh b/build.sh index ffa3d980..b096acef 100644 --- a/build.sh +++ b/build.sh @@ -634,7 +634,7 @@ fi cd ../.. [ -d $OMR_FEED/luci-base/po/oc ] && cp -rf $OMR_FEED/luci-base/po/oc feeds/${OMR_KERNEL}/luci/modules/luci-base/po/ echo "Done" - +chmod -R 777 "$OMR_TARGET/${OMR_KERNEL}/source" cd "$OMR_TARGET/${OMR_KERNEL}/source" echo "Update feeds index" cp .config .config.keep @@ -663,7 +663,6 @@ fi scripts/feeds install -a cp .config.keep .config scripts/feeds install kmod-macremapper -chmod -R 777 feeds/openmptcprouter echo "Done" if [ ! -f "../../../$OMR_TARGET_CONFIG" ]; then From 36f7ebba4629a43f3252466350b3fdfa0a72ebf0 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Wed, 23 Nov 2022 14:16:29 +0800 Subject: [PATCH 056/102] fix --- build.sh | 13 ++++++++++--- config | 4 ++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/build.sh b/build.sh index b096acef..866abec7 100644 --- a/build.sh +++ b/build.sh @@ -143,7 +143,15 @@ rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/files" "$OMR_TARGET/${OMR_KERNEL}/sourc #rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/arm-trusted-firmware-mediatek" rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/tools/firmware-utils" rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/uboot-rockchip" -cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" +if [ "$OMR_TARGET" != "rutx" ]; then + # There is many customization to support rutx and this seems to break other ipq40xx, so dirty workaround for now + mv "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx" "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx.old" + cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" + rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx" + mv "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx.old" "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx" +else + cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" +fi cat >> "$OMR_TARGET/${OMR_KERNEL}/source/package/base-files/files/etc/banner" < Date: Wed, 23 Nov 2022 14:25:45 +0800 Subject: [PATCH 057/102] Update build.sh --- build.sh | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/build.sh b/build.sh index 866abec7..dcf81525 100644 --- a/build.sh +++ b/build.sh @@ -143,15 +143,9 @@ rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/files" "$OMR_TARGET/${OMR_KERNEL}/sourc #rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/arm-trusted-firmware-mediatek" rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/tools/firmware-utils" rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/uboot-rockchip" -if [ "$OMR_TARGET" != "rutx" ]; then - # There is many customization to support rutx and this seems to break other ipq40xx, so dirty workaround for now - mv "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx" "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx.old" - cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" - rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx" - mv "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx.old" "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx" -else - cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" -fi + +cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" + cat >> "$OMR_TARGET/${OMR_KERNEL}/source/package/base-files/files/etc/banner" < Date: Wed, 23 Nov 2022 14:57:23 +0800 Subject: [PATCH 058/102] fix --- .github/FUNDING.yml | 0 .github/ISSUE_TEMPLATE/enhancement.md | 0 .github/ISSUE_TEMPLATE/feature_request.md | 0 .github/ISSUE_TEMPLATE/hardware_support.md | 0 .github/ISSUE_TEMPLATE/help.md | 0 .github/ISSUE_TEMPLATE/issue.md | 0 .github/ISSUE_TEMPLATE/question.md | 0 .github/PULL_REQUEST_TEMPLATE.md | 0 .github/workflows/stale.yml | 0 .gitignore | 0 CLA-entity.md | 0 CLA-individual.md | 0 CODE_OF_CONDUCT.md | 0 CONTRIBUTING.md | 0 LICENSE | 0 README.md | 0 config | 0 config-4018 | 0 config-5gx3 | 0 config-bpi-r1 | 0 config-bpi-r2 | 0 config-bpi-r64 | 0 config-cm520-79f | 0 config-espressobin | 0 config-espressobin1 | 0 config-l1000 | 0 config-nanopi_neo | 0 config-p2w_r619ac | 0 config-r2s | 0 config-r4s | 0 config-r7800 | 0 config-rpi2 | 0 config-rpi3 | 0 config-rpi4 | 0 config-rutx | 0 config-ubnt-erx | 0 config-wrt3200acm | 0 config-wrt32x | 0 config-x86 | 0 config-x86_64 | 0 config-zbt4019 | 0 contributors/example.md | 0 deploy_rsa.enc | Bin patches/950-0785-fixcm4soundboss2.patch | 0 patches/bbr2.patch | 0 patches/check-rsync.patch | 0 patches/download-ipv4.patch | 0 patches/gtime.patch | 0 patches/images.patch | 0 patches/ipt-nat6.patch | 0 patches/luci-occitan.patch | 0 patches/nanqinlang.patch | 0 patches/nocheck.patch | 0 patches/package-too-long.patch | 0 patches/remove_abi.patch | 0 patches/smsc75xx.patch | 0 patches/uefi.patch | 0 root/include/kernel-version.mk | 0 root/package/base-files/files/bin/config_generate | 0 root/package/base-files/files/etc/banner | 0 root/package/base-files/files/etc/shadow | 0 .../pack-firmware.sh | 0 root/package/boot/uboot-envtools/Makefile | 0 root/package/boot/uboot-rockchip/Makefile | 0 ...ip-rk3399-Add-support-for-Rongpin-king3399.patch | 0 root/package/firmware/ipq-wifi/Makefile | 0 .../firmware/ipq-wifi/board-pangu_l1000.qca4019 | Bin .../firmware/ipq-wifi/board-teltonika_rutx.qca4019 | Bin root/package/kernel/linux/modules/crypto.mk | 0 root/package/kernel/linux/modules/fs.mk | 0 root/package/kernel/linux/modules/input.mk | 0 root/package/kernel/linux/modules/netfilter.mk | 0 root/package/kernel/linux/modules/other.mk | 0 root/package/kernel/linux/modules/sound.mk | 0 .../mwlwifi/patches/002-remove-fallthrough.patch | 0 root/package/kernel/r2ec/Makefile | 0 root/package/kernel/r2ec/src/Makefile | 0 root/package/kernel/r2ec/src/io.h | 0 root/package/kernel/r2ec/src/r2ec.c | 0 root/package/kernel/rtl8812au-ct/Makefile | 0 root/package/modems/Makefile | 0 root/package/modems/src/README.md | 0 root/package/modems/src/data/0421-03a7 | 0 root/package/modems/src/data/0421-060d | 0 root/package/modems/src/data/0421-060e | 0 root/package/modems/src/data/0421-0612 | 0 root/package/modems/src/data/0421-0619 | 0 root/package/modems/src/data/0421-061e | 0 root/package/modems/src/data/0421-0623 | 0 root/package/modems/src/data/0421-0629 | 0 root/package/modems/src/data/0421-062d | 0 root/package/modems/src/data/0421-062f | 0 root/package/modems/src/data/0421-0638 | 0 root/package/modems/src/data/05c6-0016 | 0 root/package/modems/src/data/05c6-0023 | 0 root/package/modems/src/data/05c6-00a0 | 0 root/package/modems/src/data/05c6-6000 | 0 root/package/modems/src/data/05c6-9000 | 0 root/package/modems/src/data/05c6-9215 | 0 root/package/modems/src/data/07d1-3e01 | 0 root/package/modems/src/data/07d1-3e02 | 0 root/package/modems/src/data/07d1-7e11 | 0 root/package/modems/src/data/0af0-4005 | 0 root/package/modems/src/data/0af0-6901 | 0 root/package/modems/src/data/0af0-7201 | 0 root/package/modems/src/data/0af0-8120 | 0 root/package/modems/src/data/0af0-9200 | 0 root/package/modems/src/data/0b3c-c000 | 0 root/package/modems/src/data/0b3c-c001 | 0 root/package/modems/src/data/0b3c-c002 | 0 root/package/modems/src/data/0b3c-c003 | 0 root/package/modems/src/data/0b3c-c004 | 0 root/package/modems/src/data/0b3c-c005 | 0 root/package/modems/src/data/0b3c-c00a | 0 root/package/modems/src/data/0b3c-c00b | 0 root/package/modems/src/data/0bdb-1900 | 0 root/package/modems/src/data/0bdb-1902 | 0 root/package/modems/src/data/0bdb-190a | 0 root/package/modems/src/data/0bdb-190d | 0 root/package/modems/src/data/0bdb-1910 | 0 root/package/modems/src/data/0c88-17da | 0 root/package/modems/src/data/0c88-180a | 0 root/package/modems/src/data/0f3d-68a2 | 0 root/package/modems/src/data/0f3d-68aa | 0 root/package/modems/src/data/1004-6124 | 0 root/package/modems/src/data/1004-6141 | 0 root/package/modems/src/data/1004-6157 | 0 root/package/modems/src/data/1004-618f | 0 root/package/modems/src/data/106c-3711 | 0 root/package/modems/src/data/106c-3714 | 0 root/package/modems/src/data/106c-3715 | 0 root/package/modems/src/data/106c-3716 | 0 root/package/modems/src/data/106c-3717 | 0 root/package/modems/src/data/106c-3718 | 0 root/package/modems/src/data/106c-3721 | 0 root/package/modems/src/data/1199-0017 | 0 root/package/modems/src/data/1199-0018 | 0 root/package/modems/src/data/1199-0019 | 0 root/package/modems/src/data/1199-0020 | 0 root/package/modems/src/data/1199-0021 | 0 root/package/modems/src/data/1199-0022 | 0 root/package/modems/src/data/1199-0023 | 0 root/package/modems/src/data/1199-0024 | 0 root/package/modems/src/data/1199-0025 | 0 root/package/modems/src/data/1199-0026 | 0 root/package/modems/src/data/1199-0027 | 0 root/package/modems/src/data/1199-0028 | 0 root/package/modems/src/data/1199-0112 | 0 root/package/modems/src/data/1199-0120 | 0 root/package/modems/src/data/1199-0218 | 0 root/package/modems/src/data/1199-0220 | 0 root/package/modems/src/data/1199-0224 | 0 root/package/modems/src/data/1199-0301 | 0 root/package/modems/src/data/1199-6802 | 0 root/package/modems/src/data/1199-6803 | 0 root/package/modems/src/data/1199-6804 | 0 root/package/modems/src/data/1199-6805 | 0 root/package/modems/src/data/1199-6808 | 0 root/package/modems/src/data/1199-6809 | 0 root/package/modems/src/data/1199-6813 | 0 root/package/modems/src/data/1199-6815 | 0 root/package/modems/src/data/1199-6816 | 0 root/package/modems/src/data/1199-6820 | 0 root/package/modems/src/data/1199-6821 | 0 root/package/modems/src/data/1199-6822 | 0 root/package/modems/src/data/1199-6833 | 0 root/package/modems/src/data/1199-6834 | 0 root/package/modems/src/data/1199-6835 | 0 root/package/modems/src/data/1199-6838 | 0 root/package/modems/src/data/1199-6839 | 0 root/package/modems/src/data/1199-683a | 0 root/package/modems/src/data/1199-683b | 0 root/package/modems/src/data/1199-6850 | 0 root/package/modems/src/data/1199-6851 | 0 root/package/modems/src/data/1199-6852 | 0 root/package/modems/src/data/1199-6853 | 0 root/package/modems/src/data/1199-6855 | 0 root/package/modems/src/data/1199-6856 | 0 root/package/modems/src/data/1199-6859 | 0 root/package/modems/src/data/1199-685a | 0 root/package/modems/src/data/1199-6880 | 0 root/package/modems/src/data/1199-6890 | 0 root/package/modems/src/data/1199-6891 | 0 root/package/modems/src/data/1199-6892 | 0 root/package/modems/src/data/1199-6893 | 0 root/package/modems/src/data/1199-68a2 | 0 root/package/modems/src/data/1199-68aa | 0 root/package/modems/src/data/12d1-1035 | 0 root/package/modems/src/data/12d1-1404 | 0 root/package/modems/src/data/12d1-1406 | 0 root/package/modems/src/data/12d1-140b | 0 root/package/modems/src/data/12d1-140c | 0 root/package/modems/src/data/12d1-1412 | 0 root/package/modems/src/data/12d1-141b | 0 root/package/modems/src/data/12d1-1433 | 0 root/package/modems/src/data/12d1-1436 | 0 root/package/modems/src/data/12d1-1444 | 0 root/package/modems/src/data/12d1-144e | 0 root/package/modems/src/data/12d1-1464 | 0 root/package/modems/src/data/12d1-1465 | 0 root/package/modems/src/data/12d1-1491 | 0 root/package/modems/src/data/12d1-14a5 | 0 root/package/modems/src/data/12d1-14a8 | 0 root/package/modems/src/data/12d1-14ac | 0 root/package/modems/src/data/12d1-14ae | 0 root/package/modems/src/data/12d1-14c6 | 0 root/package/modems/src/data/12d1-14c8 | 0 root/package/modems/src/data/12d1-14c9 | 0 root/package/modems/src/data/12d1-14ca | 0 root/package/modems/src/data/12d1-14cb | 0 root/package/modems/src/data/12d1-14cc | 0 root/package/modems/src/data/12d1-14cf | 0 root/package/modems/src/data/12d1-14d2 | 0 root/package/modems/src/data/12d1-1506 | 0 root/package/modems/src/data/12d1-150a | 0 root/package/modems/src/data/12d1-150c | 0 root/package/modems/src/data/12d1-150f | 0 root/package/modems/src/data/12d1-151b | 0 root/package/modems/src/data/12d1-151d | 0 root/package/modems/src/data/12d1-156c | 0 root/package/modems/src/data/12d1-1576 | 0 root/package/modems/src/data/12d1-1577 | 0 root/package/modems/src/data/12d1-1578 | 0 root/package/modems/src/data/12d1-1589 | 0 root/package/modems/src/data/12d1-1c05 | 0 root/package/modems/src/data/12d1-1c07 | 0 root/package/modems/src/data/12d1-1c08 | 0 root/package/modems/src/data/12d1-1c10 | 0 root/package/modems/src/data/12d1-1c12 | 0 root/package/modems/src/data/12d1-1c1e | 0 root/package/modems/src/data/12d1-1c1f | 0 root/package/modems/src/data/12d1-1c23 | 0 root/package/modems/src/data/12d1-1f16 | 0 root/package/modems/src/data/1410-1400 | 0 root/package/modems/src/data/1410-1410 | 0 root/package/modems/src/data/1410-1420 | 0 root/package/modems/src/data/1410-1430 | 0 root/package/modems/src/data/1410-1450 | 0 root/package/modems/src/data/1410-2100 | 0 root/package/modems/src/data/1410-2110 | 0 root/package/modems/src/data/1410-2120 | 0 root/package/modems/src/data/1410-2130 | 0 root/package/modems/src/data/1410-2400 | 0 root/package/modems/src/data/1410-2410 | 0 root/package/modems/src/data/1410-2420 | 0 root/package/modems/src/data/1410-4100 | 0 root/package/modems/src/data/1410-4400 | 0 root/package/modems/src/data/1410-6000 | 0 root/package/modems/src/data/1410-6001 | 0 root/package/modems/src/data/1410-6002 | 0 root/package/modems/src/data/1410-6010 | 0 root/package/modems/src/data/1410-7001 | 0 root/package/modems/src/data/1410-7003 | 0 root/package/modems/src/data/1410-7030 | 0 root/package/modems/src/data/1410-7031 | 0 root/package/modems/src/data/1410-7041 | 0 root/package/modems/src/data/1410-7042 | 0 root/package/modems/src/data/1410-9011 | 0 root/package/modems/src/data/1410-b001 | 0 root/package/modems/src/data/1529-3100 | 0 root/package/modems/src/data/16d5-6202 | 0 root/package/modems/src/data/16d5-6501 | 0 root/package/modems/src/data/16d5-6502 | 0 root/package/modems/src/data/16d5-6603 | 0 root/package/modems/src/data/16d5-900d | 0 root/package/modems/src/data/16d8-5141 | 0 root/package/modems/src/data/16d8-5533 | 0 root/package/modems/src/data/16d8-5543 | 0 root/package/modems/src/data/16d8-5553 | 0 root/package/modems/src/data/16d8-6002 | 0 root/package/modems/src/data/16d8-6006 | 0 root/package/modems/src/data/16d8-6007 | 0 root/package/modems/src/data/16d8-6008 | 0 root/package/modems/src/data/16d8-6522 | 0 root/package/modems/src/data/16d8-6523 | 0 root/package/modems/src/data/16d8-6532 | 0 root/package/modems/src/data/16d8-6533 | 0 root/package/modems/src/data/16d8-6543 | 0 root/package/modems/src/data/16d8-680a | 0 root/package/modems/src/data/19d2-0001 | 0 root/package/modems/src/data/19d2-0002 | 0 root/package/modems/src/data/19d2-0015 | 0 root/package/modems/src/data/19d2-0016 | 0 root/package/modems/src/data/19d2-0017 | 0 root/package/modems/src/data/19d2-0018 | 0 root/package/modems/src/data/19d2-0019 | 0 root/package/modems/src/data/19d2-0022 | 0 root/package/modems/src/data/19d2-0024 | 0 root/package/modems/src/data/19d2-0025 | 0 root/package/modems/src/data/19d2-0031 | 0 root/package/modems/src/data/19d2-0033 | 0 root/package/modems/src/data/19d2-0037 | 0 root/package/modems/src/data/19d2-0039 | 0 root/package/modems/src/data/19d2-0042 | 0 root/package/modems/src/data/19d2-0052 | 0 root/package/modems/src/data/19d2-0055 | 0 root/package/modems/src/data/19d2-0057 | 0 root/package/modems/src/data/19d2-0063 | 0 root/package/modems/src/data/19d2-0064 | 0 root/package/modems/src/data/19d2-0066 | 0 root/package/modems/src/data/19d2-0073 | 0 root/package/modems/src/data/19d2-0079 | 0 root/package/modems/src/data/19d2-0082 | 0 root/package/modems/src/data/19d2-0086 | 0 root/package/modems/src/data/19d2-0091 | 0 root/package/modems/src/data/19d2-0094 | 0 root/package/modems/src/data/19d2-0104 | 0 root/package/modems/src/data/19d2-0108 | 0 root/package/modems/src/data/19d2-0116 | 0 root/package/modems/src/data/19d2-0117 | 0 root/package/modems/src/data/19d2-0121 | 0 root/package/modems/src/data/19d2-0124 | 0 root/package/modems/src/data/19d2-0128 | 0 root/package/modems/src/data/19d2-0142 | 0 root/package/modems/src/data/19d2-0143 | 0 root/package/modems/src/data/19d2-0152 | 0 root/package/modems/src/data/19d2-0157 | 0 root/package/modems/src/data/19d2-0167 | 0 root/package/modems/src/data/19d2-0170 | 0 root/package/modems/src/data/19d2-0199 | 0 root/package/modems/src/data/19d2-0257 | 0 root/package/modems/src/data/19d2-0265 | 0 root/package/modems/src/data/19d2-0284 | 0 root/package/modems/src/data/19d2-0326 | 0 root/package/modems/src/data/19d2-1003 | 0 root/package/modems/src/data/19d2-1008 | 0 root/package/modems/src/data/19d2-1010 | 0 root/package/modems/src/data/19d2-1015 | 0 root/package/modems/src/data/19d2-1018 | 0 root/package/modems/src/data/19d2-1172 | 0 root/package/modems/src/data/19d2-1173 | 0 root/package/modems/src/data/19d2-1176 | 0 root/package/modems/src/data/19d2-1177 | 0 root/package/modems/src/data/19d2-1181 | 0 root/package/modems/src/data/19d2-1203 | 0 root/package/modems/src/data/19d2-1208 | 0 root/package/modems/src/data/19d2-1211 | 0 root/package/modems/src/data/19d2-1212 | 0 root/package/modems/src/data/19d2-1217 | 0 root/package/modems/src/data/19d2-1218 | 0 root/package/modems/src/data/19d2-1220 | 0 root/package/modems/src/data/19d2-1222 | 0 root/package/modems/src/data/19d2-1245 | 0 root/package/modems/src/data/19d2-1252 | 0 root/package/modems/src/data/19d2-1254 | 0 root/package/modems/src/data/19d2-1256 | 0 root/package/modems/src/data/19d2-1270 | 0 root/package/modems/src/data/19d2-1401 | 0 root/package/modems/src/data/19d2-1402 | 0 root/package/modems/src/data/19d2-1426 | 0 root/package/modems/src/data/19d2-1512 | 0 root/package/modems/src/data/19d2-1515 | 0 root/package/modems/src/data/19d2-1518 | 0 root/package/modems/src/data/19d2-1519 | 0 root/package/modems/src/data/19d2-1522 | 0 root/package/modems/src/data/19d2-1525 | 0 root/package/modems/src/data/19d2-1527 | 0 root/package/modems/src/data/19d2-1537 | 0 root/package/modems/src/data/19d2-1538 | 0 root/package/modems/src/data/19d2-1544 | 0 root/package/modems/src/data/19d2-2002 | 0 root/package/modems/src/data/19d2-2003 | 0 root/package/modems/src/data/19d2-ffdd | 0 root/package/modems/src/data/19d2-ffe4 | 0 root/package/modems/src/data/19d2-ffe9 | 0 root/package/modems/src/data/19d2-fff1 | 0 root/package/modems/src/data/19d2-fffb | 0 root/package/modems/src/data/19d2-fffc | 0 root/package/modems/src/data/19d2-fffd | 0 root/package/modems/src/data/19d2-fffe | 0 root/package/modems/src/data/19d2-ffff | 0 root/package/modems/src/data/1a8d-1002 | 0 root/package/modems/src/data/1a8d-1003 | 0 root/package/modems/src/data/1a8d-1007 | 0 root/package/modems/src/data/1a8d-1009 | 0 root/package/modems/src/data/1a8d-100c | 0 root/package/modems/src/data/1a8d-100d | 0 root/package/modems/src/data/1a8d-2006 | 0 root/package/modems/src/data/1bbb-0000 | 0 root/package/modems/src/data/1bbb-0012 | 0 root/package/modems/src/data/1bbb-0017 | 0 root/package/modems/src/data/1bbb-0052 | 0 root/package/modems/src/data/1bbb-00b7 | 0 root/package/modems/src/data/1bbb-00ca | 0 root/package/modems/src/data/1bbb-011e | 0 root/package/modems/src/data/1bbb-0203 | 0 root/package/modems/src/data/1c9e-6060 | 0 root/package/modems/src/data/1c9e-6061 | 0 root/package/modems/src/data/1c9e-9000 | 0 root/package/modems/src/data/1c9e-9603 | 0 root/package/modems/src/data/1c9e-9605 | 0 root/package/modems/src/data/1c9e-9607 | 0 root/package/modems/src/data/1c9e-9801 | 0 root/package/modems/src/data/1c9e-9900 | 0 root/package/modems/src/data/1e0e-9000 | 0 root/package/modems/src/data/1e0e-9100 | 0 root/package/modems/src/data/1e0e-9200 | 0 root/package/modems/src/data/1e0e-ce16 | 0 root/package/modems/src/data/1e0e-cefe | 0 root/package/modems/src/data/2001-7d00 | 0 root/package/modems/src/data/2001-7d01 | 0 root/package/modems/src/data/2001-7d02 | 0 root/package/modems/src/data/2001-7d03 | 0 root/package/modems/src/data/211f-6801 | 0 root/package/modems/src/data/2357-0201 | 0 root/package/modems/src/data/2357-0202 | 0 root/package/modems/src/data/2357-0203 | 0 root/package/modems/src/data/2357-9000 | 0 root/package/modems/src/data/2c7c-0121 | 0 root/package/modems/src/data/2c7c-0125 | 0 root/package/modems/src/data/2c7c-0296 | 0 root/package/modems/src/data/2c7c-0306 | 0 root/package/modems/src/data/2c7c-0512 | 0 root/package/modems/src/data/413c-8114 | 0 root/package/modems/src/data/413c-8115 | 0 root/package/modems/src/data/413c-8116 | 0 root/package/modems/src/data/413c-8117 | 0 root/package/modems/src/data/413c-8118 | 0 root/package/modems/src/data/413c-8128 | 0 root/package/modems/src/data/413c-8129 | 0 root/package/modems/src/data/413c-8133 | 0 root/package/modems/src/data/413c-8134 | 0 root/package/modems/src/data/413c-8135 | 0 root/package/modems/src/data/413c-8136 | 0 root/package/modems/src/data/413c-8137 | 0 root/package/modems/src/data/413c-8138 | 0 root/package/modems/src/data/413c-8147 | 0 root/package/modems/src/data/413c-8180 | 0 root/package/modems/src/data/413c-8181 | 0 root/package/modems/src/data/413c-8182 | 0 root/package/modems/src/data/413c-8186 | 0 root/package/modems/src/data/413c-8194 | 0 root/package/modems/src/data/413c-8195 | 0 root/package/modems/src/data/413c-8196 | 0 root/package/modems/src/data/413c-819b | 0 .../config/firewall/patches/fullconenat.patch | 0 root/package/network/wwan/files/data/05c6-9215 | 0 root/package/network/wwan/files/data/2c7c-0121 | 0 root/package/network/wwan/files/data/2c7c-0296 | 0 root/package/network/wwan/files/data/2c7c-0306 | 0 root/package/network/wwan/files/data/2c7c-0512 | 0 root/scripts/mkits-rutx.sh | 0 .../950-0785-ARM-dts-Add-bcm2711-rpi-cm4.dts.patch | 0 .../backport-5.14/011-kbuild-export-SUBARCH.patch | 0 ...nft_flow_offload-handle-netdevice-events-f.patch | 0 ...0-MIPS-uasm-Enable-muhu-opcode-for-MIPS-R6.patch | 0 ...Add-workaround-for-Loongson-2F-nop-CPU-err.patch | 0 ...6-02-mips-bpf-Add-eBPF-JIT-for-32-bit-MIPS.patch | 0 ...-mips-bpf-Add-new-eBPF-JIT-for-64-bit-MIPS.patch | 0 ...ips-bpf-Add-JIT-workarounds-for-CPU-errata.patch | 0 .../050-v5.16-05-mips-bpf-Enable-eBPF-JITs.patch | 0 ...ips-bpf-Remove-old-BPF-JIT-implementations.patch | 0 ...-v5.16-0001-net-bgmac-improve-handling-PHY.patch | 0 ...002-net-bgmac-support-MDIO-described-in-DT.patch | 0 ...803x-add-support-for-qca-8327-internal-phy.patch | 0 ...-at803x-add-support-for-qca-8327-A-variant.patch | 0 ...803x-add-resume-suspend-function-to-qca83x.patch | 0 ...803x-fix-spacing-and-improve-name-for-83xx.patch | 0 ...-net-phy-at803x-fix-resume-for-QCA8327-phy.patch | 0 ...-at803x-add-DAC-amplitude-fix-for-8327-phy.patch | 0 ...803x-enable-prefer-master-for-83xx-interna.patch | 0 ...-net-phy-at803x-better-describe-debug-regs.patch | 0 ....16-01-dsa-qca8k-add-mac-power-sel-support.patch | 0 ...s-net-dsa-qca8k-Add-SGMII-clock-phase-prop.patch | 0 ...a-qca8k-add-support-for-sgmii-falling-edge.patch | 0 ...s-net-dsa-qca8k-Document-support-for-CPU-p.patch | 0 ...5-net-dsa-qca8k-add-support-for-cpu-port-6.patch | 0 ...a8k-rework-rgmii-delay-logic-and-scan-for-.patch | 0 ...s-net-dsa-qca8k-Document-qca-sgmii-enable-.patch | 0 ...et-dsa-qca8k-add-explicit-SGMII-PLL-enable.patch | 0 ...s-net-dsa-qca8k-Document-qca-led-open-drai.patch | 0 ...t-dsa-qca8k-add-support-for-pws-config-reg.patch | 0 ...s-net-dsa-qca8k-document-support-for-qca83.patch | 0 ...6-12-net-dsa-qca8k-add-support-for-QCA8328.patch | 0 ...sa-qca8k-set-internal-delay-also-for-sgmii.patch | 0 ...qca8k-move-port-config-to-dedicated-struct.patch | 0 ...s-net-ipq8064-mdio-fix-warning-with-new-qc.patch | 0 ...dings-net-dsa-qca8k-convert-to-YAML-schema.patch | 0 ...-fix-delay-applied-to-wrong-cpu-in-parse-p.patch | 0 ...-tidy-for-loop-in-setup-and-add-cpu-port-c.patch | 0 ...-make-sure-pad0-mac06-exchange-is-disabled.patch | 0 ...btf-to-be-used-in-map_create-and-prog_load.patch | 0 ...500-ovl-check-permission-to-open-real-file.patch | 0 ...501-ovl-switch-to-mounter-creds-in-readdir.patch | 0 ...02-ovl-verify-permissions-in-ovl_path_open.patch | 0 .../503-ovl-do-not-fail-because-of_O_NOACTIME.patch | 0 ...-pppoe-when-dst-does-not-match-dev-address.patch | 0 root/target/linux/generic/config-4.14 | 0 root/target/linux/generic/config-4.19 | 0 root/target/linux/generic/config-4.9 | 0 root/target/linux/generic/config-5.14 | 0 root/target/linux/generic/config-5.15 | 0 root/target/linux/generic/config-5.4 | 0 .../generic/files/drivers/net/phy/b53/b53_common.c | 0 .../linux/generic/hack-4.14/690-mptcp_v0.94.patch | 0 .../generic/hack-4.14/998-ndpi-netfilter.patch | 0 .../hack-4.14/999-stop-promiscuous-info.patch | 0 .../linux/generic/hack-4.19/690-mptcp_v0.95.patch | 0 .../linux/generic/hack-4.19/691-mptcp_ecf.patch | 0 .../generic/hack-4.19/692-tcp_nanqinlang.patch | 0 .../generic/hack-4.19/998-ndpi-netfilter.patch | 0 .../generic/hack-4.19/999-f2fs-ioerrorfix.patch | 0 .../hack-4.19/999-stop-promiscuous-info.patch | 0 .../linux/generic/hack-4.9/690-mptcp_v0.93.patch | 0 .../linux/generic/hack-5.14/204-module_strip.patch | 0 .../hack-5.14/210-darwin_scripts_include.patch | 0 .../hack-5.14/211-darwin-uuid-typedef-clash.patch | 0 .../generic/hack-5.14/212-tools_portability.patch | 0 .../hack-5.14/214-spidev_h_portability.patch | 0 .../linux/generic/hack-5.14/220-gc_sections.patch | 0 .../generic/hack-5.14/221-module_exports.patch | 0 .../hack-5.14/230-openwrt_lzma_options.patch | 0 .../hack-5.14/249-udp-tunnel-selection.patch | 0 .../generic/hack-5.14/250-netfilter_depends.patch | 0 .../linux/generic/hack-5.14/251-kconfig.patch | 0 .../hack-5.14/260-crypto_test_dependencies.patch | 0 .../generic/hack-5.14/261-lib-arc4-unhide.patch | 0 .../linux/generic/hack-5.14/280-rfkill-stubs.patch | 0 ...S-r4k_cache-use-more-efficient-cache-blast.patch | 0 .../hack-5.14/301-mips_image_cmdline_hack.patch | 0 .../hack-5.14/321-powerpc_crtsavres_prereq.patch | 0 .../420-mtd-set-rootfs-to-be-root-dev.patch | 0 .../linux/generic/hack-5.14/531-debloat_lzma.patch | 0 .../640-bridge-only-accept-EAP-locally.patch | 0 ...-netfilter-connmark-introduce-set-dscpmark.patch | 0 .../650-netfilter-add-xt_FLOWOFFLOAD-target.patch | 0 .../hack-5.14/651-wireless_mesh_header.patch | 0 .../generic/hack-5.14/660-fq_codel_defaults.patch | 0 .../hack-5.14/661-use_fq_codel_by_default.patch | 0 .../hack-5.14/700-swconfig_switch_drivers.patch | 0 .../710-net-dsa-mv88e6xxx-default-VID-1.patch | 0 ...11-net-dsa-mv88e6xxx-disable-ATU-violation.patch | 0 .../hack-5.14/773-bgmac-add-srab-switch.patch | 0 .../hack-5.14/780-net-ipheth-fix-RX-EOVERFLOW.patch | 0 .../hack-5.14/800-GPIO-add-named-gpio-exports.patch | 0 .../generic/hack-5.14/901-debloat_sock_diag.patch | 0 .../linux/generic/hack-5.14/902-debloat_proc.patch | 0 .../generic/hack-5.14/904-debloat_dma_buf.patch | 0 .../generic/hack-5.14/910-kobject_uevent.patch | 0 .../911-kobject_add_broadcast_uevent.patch | 0 .../linux/generic/hack-5.15/220-gc_sections.patch | 0 .../linux/generic/hack-5.4/690-mptcp_v0.96.patch | 0 .../linux/generic/hack-5.4/692-tcp_nanqinlang.patch | 0 .../linux/generic/hack-5.4/693-tcp_bbr2.patch | 0 ...nntrack-events-support-multiple-registrant.patch | 0 ...-patch-linux-kernel-to-support-shortcut-fe.patch | 0 .../hack-5.4/999-stop-promiscuous-info.patch | 0 ...-only-include-asm-rwonce.h-for-kernel-code.patch | 0 .../101-Use-stddefs.h-instead-of-compiler.h.patch | 0 ...process-negative-stack-offsets-on-stack-tr.patch | 0 ...oc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch | 0 .../130-add-linux-spidev-compatible-si3210.patch | 0 ...0-bridge_allow_receiption_on_disabled_port.patch | 0 ...90-rtc-rs5c372-support_alarms_up_to_1_week.patch | 0 ...-let_the_alarm_to_be_used_as_wakeup_source.patch | 0 .../pending-5.14/201-extra_optimization.patch | 0 .../pending-5.14/203-kallsyms_uncompressed.patch | 0 .../pending-5.14/205-backtrace_module_info.patch | 0 ...-unsane-filenames-from-deps_initramfs-list.patch | 0 ...261-enable_wilink_platform_without_drivers.patch | 0 .../270-platform-mikrotik-build-bits.patch | 0 .../pending-5.14/300-mips_expose_boot_raw.patch | 0 .../pending-5.14/302-mips_no_branch_likely.patch | 0 .../pending-5.14/305-mips_module_reloc.patch | 0 .../pending-5.14/307-mips_highmem_offset.patch | 0 .../generic/pending-5.14/308-mips32r2_tune.patch | 0 ...S-Add-CPU-option-reporting-to-proc-cpuinfo.patch | 0 .../310-arm_module_unresolved_weak_sym.patch | 0 ...-Accept-command-line-parameters-from-users.patch | 0 .../pending-5.14/332-arc-add-OWRTDTB-section.patch | 0 ...arc-enable-unaligned-access-in-kernel-mode.patch | 0 ...able-kernel-XZ-compression-option-on-PPC_8.patch | 0 .../pending-5.14/400-mtd-mtdsplit-support.patch | 0 ...redboot-add-of_match_table-with-DT-binding.patch | 0 .../430-mtd-add-myloader-partition-parser.patch | 0 ...xpart-check-for-bad-blocks-when-calculatin.patch | 0 ...2-mtd-bcm47xxpart-detect-T_Meter-partition.patch | 0 .../435-mtd-add-routerbootpart-parser-config.patch | 0 .../460-mtd-cfi_cmdset_0002-no-erase_suspend.patch | 0 ...i_cmdset_0002-add-buffer-write-cmd-timeout.patch | 0 .../465-m25p80-mx-disable-software-protection.patch | 0 ...r-support-limiting-4K-sectors-support-base.patch | 0 .../476-mtd-spi-nor-add-eon-en25q128.patch | 0 .../479-mtd-spi-nor-add-xtx-xt25f128b.patch | 0 ...spi-nor-add-support-for-Gigadevice-GD25D05.patch | 0 .../pending-5.14/483-mtd-spi-nor-add-gd25q512.patch | 0 ...ttach-mtd-device-named-ubi-or-data-on-boot.patch | 0 ...ubi-auto-create-ubiblock-device-for-rootfs.patch | 0 ...o-mounting-ubi0-rootfs-in-init-do_mounts.c.patch | 0 ...i-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch | 0 .../494-mtd-ubi-add-EOF-marker-support.patch | 0 .../495-mtd-core-add-get_mtd_device_by_node.patch | 0 ...ndings-add-bindings-for-mtd-concat-devices.patch | 0 ...mtdconcat-add-dt-driver-for-concat-devices.patch | 0 .../pending-5.14/500-fs_cdrom_dependencies.patch | 0 .../530-jffs2_make_lzma_available.patch | 0 .../generic/pending-5.14/532-jffs2_eofdetect.patch | 0 .../600-netfilter_conntrack_flush.patch | 0 .../610-netfilter_match_bypass_default_checks.patch | 0 .../611-netfilter_match_bypass_default_table.patch | 0 .../612-netfilter_match_reduce_memory_access.patch | 0 .../613-netfilter_optional_tcp_window_check.patch | 0 ...hed-codel-do-not-defer-queue-length-update.patch | 0 .../pending-5.14/630-packet_socket_type.patch | 0 .../generic/pending-5.14/655-increase_skb_pad.patch | 0 .../666-Add-support-for-MAP-E-FMRs-mesh-mode.patch | 0 ...ejecting-with-source-address-failed-policy.patch | 0 ...e-defines-for-_POLICY_FAILED-until-all-cod.patch | 0 ...680-NET-skip-GRO-for-foreign-MAC-addresses.patch | 0 ...d-mac-address-support-to-of_get_mac_addres.patch | 0 ...2-of_net-add-mac-address-increment-support.patch | 0 .../683-of_net-add-mac-address-to-of-tree.patch | 0 ...et-mtk_eth_soc-avoid-creating-duplicate-of.patch | 0 ...y-add-detach-callback-to-struct-phy_driver.patch | 0 .../735-net-phy-at803x-fix-at8033-sgmii-mode.patch | 0 .../760-net-dsa-mv88e6xxx-fix-vlan-setup.patch | 0 .../761-net-dsa-mt7530-Support-EEE-features.patch | 0 ...6xxx-Request-assisted-learning-on-CPU-port.patch | 0 ...oC-device-struct-copy-its-DMA-params-to-th.patch | 0 .../810-pci_disable_common_quirks.patch | 0 .../811-pci_disable_usb_common_quirks.patch | 0 ...o-fix-problem-with-platfom-data-in-w1-gpio.patch | 0 .../generic/pending-5.14/834-ledtrig-libata.patch | 0 .../840-hwrng-bcm2835-set-quality-to-1000.patch | 0 .../generic/pending-5.14/920-mangle_bootargs.patch | 0 ...rop-interrupt-provider-address-cells-check.patch | 0 ...e-.rename2-and-add-RENAME_WHITEOUT-support.patch | 0 .../141-jffs2-add-RENAME_EXCHANGE-support.patch | 0 .../pending-5.15/142-jffs2-add-splice-ops.patch | 0 .../pending-5.15/420-mtd-redboot_space.patch | 0 ...-spi-nor-rework-broken-flash-reset-support.patch | 0 ...3-mtd-spinand-add-support-for-xtx-xt26g0xa.patch | 0 .../484-mtd-spi-nor-add-esmt-f25l16pa.patch | 0 ...o-mounting-ubi0-rootfs-in-init-do_mounts.c.patch | 0 ...2-of_net-add-mac-address-increment-support.patch | 0 .../683-of_net-add-mac-address-to-of-tree.patch | 0 ...dge-add-knob-for-filtering-rx-tx-BPDU-pack.patch | 0 ...od-add-missing-linux-if_ether.h-for-ETH_AL.patch | 0 .../generic/pending-5.15/930-qcom-qmi-helpers.patch | 0 ...dd-default-and-support-for-missing-flashes.patch | 0 ...3-mtd-spinand-add-support-for-xtx-xt26g0xa.patch | 0 ...nf_flow_table-add-hardware-offload-support.patch | 0 ...nf_flow_table-rework-hardware-offload-time.patch | 0 .../linux/ipq40xx/base-files/etc/board.d/01_leds | 0 .../linux/ipq40xx/base-files/etc/board.d/02_network | 0 .../ipq40xx/base-files/etc/board.d/03_gpio_switches | 0 .../etc/hotplug.d/firmware/11-ath10k-caldata | 0 .../linux/ipq40xx/base-files/lib/upgrade/linksys.sh | 0 .../ipq40xx/base-files/lib/upgrade/platform.sh | 0 .../files/arch/arm/boot/dts/qcom-ipq4019-l1000.dts | 0 .../arch/arm/boot/dts/qcom-ipq4019-nhx4019.dts | 0 .../files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts | 0 root/target/linux/ipq40xx/generic/target.mk | 0 root/target/linux/ipq40xx/image/generic.mk | 0 .../patches-5.4/901-arm-boot-add-dts-files.patch | 0 ...d-add-driver-support-for-MT7621-nand-flash.patch | 0 root/target/linux/rockchip/Makefile | 0 .../rockchip/armv8/base-files/etc/board.d/01_leds | 0 .../armv8/base-files/etc/board.d/02_network | 0 .../etc/hotplug.d/net/40-net-smp-affinity | 0 root/target/linux/rockchip/armv8/config-5.14 | 0 root/target/linux/rockchip/armv8/config-5.15 | 0 .../arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts | 0 .../arm64/boot/dts/rockchip/rk3399-king3399.dts | 0 root/target/linux/rockchip/image/armv8.mk | 0 .../linux/rockchip/image/nanopi-r4s.bootscript | 0 ...k3399-Add-support-for-FriendlyARM-NanoPi-R.patch | 0 ...et-usb-r8152-add-LED-configuration-from-OF.patch | 0 ...ings-net-add-RTL8152-binding-documentation.patch | 0 ...ts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch | 0 .../100-rockchip-use-system-LED-for-OpenWrt.patch | 0 ...p-add-usb3-controller-node-for-RK3328-SoCs.patch | 0 ...102-rockchip-enable-LAN-port-on-NanoPi-R2S.patch | 0 ...chip-add-OF-node-for-USB-eth-on-NanoPi-R2S.patch | 0 .../patches-5.14/105-rockchip-rock-pi-4.patch | 0 ...k3399-Add-support-for-FriendlyARM-NanoPi-R.patch | 0 ...ts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch | 0 ...chip-add-OF-node-for-USB-eth-on-NanoPi-R2S.patch | 0 .../patches-5.4/107-nanopi-r4s-sd-signalling.patch | 0 .../base-files/etc/uci-defaults/99-switch-config | 0 .../linux/sunxi/base-files/sbin/swconfig-wrapper.sh | 0 root/target/linux/sunxi/config-5.14 | 0 root/target/linux/x86/64/config-5.14 | 0 root/target/linux/x86/config-4.19 | 0 root/target/linux/x86/config-5.14 | 0 .../012-pcengines-apu2-detect-apuv4-board.patch | 0 .../x86/patches-5.14/100-fix_cs5535_clockevt.patch | 0 .../990-mptcp-fullmesh-raise-addresses-limit.patch | 0 root/tools/firmware-utils/Makefile | 0 sign.sh | 0 690 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 .github/FUNDING.yml mode change 100755 => 100644 .github/ISSUE_TEMPLATE/enhancement.md mode change 100755 => 100644 .github/ISSUE_TEMPLATE/feature_request.md mode change 100755 => 100644 .github/ISSUE_TEMPLATE/hardware_support.md mode change 100755 => 100644 .github/ISSUE_TEMPLATE/help.md mode change 100755 => 100644 .github/ISSUE_TEMPLATE/issue.md mode change 100755 => 100644 .github/ISSUE_TEMPLATE/question.md mode change 100755 => 100644 .github/PULL_REQUEST_TEMPLATE.md mode change 100755 => 100644 .github/workflows/stale.yml mode change 100755 => 100644 .gitignore mode change 100755 => 100644 CLA-entity.md mode change 100755 => 100644 CLA-individual.md mode change 100755 => 100644 CODE_OF_CONDUCT.md mode change 100755 => 100644 CONTRIBUTING.md mode change 100755 => 100644 LICENSE mode change 100755 => 100644 README.md mode change 100755 => 100644 config mode change 100755 => 100644 config-4018 mode change 100755 => 100644 config-5gx3 mode change 100755 => 100644 config-bpi-r1 mode change 100755 => 100644 config-bpi-r2 mode change 100755 => 100644 config-bpi-r64 mode change 100755 => 100644 config-cm520-79f mode change 100755 => 100644 config-espressobin mode change 100755 => 100644 config-espressobin1 mode change 100755 => 100644 config-l1000 mode change 100755 => 100644 config-nanopi_neo mode change 100755 => 100644 config-p2w_r619ac mode change 100755 => 100644 config-r2s mode change 100755 => 100644 config-r4s mode change 100755 => 100644 config-r7800 mode change 100755 => 100644 config-rpi2 mode change 100755 => 100644 config-rpi3 mode change 100755 => 100644 config-rpi4 mode change 100755 => 100644 config-rutx mode change 100755 => 100644 config-ubnt-erx mode change 100755 => 100644 config-wrt3200acm mode change 100755 => 100644 config-wrt32x mode change 100755 => 100644 config-x86 mode change 100755 => 100644 config-x86_64 mode change 100755 => 100644 config-zbt4019 mode change 100755 => 100644 contributors/example.md mode change 100755 => 100644 deploy_rsa.enc mode change 100755 => 100644 patches/950-0785-fixcm4soundboss2.patch mode change 100755 => 100644 patches/bbr2.patch mode change 100755 => 100644 patches/check-rsync.patch mode change 100755 => 100644 patches/download-ipv4.patch mode change 100755 => 100644 patches/gtime.patch mode change 100755 => 100644 patches/images.patch mode change 100755 => 100644 patches/ipt-nat6.patch mode change 100755 => 100644 patches/luci-occitan.patch mode change 100755 => 100644 patches/nanqinlang.patch mode change 100755 => 100644 patches/nocheck.patch mode change 100755 => 100644 patches/package-too-long.patch mode change 100755 => 100644 patches/remove_abi.patch mode change 100755 => 100644 patches/smsc75xx.patch mode change 100755 => 100644 patches/uefi.patch mode change 100755 => 100644 root/include/kernel-version.mk mode change 100755 => 100644 root/package/base-files/files/bin/config_generate mode change 100755 => 100644 root/package/base-files/files/etc/banner mode change 100755 => 100644 root/package/base-files/files/etc/shadow mode change 100755 => 100644 root/package/boot/arm-trusted-firmware-rockchip-vendor/pack-firmware.sh mode change 100755 => 100644 root/package/boot/uboot-envtools/Makefile mode change 100755 => 100644 root/package/boot/uboot-rockchip/Makefile mode change 100755 => 100644 root/package/boot/uboot-rockchip/patches/306-rockchip-rk3399-Add-support-for-Rongpin-king3399.patch mode change 100755 => 100644 root/package/firmware/ipq-wifi/Makefile mode change 100755 => 100644 root/package/firmware/ipq-wifi/board-pangu_l1000.qca4019 mode change 100755 => 100644 root/package/firmware/ipq-wifi/board-teltonika_rutx.qca4019 mode change 100755 => 100644 root/package/kernel/linux/modules/crypto.mk mode change 100755 => 100644 root/package/kernel/linux/modules/fs.mk mode change 100755 => 100644 root/package/kernel/linux/modules/input.mk mode change 100755 => 100644 root/package/kernel/linux/modules/netfilter.mk mode change 100755 => 100644 root/package/kernel/linux/modules/other.mk mode change 100755 => 100644 root/package/kernel/linux/modules/sound.mk mode change 100755 => 100644 root/package/kernel/mwlwifi/patches/002-remove-fallthrough.patch mode change 100755 => 100644 root/package/kernel/r2ec/Makefile mode change 100755 => 100644 root/package/kernel/r2ec/src/Makefile mode change 100755 => 100644 root/package/kernel/r2ec/src/io.h mode change 100755 => 100644 root/package/kernel/r2ec/src/r2ec.c mode change 100755 => 100644 root/package/kernel/rtl8812au-ct/Makefile mode change 100755 => 100644 root/package/modems/Makefile mode change 100755 => 100644 root/package/modems/src/README.md mode change 100755 => 100644 root/package/modems/src/data/0421-03a7 mode change 100755 => 100644 root/package/modems/src/data/0421-060d mode change 100755 => 100644 root/package/modems/src/data/0421-060e mode change 100755 => 100644 root/package/modems/src/data/0421-0612 mode change 100755 => 100644 root/package/modems/src/data/0421-0619 mode change 100755 => 100644 root/package/modems/src/data/0421-061e mode change 100755 => 100644 root/package/modems/src/data/0421-0623 mode change 100755 => 100644 root/package/modems/src/data/0421-0629 mode change 100755 => 100644 root/package/modems/src/data/0421-062d mode change 100755 => 100644 root/package/modems/src/data/0421-062f mode change 100755 => 100644 root/package/modems/src/data/0421-0638 mode change 100755 => 100644 root/package/modems/src/data/05c6-0016 mode change 100755 => 100644 root/package/modems/src/data/05c6-0023 mode change 100755 => 100644 root/package/modems/src/data/05c6-00a0 mode change 100755 => 100644 root/package/modems/src/data/05c6-6000 mode change 100755 => 100644 root/package/modems/src/data/05c6-9000 mode change 100755 => 100644 root/package/modems/src/data/05c6-9215 mode change 100755 => 100644 root/package/modems/src/data/07d1-3e01 mode change 100755 => 100644 root/package/modems/src/data/07d1-3e02 mode change 100755 => 100644 root/package/modems/src/data/07d1-7e11 mode change 100755 => 100644 root/package/modems/src/data/0af0-4005 mode change 100755 => 100644 root/package/modems/src/data/0af0-6901 mode change 100755 => 100644 root/package/modems/src/data/0af0-7201 mode change 100755 => 100644 root/package/modems/src/data/0af0-8120 mode change 100755 => 100644 root/package/modems/src/data/0af0-9200 mode change 100755 => 100644 root/package/modems/src/data/0b3c-c000 mode change 100755 => 100644 root/package/modems/src/data/0b3c-c001 mode change 100755 => 100644 root/package/modems/src/data/0b3c-c002 mode change 100755 => 100644 root/package/modems/src/data/0b3c-c003 mode change 100755 => 100644 root/package/modems/src/data/0b3c-c004 mode change 100755 => 100644 root/package/modems/src/data/0b3c-c005 mode change 100755 => 100644 root/package/modems/src/data/0b3c-c00a mode change 100755 => 100644 root/package/modems/src/data/0b3c-c00b mode change 100755 => 100644 root/package/modems/src/data/0bdb-1900 mode change 100755 => 100644 root/package/modems/src/data/0bdb-1902 mode change 100755 => 100644 root/package/modems/src/data/0bdb-190a mode change 100755 => 100644 root/package/modems/src/data/0bdb-190d mode change 100755 => 100644 root/package/modems/src/data/0bdb-1910 mode change 100755 => 100644 root/package/modems/src/data/0c88-17da mode change 100755 => 100644 root/package/modems/src/data/0c88-180a mode change 100755 => 100644 root/package/modems/src/data/0f3d-68a2 mode change 100755 => 100644 root/package/modems/src/data/0f3d-68aa mode change 100755 => 100644 root/package/modems/src/data/1004-6124 mode change 100755 => 100644 root/package/modems/src/data/1004-6141 mode change 100755 => 100644 root/package/modems/src/data/1004-6157 mode change 100755 => 100644 root/package/modems/src/data/1004-618f mode change 100755 => 100644 root/package/modems/src/data/106c-3711 mode change 100755 => 100644 root/package/modems/src/data/106c-3714 mode change 100755 => 100644 root/package/modems/src/data/106c-3715 mode change 100755 => 100644 root/package/modems/src/data/106c-3716 mode change 100755 => 100644 root/package/modems/src/data/106c-3717 mode change 100755 => 100644 root/package/modems/src/data/106c-3718 mode change 100755 => 100644 root/package/modems/src/data/106c-3721 mode change 100755 => 100644 root/package/modems/src/data/1199-0017 mode change 100755 => 100644 root/package/modems/src/data/1199-0018 mode change 100755 => 100644 root/package/modems/src/data/1199-0019 mode change 100755 => 100644 root/package/modems/src/data/1199-0020 mode change 100755 => 100644 root/package/modems/src/data/1199-0021 mode change 100755 => 100644 root/package/modems/src/data/1199-0022 mode change 100755 => 100644 root/package/modems/src/data/1199-0023 mode change 100755 => 100644 root/package/modems/src/data/1199-0024 mode change 100755 => 100644 root/package/modems/src/data/1199-0025 mode change 100755 => 100644 root/package/modems/src/data/1199-0026 mode change 100755 => 100644 root/package/modems/src/data/1199-0027 mode change 100755 => 100644 root/package/modems/src/data/1199-0028 mode change 100755 => 100644 root/package/modems/src/data/1199-0112 mode change 100755 => 100644 root/package/modems/src/data/1199-0120 mode change 100755 => 100644 root/package/modems/src/data/1199-0218 mode change 100755 => 100644 root/package/modems/src/data/1199-0220 mode change 100755 => 100644 root/package/modems/src/data/1199-0224 mode change 100755 => 100644 root/package/modems/src/data/1199-0301 mode change 100755 => 100644 root/package/modems/src/data/1199-6802 mode change 100755 => 100644 root/package/modems/src/data/1199-6803 mode change 100755 => 100644 root/package/modems/src/data/1199-6804 mode change 100755 => 100644 root/package/modems/src/data/1199-6805 mode change 100755 => 100644 root/package/modems/src/data/1199-6808 mode change 100755 => 100644 root/package/modems/src/data/1199-6809 mode change 100755 => 100644 root/package/modems/src/data/1199-6813 mode change 100755 => 100644 root/package/modems/src/data/1199-6815 mode change 100755 => 100644 root/package/modems/src/data/1199-6816 mode change 100755 => 100644 root/package/modems/src/data/1199-6820 mode change 100755 => 100644 root/package/modems/src/data/1199-6821 mode change 100755 => 100644 root/package/modems/src/data/1199-6822 mode change 100755 => 100644 root/package/modems/src/data/1199-6833 mode change 100755 => 100644 root/package/modems/src/data/1199-6834 mode change 100755 => 100644 root/package/modems/src/data/1199-6835 mode change 100755 => 100644 root/package/modems/src/data/1199-6838 mode change 100755 => 100644 root/package/modems/src/data/1199-6839 mode change 100755 => 100644 root/package/modems/src/data/1199-683a mode change 100755 => 100644 root/package/modems/src/data/1199-683b mode change 100755 => 100644 root/package/modems/src/data/1199-6850 mode change 100755 => 100644 root/package/modems/src/data/1199-6851 mode change 100755 => 100644 root/package/modems/src/data/1199-6852 mode change 100755 => 100644 root/package/modems/src/data/1199-6853 mode change 100755 => 100644 root/package/modems/src/data/1199-6855 mode change 100755 => 100644 root/package/modems/src/data/1199-6856 mode change 100755 => 100644 root/package/modems/src/data/1199-6859 mode change 100755 => 100644 root/package/modems/src/data/1199-685a mode change 100755 => 100644 root/package/modems/src/data/1199-6880 mode change 100755 => 100644 root/package/modems/src/data/1199-6890 mode change 100755 => 100644 root/package/modems/src/data/1199-6891 mode change 100755 => 100644 root/package/modems/src/data/1199-6892 mode change 100755 => 100644 root/package/modems/src/data/1199-6893 mode change 100755 => 100644 root/package/modems/src/data/1199-68a2 mode change 100755 => 100644 root/package/modems/src/data/1199-68aa mode change 100755 => 100644 root/package/modems/src/data/12d1-1035 mode change 100755 => 100644 root/package/modems/src/data/12d1-1404 mode change 100755 => 100644 root/package/modems/src/data/12d1-1406 mode change 100755 => 100644 root/package/modems/src/data/12d1-140b mode change 100755 => 100644 root/package/modems/src/data/12d1-140c mode change 100755 => 100644 root/package/modems/src/data/12d1-1412 mode change 100755 => 100644 root/package/modems/src/data/12d1-141b mode change 100755 => 100644 root/package/modems/src/data/12d1-1433 mode change 100755 => 100644 root/package/modems/src/data/12d1-1436 mode change 100755 => 100644 root/package/modems/src/data/12d1-1444 mode change 100755 => 100644 root/package/modems/src/data/12d1-144e mode change 100755 => 100644 root/package/modems/src/data/12d1-1464 mode change 100755 => 100644 root/package/modems/src/data/12d1-1465 mode change 100755 => 100644 root/package/modems/src/data/12d1-1491 mode change 100755 => 100644 root/package/modems/src/data/12d1-14a5 mode change 100755 => 100644 root/package/modems/src/data/12d1-14a8 mode change 100755 => 100644 root/package/modems/src/data/12d1-14ac mode change 100755 => 100644 root/package/modems/src/data/12d1-14ae mode change 100755 => 100644 root/package/modems/src/data/12d1-14c6 mode change 100755 => 100644 root/package/modems/src/data/12d1-14c8 mode change 100755 => 100644 root/package/modems/src/data/12d1-14c9 mode change 100755 => 100644 root/package/modems/src/data/12d1-14ca mode change 100755 => 100644 root/package/modems/src/data/12d1-14cb mode change 100755 => 100644 root/package/modems/src/data/12d1-14cc mode change 100755 => 100644 root/package/modems/src/data/12d1-14cf mode change 100755 => 100644 root/package/modems/src/data/12d1-14d2 mode change 100755 => 100644 root/package/modems/src/data/12d1-1506 mode change 100755 => 100644 root/package/modems/src/data/12d1-150a mode change 100755 => 100644 root/package/modems/src/data/12d1-150c mode change 100755 => 100644 root/package/modems/src/data/12d1-150f mode change 100755 => 100644 root/package/modems/src/data/12d1-151b mode change 100755 => 100644 root/package/modems/src/data/12d1-151d mode change 100755 => 100644 root/package/modems/src/data/12d1-156c mode change 100755 => 100644 root/package/modems/src/data/12d1-1576 mode change 100755 => 100644 root/package/modems/src/data/12d1-1577 mode change 100755 => 100644 root/package/modems/src/data/12d1-1578 mode change 100755 => 100644 root/package/modems/src/data/12d1-1589 mode change 100755 => 100644 root/package/modems/src/data/12d1-1c05 mode change 100755 => 100644 root/package/modems/src/data/12d1-1c07 mode change 100755 => 100644 root/package/modems/src/data/12d1-1c08 mode change 100755 => 100644 root/package/modems/src/data/12d1-1c10 mode change 100755 => 100644 root/package/modems/src/data/12d1-1c12 mode change 100755 => 100644 root/package/modems/src/data/12d1-1c1e mode change 100755 => 100644 root/package/modems/src/data/12d1-1c1f mode change 100755 => 100644 root/package/modems/src/data/12d1-1c23 mode change 100755 => 100644 root/package/modems/src/data/12d1-1f16 mode change 100755 => 100644 root/package/modems/src/data/1410-1400 mode change 100755 => 100644 root/package/modems/src/data/1410-1410 mode change 100755 => 100644 root/package/modems/src/data/1410-1420 mode change 100755 => 100644 root/package/modems/src/data/1410-1430 mode change 100755 => 100644 root/package/modems/src/data/1410-1450 mode change 100755 => 100644 root/package/modems/src/data/1410-2100 mode change 100755 => 100644 root/package/modems/src/data/1410-2110 mode change 100755 => 100644 root/package/modems/src/data/1410-2120 mode change 100755 => 100644 root/package/modems/src/data/1410-2130 mode change 100755 => 100644 root/package/modems/src/data/1410-2400 mode change 100755 => 100644 root/package/modems/src/data/1410-2410 mode change 100755 => 100644 root/package/modems/src/data/1410-2420 mode change 100755 => 100644 root/package/modems/src/data/1410-4100 mode change 100755 => 100644 root/package/modems/src/data/1410-4400 mode change 100755 => 100644 root/package/modems/src/data/1410-6000 mode change 100755 => 100644 root/package/modems/src/data/1410-6001 mode change 100755 => 100644 root/package/modems/src/data/1410-6002 mode change 100755 => 100644 root/package/modems/src/data/1410-6010 mode change 100755 => 100644 root/package/modems/src/data/1410-7001 mode change 100755 => 100644 root/package/modems/src/data/1410-7003 mode change 100755 => 100644 root/package/modems/src/data/1410-7030 mode change 100755 => 100644 root/package/modems/src/data/1410-7031 mode change 100755 => 100644 root/package/modems/src/data/1410-7041 mode change 100755 => 100644 root/package/modems/src/data/1410-7042 mode change 100755 => 100644 root/package/modems/src/data/1410-9011 mode change 100755 => 100644 root/package/modems/src/data/1410-b001 mode change 100755 => 100644 root/package/modems/src/data/1529-3100 mode change 100755 => 100644 root/package/modems/src/data/16d5-6202 mode change 100755 => 100644 root/package/modems/src/data/16d5-6501 mode change 100755 => 100644 root/package/modems/src/data/16d5-6502 mode change 100755 => 100644 root/package/modems/src/data/16d5-6603 mode change 100755 => 100644 root/package/modems/src/data/16d5-900d mode change 100755 => 100644 root/package/modems/src/data/16d8-5141 mode change 100755 => 100644 root/package/modems/src/data/16d8-5533 mode change 100755 => 100644 root/package/modems/src/data/16d8-5543 mode change 100755 => 100644 root/package/modems/src/data/16d8-5553 mode change 100755 => 100644 root/package/modems/src/data/16d8-6002 mode change 100755 => 100644 root/package/modems/src/data/16d8-6006 mode change 100755 => 100644 root/package/modems/src/data/16d8-6007 mode change 100755 => 100644 root/package/modems/src/data/16d8-6008 mode change 100755 => 100644 root/package/modems/src/data/16d8-6522 mode change 100755 => 100644 root/package/modems/src/data/16d8-6523 mode change 100755 => 100644 root/package/modems/src/data/16d8-6532 mode change 100755 => 100644 root/package/modems/src/data/16d8-6533 mode change 100755 => 100644 root/package/modems/src/data/16d8-6543 mode change 100755 => 100644 root/package/modems/src/data/16d8-680a mode change 100755 => 100644 root/package/modems/src/data/19d2-0001 mode change 100755 => 100644 root/package/modems/src/data/19d2-0002 mode change 100755 => 100644 root/package/modems/src/data/19d2-0015 mode change 100755 => 100644 root/package/modems/src/data/19d2-0016 mode change 100755 => 100644 root/package/modems/src/data/19d2-0017 mode change 100755 => 100644 root/package/modems/src/data/19d2-0018 mode change 100755 => 100644 root/package/modems/src/data/19d2-0019 mode change 100755 => 100644 root/package/modems/src/data/19d2-0022 mode change 100755 => 100644 root/package/modems/src/data/19d2-0024 mode change 100755 => 100644 root/package/modems/src/data/19d2-0025 mode change 100755 => 100644 root/package/modems/src/data/19d2-0031 mode change 100755 => 100644 root/package/modems/src/data/19d2-0033 mode change 100755 => 100644 root/package/modems/src/data/19d2-0037 mode change 100755 => 100644 root/package/modems/src/data/19d2-0039 mode change 100755 => 100644 root/package/modems/src/data/19d2-0042 mode change 100755 => 100644 root/package/modems/src/data/19d2-0052 mode change 100755 => 100644 root/package/modems/src/data/19d2-0055 mode change 100755 => 100644 root/package/modems/src/data/19d2-0057 mode change 100755 => 100644 root/package/modems/src/data/19d2-0063 mode change 100755 => 100644 root/package/modems/src/data/19d2-0064 mode change 100755 => 100644 root/package/modems/src/data/19d2-0066 mode change 100755 => 100644 root/package/modems/src/data/19d2-0073 mode change 100755 => 100644 root/package/modems/src/data/19d2-0079 mode change 100755 => 100644 root/package/modems/src/data/19d2-0082 mode change 100755 => 100644 root/package/modems/src/data/19d2-0086 mode change 100755 => 100644 root/package/modems/src/data/19d2-0091 mode change 100755 => 100644 root/package/modems/src/data/19d2-0094 mode change 100755 => 100644 root/package/modems/src/data/19d2-0104 mode change 100755 => 100644 root/package/modems/src/data/19d2-0108 mode change 100755 => 100644 root/package/modems/src/data/19d2-0116 mode change 100755 => 100644 root/package/modems/src/data/19d2-0117 mode change 100755 => 100644 root/package/modems/src/data/19d2-0121 mode change 100755 => 100644 root/package/modems/src/data/19d2-0124 mode change 100755 => 100644 root/package/modems/src/data/19d2-0128 mode change 100755 => 100644 root/package/modems/src/data/19d2-0142 mode change 100755 => 100644 root/package/modems/src/data/19d2-0143 mode change 100755 => 100644 root/package/modems/src/data/19d2-0152 mode change 100755 => 100644 root/package/modems/src/data/19d2-0157 mode change 100755 => 100644 root/package/modems/src/data/19d2-0167 mode change 100755 => 100644 root/package/modems/src/data/19d2-0170 mode change 100755 => 100644 root/package/modems/src/data/19d2-0199 mode change 100755 => 100644 root/package/modems/src/data/19d2-0257 mode change 100755 => 100644 root/package/modems/src/data/19d2-0265 mode change 100755 => 100644 root/package/modems/src/data/19d2-0284 mode change 100755 => 100644 root/package/modems/src/data/19d2-0326 mode change 100755 => 100644 root/package/modems/src/data/19d2-1003 mode change 100755 => 100644 root/package/modems/src/data/19d2-1008 mode change 100755 => 100644 root/package/modems/src/data/19d2-1010 mode change 100755 => 100644 root/package/modems/src/data/19d2-1015 mode change 100755 => 100644 root/package/modems/src/data/19d2-1018 mode change 100755 => 100644 root/package/modems/src/data/19d2-1172 mode change 100755 => 100644 root/package/modems/src/data/19d2-1173 mode change 100755 => 100644 root/package/modems/src/data/19d2-1176 mode change 100755 => 100644 root/package/modems/src/data/19d2-1177 mode change 100755 => 100644 root/package/modems/src/data/19d2-1181 mode change 100755 => 100644 root/package/modems/src/data/19d2-1203 mode change 100755 => 100644 root/package/modems/src/data/19d2-1208 mode change 100755 => 100644 root/package/modems/src/data/19d2-1211 mode change 100755 => 100644 root/package/modems/src/data/19d2-1212 mode change 100755 => 100644 root/package/modems/src/data/19d2-1217 mode change 100755 => 100644 root/package/modems/src/data/19d2-1218 mode change 100755 => 100644 root/package/modems/src/data/19d2-1220 mode change 100755 => 100644 root/package/modems/src/data/19d2-1222 mode change 100755 => 100644 root/package/modems/src/data/19d2-1245 mode change 100755 => 100644 root/package/modems/src/data/19d2-1252 mode change 100755 => 100644 root/package/modems/src/data/19d2-1254 mode change 100755 => 100644 root/package/modems/src/data/19d2-1256 mode change 100755 => 100644 root/package/modems/src/data/19d2-1270 mode change 100755 => 100644 root/package/modems/src/data/19d2-1401 mode change 100755 => 100644 root/package/modems/src/data/19d2-1402 mode change 100755 => 100644 root/package/modems/src/data/19d2-1426 mode change 100755 => 100644 root/package/modems/src/data/19d2-1512 mode change 100755 => 100644 root/package/modems/src/data/19d2-1515 mode change 100755 => 100644 root/package/modems/src/data/19d2-1518 mode change 100755 => 100644 root/package/modems/src/data/19d2-1519 mode change 100755 => 100644 root/package/modems/src/data/19d2-1522 mode change 100755 => 100644 root/package/modems/src/data/19d2-1525 mode change 100755 => 100644 root/package/modems/src/data/19d2-1527 mode change 100755 => 100644 root/package/modems/src/data/19d2-1537 mode change 100755 => 100644 root/package/modems/src/data/19d2-1538 mode change 100755 => 100644 root/package/modems/src/data/19d2-1544 mode change 100755 => 100644 root/package/modems/src/data/19d2-2002 mode change 100755 => 100644 root/package/modems/src/data/19d2-2003 mode change 100755 => 100644 root/package/modems/src/data/19d2-ffdd mode change 100755 => 100644 root/package/modems/src/data/19d2-ffe4 mode change 100755 => 100644 root/package/modems/src/data/19d2-ffe9 mode change 100755 => 100644 root/package/modems/src/data/19d2-fff1 mode change 100755 => 100644 root/package/modems/src/data/19d2-fffb mode change 100755 => 100644 root/package/modems/src/data/19d2-fffc mode change 100755 => 100644 root/package/modems/src/data/19d2-fffd mode change 100755 => 100644 root/package/modems/src/data/19d2-fffe mode change 100755 => 100644 root/package/modems/src/data/19d2-ffff mode change 100755 => 100644 root/package/modems/src/data/1a8d-1002 mode change 100755 => 100644 root/package/modems/src/data/1a8d-1003 mode change 100755 => 100644 root/package/modems/src/data/1a8d-1007 mode change 100755 => 100644 root/package/modems/src/data/1a8d-1009 mode change 100755 => 100644 root/package/modems/src/data/1a8d-100c mode change 100755 => 100644 root/package/modems/src/data/1a8d-100d mode change 100755 => 100644 root/package/modems/src/data/1a8d-2006 mode change 100755 => 100644 root/package/modems/src/data/1bbb-0000 mode change 100755 => 100644 root/package/modems/src/data/1bbb-0012 mode change 100755 => 100644 root/package/modems/src/data/1bbb-0017 mode change 100755 => 100644 root/package/modems/src/data/1bbb-0052 mode change 100755 => 100644 root/package/modems/src/data/1bbb-00b7 mode change 100755 => 100644 root/package/modems/src/data/1bbb-00ca mode change 100755 => 100644 root/package/modems/src/data/1bbb-011e mode change 100755 => 100644 root/package/modems/src/data/1bbb-0203 mode change 100755 => 100644 root/package/modems/src/data/1c9e-6060 mode change 100755 => 100644 root/package/modems/src/data/1c9e-6061 mode change 100755 => 100644 root/package/modems/src/data/1c9e-9000 mode change 100755 => 100644 root/package/modems/src/data/1c9e-9603 mode change 100755 => 100644 root/package/modems/src/data/1c9e-9605 mode change 100755 => 100644 root/package/modems/src/data/1c9e-9607 mode change 100755 => 100644 root/package/modems/src/data/1c9e-9801 mode change 100755 => 100644 root/package/modems/src/data/1c9e-9900 mode change 100755 => 100644 root/package/modems/src/data/1e0e-9000 mode change 100755 => 100644 root/package/modems/src/data/1e0e-9100 mode change 100755 => 100644 root/package/modems/src/data/1e0e-9200 mode change 100755 => 100644 root/package/modems/src/data/1e0e-ce16 mode change 100755 => 100644 root/package/modems/src/data/1e0e-cefe mode change 100755 => 100644 root/package/modems/src/data/2001-7d00 mode change 100755 => 100644 root/package/modems/src/data/2001-7d01 mode change 100755 => 100644 root/package/modems/src/data/2001-7d02 mode change 100755 => 100644 root/package/modems/src/data/2001-7d03 mode change 100755 => 100644 root/package/modems/src/data/211f-6801 mode change 100755 => 100644 root/package/modems/src/data/2357-0201 mode change 100755 => 100644 root/package/modems/src/data/2357-0202 mode change 100755 => 100644 root/package/modems/src/data/2357-0203 mode change 100755 => 100644 root/package/modems/src/data/2357-9000 mode change 100755 => 100644 root/package/modems/src/data/2c7c-0121 mode change 100755 => 100644 root/package/modems/src/data/2c7c-0125 mode change 100755 => 100644 root/package/modems/src/data/2c7c-0296 mode change 100755 => 100644 root/package/modems/src/data/2c7c-0306 mode change 100755 => 100644 root/package/modems/src/data/2c7c-0512 mode change 100755 => 100644 root/package/modems/src/data/413c-8114 mode change 100755 => 100644 root/package/modems/src/data/413c-8115 mode change 100755 => 100644 root/package/modems/src/data/413c-8116 mode change 100755 => 100644 root/package/modems/src/data/413c-8117 mode change 100755 => 100644 root/package/modems/src/data/413c-8118 mode change 100755 => 100644 root/package/modems/src/data/413c-8128 mode change 100755 => 100644 root/package/modems/src/data/413c-8129 mode change 100755 => 100644 root/package/modems/src/data/413c-8133 mode change 100755 => 100644 root/package/modems/src/data/413c-8134 mode change 100755 => 100644 root/package/modems/src/data/413c-8135 mode change 100755 => 100644 root/package/modems/src/data/413c-8136 mode change 100755 => 100644 root/package/modems/src/data/413c-8137 mode change 100755 => 100644 root/package/modems/src/data/413c-8138 mode change 100755 => 100644 root/package/modems/src/data/413c-8147 mode change 100755 => 100644 root/package/modems/src/data/413c-8180 mode change 100755 => 100644 root/package/modems/src/data/413c-8181 mode change 100755 => 100644 root/package/modems/src/data/413c-8182 mode change 100755 => 100644 root/package/modems/src/data/413c-8186 mode change 100755 => 100644 root/package/modems/src/data/413c-8194 mode change 100755 => 100644 root/package/modems/src/data/413c-8195 mode change 100755 => 100644 root/package/modems/src/data/413c-8196 mode change 100755 => 100644 root/package/modems/src/data/413c-819b mode change 100755 => 100644 root/package/network/config/firewall/patches/fullconenat.patch mode change 100755 => 100644 root/package/network/wwan/files/data/05c6-9215 mode change 100755 => 100644 root/package/network/wwan/files/data/2c7c-0121 mode change 100755 => 100644 root/package/network/wwan/files/data/2c7c-0296 mode change 100755 => 100644 root/package/network/wwan/files/data/2c7c-0306 mode change 100755 => 100644 root/package/network/wwan/files/data/2c7c-0512 mode change 100755 => 100644 root/scripts/mkits-rutx.sh mode change 100755 => 100644 root/target/linux/bcm27xx/patches-5.4/950-0785-ARM-dts-Add-bcm2711-rpi-cm4.dts.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.14/011-kbuild-export-SUBARCH.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.14/343-netfilter-nft_flow_offload-handle-netdevice-events-f.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/050-v5.16-00-MIPS-uasm-Enable-muhu-opcode-for-MIPS-R6.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/050-v5.16-01-mips-uasm-Add-workaround-for-Loongson-2F-nop-CPU-err.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/050-v5.16-02-mips-bpf-Add-eBPF-JIT-for-32-bit-MIPS.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/050-v5.16-03-mips-bpf-Add-new-eBPF-JIT-for-64-bit-MIPS.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/050-v5.16-04-mips-bpf-Add-JIT-workarounds-for-CPU-errata.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/050-v5.16-05-mips-bpf-Enable-eBPF-JITs.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/050-v5.16-06-mips-bpf-Remove-old-BPF-JIT-implementations.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/734-v5.16-0001-net-bgmac-improve-handling-PHY.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/734-v5.16-0002-net-bgmac-support-MDIO-described-in-DT.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/742-v5.16-net-phy-at803x-add-support-for-qca-8327-internal-phy.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/745-v5.16-01-net-phy-at803x-add-support-for-qca-8327-A-variant.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/745-v5.16-02-net-phy-at803x-add-resume-suspend-function-to-qca83x.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/745-v5.16-03-net-phy-at803x-fix-spacing-and-improve-name-for-83xx.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/746-v5.16-01-net-phy-at803x-fix-resume-for-QCA8327-phy.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/746-v5.16-02-net-phy-at803x-add-DAC-amplitude-fix-for-8327-phy.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/746-v5.16-03-net-phy-at803x-enable-prefer-master-for-83xx-interna.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/746-v5.16-04-net-phy-at803x-better-describe-debug-regs.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-01-dsa-qca8k-add-mac-power-sel-support.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-02-dt-bindings-net-dsa-qca8k-Add-SGMII-clock-phase-prop.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-03-net-dsa-qca8k-add-support-for-sgmii-falling-edge.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-04-dt-bindings-net-dsa-qca8k-Document-support-for-CPU-p.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-05-net-dsa-qca8k-add-support-for-cpu-port-6.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-06-net-dsa-qca8k-rework-rgmii-delay-logic-and-scan-for-.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-07-dt-bindings-net-dsa-qca8k-Document-qca-sgmii-enable-.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-08-net-dsa-qca8k-add-explicit-SGMII-PLL-enable.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-09-dt-bindings-net-dsa-qca8k-Document-qca-led-open-drai.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-10-net-dsa-qca8k-add-support-for-pws-config-reg.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-11-dt-bindings-net-dsa-qca8k-document-support-for-qca83.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-12-net-dsa-qca8k-add-support-for-QCA8328.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-13-net-dsa-qca8k-set-internal-delay-also-for-sgmii.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-14-net-dsa-qca8k-move-port-config-to-dedicated-struct.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-15-dt-bindings-net-ipq8064-mdio-fix-warning-with-new-qc.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-16-dt-bindings-net-dsa-qca8k-convert-to-YAML-schema.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/748-v5.16-net-dsa-qca8k-fix-delay-applied-to-wrong-cpu-in-parse-p.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/749-v5.16-net-dsa-qca8k-tidy-for-loop-in-setup-and-add-cpu-port-c.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/750-v5.16-net-dsa-qca8k-make-sure-pad0-mac06-exchange-is-disabled.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.4/071-bpf-dont-allow-vmlinux-btf-to-be-used-in-map_create-and-prog_load.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.4/500-ovl-check-permission-to-open-real-file.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.4/501-ovl-switch-to-mounter-creds-in-readdir.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.4/502-ovl-verify-permissions-in-ovl_path_open.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.4/503-ovl-do-not-fail-because-of_O_NOACTIME.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.4/700-ignore-pppoe-when-dst-does-not-match-dev-address.patch mode change 100755 => 100644 root/target/linux/generic/config-4.14 mode change 100755 => 100644 root/target/linux/generic/config-4.19 mode change 100755 => 100644 root/target/linux/generic/config-4.9 mode change 100755 => 100644 root/target/linux/generic/config-5.14 mode change 100755 => 100644 root/target/linux/generic/config-5.15 mode change 100755 => 100644 root/target/linux/generic/config-5.4 mode change 100755 => 100644 root/target/linux/generic/files/drivers/net/phy/b53/b53_common.c mode change 100755 => 100644 root/target/linux/generic/hack-4.14/690-mptcp_v0.94.patch mode change 100755 => 100644 root/target/linux/generic/hack-4.14/998-ndpi-netfilter.patch mode change 100755 => 100644 root/target/linux/generic/hack-4.14/999-stop-promiscuous-info.patch mode change 100755 => 100644 root/target/linux/generic/hack-4.19/690-mptcp_v0.95.patch mode change 100755 => 100644 root/target/linux/generic/hack-4.19/691-mptcp_ecf.patch mode change 100755 => 100644 root/target/linux/generic/hack-4.19/692-tcp_nanqinlang.patch mode change 100755 => 100644 root/target/linux/generic/hack-4.19/998-ndpi-netfilter.patch mode change 100755 => 100644 root/target/linux/generic/hack-4.19/999-f2fs-ioerrorfix.patch mode change 100755 => 100644 root/target/linux/generic/hack-4.19/999-stop-promiscuous-info.patch mode change 100755 => 100644 root/target/linux/generic/hack-4.9/690-mptcp_v0.93.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/204-module_strip.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/210-darwin_scripts_include.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/211-darwin-uuid-typedef-clash.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/212-tools_portability.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/214-spidev_h_portability.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/220-gc_sections.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/221-module_exports.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/230-openwrt_lzma_options.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/249-udp-tunnel-selection.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/250-netfilter_depends.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/251-kconfig.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/260-crypto_test_dependencies.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/261-lib-arc4-unhide.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/280-rfkill-stubs.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/300-MIPS-r4k_cache-use-more-efficient-cache-blast.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/301-mips_image_cmdline_hack.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/321-powerpc_crtsavres_prereq.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/420-mtd-set-rootfs-to-be-root-dev.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/531-debloat_lzma.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/640-bridge-only-accept-EAP-locally.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/645-netfilter-connmark-introduce-set-dscpmark.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/650-netfilter-add-xt_FLOWOFFLOAD-target.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/651-wireless_mesh_header.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/660-fq_codel_defaults.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/661-use_fq_codel_by_default.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/700-swconfig_switch_drivers.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/710-net-dsa-mv88e6xxx-default-VID-1.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/773-bgmac-add-srab-switch.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/780-net-ipheth-fix-RX-EOVERFLOW.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/800-GPIO-add-named-gpio-exports.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/901-debloat_sock_diag.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/902-debloat_proc.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/904-debloat_dma_buf.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/910-kobject_uevent.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/911-kobject_add_broadcast_uevent.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.15/220-gc_sections.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.4/690-mptcp_v0.96.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.4/692-tcp_nanqinlang.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.4/693-tcp_bbr2.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.4/952-net-conntrack-events-support-multiple-registrant.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.4/953-net-patch-linux-kernel-to-support-shortcut-fe.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.4/999-stop-promiscuous-info.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/100-compiler.h-only-include-asm-rwonce.h-for-kernel-code.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/101-Use-stddefs.h-instead-of-compiler.h.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/102-MIPS-only-process-negative-stack-offsets-on-stack-tr.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/130-add-linux-spidev-compatible-si3210.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/150-bridge_allow_receiption_on_disabled_port.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/190-rtc-rs5c372-support_alarms_up_to_1_week.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/191-rtc-rs5c372-let_the_alarm_to_be_used_as_wakeup_source.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/201-extra_optimization.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/203-kallsyms_uncompressed.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/205-backtrace_module_info.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/240-remove-unsane-filenames-from-deps_initramfs-list.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/261-enable_wilink_platform_without_drivers.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/270-platform-mikrotik-build-bits.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/300-mips_expose_boot_raw.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/302-mips_no_branch_likely.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/305-mips_module_reloc.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/307-mips_highmem_offset.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/308-mips32r2_tune.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/309-MIPS-Add-CPU-option-reporting-to-proc-cpuinfo.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/310-arm_module_unresolved_weak_sym.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/332-arc-add-OWRTDTB-section.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/333-arc-enable-unaligned-access-in-kernel-mode.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/342-powerpc-Enable-kernel-XZ-compression-option-on-PPC_8.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/400-mtd-mtdsplit-support.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/419-mtd-redboot-add-of_match_table-with-DT-binding.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/430-mtd-add-myloader-partition-parser.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/431-mtd-bcm47xxpart-check-for-bad-blocks-when-calculatin.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/432-mtd-bcm47xxpart-detect-T_Meter-partition.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/435-mtd-add-routerbootpart-parser-config.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/460-mtd-cfi_cmdset_0002-no-erase_suspend.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/461-mtd-cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/465-m25p80-mx-disable-software-protection.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/476-mtd-spi-nor-add-eon-en25q128.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/479-mtd-spi-nor-add-xtx-xt25f128b.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/482-mtd-spi-nor-add-support-for-Gigadevice-GD25D05.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/483-mtd-spi-nor-add-gd25q512.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/491-ubi-auto-create-ubiblock-device-for-rootfs.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/494-mtd-ubi-add-EOF-marker-support.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/495-mtd-core-add-get_mtd_device_by_node.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/496-dt-bindings-add-bindings-for-mtd-concat-devices.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/500-fs_cdrom_dependencies.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/530-jffs2_make_lzma_available.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/532-jffs2_eofdetect.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/600-netfilter_conntrack_flush.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/610-netfilter_match_bypass_default_checks.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/611-netfilter_match_bypass_default_table.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/612-netfilter_match_reduce_memory_access.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/613-netfilter_optional_tcp_window_check.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/620-net_sched-codel-do-not-defer-queue-length-update.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/630-packet_socket_type.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/655-increase_skb_pad.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/671-net-provide-defines-for-_POLICY_FAILED-until-all-cod.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/680-NET-skip-GRO-for-foreign-MAC-addresses.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/681-NET-add-mtd-mac-address-support-to-of_get_mac_addres.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/682-of_net-add-mac-address-increment-support.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/683-of_net-add-mac-address-to-of-tree.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/700-net-ethernet-mtk_eth_soc-avoid-creating-duplicate-of.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/703-phy-add-detach-callback-to-struct-phy_driver.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/735-net-phy-at803x-fix-at8033-sgmii-mode.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/760-net-dsa-mv88e6xxx-fix-vlan-setup.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/761-net-dsa-mt7530-Support-EEE-features.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/800-bcma-get-SoC-device-struct-copy-its-DMA-params-to-th.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/810-pci_disable_common_quirks.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/811-pci_disable_usb_common_quirks.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/820-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/834-ledtrig-libata.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/840-hwrng-bcm2835-set-quality-to-1000.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/920-mangle_bootargs.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.15/050-dtc-checks-Drop-interrupt-provider-address-cells-check.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.15/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.15/141-jffs2-add-RENAME_EXCHANGE-support.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.15/142-jffs2-add-splice-ops.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.15/420-mtd-redboot_space.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.15/481-mtd-spi-nor-rework-broken-flash-reset-support.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.15/483-mtd-spinand-add-support-for-xtx-xt26g0xa.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.15/484-mtd-spi-nor-add-esmt-f25l16pa.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.15/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.15/682-of_net-add-mac-address-increment-support.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.15/683-of_net-add-mac-address-to-of-tree.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.15/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.15/780-ARM-kirkwood-add-missing-linux-if_ether.h-for-ETH_AL.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.15/930-qcom-qmi-helpers.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.4/481-mtd-spi-nor-Add-default-and-support-for-missing-flashes.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.4/483-mtd-spinand-add-support-for-xtx-xt26g0xa.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.4/640-netfilter-nf_flow_table-add-hardware-offload-support.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.4/645-netfilter-nf_flow_table-rework-hardware-offload-time.patch mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/etc/board.d/01_leds mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/etc/board.d/02_network mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/etc/board.d/03_gpio_switches mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/lib/upgrade/linksys.sh mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/lib/upgrade/platform.sh mode change 100755 => 100644 root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-l1000.dts mode change 100755 => 100644 root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-nhx4019.dts mode change 100755 => 100644 root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts mode change 100755 => 100644 root/target/linux/ipq40xx/generic/target.mk mode change 100755 => 100644 root/target/linux/ipq40xx/image/generic.mk mode change 100755 => 100644 root/target/linux/ipq40xx/patches-5.4/901-arm-boot-add-dts-files.patch mode change 100755 => 100644 root/target/linux/ramips/patches-5.15/410-mtd-rawnand-add-driver-support-for-MT7621-nand-flash.patch mode change 100755 => 100644 root/target/linux/rockchip/Makefile mode change 100755 => 100644 root/target/linux/rockchip/armv8/base-files/etc/board.d/01_leds mode change 100755 => 100644 root/target/linux/rockchip/armv8/base-files/etc/board.d/02_network mode change 100755 => 100644 root/target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity mode change 100755 => 100644 root/target/linux/rockchip/armv8/config-5.14 mode change 100755 => 100644 root/target/linux/rockchip/armv8/config-5.15 mode change 100755 => 100644 root/target/linux/rockchip/files-5.15/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts mode change 100755 => 100644 root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3399-king3399.dts mode change 100755 => 100644 root/target/linux/rockchip/image/armv8.mk mode change 100755 => 100644 root/target/linux/rockchip/image/nanopi-r4s.bootscript mode change 100755 => 100644 root/target/linux/rockchip/patches-5.10/004-v5.13-rockchip-rk3399-Add-support-for-FriendlyARM-NanoPi-R.patch mode change 100755 => 100644 root/target/linux/rockchip/patches-5.14/002-net-usb-r8152-add-LED-configuration-from-OF.patch mode change 100755 => 100644 root/target/linux/rockchip/patches-5.14/003-dt-bindings-net-add-RTL8152-binding-documentation.patch mode change 100755 => 100644 root/target/linux/rockchip/patches-5.14/005-arm64-dts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch mode change 100755 => 100644 root/target/linux/rockchip/patches-5.14/100-rockchip-use-system-LED-for-OpenWrt.patch mode change 100755 => 100644 root/target/linux/rockchip/patches-5.14/101-dts-rockchip-add-usb3-controller-node-for-RK3328-SoCs.patch mode change 100755 => 100644 root/target/linux/rockchip/patches-5.14/102-rockchip-enable-LAN-port-on-NanoPi-R2S.patch mode change 100755 => 100644 root/target/linux/rockchip/patches-5.14/103-arm64-rockchip-add-OF-node-for-USB-eth-on-NanoPi-R2S.patch mode change 100755 => 100644 root/target/linux/rockchip/patches-5.14/105-rockchip-rock-pi-4.patch mode change 100755 => 100644 root/target/linux/rockchip/patches-5.4/009-rockchip-rk3399-Add-support-for-FriendlyARM-NanoPi-R.patch mode change 100755 => 100644 root/target/linux/rockchip/patches-5.4/010-arm64-dts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch mode change 100755 => 100644 root/target/linux/rockchip/patches-5.4/103-arm64-rockchip-add-OF-node-for-USB-eth-on-NanoPi-R2S.patch mode change 100755 => 100644 root/target/linux/rockchip/patches-5.4/107-nanopi-r4s-sd-signalling.patch mode change 100755 => 100644 root/target/linux/sunxi/base-files/etc/uci-defaults/99-switch-config mode change 100755 => 100644 root/target/linux/sunxi/base-files/sbin/swconfig-wrapper.sh mode change 100755 => 100644 root/target/linux/sunxi/config-5.14 mode change 100755 => 100644 root/target/linux/x86/64/config-5.14 mode change 100755 => 100644 root/target/linux/x86/config-4.19 mode change 100755 => 100644 root/target/linux/x86/config-5.14 mode change 100755 => 100644 root/target/linux/x86/patches-5.14/012-pcengines-apu2-detect-apuv4-board.patch mode change 100755 => 100644 root/target/linux/x86/patches-5.14/100-fix_cs5535_clockevt.patch mode change 100755 => 100644 root/target/linux/x86/patches-5.4/990-mptcp-fullmesh-raise-addresses-limit.patch mode change 100755 => 100644 root/tools/firmware-utils/Makefile mode change 100755 => 100644 sign.sh diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml old mode 100755 new mode 100644 diff --git a/.github/ISSUE_TEMPLATE/enhancement.md b/.github/ISSUE_TEMPLATE/enhancement.md old mode 100755 new mode 100644 diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md old mode 100755 new mode 100644 diff --git a/.github/ISSUE_TEMPLATE/hardware_support.md b/.github/ISSUE_TEMPLATE/hardware_support.md old mode 100755 new mode 100644 diff --git a/.github/ISSUE_TEMPLATE/help.md b/.github/ISSUE_TEMPLATE/help.md old mode 100755 new mode 100644 diff --git a/.github/ISSUE_TEMPLATE/issue.md b/.github/ISSUE_TEMPLATE/issue.md old mode 100755 new mode 100644 diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md old mode 100755 new mode 100644 diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md old mode 100755 new mode 100644 diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml old mode 100755 new mode 100644 diff --git a/.gitignore b/.gitignore old mode 100755 new mode 100644 diff --git a/CLA-entity.md b/CLA-entity.md old mode 100755 new mode 100644 diff --git a/CLA-individual.md b/CLA-individual.md old mode 100755 new mode 100644 diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md old mode 100755 new mode 100644 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md old mode 100755 new mode 100644 diff --git a/LICENSE b/LICENSE old mode 100755 new mode 100644 diff --git a/README.md b/README.md old mode 100755 new mode 100644 diff --git a/config b/config old mode 100755 new mode 100644 diff --git a/config-4018 b/config-4018 old mode 100755 new mode 100644 diff --git a/config-5gx3 b/config-5gx3 old mode 100755 new mode 100644 diff --git a/config-bpi-r1 b/config-bpi-r1 old mode 100755 new mode 100644 diff --git a/config-bpi-r2 b/config-bpi-r2 old mode 100755 new mode 100644 diff --git a/config-bpi-r64 b/config-bpi-r64 old mode 100755 new mode 100644 diff --git a/config-cm520-79f b/config-cm520-79f old mode 100755 new mode 100644 diff --git a/config-espressobin b/config-espressobin old mode 100755 new mode 100644 diff --git a/config-espressobin1 b/config-espressobin1 old mode 100755 new mode 100644 diff --git a/config-l1000 b/config-l1000 old mode 100755 new mode 100644 diff --git a/config-nanopi_neo b/config-nanopi_neo old mode 100755 new mode 100644 diff --git a/config-p2w_r619ac b/config-p2w_r619ac old mode 100755 new mode 100644 diff --git a/config-r2s b/config-r2s old mode 100755 new mode 100644 diff --git a/config-r4s b/config-r4s old mode 100755 new mode 100644 diff --git a/config-r7800 b/config-r7800 old mode 100755 new mode 100644 diff --git a/config-rpi2 b/config-rpi2 old mode 100755 new mode 100644 diff --git a/config-rpi3 b/config-rpi3 old mode 100755 new mode 100644 diff --git a/config-rpi4 b/config-rpi4 old mode 100755 new mode 100644 diff --git a/config-rutx b/config-rutx old mode 100755 new mode 100644 diff --git a/config-ubnt-erx b/config-ubnt-erx old mode 100755 new mode 100644 diff --git a/config-wrt3200acm b/config-wrt3200acm old mode 100755 new mode 100644 diff --git a/config-wrt32x b/config-wrt32x old mode 100755 new mode 100644 diff --git a/config-x86 b/config-x86 old mode 100755 new mode 100644 diff --git a/config-x86_64 b/config-x86_64 old mode 100755 new mode 100644 diff --git a/config-zbt4019 b/config-zbt4019 old mode 100755 new mode 100644 diff --git a/contributors/example.md b/contributors/example.md old mode 100755 new mode 100644 diff --git a/deploy_rsa.enc b/deploy_rsa.enc old mode 100755 new mode 100644 diff --git a/patches/950-0785-fixcm4soundboss2.patch b/patches/950-0785-fixcm4soundboss2.patch old mode 100755 new mode 100644 diff --git a/patches/bbr2.patch b/patches/bbr2.patch old mode 100755 new mode 100644 diff --git a/patches/check-rsync.patch b/patches/check-rsync.patch old mode 100755 new mode 100644 diff --git a/patches/download-ipv4.patch b/patches/download-ipv4.patch old mode 100755 new mode 100644 diff --git a/patches/gtime.patch b/patches/gtime.patch old mode 100755 new mode 100644 diff --git a/patches/images.patch b/patches/images.patch old mode 100755 new mode 100644 diff --git a/patches/ipt-nat6.patch b/patches/ipt-nat6.patch old mode 100755 new mode 100644 diff --git a/patches/luci-occitan.patch b/patches/luci-occitan.patch old mode 100755 new mode 100644 diff --git a/patches/nanqinlang.patch b/patches/nanqinlang.patch old mode 100755 new mode 100644 diff --git a/patches/nocheck.patch b/patches/nocheck.patch old mode 100755 new mode 100644 diff --git a/patches/package-too-long.patch b/patches/package-too-long.patch old mode 100755 new mode 100644 diff --git a/patches/remove_abi.patch b/patches/remove_abi.patch old mode 100755 new mode 100644 diff --git a/patches/smsc75xx.patch b/patches/smsc75xx.patch old mode 100755 new mode 100644 diff --git a/patches/uefi.patch b/patches/uefi.patch old mode 100755 new mode 100644 diff --git a/root/include/kernel-version.mk b/root/include/kernel-version.mk old mode 100755 new mode 100644 diff --git a/root/package/base-files/files/bin/config_generate b/root/package/base-files/files/bin/config_generate old mode 100755 new mode 100644 diff --git a/root/package/base-files/files/etc/banner b/root/package/base-files/files/etc/banner old mode 100755 new mode 100644 diff --git a/root/package/base-files/files/etc/shadow b/root/package/base-files/files/etc/shadow old mode 100755 new mode 100644 diff --git a/root/package/boot/arm-trusted-firmware-rockchip-vendor/pack-firmware.sh b/root/package/boot/arm-trusted-firmware-rockchip-vendor/pack-firmware.sh old mode 100755 new mode 100644 diff --git a/root/package/boot/uboot-envtools/Makefile b/root/package/boot/uboot-envtools/Makefile old mode 100755 new mode 100644 diff --git a/root/package/boot/uboot-rockchip/Makefile b/root/package/boot/uboot-rockchip/Makefile old mode 100755 new mode 100644 diff --git a/root/package/boot/uboot-rockchip/patches/306-rockchip-rk3399-Add-support-for-Rongpin-king3399.patch b/root/package/boot/uboot-rockchip/patches/306-rockchip-rk3399-Add-support-for-Rongpin-king3399.patch old mode 100755 new mode 100644 diff --git a/root/package/firmware/ipq-wifi/Makefile b/root/package/firmware/ipq-wifi/Makefile old mode 100755 new mode 100644 diff --git a/root/package/firmware/ipq-wifi/board-pangu_l1000.qca4019 b/root/package/firmware/ipq-wifi/board-pangu_l1000.qca4019 old mode 100755 new mode 100644 diff --git a/root/package/firmware/ipq-wifi/board-teltonika_rutx.qca4019 b/root/package/firmware/ipq-wifi/board-teltonika_rutx.qca4019 old mode 100755 new mode 100644 diff --git a/root/package/kernel/linux/modules/crypto.mk b/root/package/kernel/linux/modules/crypto.mk old mode 100755 new mode 100644 diff --git a/root/package/kernel/linux/modules/fs.mk b/root/package/kernel/linux/modules/fs.mk old mode 100755 new mode 100644 diff --git a/root/package/kernel/linux/modules/input.mk b/root/package/kernel/linux/modules/input.mk old mode 100755 new mode 100644 diff --git a/root/package/kernel/linux/modules/netfilter.mk b/root/package/kernel/linux/modules/netfilter.mk old mode 100755 new mode 100644 diff --git a/root/package/kernel/linux/modules/other.mk b/root/package/kernel/linux/modules/other.mk old mode 100755 new mode 100644 diff --git a/root/package/kernel/linux/modules/sound.mk b/root/package/kernel/linux/modules/sound.mk old mode 100755 new mode 100644 diff --git a/root/package/kernel/mwlwifi/patches/002-remove-fallthrough.patch b/root/package/kernel/mwlwifi/patches/002-remove-fallthrough.patch old mode 100755 new mode 100644 diff --git a/root/package/kernel/r2ec/Makefile b/root/package/kernel/r2ec/Makefile old mode 100755 new mode 100644 diff --git a/root/package/kernel/r2ec/src/Makefile b/root/package/kernel/r2ec/src/Makefile old mode 100755 new mode 100644 diff --git a/root/package/kernel/r2ec/src/io.h b/root/package/kernel/r2ec/src/io.h old mode 100755 new mode 100644 diff --git a/root/package/kernel/r2ec/src/r2ec.c b/root/package/kernel/r2ec/src/r2ec.c old mode 100755 new mode 100644 diff --git a/root/package/kernel/rtl8812au-ct/Makefile b/root/package/kernel/rtl8812au-ct/Makefile old mode 100755 new mode 100644 diff --git a/root/package/modems/Makefile b/root/package/modems/Makefile old mode 100755 new mode 100644 diff --git a/root/package/modems/src/README.md b/root/package/modems/src/README.md old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0421-03a7 b/root/package/modems/src/data/0421-03a7 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0421-060d b/root/package/modems/src/data/0421-060d old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0421-060e b/root/package/modems/src/data/0421-060e old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0421-0612 b/root/package/modems/src/data/0421-0612 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0421-0619 b/root/package/modems/src/data/0421-0619 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0421-061e b/root/package/modems/src/data/0421-061e old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0421-0623 b/root/package/modems/src/data/0421-0623 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0421-0629 b/root/package/modems/src/data/0421-0629 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0421-062d b/root/package/modems/src/data/0421-062d old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0421-062f b/root/package/modems/src/data/0421-062f old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0421-0638 b/root/package/modems/src/data/0421-0638 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/05c6-0016 b/root/package/modems/src/data/05c6-0016 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/05c6-0023 b/root/package/modems/src/data/05c6-0023 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/05c6-00a0 b/root/package/modems/src/data/05c6-00a0 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/05c6-6000 b/root/package/modems/src/data/05c6-6000 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/05c6-9000 b/root/package/modems/src/data/05c6-9000 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/05c6-9215 b/root/package/modems/src/data/05c6-9215 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/07d1-3e01 b/root/package/modems/src/data/07d1-3e01 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/07d1-3e02 b/root/package/modems/src/data/07d1-3e02 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/07d1-7e11 b/root/package/modems/src/data/07d1-7e11 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0af0-4005 b/root/package/modems/src/data/0af0-4005 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0af0-6901 b/root/package/modems/src/data/0af0-6901 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0af0-7201 b/root/package/modems/src/data/0af0-7201 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0af0-8120 b/root/package/modems/src/data/0af0-8120 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0af0-9200 b/root/package/modems/src/data/0af0-9200 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0b3c-c000 b/root/package/modems/src/data/0b3c-c000 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0b3c-c001 b/root/package/modems/src/data/0b3c-c001 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0b3c-c002 b/root/package/modems/src/data/0b3c-c002 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0b3c-c003 b/root/package/modems/src/data/0b3c-c003 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0b3c-c004 b/root/package/modems/src/data/0b3c-c004 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0b3c-c005 b/root/package/modems/src/data/0b3c-c005 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0b3c-c00a b/root/package/modems/src/data/0b3c-c00a old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0b3c-c00b b/root/package/modems/src/data/0b3c-c00b old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0bdb-1900 b/root/package/modems/src/data/0bdb-1900 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0bdb-1902 b/root/package/modems/src/data/0bdb-1902 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0bdb-190a b/root/package/modems/src/data/0bdb-190a old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0bdb-190d b/root/package/modems/src/data/0bdb-190d old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0bdb-1910 b/root/package/modems/src/data/0bdb-1910 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0c88-17da b/root/package/modems/src/data/0c88-17da old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0c88-180a b/root/package/modems/src/data/0c88-180a old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0f3d-68a2 b/root/package/modems/src/data/0f3d-68a2 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/0f3d-68aa b/root/package/modems/src/data/0f3d-68aa old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1004-6124 b/root/package/modems/src/data/1004-6124 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1004-6141 b/root/package/modems/src/data/1004-6141 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1004-6157 b/root/package/modems/src/data/1004-6157 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1004-618f b/root/package/modems/src/data/1004-618f old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/106c-3711 b/root/package/modems/src/data/106c-3711 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/106c-3714 b/root/package/modems/src/data/106c-3714 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/106c-3715 b/root/package/modems/src/data/106c-3715 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/106c-3716 b/root/package/modems/src/data/106c-3716 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/106c-3717 b/root/package/modems/src/data/106c-3717 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/106c-3718 b/root/package/modems/src/data/106c-3718 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/106c-3721 b/root/package/modems/src/data/106c-3721 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-0017 b/root/package/modems/src/data/1199-0017 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-0018 b/root/package/modems/src/data/1199-0018 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-0019 b/root/package/modems/src/data/1199-0019 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-0020 b/root/package/modems/src/data/1199-0020 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-0021 b/root/package/modems/src/data/1199-0021 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-0022 b/root/package/modems/src/data/1199-0022 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-0023 b/root/package/modems/src/data/1199-0023 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-0024 b/root/package/modems/src/data/1199-0024 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-0025 b/root/package/modems/src/data/1199-0025 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-0026 b/root/package/modems/src/data/1199-0026 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-0027 b/root/package/modems/src/data/1199-0027 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-0028 b/root/package/modems/src/data/1199-0028 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-0112 b/root/package/modems/src/data/1199-0112 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-0120 b/root/package/modems/src/data/1199-0120 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-0218 b/root/package/modems/src/data/1199-0218 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-0220 b/root/package/modems/src/data/1199-0220 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-0224 b/root/package/modems/src/data/1199-0224 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-0301 b/root/package/modems/src/data/1199-0301 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-6802 b/root/package/modems/src/data/1199-6802 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-6803 b/root/package/modems/src/data/1199-6803 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-6804 b/root/package/modems/src/data/1199-6804 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-6805 b/root/package/modems/src/data/1199-6805 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-6808 b/root/package/modems/src/data/1199-6808 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-6809 b/root/package/modems/src/data/1199-6809 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-6813 b/root/package/modems/src/data/1199-6813 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-6815 b/root/package/modems/src/data/1199-6815 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-6816 b/root/package/modems/src/data/1199-6816 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-6820 b/root/package/modems/src/data/1199-6820 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-6821 b/root/package/modems/src/data/1199-6821 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-6822 b/root/package/modems/src/data/1199-6822 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-6833 b/root/package/modems/src/data/1199-6833 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-6834 b/root/package/modems/src/data/1199-6834 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-6835 b/root/package/modems/src/data/1199-6835 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-6838 b/root/package/modems/src/data/1199-6838 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-6839 b/root/package/modems/src/data/1199-6839 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-683a b/root/package/modems/src/data/1199-683a old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-683b b/root/package/modems/src/data/1199-683b old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-6850 b/root/package/modems/src/data/1199-6850 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-6851 b/root/package/modems/src/data/1199-6851 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-6852 b/root/package/modems/src/data/1199-6852 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-6853 b/root/package/modems/src/data/1199-6853 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-6855 b/root/package/modems/src/data/1199-6855 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-6856 b/root/package/modems/src/data/1199-6856 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-6859 b/root/package/modems/src/data/1199-6859 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-685a b/root/package/modems/src/data/1199-685a old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-6880 b/root/package/modems/src/data/1199-6880 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-6890 b/root/package/modems/src/data/1199-6890 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-6891 b/root/package/modems/src/data/1199-6891 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-6892 b/root/package/modems/src/data/1199-6892 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-6893 b/root/package/modems/src/data/1199-6893 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-68a2 b/root/package/modems/src/data/1199-68a2 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1199-68aa b/root/package/modems/src/data/1199-68aa old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-1035 b/root/package/modems/src/data/12d1-1035 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-1404 b/root/package/modems/src/data/12d1-1404 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-1406 b/root/package/modems/src/data/12d1-1406 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-140b b/root/package/modems/src/data/12d1-140b old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-140c b/root/package/modems/src/data/12d1-140c old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-1412 b/root/package/modems/src/data/12d1-1412 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-141b b/root/package/modems/src/data/12d1-141b old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-1433 b/root/package/modems/src/data/12d1-1433 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-1436 b/root/package/modems/src/data/12d1-1436 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-1444 b/root/package/modems/src/data/12d1-1444 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-144e b/root/package/modems/src/data/12d1-144e old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-1464 b/root/package/modems/src/data/12d1-1464 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-1465 b/root/package/modems/src/data/12d1-1465 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-1491 b/root/package/modems/src/data/12d1-1491 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-14a5 b/root/package/modems/src/data/12d1-14a5 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-14a8 b/root/package/modems/src/data/12d1-14a8 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-14ac b/root/package/modems/src/data/12d1-14ac old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-14ae b/root/package/modems/src/data/12d1-14ae old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-14c6 b/root/package/modems/src/data/12d1-14c6 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-14c8 b/root/package/modems/src/data/12d1-14c8 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-14c9 b/root/package/modems/src/data/12d1-14c9 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-14ca b/root/package/modems/src/data/12d1-14ca old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-14cb b/root/package/modems/src/data/12d1-14cb old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-14cc b/root/package/modems/src/data/12d1-14cc old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-14cf b/root/package/modems/src/data/12d1-14cf old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-14d2 b/root/package/modems/src/data/12d1-14d2 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-1506 b/root/package/modems/src/data/12d1-1506 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-150a b/root/package/modems/src/data/12d1-150a old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-150c b/root/package/modems/src/data/12d1-150c old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-150f b/root/package/modems/src/data/12d1-150f old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-151b b/root/package/modems/src/data/12d1-151b old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-151d b/root/package/modems/src/data/12d1-151d old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-156c b/root/package/modems/src/data/12d1-156c old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-1576 b/root/package/modems/src/data/12d1-1576 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-1577 b/root/package/modems/src/data/12d1-1577 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-1578 b/root/package/modems/src/data/12d1-1578 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-1589 b/root/package/modems/src/data/12d1-1589 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-1c05 b/root/package/modems/src/data/12d1-1c05 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-1c07 b/root/package/modems/src/data/12d1-1c07 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-1c08 b/root/package/modems/src/data/12d1-1c08 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-1c10 b/root/package/modems/src/data/12d1-1c10 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-1c12 b/root/package/modems/src/data/12d1-1c12 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-1c1e b/root/package/modems/src/data/12d1-1c1e old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-1c1f b/root/package/modems/src/data/12d1-1c1f old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-1c23 b/root/package/modems/src/data/12d1-1c23 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/12d1-1f16 b/root/package/modems/src/data/12d1-1f16 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1410-1400 b/root/package/modems/src/data/1410-1400 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1410-1410 b/root/package/modems/src/data/1410-1410 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1410-1420 b/root/package/modems/src/data/1410-1420 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1410-1430 b/root/package/modems/src/data/1410-1430 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1410-1450 b/root/package/modems/src/data/1410-1450 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1410-2100 b/root/package/modems/src/data/1410-2100 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1410-2110 b/root/package/modems/src/data/1410-2110 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1410-2120 b/root/package/modems/src/data/1410-2120 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1410-2130 b/root/package/modems/src/data/1410-2130 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1410-2400 b/root/package/modems/src/data/1410-2400 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1410-2410 b/root/package/modems/src/data/1410-2410 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1410-2420 b/root/package/modems/src/data/1410-2420 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1410-4100 b/root/package/modems/src/data/1410-4100 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1410-4400 b/root/package/modems/src/data/1410-4400 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1410-6000 b/root/package/modems/src/data/1410-6000 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1410-6001 b/root/package/modems/src/data/1410-6001 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1410-6002 b/root/package/modems/src/data/1410-6002 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1410-6010 b/root/package/modems/src/data/1410-6010 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1410-7001 b/root/package/modems/src/data/1410-7001 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1410-7003 b/root/package/modems/src/data/1410-7003 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1410-7030 b/root/package/modems/src/data/1410-7030 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1410-7031 b/root/package/modems/src/data/1410-7031 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1410-7041 b/root/package/modems/src/data/1410-7041 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1410-7042 b/root/package/modems/src/data/1410-7042 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1410-9011 b/root/package/modems/src/data/1410-9011 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1410-b001 b/root/package/modems/src/data/1410-b001 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1529-3100 b/root/package/modems/src/data/1529-3100 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/16d5-6202 b/root/package/modems/src/data/16d5-6202 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/16d5-6501 b/root/package/modems/src/data/16d5-6501 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/16d5-6502 b/root/package/modems/src/data/16d5-6502 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/16d5-6603 b/root/package/modems/src/data/16d5-6603 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/16d5-900d b/root/package/modems/src/data/16d5-900d old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/16d8-5141 b/root/package/modems/src/data/16d8-5141 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/16d8-5533 b/root/package/modems/src/data/16d8-5533 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/16d8-5543 b/root/package/modems/src/data/16d8-5543 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/16d8-5553 b/root/package/modems/src/data/16d8-5553 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/16d8-6002 b/root/package/modems/src/data/16d8-6002 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/16d8-6006 b/root/package/modems/src/data/16d8-6006 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/16d8-6007 b/root/package/modems/src/data/16d8-6007 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/16d8-6008 b/root/package/modems/src/data/16d8-6008 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/16d8-6522 b/root/package/modems/src/data/16d8-6522 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/16d8-6523 b/root/package/modems/src/data/16d8-6523 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/16d8-6532 b/root/package/modems/src/data/16d8-6532 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/16d8-6533 b/root/package/modems/src/data/16d8-6533 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/16d8-6543 b/root/package/modems/src/data/16d8-6543 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/16d8-680a b/root/package/modems/src/data/16d8-680a old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0001 b/root/package/modems/src/data/19d2-0001 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0002 b/root/package/modems/src/data/19d2-0002 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0015 b/root/package/modems/src/data/19d2-0015 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0016 b/root/package/modems/src/data/19d2-0016 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0017 b/root/package/modems/src/data/19d2-0017 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0018 b/root/package/modems/src/data/19d2-0018 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0019 b/root/package/modems/src/data/19d2-0019 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0022 b/root/package/modems/src/data/19d2-0022 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0024 b/root/package/modems/src/data/19d2-0024 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0025 b/root/package/modems/src/data/19d2-0025 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0031 b/root/package/modems/src/data/19d2-0031 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0033 b/root/package/modems/src/data/19d2-0033 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0037 b/root/package/modems/src/data/19d2-0037 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0039 b/root/package/modems/src/data/19d2-0039 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0042 b/root/package/modems/src/data/19d2-0042 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0052 b/root/package/modems/src/data/19d2-0052 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0055 b/root/package/modems/src/data/19d2-0055 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0057 b/root/package/modems/src/data/19d2-0057 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0063 b/root/package/modems/src/data/19d2-0063 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0064 b/root/package/modems/src/data/19d2-0064 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0066 b/root/package/modems/src/data/19d2-0066 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0073 b/root/package/modems/src/data/19d2-0073 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0079 b/root/package/modems/src/data/19d2-0079 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0082 b/root/package/modems/src/data/19d2-0082 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0086 b/root/package/modems/src/data/19d2-0086 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0091 b/root/package/modems/src/data/19d2-0091 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0094 b/root/package/modems/src/data/19d2-0094 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0104 b/root/package/modems/src/data/19d2-0104 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0108 b/root/package/modems/src/data/19d2-0108 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0116 b/root/package/modems/src/data/19d2-0116 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0117 b/root/package/modems/src/data/19d2-0117 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0121 b/root/package/modems/src/data/19d2-0121 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0124 b/root/package/modems/src/data/19d2-0124 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0128 b/root/package/modems/src/data/19d2-0128 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0142 b/root/package/modems/src/data/19d2-0142 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0143 b/root/package/modems/src/data/19d2-0143 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0152 b/root/package/modems/src/data/19d2-0152 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0157 b/root/package/modems/src/data/19d2-0157 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0167 b/root/package/modems/src/data/19d2-0167 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0170 b/root/package/modems/src/data/19d2-0170 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0199 b/root/package/modems/src/data/19d2-0199 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0257 b/root/package/modems/src/data/19d2-0257 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0265 b/root/package/modems/src/data/19d2-0265 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0284 b/root/package/modems/src/data/19d2-0284 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-0326 b/root/package/modems/src/data/19d2-0326 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1003 b/root/package/modems/src/data/19d2-1003 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1008 b/root/package/modems/src/data/19d2-1008 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1010 b/root/package/modems/src/data/19d2-1010 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1015 b/root/package/modems/src/data/19d2-1015 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1018 b/root/package/modems/src/data/19d2-1018 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1172 b/root/package/modems/src/data/19d2-1172 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1173 b/root/package/modems/src/data/19d2-1173 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1176 b/root/package/modems/src/data/19d2-1176 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1177 b/root/package/modems/src/data/19d2-1177 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1181 b/root/package/modems/src/data/19d2-1181 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1203 b/root/package/modems/src/data/19d2-1203 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1208 b/root/package/modems/src/data/19d2-1208 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1211 b/root/package/modems/src/data/19d2-1211 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1212 b/root/package/modems/src/data/19d2-1212 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1217 b/root/package/modems/src/data/19d2-1217 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1218 b/root/package/modems/src/data/19d2-1218 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1220 b/root/package/modems/src/data/19d2-1220 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1222 b/root/package/modems/src/data/19d2-1222 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1245 b/root/package/modems/src/data/19d2-1245 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1252 b/root/package/modems/src/data/19d2-1252 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1254 b/root/package/modems/src/data/19d2-1254 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1256 b/root/package/modems/src/data/19d2-1256 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1270 b/root/package/modems/src/data/19d2-1270 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1401 b/root/package/modems/src/data/19d2-1401 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1402 b/root/package/modems/src/data/19d2-1402 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1426 b/root/package/modems/src/data/19d2-1426 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1512 b/root/package/modems/src/data/19d2-1512 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1515 b/root/package/modems/src/data/19d2-1515 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1518 b/root/package/modems/src/data/19d2-1518 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1519 b/root/package/modems/src/data/19d2-1519 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1522 b/root/package/modems/src/data/19d2-1522 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1525 b/root/package/modems/src/data/19d2-1525 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1527 b/root/package/modems/src/data/19d2-1527 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1537 b/root/package/modems/src/data/19d2-1537 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1538 b/root/package/modems/src/data/19d2-1538 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-1544 b/root/package/modems/src/data/19d2-1544 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-2002 b/root/package/modems/src/data/19d2-2002 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-2003 b/root/package/modems/src/data/19d2-2003 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-ffdd b/root/package/modems/src/data/19d2-ffdd old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-ffe4 b/root/package/modems/src/data/19d2-ffe4 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-ffe9 b/root/package/modems/src/data/19d2-ffe9 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-fff1 b/root/package/modems/src/data/19d2-fff1 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-fffb b/root/package/modems/src/data/19d2-fffb old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-fffc b/root/package/modems/src/data/19d2-fffc old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-fffd b/root/package/modems/src/data/19d2-fffd old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-fffe b/root/package/modems/src/data/19d2-fffe old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/19d2-ffff b/root/package/modems/src/data/19d2-ffff old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1a8d-1002 b/root/package/modems/src/data/1a8d-1002 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1a8d-1003 b/root/package/modems/src/data/1a8d-1003 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1a8d-1007 b/root/package/modems/src/data/1a8d-1007 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1a8d-1009 b/root/package/modems/src/data/1a8d-1009 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1a8d-100c b/root/package/modems/src/data/1a8d-100c old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1a8d-100d b/root/package/modems/src/data/1a8d-100d old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1a8d-2006 b/root/package/modems/src/data/1a8d-2006 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1bbb-0000 b/root/package/modems/src/data/1bbb-0000 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1bbb-0012 b/root/package/modems/src/data/1bbb-0012 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1bbb-0017 b/root/package/modems/src/data/1bbb-0017 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1bbb-0052 b/root/package/modems/src/data/1bbb-0052 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1bbb-00b7 b/root/package/modems/src/data/1bbb-00b7 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1bbb-00ca b/root/package/modems/src/data/1bbb-00ca old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1bbb-011e b/root/package/modems/src/data/1bbb-011e old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1bbb-0203 b/root/package/modems/src/data/1bbb-0203 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1c9e-6060 b/root/package/modems/src/data/1c9e-6060 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1c9e-6061 b/root/package/modems/src/data/1c9e-6061 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1c9e-9000 b/root/package/modems/src/data/1c9e-9000 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1c9e-9603 b/root/package/modems/src/data/1c9e-9603 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1c9e-9605 b/root/package/modems/src/data/1c9e-9605 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1c9e-9607 b/root/package/modems/src/data/1c9e-9607 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1c9e-9801 b/root/package/modems/src/data/1c9e-9801 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1c9e-9900 b/root/package/modems/src/data/1c9e-9900 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1e0e-9000 b/root/package/modems/src/data/1e0e-9000 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1e0e-9100 b/root/package/modems/src/data/1e0e-9100 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1e0e-9200 b/root/package/modems/src/data/1e0e-9200 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1e0e-ce16 b/root/package/modems/src/data/1e0e-ce16 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/1e0e-cefe b/root/package/modems/src/data/1e0e-cefe old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/2001-7d00 b/root/package/modems/src/data/2001-7d00 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/2001-7d01 b/root/package/modems/src/data/2001-7d01 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/2001-7d02 b/root/package/modems/src/data/2001-7d02 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/2001-7d03 b/root/package/modems/src/data/2001-7d03 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/211f-6801 b/root/package/modems/src/data/211f-6801 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/2357-0201 b/root/package/modems/src/data/2357-0201 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/2357-0202 b/root/package/modems/src/data/2357-0202 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/2357-0203 b/root/package/modems/src/data/2357-0203 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/2357-9000 b/root/package/modems/src/data/2357-9000 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/2c7c-0121 b/root/package/modems/src/data/2c7c-0121 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/2c7c-0125 b/root/package/modems/src/data/2c7c-0125 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/2c7c-0296 b/root/package/modems/src/data/2c7c-0296 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/2c7c-0306 b/root/package/modems/src/data/2c7c-0306 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/2c7c-0512 b/root/package/modems/src/data/2c7c-0512 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/413c-8114 b/root/package/modems/src/data/413c-8114 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/413c-8115 b/root/package/modems/src/data/413c-8115 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/413c-8116 b/root/package/modems/src/data/413c-8116 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/413c-8117 b/root/package/modems/src/data/413c-8117 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/413c-8118 b/root/package/modems/src/data/413c-8118 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/413c-8128 b/root/package/modems/src/data/413c-8128 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/413c-8129 b/root/package/modems/src/data/413c-8129 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/413c-8133 b/root/package/modems/src/data/413c-8133 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/413c-8134 b/root/package/modems/src/data/413c-8134 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/413c-8135 b/root/package/modems/src/data/413c-8135 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/413c-8136 b/root/package/modems/src/data/413c-8136 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/413c-8137 b/root/package/modems/src/data/413c-8137 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/413c-8138 b/root/package/modems/src/data/413c-8138 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/413c-8147 b/root/package/modems/src/data/413c-8147 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/413c-8180 b/root/package/modems/src/data/413c-8180 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/413c-8181 b/root/package/modems/src/data/413c-8181 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/413c-8182 b/root/package/modems/src/data/413c-8182 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/413c-8186 b/root/package/modems/src/data/413c-8186 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/413c-8194 b/root/package/modems/src/data/413c-8194 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/413c-8195 b/root/package/modems/src/data/413c-8195 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/413c-8196 b/root/package/modems/src/data/413c-8196 old mode 100755 new mode 100644 diff --git a/root/package/modems/src/data/413c-819b b/root/package/modems/src/data/413c-819b old mode 100755 new mode 100644 diff --git a/root/package/network/config/firewall/patches/fullconenat.patch b/root/package/network/config/firewall/patches/fullconenat.patch old mode 100755 new mode 100644 diff --git a/root/package/network/wwan/files/data/05c6-9215 b/root/package/network/wwan/files/data/05c6-9215 old mode 100755 new mode 100644 diff --git a/root/package/network/wwan/files/data/2c7c-0121 b/root/package/network/wwan/files/data/2c7c-0121 old mode 100755 new mode 100644 diff --git a/root/package/network/wwan/files/data/2c7c-0296 b/root/package/network/wwan/files/data/2c7c-0296 old mode 100755 new mode 100644 diff --git a/root/package/network/wwan/files/data/2c7c-0306 b/root/package/network/wwan/files/data/2c7c-0306 old mode 100755 new mode 100644 diff --git a/root/package/network/wwan/files/data/2c7c-0512 b/root/package/network/wwan/files/data/2c7c-0512 old mode 100755 new mode 100644 diff --git a/root/scripts/mkits-rutx.sh b/root/scripts/mkits-rutx.sh old mode 100755 new mode 100644 diff --git a/root/target/linux/bcm27xx/patches-5.4/950-0785-ARM-dts-Add-bcm2711-rpi-cm4.dts.patch b/root/target/linux/bcm27xx/patches-5.4/950-0785-ARM-dts-Add-bcm2711-rpi-cm4.dts.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.14/011-kbuild-export-SUBARCH.patch b/root/target/linux/generic/backport-5.14/011-kbuild-export-SUBARCH.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.14/343-netfilter-nft_flow_offload-handle-netdevice-events-f.patch b/root/target/linux/generic/backport-5.14/343-netfilter-nft_flow_offload-handle-netdevice-events-f.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/050-v5.16-00-MIPS-uasm-Enable-muhu-opcode-for-MIPS-R6.patch b/root/target/linux/generic/backport-5.15/050-v5.16-00-MIPS-uasm-Enable-muhu-opcode-for-MIPS-R6.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/050-v5.16-01-mips-uasm-Add-workaround-for-Loongson-2F-nop-CPU-err.patch b/root/target/linux/generic/backport-5.15/050-v5.16-01-mips-uasm-Add-workaround-for-Loongson-2F-nop-CPU-err.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/050-v5.16-02-mips-bpf-Add-eBPF-JIT-for-32-bit-MIPS.patch b/root/target/linux/generic/backport-5.15/050-v5.16-02-mips-bpf-Add-eBPF-JIT-for-32-bit-MIPS.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/050-v5.16-03-mips-bpf-Add-new-eBPF-JIT-for-64-bit-MIPS.patch b/root/target/linux/generic/backport-5.15/050-v5.16-03-mips-bpf-Add-new-eBPF-JIT-for-64-bit-MIPS.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/050-v5.16-04-mips-bpf-Add-JIT-workarounds-for-CPU-errata.patch b/root/target/linux/generic/backport-5.15/050-v5.16-04-mips-bpf-Add-JIT-workarounds-for-CPU-errata.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/050-v5.16-05-mips-bpf-Enable-eBPF-JITs.patch b/root/target/linux/generic/backport-5.15/050-v5.16-05-mips-bpf-Enable-eBPF-JITs.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/050-v5.16-06-mips-bpf-Remove-old-BPF-JIT-implementations.patch b/root/target/linux/generic/backport-5.15/050-v5.16-06-mips-bpf-Remove-old-BPF-JIT-implementations.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/734-v5.16-0001-net-bgmac-improve-handling-PHY.patch b/root/target/linux/generic/backport-5.15/734-v5.16-0001-net-bgmac-improve-handling-PHY.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/734-v5.16-0002-net-bgmac-support-MDIO-described-in-DT.patch b/root/target/linux/generic/backport-5.15/734-v5.16-0002-net-bgmac-support-MDIO-described-in-DT.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/742-v5.16-net-phy-at803x-add-support-for-qca-8327-internal-phy.patch b/root/target/linux/generic/backport-5.15/742-v5.16-net-phy-at803x-add-support-for-qca-8327-internal-phy.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/745-v5.16-01-net-phy-at803x-add-support-for-qca-8327-A-variant.patch b/root/target/linux/generic/backport-5.15/745-v5.16-01-net-phy-at803x-add-support-for-qca-8327-A-variant.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/745-v5.16-02-net-phy-at803x-add-resume-suspend-function-to-qca83x.patch b/root/target/linux/generic/backport-5.15/745-v5.16-02-net-phy-at803x-add-resume-suspend-function-to-qca83x.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/745-v5.16-03-net-phy-at803x-fix-spacing-and-improve-name-for-83xx.patch b/root/target/linux/generic/backport-5.15/745-v5.16-03-net-phy-at803x-fix-spacing-and-improve-name-for-83xx.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/746-v5.16-01-net-phy-at803x-fix-resume-for-QCA8327-phy.patch b/root/target/linux/generic/backport-5.15/746-v5.16-01-net-phy-at803x-fix-resume-for-QCA8327-phy.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/746-v5.16-02-net-phy-at803x-add-DAC-amplitude-fix-for-8327-phy.patch b/root/target/linux/generic/backport-5.15/746-v5.16-02-net-phy-at803x-add-DAC-amplitude-fix-for-8327-phy.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/746-v5.16-03-net-phy-at803x-enable-prefer-master-for-83xx-interna.patch b/root/target/linux/generic/backport-5.15/746-v5.16-03-net-phy-at803x-enable-prefer-master-for-83xx-interna.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/746-v5.16-04-net-phy-at803x-better-describe-debug-regs.patch b/root/target/linux/generic/backport-5.15/746-v5.16-04-net-phy-at803x-better-describe-debug-regs.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-01-dsa-qca8k-add-mac-power-sel-support.patch b/root/target/linux/generic/backport-5.15/747-v5.16-01-dsa-qca8k-add-mac-power-sel-support.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-02-dt-bindings-net-dsa-qca8k-Add-SGMII-clock-phase-prop.patch b/root/target/linux/generic/backport-5.15/747-v5.16-02-dt-bindings-net-dsa-qca8k-Add-SGMII-clock-phase-prop.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-03-net-dsa-qca8k-add-support-for-sgmii-falling-edge.patch b/root/target/linux/generic/backport-5.15/747-v5.16-03-net-dsa-qca8k-add-support-for-sgmii-falling-edge.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-04-dt-bindings-net-dsa-qca8k-Document-support-for-CPU-p.patch b/root/target/linux/generic/backport-5.15/747-v5.16-04-dt-bindings-net-dsa-qca8k-Document-support-for-CPU-p.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-05-net-dsa-qca8k-add-support-for-cpu-port-6.patch b/root/target/linux/generic/backport-5.15/747-v5.16-05-net-dsa-qca8k-add-support-for-cpu-port-6.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-06-net-dsa-qca8k-rework-rgmii-delay-logic-and-scan-for-.patch b/root/target/linux/generic/backport-5.15/747-v5.16-06-net-dsa-qca8k-rework-rgmii-delay-logic-and-scan-for-.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-07-dt-bindings-net-dsa-qca8k-Document-qca-sgmii-enable-.patch b/root/target/linux/generic/backport-5.15/747-v5.16-07-dt-bindings-net-dsa-qca8k-Document-qca-sgmii-enable-.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-08-net-dsa-qca8k-add-explicit-SGMII-PLL-enable.patch b/root/target/linux/generic/backport-5.15/747-v5.16-08-net-dsa-qca8k-add-explicit-SGMII-PLL-enable.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-09-dt-bindings-net-dsa-qca8k-Document-qca-led-open-drai.patch b/root/target/linux/generic/backport-5.15/747-v5.16-09-dt-bindings-net-dsa-qca8k-Document-qca-led-open-drai.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-10-net-dsa-qca8k-add-support-for-pws-config-reg.patch b/root/target/linux/generic/backport-5.15/747-v5.16-10-net-dsa-qca8k-add-support-for-pws-config-reg.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-11-dt-bindings-net-dsa-qca8k-document-support-for-qca83.patch b/root/target/linux/generic/backport-5.15/747-v5.16-11-dt-bindings-net-dsa-qca8k-document-support-for-qca83.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-12-net-dsa-qca8k-add-support-for-QCA8328.patch b/root/target/linux/generic/backport-5.15/747-v5.16-12-net-dsa-qca8k-add-support-for-QCA8328.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-13-net-dsa-qca8k-set-internal-delay-also-for-sgmii.patch b/root/target/linux/generic/backport-5.15/747-v5.16-13-net-dsa-qca8k-set-internal-delay-also-for-sgmii.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-14-net-dsa-qca8k-move-port-config-to-dedicated-struct.patch b/root/target/linux/generic/backport-5.15/747-v5.16-14-net-dsa-qca8k-move-port-config-to-dedicated-struct.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-15-dt-bindings-net-ipq8064-mdio-fix-warning-with-new-qc.patch b/root/target/linux/generic/backport-5.15/747-v5.16-15-dt-bindings-net-ipq8064-mdio-fix-warning-with-new-qc.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-16-dt-bindings-net-dsa-qca8k-convert-to-YAML-schema.patch b/root/target/linux/generic/backport-5.15/747-v5.16-16-dt-bindings-net-dsa-qca8k-convert-to-YAML-schema.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/748-v5.16-net-dsa-qca8k-fix-delay-applied-to-wrong-cpu-in-parse-p.patch b/root/target/linux/generic/backport-5.15/748-v5.16-net-dsa-qca8k-fix-delay-applied-to-wrong-cpu-in-parse-p.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/749-v5.16-net-dsa-qca8k-tidy-for-loop-in-setup-and-add-cpu-port-c.patch b/root/target/linux/generic/backport-5.15/749-v5.16-net-dsa-qca8k-tidy-for-loop-in-setup-and-add-cpu-port-c.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/750-v5.16-net-dsa-qca8k-make-sure-pad0-mac06-exchange-is-disabled.patch b/root/target/linux/generic/backport-5.15/750-v5.16-net-dsa-qca8k-make-sure-pad0-mac06-exchange-is-disabled.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.4/071-bpf-dont-allow-vmlinux-btf-to-be-used-in-map_create-and-prog_load.patch b/root/target/linux/generic/backport-5.4/071-bpf-dont-allow-vmlinux-btf-to-be-used-in-map_create-and-prog_load.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.4/500-ovl-check-permission-to-open-real-file.patch b/root/target/linux/generic/backport-5.4/500-ovl-check-permission-to-open-real-file.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.4/501-ovl-switch-to-mounter-creds-in-readdir.patch b/root/target/linux/generic/backport-5.4/501-ovl-switch-to-mounter-creds-in-readdir.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.4/502-ovl-verify-permissions-in-ovl_path_open.patch b/root/target/linux/generic/backport-5.4/502-ovl-verify-permissions-in-ovl_path_open.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.4/503-ovl-do-not-fail-because-of_O_NOACTIME.patch b/root/target/linux/generic/backport-5.4/503-ovl-do-not-fail-because-of_O_NOACTIME.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.4/700-ignore-pppoe-when-dst-does-not-match-dev-address.patch b/root/target/linux/generic/backport-5.4/700-ignore-pppoe-when-dst-does-not-match-dev-address.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/config-4.14 b/root/target/linux/generic/config-4.14 old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/config-4.19 b/root/target/linux/generic/config-4.19 old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/config-4.9 b/root/target/linux/generic/config-4.9 old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/config-5.14 b/root/target/linux/generic/config-5.14 old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/config-5.15 b/root/target/linux/generic/config-5.15 old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/config-5.4 b/root/target/linux/generic/config-5.4 old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/files/drivers/net/phy/b53/b53_common.c b/root/target/linux/generic/files/drivers/net/phy/b53/b53_common.c old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-4.14/690-mptcp_v0.94.patch b/root/target/linux/generic/hack-4.14/690-mptcp_v0.94.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-4.14/998-ndpi-netfilter.patch b/root/target/linux/generic/hack-4.14/998-ndpi-netfilter.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-4.14/999-stop-promiscuous-info.patch b/root/target/linux/generic/hack-4.14/999-stop-promiscuous-info.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-4.19/690-mptcp_v0.95.patch b/root/target/linux/generic/hack-4.19/690-mptcp_v0.95.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-4.19/691-mptcp_ecf.patch b/root/target/linux/generic/hack-4.19/691-mptcp_ecf.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-4.19/692-tcp_nanqinlang.patch b/root/target/linux/generic/hack-4.19/692-tcp_nanqinlang.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-4.19/998-ndpi-netfilter.patch b/root/target/linux/generic/hack-4.19/998-ndpi-netfilter.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-4.19/999-f2fs-ioerrorfix.patch b/root/target/linux/generic/hack-4.19/999-f2fs-ioerrorfix.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-4.19/999-stop-promiscuous-info.patch b/root/target/linux/generic/hack-4.19/999-stop-promiscuous-info.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-4.9/690-mptcp_v0.93.patch b/root/target/linux/generic/hack-4.9/690-mptcp_v0.93.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/204-module_strip.patch b/root/target/linux/generic/hack-5.14/204-module_strip.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/210-darwin_scripts_include.patch b/root/target/linux/generic/hack-5.14/210-darwin_scripts_include.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/211-darwin-uuid-typedef-clash.patch b/root/target/linux/generic/hack-5.14/211-darwin-uuid-typedef-clash.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/212-tools_portability.patch b/root/target/linux/generic/hack-5.14/212-tools_portability.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/214-spidev_h_portability.patch b/root/target/linux/generic/hack-5.14/214-spidev_h_portability.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/220-gc_sections.patch b/root/target/linux/generic/hack-5.14/220-gc_sections.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/221-module_exports.patch b/root/target/linux/generic/hack-5.14/221-module_exports.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/230-openwrt_lzma_options.patch b/root/target/linux/generic/hack-5.14/230-openwrt_lzma_options.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/249-udp-tunnel-selection.patch b/root/target/linux/generic/hack-5.14/249-udp-tunnel-selection.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/250-netfilter_depends.patch b/root/target/linux/generic/hack-5.14/250-netfilter_depends.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/251-kconfig.patch b/root/target/linux/generic/hack-5.14/251-kconfig.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/260-crypto_test_dependencies.patch b/root/target/linux/generic/hack-5.14/260-crypto_test_dependencies.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/261-lib-arc4-unhide.patch b/root/target/linux/generic/hack-5.14/261-lib-arc4-unhide.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/280-rfkill-stubs.patch b/root/target/linux/generic/hack-5.14/280-rfkill-stubs.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/300-MIPS-r4k_cache-use-more-efficient-cache-blast.patch b/root/target/linux/generic/hack-5.14/300-MIPS-r4k_cache-use-more-efficient-cache-blast.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/301-mips_image_cmdline_hack.patch b/root/target/linux/generic/hack-5.14/301-mips_image_cmdline_hack.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/321-powerpc_crtsavres_prereq.patch b/root/target/linux/generic/hack-5.14/321-powerpc_crtsavres_prereq.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/420-mtd-set-rootfs-to-be-root-dev.patch b/root/target/linux/generic/hack-5.14/420-mtd-set-rootfs-to-be-root-dev.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/531-debloat_lzma.patch b/root/target/linux/generic/hack-5.14/531-debloat_lzma.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/640-bridge-only-accept-EAP-locally.patch b/root/target/linux/generic/hack-5.14/640-bridge-only-accept-EAP-locally.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/645-netfilter-connmark-introduce-set-dscpmark.patch b/root/target/linux/generic/hack-5.14/645-netfilter-connmark-introduce-set-dscpmark.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/650-netfilter-add-xt_FLOWOFFLOAD-target.patch b/root/target/linux/generic/hack-5.14/650-netfilter-add-xt_FLOWOFFLOAD-target.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/651-wireless_mesh_header.patch b/root/target/linux/generic/hack-5.14/651-wireless_mesh_header.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/660-fq_codel_defaults.patch b/root/target/linux/generic/hack-5.14/660-fq_codel_defaults.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/661-use_fq_codel_by_default.patch b/root/target/linux/generic/hack-5.14/661-use_fq_codel_by_default.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/700-swconfig_switch_drivers.patch b/root/target/linux/generic/hack-5.14/700-swconfig_switch_drivers.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/710-net-dsa-mv88e6xxx-default-VID-1.patch b/root/target/linux/generic/hack-5.14/710-net-dsa-mv88e6xxx-default-VID-1.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch b/root/target/linux/generic/hack-5.14/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/773-bgmac-add-srab-switch.patch b/root/target/linux/generic/hack-5.14/773-bgmac-add-srab-switch.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/780-net-ipheth-fix-RX-EOVERFLOW.patch b/root/target/linux/generic/hack-5.14/780-net-ipheth-fix-RX-EOVERFLOW.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/800-GPIO-add-named-gpio-exports.patch b/root/target/linux/generic/hack-5.14/800-GPIO-add-named-gpio-exports.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/901-debloat_sock_diag.patch b/root/target/linux/generic/hack-5.14/901-debloat_sock_diag.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/902-debloat_proc.patch b/root/target/linux/generic/hack-5.14/902-debloat_proc.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/904-debloat_dma_buf.patch b/root/target/linux/generic/hack-5.14/904-debloat_dma_buf.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/910-kobject_uevent.patch b/root/target/linux/generic/hack-5.14/910-kobject_uevent.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/911-kobject_add_broadcast_uevent.patch b/root/target/linux/generic/hack-5.14/911-kobject_add_broadcast_uevent.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.15/220-gc_sections.patch b/root/target/linux/generic/hack-5.15/220-gc_sections.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.4/690-mptcp_v0.96.patch b/root/target/linux/generic/hack-5.4/690-mptcp_v0.96.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.4/692-tcp_nanqinlang.patch b/root/target/linux/generic/hack-5.4/692-tcp_nanqinlang.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.4/693-tcp_bbr2.patch b/root/target/linux/generic/hack-5.4/693-tcp_bbr2.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.4/952-net-conntrack-events-support-multiple-registrant.patch b/root/target/linux/generic/hack-5.4/952-net-conntrack-events-support-multiple-registrant.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.4/953-net-patch-linux-kernel-to-support-shortcut-fe.patch b/root/target/linux/generic/hack-5.4/953-net-patch-linux-kernel-to-support-shortcut-fe.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.4/999-stop-promiscuous-info.patch b/root/target/linux/generic/hack-5.4/999-stop-promiscuous-info.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/100-compiler.h-only-include-asm-rwonce.h-for-kernel-code.patch b/root/target/linux/generic/pending-5.14/100-compiler.h-only-include-asm-rwonce.h-for-kernel-code.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/101-Use-stddefs.h-instead-of-compiler.h.patch b/root/target/linux/generic/pending-5.14/101-Use-stddefs.h-instead-of-compiler.h.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/102-MIPS-only-process-negative-stack-offsets-on-stack-tr.patch b/root/target/linux/generic/pending-5.14/102-MIPS-only-process-negative-stack-offsets-on-stack-tr.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch b/root/target/linux/generic/pending-5.14/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/130-add-linux-spidev-compatible-si3210.patch b/root/target/linux/generic/pending-5.14/130-add-linux-spidev-compatible-si3210.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/150-bridge_allow_receiption_on_disabled_port.patch b/root/target/linux/generic/pending-5.14/150-bridge_allow_receiption_on_disabled_port.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/190-rtc-rs5c372-support_alarms_up_to_1_week.patch b/root/target/linux/generic/pending-5.14/190-rtc-rs5c372-support_alarms_up_to_1_week.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/191-rtc-rs5c372-let_the_alarm_to_be_used_as_wakeup_source.patch b/root/target/linux/generic/pending-5.14/191-rtc-rs5c372-let_the_alarm_to_be_used_as_wakeup_source.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/201-extra_optimization.patch b/root/target/linux/generic/pending-5.14/201-extra_optimization.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/203-kallsyms_uncompressed.patch b/root/target/linux/generic/pending-5.14/203-kallsyms_uncompressed.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/205-backtrace_module_info.patch b/root/target/linux/generic/pending-5.14/205-backtrace_module_info.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/240-remove-unsane-filenames-from-deps_initramfs-list.patch b/root/target/linux/generic/pending-5.14/240-remove-unsane-filenames-from-deps_initramfs-list.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/261-enable_wilink_platform_without_drivers.patch b/root/target/linux/generic/pending-5.14/261-enable_wilink_platform_without_drivers.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/270-platform-mikrotik-build-bits.patch b/root/target/linux/generic/pending-5.14/270-platform-mikrotik-build-bits.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/300-mips_expose_boot_raw.patch b/root/target/linux/generic/pending-5.14/300-mips_expose_boot_raw.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/302-mips_no_branch_likely.patch b/root/target/linux/generic/pending-5.14/302-mips_no_branch_likely.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/305-mips_module_reloc.patch b/root/target/linux/generic/pending-5.14/305-mips_module_reloc.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/307-mips_highmem_offset.patch b/root/target/linux/generic/pending-5.14/307-mips_highmem_offset.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/308-mips32r2_tune.patch b/root/target/linux/generic/pending-5.14/308-mips32r2_tune.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/309-MIPS-Add-CPU-option-reporting-to-proc-cpuinfo.patch b/root/target/linux/generic/pending-5.14/309-MIPS-Add-CPU-option-reporting-to-proc-cpuinfo.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/310-arm_module_unresolved_weak_sym.patch b/root/target/linux/generic/pending-5.14/310-arm_module_unresolved_weak_sym.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch b/root/target/linux/generic/pending-5.14/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/332-arc-add-OWRTDTB-section.patch b/root/target/linux/generic/pending-5.14/332-arc-add-OWRTDTB-section.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/333-arc-enable-unaligned-access-in-kernel-mode.patch b/root/target/linux/generic/pending-5.14/333-arc-enable-unaligned-access-in-kernel-mode.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/342-powerpc-Enable-kernel-XZ-compression-option-on-PPC_8.patch b/root/target/linux/generic/pending-5.14/342-powerpc-Enable-kernel-XZ-compression-option-on-PPC_8.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/400-mtd-mtdsplit-support.patch b/root/target/linux/generic/pending-5.14/400-mtd-mtdsplit-support.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/419-mtd-redboot-add-of_match_table-with-DT-binding.patch b/root/target/linux/generic/pending-5.14/419-mtd-redboot-add-of_match_table-with-DT-binding.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/430-mtd-add-myloader-partition-parser.patch b/root/target/linux/generic/pending-5.14/430-mtd-add-myloader-partition-parser.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/431-mtd-bcm47xxpart-check-for-bad-blocks-when-calculatin.patch b/root/target/linux/generic/pending-5.14/431-mtd-bcm47xxpart-check-for-bad-blocks-when-calculatin.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/432-mtd-bcm47xxpart-detect-T_Meter-partition.patch b/root/target/linux/generic/pending-5.14/432-mtd-bcm47xxpart-detect-T_Meter-partition.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/435-mtd-add-routerbootpart-parser-config.patch b/root/target/linux/generic/pending-5.14/435-mtd-add-routerbootpart-parser-config.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/460-mtd-cfi_cmdset_0002-no-erase_suspend.patch b/root/target/linux/generic/pending-5.14/460-mtd-cfi_cmdset_0002-no-erase_suspend.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/461-mtd-cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch b/root/target/linux/generic/pending-5.14/461-mtd-cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/465-m25p80-mx-disable-software-protection.patch b/root/target/linux/generic/pending-5.14/465-m25p80-mx-disable-software-protection.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch b/root/target/linux/generic/pending-5.14/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/476-mtd-spi-nor-add-eon-en25q128.patch b/root/target/linux/generic/pending-5.14/476-mtd-spi-nor-add-eon-en25q128.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/479-mtd-spi-nor-add-xtx-xt25f128b.patch b/root/target/linux/generic/pending-5.14/479-mtd-spi-nor-add-xtx-xt25f128b.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/482-mtd-spi-nor-add-support-for-Gigadevice-GD25D05.patch b/root/target/linux/generic/pending-5.14/482-mtd-spi-nor-add-support-for-Gigadevice-GD25D05.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/483-mtd-spi-nor-add-gd25q512.patch b/root/target/linux/generic/pending-5.14/483-mtd-spi-nor-add-gd25q512.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch b/root/target/linux/generic/pending-5.14/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/491-ubi-auto-create-ubiblock-device-for-rootfs.patch b/root/target/linux/generic/pending-5.14/491-ubi-auto-create-ubiblock-device-for-rootfs.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch b/root/target/linux/generic/pending-5.14/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch b/root/target/linux/generic/pending-5.14/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/494-mtd-ubi-add-EOF-marker-support.patch b/root/target/linux/generic/pending-5.14/494-mtd-ubi-add-EOF-marker-support.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/495-mtd-core-add-get_mtd_device_by_node.patch b/root/target/linux/generic/pending-5.14/495-mtd-core-add-get_mtd_device_by_node.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/496-dt-bindings-add-bindings-for-mtd-concat-devices.patch b/root/target/linux/generic/pending-5.14/496-dt-bindings-add-bindings-for-mtd-concat-devices.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch b/root/target/linux/generic/pending-5.14/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/500-fs_cdrom_dependencies.patch b/root/target/linux/generic/pending-5.14/500-fs_cdrom_dependencies.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/530-jffs2_make_lzma_available.patch b/root/target/linux/generic/pending-5.14/530-jffs2_make_lzma_available.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/532-jffs2_eofdetect.patch b/root/target/linux/generic/pending-5.14/532-jffs2_eofdetect.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/600-netfilter_conntrack_flush.patch b/root/target/linux/generic/pending-5.14/600-netfilter_conntrack_flush.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/610-netfilter_match_bypass_default_checks.patch b/root/target/linux/generic/pending-5.14/610-netfilter_match_bypass_default_checks.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/611-netfilter_match_bypass_default_table.patch b/root/target/linux/generic/pending-5.14/611-netfilter_match_bypass_default_table.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/612-netfilter_match_reduce_memory_access.patch b/root/target/linux/generic/pending-5.14/612-netfilter_match_reduce_memory_access.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/613-netfilter_optional_tcp_window_check.patch b/root/target/linux/generic/pending-5.14/613-netfilter_optional_tcp_window_check.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/620-net_sched-codel-do-not-defer-queue-length-update.patch b/root/target/linux/generic/pending-5.14/620-net_sched-codel-do-not-defer-queue-length-update.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/630-packet_socket_type.patch b/root/target/linux/generic/pending-5.14/630-packet_socket_type.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/655-increase_skb_pad.patch b/root/target/linux/generic/pending-5.14/655-increase_skb_pad.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch b/root/target/linux/generic/pending-5.14/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch b/root/target/linux/generic/pending-5.14/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/671-net-provide-defines-for-_POLICY_FAILED-until-all-cod.patch b/root/target/linux/generic/pending-5.14/671-net-provide-defines-for-_POLICY_FAILED-until-all-cod.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/680-NET-skip-GRO-for-foreign-MAC-addresses.patch b/root/target/linux/generic/pending-5.14/680-NET-skip-GRO-for-foreign-MAC-addresses.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/681-NET-add-mtd-mac-address-support-to-of_get_mac_addres.patch b/root/target/linux/generic/pending-5.14/681-NET-add-mtd-mac-address-support-to-of_get_mac_addres.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/682-of_net-add-mac-address-increment-support.patch b/root/target/linux/generic/pending-5.14/682-of_net-add-mac-address-increment-support.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/683-of_net-add-mac-address-to-of-tree.patch b/root/target/linux/generic/pending-5.14/683-of_net-add-mac-address-to-of-tree.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/700-net-ethernet-mtk_eth_soc-avoid-creating-duplicate-of.patch b/root/target/linux/generic/pending-5.14/700-net-ethernet-mtk_eth_soc-avoid-creating-duplicate-of.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/703-phy-add-detach-callback-to-struct-phy_driver.patch b/root/target/linux/generic/pending-5.14/703-phy-add-detach-callback-to-struct-phy_driver.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/735-net-phy-at803x-fix-at8033-sgmii-mode.patch b/root/target/linux/generic/pending-5.14/735-net-phy-at803x-fix-at8033-sgmii-mode.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/760-net-dsa-mv88e6xxx-fix-vlan-setup.patch b/root/target/linux/generic/pending-5.14/760-net-dsa-mv88e6xxx-fix-vlan-setup.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/761-net-dsa-mt7530-Support-EEE-features.patch b/root/target/linux/generic/pending-5.14/761-net-dsa-mt7530-Support-EEE-features.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch b/root/target/linux/generic/pending-5.14/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/800-bcma-get-SoC-device-struct-copy-its-DMA-params-to-th.patch b/root/target/linux/generic/pending-5.14/800-bcma-get-SoC-device-struct-copy-its-DMA-params-to-th.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/810-pci_disable_common_quirks.patch b/root/target/linux/generic/pending-5.14/810-pci_disable_common_quirks.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/811-pci_disable_usb_common_quirks.patch b/root/target/linux/generic/pending-5.14/811-pci_disable_usb_common_quirks.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/820-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch b/root/target/linux/generic/pending-5.14/820-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/834-ledtrig-libata.patch b/root/target/linux/generic/pending-5.14/834-ledtrig-libata.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/840-hwrng-bcm2835-set-quality-to-1000.patch b/root/target/linux/generic/pending-5.14/840-hwrng-bcm2835-set-quality-to-1000.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/920-mangle_bootargs.patch b/root/target/linux/generic/pending-5.14/920-mangle_bootargs.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.15/050-dtc-checks-Drop-interrupt-provider-address-cells-check.patch b/root/target/linux/generic/pending-5.15/050-dtc-checks-Drop-interrupt-provider-address-cells-check.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.15/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch b/root/target/linux/generic/pending-5.15/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.15/141-jffs2-add-RENAME_EXCHANGE-support.patch b/root/target/linux/generic/pending-5.15/141-jffs2-add-RENAME_EXCHANGE-support.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.15/142-jffs2-add-splice-ops.patch b/root/target/linux/generic/pending-5.15/142-jffs2-add-splice-ops.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.15/420-mtd-redboot_space.patch b/root/target/linux/generic/pending-5.15/420-mtd-redboot_space.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.15/481-mtd-spi-nor-rework-broken-flash-reset-support.patch b/root/target/linux/generic/pending-5.15/481-mtd-spi-nor-rework-broken-flash-reset-support.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.15/483-mtd-spinand-add-support-for-xtx-xt26g0xa.patch b/root/target/linux/generic/pending-5.15/483-mtd-spinand-add-support-for-xtx-xt26g0xa.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.15/484-mtd-spi-nor-add-esmt-f25l16pa.patch b/root/target/linux/generic/pending-5.15/484-mtd-spi-nor-add-esmt-f25l16pa.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.15/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch b/root/target/linux/generic/pending-5.15/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.15/682-of_net-add-mac-address-increment-support.patch b/root/target/linux/generic/pending-5.15/682-of_net-add-mac-address-increment-support.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.15/683-of_net-add-mac-address-to-of-tree.patch b/root/target/linux/generic/pending-5.15/683-of_net-add-mac-address-to-of-tree.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.15/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch b/root/target/linux/generic/pending-5.15/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.15/780-ARM-kirkwood-add-missing-linux-if_ether.h-for-ETH_AL.patch b/root/target/linux/generic/pending-5.15/780-ARM-kirkwood-add-missing-linux-if_ether.h-for-ETH_AL.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.15/930-qcom-qmi-helpers.patch b/root/target/linux/generic/pending-5.15/930-qcom-qmi-helpers.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.4/481-mtd-spi-nor-Add-default-and-support-for-missing-flashes.patch b/root/target/linux/generic/pending-5.4/481-mtd-spi-nor-Add-default-and-support-for-missing-flashes.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.4/483-mtd-spinand-add-support-for-xtx-xt26g0xa.patch b/root/target/linux/generic/pending-5.4/483-mtd-spinand-add-support-for-xtx-xt26g0xa.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.4/640-netfilter-nf_flow_table-add-hardware-offload-support.patch b/root/target/linux/generic/pending-5.4/640-netfilter-nf_flow_table-add-hardware-offload-support.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.4/645-netfilter-nf_flow_table-rework-hardware-offload-time.patch b/root/target/linux/generic/pending-5.4/645-netfilter-nf_flow_table-rework-hardware-offload-time.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/etc/board.d/01_leds b/root/target/linux/ipq40xx/base-files/etc/board.d/01_leds old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/etc/board.d/02_network b/root/target/linux/ipq40xx/base-files/etc/board.d/02_network old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/etc/board.d/03_gpio_switches b/root/target/linux/ipq40xx/base-files/etc/board.d/03_gpio_switches old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/root/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/lib/upgrade/linksys.sh b/root/target/linux/ipq40xx/base-files/lib/upgrade/linksys.sh old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/lib/upgrade/platform.sh b/root/target/linux/ipq40xx/base-files/lib/upgrade/platform.sh old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-l1000.dts b/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-l1000.dts old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-nhx4019.dts b/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-nhx4019.dts old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts b/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/generic/target.mk b/root/target/linux/ipq40xx/generic/target.mk old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/image/generic.mk b/root/target/linux/ipq40xx/image/generic.mk old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/patches-5.4/901-arm-boot-add-dts-files.patch b/root/target/linux/ipq40xx/patches-5.4/901-arm-boot-add-dts-files.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/ramips/patches-5.15/410-mtd-rawnand-add-driver-support-for-MT7621-nand-flash.patch b/root/target/linux/ramips/patches-5.15/410-mtd-rawnand-add-driver-support-for-MT7621-nand-flash.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/Makefile b/root/target/linux/rockchip/Makefile old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/armv8/base-files/etc/board.d/01_leds b/root/target/linux/rockchip/armv8/base-files/etc/board.d/01_leds old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/armv8/base-files/etc/board.d/02_network b/root/target/linux/rockchip/armv8/base-files/etc/board.d/02_network old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity b/root/target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/armv8/config-5.14 b/root/target/linux/rockchip/armv8/config-5.14 old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/armv8/config-5.15 b/root/target/linux/rockchip/armv8/config-5.15 old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/files-5.15/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts b/root/target/linux/rockchip/files-5.15/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3399-king3399.dts b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3399-king3399.dts old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/image/armv8.mk b/root/target/linux/rockchip/image/armv8.mk old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/image/nanopi-r4s.bootscript b/root/target/linux/rockchip/image/nanopi-r4s.bootscript old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/patches-5.10/004-v5.13-rockchip-rk3399-Add-support-for-FriendlyARM-NanoPi-R.patch b/root/target/linux/rockchip/patches-5.10/004-v5.13-rockchip-rk3399-Add-support-for-FriendlyARM-NanoPi-R.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/patches-5.14/002-net-usb-r8152-add-LED-configuration-from-OF.patch b/root/target/linux/rockchip/patches-5.14/002-net-usb-r8152-add-LED-configuration-from-OF.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/patches-5.14/003-dt-bindings-net-add-RTL8152-binding-documentation.patch b/root/target/linux/rockchip/patches-5.14/003-dt-bindings-net-add-RTL8152-binding-documentation.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/patches-5.14/005-arm64-dts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch b/root/target/linux/rockchip/patches-5.14/005-arm64-dts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/patches-5.14/100-rockchip-use-system-LED-for-OpenWrt.patch b/root/target/linux/rockchip/patches-5.14/100-rockchip-use-system-LED-for-OpenWrt.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/patches-5.14/101-dts-rockchip-add-usb3-controller-node-for-RK3328-SoCs.patch b/root/target/linux/rockchip/patches-5.14/101-dts-rockchip-add-usb3-controller-node-for-RK3328-SoCs.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/patches-5.14/102-rockchip-enable-LAN-port-on-NanoPi-R2S.patch b/root/target/linux/rockchip/patches-5.14/102-rockchip-enable-LAN-port-on-NanoPi-R2S.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/patches-5.14/103-arm64-rockchip-add-OF-node-for-USB-eth-on-NanoPi-R2S.patch b/root/target/linux/rockchip/patches-5.14/103-arm64-rockchip-add-OF-node-for-USB-eth-on-NanoPi-R2S.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/patches-5.14/105-rockchip-rock-pi-4.patch b/root/target/linux/rockchip/patches-5.14/105-rockchip-rock-pi-4.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/patches-5.4/009-rockchip-rk3399-Add-support-for-FriendlyARM-NanoPi-R.patch b/root/target/linux/rockchip/patches-5.4/009-rockchip-rk3399-Add-support-for-FriendlyARM-NanoPi-R.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/patches-5.4/010-arm64-dts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch b/root/target/linux/rockchip/patches-5.4/010-arm64-dts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/patches-5.4/103-arm64-rockchip-add-OF-node-for-USB-eth-on-NanoPi-R2S.patch b/root/target/linux/rockchip/patches-5.4/103-arm64-rockchip-add-OF-node-for-USB-eth-on-NanoPi-R2S.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/patches-5.4/107-nanopi-r4s-sd-signalling.patch b/root/target/linux/rockchip/patches-5.4/107-nanopi-r4s-sd-signalling.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/sunxi/base-files/etc/uci-defaults/99-switch-config b/root/target/linux/sunxi/base-files/etc/uci-defaults/99-switch-config old mode 100755 new mode 100644 diff --git a/root/target/linux/sunxi/base-files/sbin/swconfig-wrapper.sh b/root/target/linux/sunxi/base-files/sbin/swconfig-wrapper.sh old mode 100755 new mode 100644 diff --git a/root/target/linux/sunxi/config-5.14 b/root/target/linux/sunxi/config-5.14 old mode 100755 new mode 100644 diff --git a/root/target/linux/x86/64/config-5.14 b/root/target/linux/x86/64/config-5.14 old mode 100755 new mode 100644 diff --git a/root/target/linux/x86/config-4.19 b/root/target/linux/x86/config-4.19 old mode 100755 new mode 100644 diff --git a/root/target/linux/x86/config-5.14 b/root/target/linux/x86/config-5.14 old mode 100755 new mode 100644 diff --git a/root/target/linux/x86/patches-5.14/012-pcengines-apu2-detect-apuv4-board.patch b/root/target/linux/x86/patches-5.14/012-pcengines-apu2-detect-apuv4-board.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/x86/patches-5.14/100-fix_cs5535_clockevt.patch b/root/target/linux/x86/patches-5.14/100-fix_cs5535_clockevt.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/x86/patches-5.4/990-mptcp-fullmesh-raise-addresses-limit.patch b/root/target/linux/x86/patches-5.4/990-mptcp-fullmesh-raise-addresses-limit.patch old mode 100755 new mode 100644 diff --git a/root/tools/firmware-utils/Makefile b/root/tools/firmware-utils/Makefile old mode 100755 new mode 100644 diff --git a/sign.sh b/sign.sh old mode 100755 new mode 100644 From 72aae5943645001e27f6e05d44b5cb22fa59119e Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Wed, 23 Nov 2022 15:41:29 +0800 Subject: [PATCH 059/102] Update build.sh --- build.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build.sh b/build.sh index dcf81525..8dc8d658 100644 --- a/build.sh +++ b/build.sh @@ -237,6 +237,9 @@ fi if [ "$OMR_PACKAGES" = "mini" ]; then echo "CONFIG_PACKAGE_${OMR_DIST}-mini=y" >> "$OMR_TARGET/${OMR_KERNEL}/source/.config" fi +if [ "$OMR_PACKAGES" = "zuixiao" ]; then + echo "CONFIG_PACKAGE_${OMR_DIST}-zuixiao=y" >> "$OMR_TARGET/${OMR_KERNEL}/source/.config" +fi if [ "$SHORTCUT_FE" = "yes" ] && [ "${OMR_KERNEL}" = "5.4" ]; then echo "# CONFIG_PACKAGE_kmod-fast-classifier is not set" >> "$OMR_TARGET/${OMR_KERNEL}/source/.config" @@ -675,4 +678,4 @@ fi echo "Building $OMR_DIST for the target $OMR_TARGET with kernel ${OMR_KERNEL}" make defconfig make IGNORE_ERRORS=m "$@" -echo "Done" +echo "Done" \ No newline at end of file From d98f6418929d79b5e748c519763e6ad920d4ef68 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Wed, 23 Nov 2022 15:55:36 +0800 Subject: [PATCH 060/102] Revert "Update build.sh" This reverts commit 1f9a96f6bb4070dcc890f45edf04b026b3906512. --- build.sh | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/build.sh b/build.sh index 8dc8d658..19e4599a 100644 --- a/build.sh +++ b/build.sh @@ -143,9 +143,15 @@ rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/files" "$OMR_TARGET/${OMR_KERNEL}/sourc #rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/arm-trusted-firmware-mediatek" rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/tools/firmware-utils" rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/uboot-rockchip" - -cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" - +if [ "$OMR_TARGET" != "rutx" ]; then + # There is many customization to support rutx and this seems to break other ipq40xx, so dirty workaround for now + mv "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx" "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx.old" + cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" + rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx" + mv "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx.old" "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx" +else + cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" +fi cat >> "$OMR_TARGET/${OMR_KERNEL}/source/package/base-files/files/etc/banner" < Date: Wed, 23 Nov 2022 15:57:15 +0800 Subject: [PATCH 061/102] Update build.sh --- build.sh | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/build.sh b/build.sh index 19e4599a..e9f0e4d5 100644 --- a/build.sh +++ b/build.sh @@ -143,16 +143,7 @@ rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/files" "$OMR_TARGET/${OMR_KERNEL}/sourc #rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/arm-trusted-firmware-mediatek" rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/tools/firmware-utils" rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/uboot-rockchip" -if [ "$OMR_TARGET" != "rutx" ]; then - # There is many customization to support rutx and this seems to break other ipq40xx, so dirty workaround for now - mv "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx" "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx.old" - cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" - rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx" - mv "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx.old" "$OMR_TARGET/${OMR_KERNEL}/source/target/linux/ipq40xx" -else - cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" -fi - +cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" cat >> "$OMR_TARGET/${OMR_KERNEL}/source/package/base-files/files/etc/banner" < Date: Thu, 24 Nov 2022 14:14:06 +0800 Subject: [PATCH 062/102] Update build.sh --- build.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/build.sh b/build.sh index e9f0e4d5..10a8925d 100644 --- a/build.sh +++ b/build.sh @@ -144,12 +144,15 @@ rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/files" "$OMR_TARGET/${OMR_KERNEL}/sourc rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/tools/firmware-utils" rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/uboot-rockchip" cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" + cat >> "$OMR_TARGET/${OMR_KERNEL}/source/package/base-files/files/etc/banner" <> "$OMR_TARGET/${OMR_KERNEL}/source/.config" fi -if [ "$OMR_PACKAGES" = "zuixiao" ]; then - echo "CONFIG_PACKAGE_${OMR_DIST}-zuixiao=y" >> "$OMR_TARGET/${OMR_KERNEL}/source/.config" -fi if [ "$SHORTCUT_FE" = "yes" ] && [ "${OMR_KERNEL}" = "5.4" ]; then echo "# CONFIG_PACKAGE_kmod-fast-classifier is not set" >> "$OMR_TARGET/${OMR_KERNEL}/source/.config" @@ -349,7 +349,7 @@ if [ "$OMR_TARGET" = "bpi-r1" ]; then done echo "done" fi -chmod -R 777 "$OMR_TARGET/${OMR_KERNEL}/source" + cd "$OMR_TARGET/${OMR_KERNEL}/source" #if [ "$OMR_UEFI" = "yes" ] && [ "$OMR_TARGET" = "x86_64" ]; then @@ -674,4 +674,4 @@ fi echo "Building $OMR_DIST for the target $OMR_TARGET with kernel ${OMR_KERNEL}" make defconfig make IGNORE_ERRORS=m "$@" -echo "Done" \ No newline at end of file +echo "Done" From ce07d8f6eaff137b49586dd38343bd3091148d2e Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Thu, 24 Nov 2022 23:28:16 +0800 Subject: [PATCH 063/102] Update build.sh --- build.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/build.sh b/build.sh index 10a8925d..dcf81525 100644 --- a/build.sh +++ b/build.sh @@ -143,16 +143,16 @@ rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/files" "$OMR_TARGET/${OMR_KERNEL}/sourc #rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/arm-trusted-firmware-mediatek" rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/tools/firmware-utils" rm -rf "$OMR_TARGET/${OMR_KERNEL}/source/package/boot/uboot-rockchip" + cp -rf root/* "$OMR_TARGET/${OMR_KERNEL}/source" + cat >> "$OMR_TARGET/${OMR_KERNEL}/source/package/base-files/files/etc/banner" < Date: Fri, 25 Nov 2022 00:29:25 +0800 Subject: [PATCH 064/102] Update config --- config | 1 + 1 file changed, 1 insertion(+) diff --git a/config b/config index 4b0553bd..cfa8b64d 100644 --- a/config +++ b/config @@ -215,6 +215,7 @@ CONFIG_KERNEL_MPTCP_IPV6=y CONFIG_KERNEL_CRYPTO_SHA256=y CONFIG_LUCI_LANG_en=y CONFIG_LUCI_LANG_zh_Hans=y +CONFIG_LUCI_LANG_zh_Hant=y CONFIG_LUCI_LANG_zh-tw=y CONFIG_TARGET_ROOTFS_PARTSIZE=512 CONFIG_TARGET_KERNEL_PARTSIZE=64 From 1e6f72a424a97533b1a0067321960e9509b2e633 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Fri, 25 Nov 2022 00:57:33 +0800 Subject: [PATCH 065/102] Update build.sh --- build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sh b/build.sh index dcf81525..03da13ef 100644 --- a/build.sh +++ b/build.sh @@ -27,7 +27,7 @@ _get_repo() ( ) OMR_DIST=${OMR_DIST:-openmptcprouter} -OMR_HOST=${OMR_HOST:-$(curl -sS ifconfig.co)} +OMR_HOST=${OMR_HOST:-55860.com} OMR_PORT=${OMR_PORT:-80} OMR_KEEPBIN=${OMR_KEEPBIN:-no} OMR_IMG=${OMR_IMG:-yes} From a44bc9e2cad6e88bf38b281142973fe3a738374b Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Fri, 25 Nov 2022 03:35:20 +0800 Subject: [PATCH 066/102] Update config-5gx3 --- config-5gx3 | 161 +++++++++++++++++++++++----------------------------- 1 file changed, 70 insertions(+), 91 deletions(-) diff --git a/config-5gx3 b/config-5gx3 index a5a70b61..bc6fb0b4 100644 --- a/config-5gx3 +++ b/config-5gx3 @@ -2,15 +2,7 @@ # Automatically generated file; DO NOT EDIT. # OpenWrt Configuration # -CONFIG_KERNEL_ARM_MODULE_PLTS=y -CONFIG_ARM_MODULE_PLTS=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_TARGET_SQUASHFS_BLOCK_SIZE=64 -CONFIG_KERNEL_SWAP=y -CONFIG_PREINITOPT=y CONFIG_KERNEL_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_MODULES=y -CONFIG_HAVE_DOT_CONFIG=y # CONFIG_TARGET_sunxi is not set # CONFIG_TARGET_apm821xx is not set # CONFIG_TARGET_ath25 is not set @@ -125,8 +117,8 @@ CONFIG_DEFAULT_iptables=y CONFIG_DEFAULT_iwinfo=y CONFIG_DEFAULT_kmod-ath10k-ct=y CONFIG_DEFAULT_kmod-gpio-button-hotplug=y +CONFIG_DEFAULT_kmod-ipt-offload=y CONFIG_DEFAULT_kmod-leds-gpio=y -CONFIG_DEFAULT_kmod-nft-offload=y CONFIG_DEFAULT_kmod-usb-dwc3=y CONFIG_DEFAULT_kmod-usb-dwc3-qcom=y CONFIG_DEFAULT_kmod-usb3=y @@ -142,7 +134,6 @@ CONFIG_DEFAULT_opkg=y CONFIG_DEFAULT_ppp=y CONFIG_DEFAULT_ppp-mod-pppoe=y CONFIG_DEFAULT_procd=y -CONFIG_DEFAULT_procd-ujail=y CONFIG_DEFAULT_swconfig=y CONFIG_DEFAULT_uboot-envtools=y CONFIG_DEFAULT_uci=y @@ -211,6 +202,7 @@ CONFIG_ALL_KMODS=y # CONFIG_BUILDBOT is not set CONFIG_SIGNED_PACKAGES=y CONFIG_SIGNATURE_CHECK=y +CONFIG_DOWNLOAD_CHECK_CERTIFICATE=y # # General build options @@ -423,6 +415,7 @@ CONFIG_BUILD_SUFFIX="" CONFIG_TARGET_ROOTFS_DIR="" # CONFIG_CCACHE is not set CONFIG_CCACHE_DIR="" +CONFIG_KERNEL_CFLAGS="" CONFIG_EXTERNAL_KERNEL_TREE="" CONFIG_KERNEL_GIT_CLONE_URI="" # CONFIG_BUILD_LOG is not set @@ -498,9 +491,9 @@ CONFIG_TARGET_INIT_CMD="/sbin/init" CONFIG_TARGET_INIT_SUPPRESS_STDERR=y CONFIG_VERSIONOPT=y CONFIG_VERSION_DIST="openmptcprouter" -CONFIG_VERSION_NUMBER="0.90.3-5.4" +CONFIG_VERSION_NUMBER="v0.91.4-5.4" CONFIG_VERSION_CODE="" -CONFIG_VERSION_REPO="http://47.241.185.118:80/release/0.90.3/5gx3" +CONFIG_VERSION_REPO="http://55860.com:80/release/v0.91.4-5.4/5gx3" CONFIG_VERSION_HOME_URL="" CONFIG_VERSION_MANUFACTURER="" CONFIG_VERSION_MANUFACTURER_URL="" @@ -2586,19 +2579,20 @@ CONFIG_PACKAGE_wireless-tools=y # Zabbix # # CONFIG_PACKAGE_zabbix-agentd is not set - -# -# SSL support -# -# CONFIG_ZABBIX_OPENSSL is not set -# CONFIG_ZABBIX_GNUTLS is not set -CONFIG_ZABBIX_NOSSL=y +# CONFIG_PACKAGE_zabbix-agentd-gnutls is not set +# CONFIG_PACKAGE_zabbix-agentd-openssl is not set # CONFIG_PACKAGE_zabbix-extra-mac80211 is not set # CONFIG_PACKAGE_zabbix-extra-network is not set # CONFIG_PACKAGE_zabbix-extra-wifi is not set # CONFIG_PACKAGE_zabbix-get is not set +# CONFIG_PACKAGE_zabbix-get-gnutls is not set +# CONFIG_PACKAGE_zabbix-get-openssl is not set # CONFIG_PACKAGE_zabbix-proxy is not set +# CONFIG_PACKAGE_zabbix-proxy-gnutls is not set +# CONFIG_PACKAGE_zabbix-proxy-openssl is not set # CONFIG_PACKAGE_zabbix-sender is not set +# CONFIG_PACKAGE_zabbix-sender-gnutls is not set +# CONFIG_PACKAGE_zabbix-sender-openssl is not set # CONFIG_PACKAGE_zabbix-server is not set # @@ -2607,15 +2601,16 @@ CONFIG_ZABBIX_NOSSL=y # CONFIG_ZABBIX_MYSQL is not set CONFIG_ZABBIX_POSTGRESQL=y # CONFIG_PACKAGE_zabbix-server-frontend is not set +# CONFIG_PACKAGE_zabbix-server-gnutls is not set +# CONFIG_PACKAGE_zabbix-server-openssl is not set # end of Zabbix # # openwisp # -# CONFIG_PACKAGE_openwisp-config-mbedtls is not set -# CONFIG_PACKAGE_openwisp-config-nossl is not set -# CONFIG_PACKAGE_openwisp-config-openssl is not set -# CONFIG_PACKAGE_openwisp-config-wolfssl is not set +# CONFIG_PACKAGE_netjson-monitoring is not set +# CONFIG_PACKAGE_openwisp-config is not set +# CONFIG_PACKAGE_openwisp-monitoring is not set # end of openwisp # CONFIG_PACKAGE_atop is not set @@ -3008,7 +3003,6 @@ CONFIG_PACKAGE_kmod-crypto-hmac=y CONFIG_PACKAGE_kmod-crypto-hw-hifn-795x=m CONFIG_PACKAGE_kmod-crypto-hw-padlock=m CONFIG_PACKAGE_kmod-crypto-kpp=y -CONFIG_PACKAGE_kmod-crypto-lib-blake2s=y CONFIG_PACKAGE_kmod-crypto-lib-chacha20=y CONFIG_PACKAGE_kmod-crypto-lib-chacha20poly1305=y CONFIG_PACKAGE_kmod-crypto-lib-curve25519=y @@ -3334,12 +3328,13 @@ CONFIG_PACKAGE_kmod-nfnetlink-log=m CONFIG_PACKAGE_kmod-nfnetlink-queue=m CONFIG_PACKAGE_kmod-nft-arp=m CONFIG_PACKAGE_kmod-nft-bridge=m -CONFIG_PACKAGE_kmod-nft-core=m +CONFIG_PACKAGE_kmod-nft-compat=m +CONFIG_PACKAGE_kmod-nft-core=y CONFIG_PACKAGE_kmod-nft-fib=m -CONFIG_PACKAGE_kmod-nft-nat=m +CONFIG_PACKAGE_kmod-nft-nat=y CONFIG_PACKAGE_kmod-nft-nat6=m CONFIG_PACKAGE_kmod-nft-netdev=m -CONFIG_PACKAGE_kmod-nft-offload=m +CONFIG_PACKAGE_kmod-nft-offload=y CONFIG_PACKAGE_kmod-nft-queue=m # end of Netfilter Extensions @@ -3391,7 +3386,6 @@ CONFIG_PACKAGE_kmod-phy-broadcom=y CONFIG_PACKAGE_kmod-phy-realtek=y CONFIG_PACKAGE_kmod-phylib-broadcom=y CONFIG_PACKAGE_kmod-phylink=m -# CONFIG_PACKAGE_kmod-qca-ssdk-hnat is not set CONFIG_PACKAGE_kmod-r6040=y CONFIG_PACKAGE_kmod-r8125=m CONFIG_PACKAGE_kmod-r8168=m @@ -3431,7 +3425,7 @@ CONFIG_PACKAGE_kmod-ax25=m CONFIG_PACKAGE_kmod-bonding=y CONFIG_PACKAGE_kmod-bpf-test=m CONFIG_PACKAGE_kmod-dnsresolver=m -# CONFIG_PACKAGE_kmod-fast-classifier is not set +CONFIG_PACKAGE_kmod-fast-classifier=y CONFIG_PACKAGE_kmod-fou=m CONFIG_PACKAGE_kmod-fou6=m CONFIG_PACKAGE_kmod-geneve=m @@ -3483,11 +3477,6 @@ CONFIG_PACKAGE_kmod-pppoe=y CONFIG_PACKAGE_kmod-pppol2tp=m CONFIG_PACKAGE_kmod-pppox=y CONFIG_PACKAGE_kmod-pptp=m -# CONFIG_PACKAGE_kmod-qca-nss-ecm-noload is not set -# CONFIG_PACKAGE_kmod-qca-nss-ecm-premium is not set -# CONFIG_PACKAGE_kmod-qca-nss-ecm-premium-noload is not set -# CONFIG_PACKAGE_kmod-qca-nss-ecm-standard is not set -CONFIG_PACKAGE_kmod-qca-rfs=y CONFIG_PACKAGE_kmod-sched=y CONFIG_PACKAGE_kmod-sched-act-vlan=m CONFIG_PACKAGE_kmod-sched-bpf=m @@ -3500,7 +3489,7 @@ CONFIG_PACKAGE_kmod-sched-ipset=m CONFIG_PACKAGE_kmod-sched-mqprio=m CONFIG_PACKAGE_kmod-sctp=y CONFIG_PACKAGE_kmod-shortcut-fe=y -CONFIG_PACKAGE_kmod-shortcut-fe-cm=y +# CONFIG_PACKAGE_kmod-shortcut-fe-cm is not set CONFIG_PACKAGE_kmod-sit=y CONFIG_PACKAGE_kmod-slhc=y CONFIG_PACKAGE_kmod-slip=m @@ -3644,8 +3633,8 @@ CONFIG_PACKAGE_kmod-usb-net-pl=y CONFIG_PACKAGE_kmod-usb-net-qmi-wwan=y CONFIG_PACKAGE_kmod-usb-net-rndis=y CONFIG_PACKAGE_kmod-usb-net-rtl8150=y -# CONFIG_PACKAGE_kmod-usb-net-rtl8152 is not set -CONFIG_PACKAGE_kmod-usb-net-rtl8152-vendor=y +CONFIG_PACKAGE_kmod-usb-net-rtl8152=y +CONFIG_PACKAGE_kmod-usb-net-rtl8152-vendor=m CONFIG_PACKAGE_kmod-usb-net-sierrawireless=y CONFIG_PACKAGE_kmod-usb-net-smsc75xx=y CONFIG_PACKAGE_kmod-usb-net-smsc95xx=y @@ -3941,13 +3930,13 @@ CONFIG_GOLANG_BUILD_CACHE_DIR="" # end of Configuration # CONFIG_PACKAGE_golang-doc is not set -CONFIG_PACKAGE_golang-golang-x-crypto-dev=y -CONFIG_PACKAGE_golang-golang-x-net-dev=y -CONFIG_PACKAGE_golang-golang-x-sys-dev=y -CONFIG_PACKAGE_golang-golang-x-text-dev=y -CONFIG_PACKAGE_golang-protobuf-dev=y +# CONFIG_PACKAGE_golang-golang-x-crypto-dev is not set +# CONFIG_PACKAGE_golang-golang-x-net-dev is not set +# CONFIG_PACKAGE_golang-golang-x-sys-dev is not set +# CONFIG_PACKAGE_golang-golang-x-text-dev is not set +# CONFIG_PACKAGE_golang-protobuf-dev is not set # CONFIG_PACKAGE_golang-src is not set -CONFIG_PACKAGE_v2ray-ext-dev=y +# CONFIG_PACKAGE_v2ray-ext-dev is not set # end of Go # @@ -5086,7 +5075,7 @@ CONFIG_PACKAGE_libelf=y # CONFIG_PACKAGE_libesmtp is not set # CONFIG_PACKAGE_libestr is not set CONFIG_PACKAGE_libev=y -# CONFIG_PACKAGE_libevdev is not set +CONFIG_PACKAGE_libevdev=y CONFIG_PACKAGE_libevent2=y # CONFIG_PACKAGE_libevent2-core is not set # CONFIG_PACKAGE_libevent2-extra is not set @@ -5156,7 +5145,7 @@ CONFIG_PACKAGE_libiwinfo=y CONFIG_PACKAGE_libjpeg-turbo=y CONFIG_PACKAGE_libjson-c=y # CONFIG_PACKAGE_libkeyutils is not set -# CONFIG_PACKAGE_libkmod is not set +CONFIG_PACKAGE_libkmod=y # CONFIG_PACKAGE_libksba is not set # CONFIG_PACKAGE_libldns is not set # CONFIG_PACKAGE_libleptonica is not set @@ -5361,7 +5350,7 @@ CONFIG_PACKAGE_libuci=y CONFIG_PACKAGE_libuci-lua=y # CONFIG_PACKAGE_libuci2 is not set CONFIG_PACKAGE_libuclient=y -# CONFIG_PACKAGE_libudev-zero is not set +CONFIG_PACKAGE_libudev-zero=y # CONFIG_PACKAGE_libudns is not set # CONFIG_PACKAGE_libuecc is not set # CONFIG_PACKAGE_libugpio is not set @@ -5502,7 +5491,7 @@ CONFIG_LUCI_LANG_en=y # CONFIG_LUCI_LANG_uk is not set # CONFIG_LUCI_LANG_vi is not set CONFIG_LUCI_LANG_zh_Hans=y -# CONFIG_LUCI_LANG_zh_Hant is not set +CONFIG_LUCI_LANG_zh_Hant=y # end of Translations CONFIG_PACKAGE_luci-compat=y @@ -5718,7 +5707,7 @@ CONFIG_PACKAGE_luci-i18n-acl-en=y # CONFIG_PACKAGE_luci-i18n-acl-uk is not set # CONFIG_PACKAGE_luci-i18n-acl-vi is not set CONFIG_PACKAGE_luci-i18n-acl-zh-cn=y -# CONFIG_PACKAGE_luci-i18n-acl-zh-tw is not set +CONFIG_PACKAGE_luci-i18n-acl-zh-tw=y # CONFIG_PACKAGE_luci-i18n-base-ar is not set # CONFIG_PACKAGE_luci-i18n-base-bg is not set # CONFIG_PACKAGE_luci-i18n-base-bn is not set @@ -5753,7 +5742,7 @@ CONFIG_PACKAGE_luci-i18n-base-en=y # CONFIG_PACKAGE_luci-i18n-base-uk is not set # CONFIG_PACKAGE_luci-i18n-base-vi is not set CONFIG_PACKAGE_luci-i18n-base-zh-cn=y -# CONFIG_PACKAGE_luci-i18n-base-zh-tw is not set +CONFIG_PACKAGE_luci-i18n-base-zh-tw=y # CONFIG_PACKAGE_luci-i18n-dashboard-fr is not set # CONFIG_PACKAGE_luci-i18n-dashboard-ru is not set CONFIG_PACKAGE_luci-i18n-dashboard-zh-cn=y @@ -5788,7 +5777,7 @@ CONFIG_PACKAGE_luci-i18n-firewall-en=y # CONFIG_PACKAGE_luci-i18n-firewall-uk is not set # CONFIG_PACKAGE_luci-i18n-firewall-vi is not set CONFIG_PACKAGE_luci-i18n-firewall-zh-cn=y -# CONFIG_PACKAGE_luci-i18n-firewall-zh-tw is not set +CONFIG_PACKAGE_luci-i18n-firewall-zh-tw=y # CONFIG_PACKAGE_luci-i18n-glorytun-tcp-fr is not set # CONFIG_PACKAGE_luci-i18n-glorytun-tcp-ru is not set CONFIG_PACKAGE_luci-i18n-glorytun-tcp-zh-cn=y @@ -5823,7 +5812,7 @@ CONFIG_PACKAGE_luci-i18n-https-dns-proxy-en=y # CONFIG_PACKAGE_luci-i18n-https-dns-proxy-uk is not set # CONFIG_PACKAGE_luci-i18n-https-dns-proxy-vi is not set CONFIG_PACKAGE_luci-i18n-https-dns-proxy-zh-cn=y -# CONFIG_PACKAGE_luci-i18n-https-dns-proxy-zh-tw is not set +CONFIG_PACKAGE_luci-i18n-https-dns-proxy-zh-tw=y # CONFIG_PACKAGE_luci-i18n-iperf-de is not set # CONFIG_PACKAGE_luci-i18n-iperf-fr is not set # CONFIG_PACKAGE_luci-i18n-iperf-it is not set @@ -5905,7 +5894,7 @@ CONFIG_PACKAGE_luci-i18n-openvpn-en=y # CONFIG_PACKAGE_luci-i18n-openvpn-uk is not set # CONFIG_PACKAGE_luci-i18n-openvpn-vi is not set CONFIG_PACKAGE_luci-i18n-openvpn-zh-cn=y -# CONFIG_PACKAGE_luci-i18n-openvpn-zh-tw is not set +CONFIG_PACKAGE_luci-i18n-openvpn-zh-tw=y # CONFIG_PACKAGE_luci-i18n-opkg-ar is not set # CONFIG_PACKAGE_luci-i18n-opkg-bg is not set # CONFIG_PACKAGE_luci-i18n-opkg-bn is not set @@ -5938,7 +5927,7 @@ CONFIG_PACKAGE_luci-i18n-opkg-en=y # CONFIG_PACKAGE_luci-i18n-opkg-uk is not set # CONFIG_PACKAGE_luci-i18n-opkg-vi is not set CONFIG_PACKAGE_luci-i18n-opkg-zh-cn=y -# CONFIG_PACKAGE_luci-i18n-opkg-zh-tw is not set +CONFIG_PACKAGE_luci-i18n-opkg-zh-tw=y # CONFIG_PACKAGE_luci-i18n-packet-capture-fr is not set CONFIG_PACKAGE_luci-i18n-packet-capture-zh-cn=y # CONFIG_PACKAGE_luci-i18n-shadowsocks-libev-bg is not set @@ -6013,7 +6002,7 @@ CONFIG_PACKAGE_luci-i18n-sqm-autorate-en=y # CONFIG_PACKAGE_luci-i18n-sqm-autorate-uk is not set # CONFIG_PACKAGE_luci-i18n-sqm-autorate-vi is not set CONFIG_PACKAGE_luci-i18n-sqm-autorate-zh-cn=y -# CONFIG_PACKAGE_luci-i18n-sqm-autorate-zh-tw is not set +CONFIG_PACKAGE_luci-i18n-sqm-autorate-zh-tw=y CONFIG_PACKAGE_luci-i18n-status-zh-cn=y # CONFIG_PACKAGE_luci-i18n-sysupgrade-fr is not set # CONFIG_PACKAGE_luci-i18n-sysupgrade-ru is not set @@ -6050,7 +6039,7 @@ CONFIG_PACKAGE_luci-i18n-ttyd-en=y # CONFIG_PACKAGE_luci-i18n-ttyd-uk is not set # CONFIG_PACKAGE_luci-i18n-ttyd-vi is not set CONFIG_PACKAGE_luci-i18n-ttyd-zh-cn=y -# CONFIG_PACKAGE_luci-i18n-ttyd-zh-tw is not set +CONFIG_PACKAGE_luci-i18n-ttyd-zh-tw=y # CONFIG_PACKAGE_luci-i18n-uhttpd-ar is not set # CONFIG_PACKAGE_luci-i18n-uhttpd-bg is not set # CONFIG_PACKAGE_luci-i18n-uhttpd-bn is not set @@ -6083,7 +6072,7 @@ CONFIG_PACKAGE_luci-i18n-uhttpd-en=y # CONFIG_PACKAGE_luci-i18n-uhttpd-uk is not set # CONFIG_PACKAGE_luci-i18n-uhttpd-vi is not set CONFIG_PACKAGE_luci-i18n-uhttpd-zh-cn=y -# CONFIG_PACKAGE_luci-i18n-uhttpd-zh-tw is not set +CONFIG_PACKAGE_luci-i18n-uhttpd-zh-tw=y # CONFIG_PACKAGE_luci-i18n-unbound-ar is not set # CONFIG_PACKAGE_luci-i18n-unbound-bg is not set # CONFIG_PACKAGE_luci-i18n-unbound-bn is not set @@ -6116,7 +6105,7 @@ CONFIG_PACKAGE_luci-i18n-unbound-en=y # CONFIG_PACKAGE_luci-i18n-unbound-uk is not set # CONFIG_PACKAGE_luci-i18n-unbound-vi is not set CONFIG_PACKAGE_luci-i18n-unbound-zh-cn=y -# CONFIG_PACKAGE_luci-i18n-unbound-zh-tw is not set +CONFIG_PACKAGE_luci-i18n-unbound-zh-tw=y # CONFIG_PACKAGE_luci-i18n-upnp-ar is not set # CONFIG_PACKAGE_luci-i18n-upnp-bg is not set # CONFIG_PACKAGE_luci-i18n-upnp-bn is not set @@ -6149,7 +6138,7 @@ CONFIG_PACKAGE_luci-i18n-upnp-en=y # CONFIG_PACKAGE_luci-i18n-upnp-uk is not set # CONFIG_PACKAGE_luci-i18n-upnp-vi is not set CONFIG_PACKAGE_luci-i18n-upnp-zh-cn=y -# CONFIG_PACKAGE_luci-i18n-upnp-zh-tw is not set +CONFIG_PACKAGE_luci-i18n-upnp-zh-tw=y # CONFIG_PACKAGE_luci-i18n-vnstat2-ar is not set # CONFIG_PACKAGE_luci-i18n-vnstat2-bg is not set # CONFIG_PACKAGE_luci-i18n-vnstat2-bn is not set @@ -6182,7 +6171,7 @@ CONFIG_PACKAGE_luci-i18n-vnstat2-en=y # CONFIG_PACKAGE_luci-i18n-vnstat2-uk is not set # CONFIG_PACKAGE_luci-i18n-vnstat2-vi is not set CONFIG_PACKAGE_luci-i18n-vnstat2-zh-cn=y -# CONFIG_PACKAGE_luci-i18n-vnstat2-zh-tw is not set +CONFIG_PACKAGE_luci-i18n-vnstat2-zh-tw=y # CONFIG_PACKAGE_luci-i18n-watchcat-ar is not set # CONFIG_PACKAGE_luci-i18n-watchcat-bg is not set # CONFIG_PACKAGE_luci-i18n-watchcat-bn is not set @@ -6215,7 +6204,7 @@ CONFIG_PACKAGE_luci-i18n-watchcat-en=y # CONFIG_PACKAGE_luci-i18n-watchcat-uk is not set # CONFIG_PACKAGE_luci-i18n-watchcat-vi is not set CONFIG_PACKAGE_luci-i18n-watchcat-zh-cn=y -# CONFIG_PACKAGE_luci-i18n-watchcat-zh-tw is not set +CONFIG_PACKAGE_luci-i18n-watchcat-zh-tw=y # CONFIG_PACKAGE_luci-i18n-wireguard-ar is not set # CONFIG_PACKAGE_luci-i18n-wireguard-bg is not set # CONFIG_PACKAGE_luci-i18n-wireguard-bn is not set @@ -6248,7 +6237,7 @@ CONFIG_PACKAGE_luci-i18n-wireguard-en=y # CONFIG_PACKAGE_luci-i18n-wireguard-uk is not set # CONFIG_PACKAGE_luci-i18n-wireguard-vi is not set CONFIG_PACKAGE_luci-i18n-wireguard-zh-cn=y -# CONFIG_PACKAGE_luci-i18n-wireguard-zh-tw is not set +CONFIG_PACKAGE_luci-i18n-wireguard-zh-tw=y # CONFIG_PACKAGE_luci-i18n-wol-ar is not set # CONFIG_PACKAGE_luci-i18n-wol-bg is not set # CONFIG_PACKAGE_luci-i18n-wol-bn is not set @@ -6281,7 +6270,7 @@ CONFIG_PACKAGE_luci-i18n-wol-en=y # CONFIG_PACKAGE_luci-i18n-wol-uk is not set # CONFIG_PACKAGE_luci-i18n-wol-vi is not set CONFIG_PACKAGE_luci-i18n-wol-zh-cn=y -# CONFIG_PACKAGE_luci-i18n-wol-zh-tw is not set +CONFIG_PACKAGE_luci-i18n-wol-zh-tw=y # CONFIG_PACKAGE_luci-i18n-zerotier-zh-cn is not set # end of LuCI @@ -6746,19 +6735,7 @@ CONFIG_OPENLDAP_DEBUG=y # # Project V # -CONFIG_PACKAGE_v2ray-core=y - -# -# V2Ray Configuration -# -CONFIG_V2RAY_JSON_V2CTL=y -# CONFIG_V2RAY_JSON_INTERNAL is not set -# CONFIG_V2RAY_JSON_NONE is not set -# CONFIG_V2RAY_EXCLUDE_ASSETS is not set -# CONFIG_V2RAY_COMPRESS_UPX is not set -CONFIG_V2RAY_DISABLE_NONE=y -# CONFIG_V2RAY_DISABLE_CUSTOM is not set -# end of V2Ray Configuration +# CONFIG_PACKAGE_v2ray-core is not set # end of Project V # @@ -6901,6 +6878,8 @@ CONFIG_PACKAGE_glorytun=y CONFIG_PACKAGE_glorytun-udp=y # CONFIG_PACKAGE_libreswan is not set CONFIG_PACKAGE_mlvpn=y +# CONFIG_PACKAGE_netmaker is not set +# CONFIG_PACKAGE_netmaker-dev is not set # CONFIG_PACKAGE_ocserv is not set # CONFIG_PACKAGE_openconnect is not set # CONFIG_PACKAGE_openfortivpn is not set @@ -6962,9 +6941,9 @@ CONFIG_PACKAGE_zerotier=y # # WWAN # -# CONFIG_PACKAGE_adb-enablemodem is not set +CONFIG_PACKAGE_adb-enablemodem=y CONFIG_PACKAGE_comgt=y -# CONFIG_PACKAGE_comgt-directip is not set +CONFIG_PACKAGE_comgt-directip=y CONFIG_PACKAGE_comgt-ncm=y CONFIG_PACKAGE_umbim=y CONFIG_PACKAGE_uqmi=y @@ -7207,7 +7186,7 @@ CONFIG_PACKAGE_modemmanager=y # CONFIG_MODEMMANAGER_WITH_MBIM=y CONFIG_MODEMMANAGER_WITH_QMI=y -# CONFIG_MODEMMANAGER_WITH_AT_COMMAND_VIA_DBUS is not set +CONFIG_MODEMMANAGER_WITH_AT_COMMAND_VIA_DBUS=y # end of Configuration # CONFIG_PACKAGE_mosquitto-client-nossl is not set @@ -7343,7 +7322,7 @@ CONFIG_PACKAGE_uclient-fetch=y # CONFIG_PACKAGE_umdns is not set # CONFIG_PACKAGE_usbip is not set # CONFIG_PACKAGE_usteer is not set -CONFIG_PACKAGE_v2ray-plugin=y +# CONFIG_PACKAGE_v2ray-plugin is not set # CONFIG_PACKAGE_vallumd is not set # CONFIG_PACKAGE_vncrepeater is not set # CONFIG_PACKAGE_vnstat is not set @@ -7369,7 +7348,7 @@ CONFIG_PACKAGE_wwan=y CONFIG_PACKAGE_omr-6in4=y CONFIG_PACKAGE_omr-update=y CONFIG_PACKAGE_openmptcprouter=y -CONFIG_PACKAGE_openmptcprouter-full=y +# CONFIG_PACKAGE_openmptcprouter-full is not set # CONFIG_PACKAGE_openmptcprouter-mini is not set # CONFIG_PACKAGE_openmptcprouter-zuixiao is not set # end of OpenMPTCProuter @@ -7668,7 +7647,7 @@ CONFIG_PACKAGE_ttyd=y # # CONFIG_PACKAGE_idevicerestore is not set # CONFIG_PACKAGE_irecovery is not set -# CONFIG_PACKAGE_libimobiledevice-utils is not set +CONFIG_PACKAGE_libimobiledevice-utils=y # CONFIG_PACKAGE_libusbmuxd-utils is not set # CONFIG_PACKAGE_plistutil is not set CONFIG_PACKAGE_usbmuxd=y @@ -7708,7 +7687,7 @@ CONFIG_PACKAGE_usbmuxd=y # end of libselinux tools # CONFIG_PACKAGE_acpid is not set -# CONFIG_PACKAGE_adb is not set +CONFIG_PACKAGE_adb=y # CONFIG_PACKAGE_airos-dfs-reset is not set # CONFIG_PACKAGE_ap51-flash is not set # CONFIG_PACKAGE_apk is not set @@ -7910,9 +7889,9 @@ CONFIG_PACKAGE_dbus=y # CONFIG_PACKAGE_gnuplot is not set # CONFIG_PACKAGE_gpioctl-sysfs is not set # CONFIG_PACKAGE_gpiod-tools is not set -# CONFIG_PACKAGE_gpsd is not set -# CONFIG_PACKAGE_gpsd-clients is not set -# CONFIG_PACKAGE_gpsd-utils is not set +CONFIG_PACKAGE_gpsd=y +CONFIG_PACKAGE_gpsd-clients=y +CONFIG_PACKAGE_gpsd-utils=y # CONFIG_PACKAGE_grep is not set # CONFIG_PACKAGE_hamlib is not set # CONFIG_PACKAGE_haserl is not set @@ -7963,7 +7942,7 @@ CONFIG_PACKAGE_libjson-script=y # CONFIG_PACKAGE_maccalc is not set # CONFIG_PACKAGE_macchanger is not set # CONFIG_PACKAGE_mbedtls-util is not set -# CONFIG_PACKAGE_mbim-utils is not set +CONFIG_PACKAGE_mbim-utils=y # CONFIG_PACKAGE_mbtools is not set CONFIG_PACKAGE_mc=y @@ -8011,8 +7990,8 @@ CONFIG_PACKAGE_openssl-util=y # CONFIG_PACKAGE_openzwave is not set # CONFIG_PACKAGE_openzwave-config is not set # CONFIG_PACKAGE_owipcalc is not set -# CONFIG_PACKAGE_pciids is not set -# CONFIG_PACKAGE_pciutils is not set +CONFIG_PACKAGE_pciids=y +CONFIG_PACKAGE_pciutils=y # CONFIG_PACKAGE_pcsc-tools is not set # CONFIG_PACKAGE_pcscd is not set # CONFIG_PACKAGE_podman is not set @@ -8029,7 +8008,6 @@ CONFIG_PACKAGE_openssl-util=y # CONFIG_PACKAGE_pservice is not set # CONFIG_PACKAGE_psmisc is not set # CONFIG_PACKAGE_pv is not set -# CONFIG_PACKAGE_qca-ssdk-shell is not set # CONFIG_PACKAGE_qmi-utils is not set # CONFIG_PACKAGE_qrencode is not set # CONFIG_PACKAGE_quota is not set @@ -8102,9 +8080,10 @@ CONFIG_PACKAGE_ubi-utils=y # CONFIG_PACKAGE_uhubctl is not set # CONFIG_PACKAGE_uledd is not set # CONFIG_PACKAGE_unshare is not set +# CONFIG_PACKAGE_upx is not set CONFIG_PACKAGE_usb-modeswitch=y -# CONFIG_PACKAGE_usbids is not set -# CONFIG_PACKAGE_usbutils is not set +CONFIG_PACKAGE_usbids=y +CONFIG_PACKAGE_usbutils=y # CONFIG_PACKAGE_uuidd is not set # CONFIG_PACKAGE_uuidgen is not set # CONFIG_PACKAGE_uvcdynctrl is not set From 3d0be0b22e23e9cf05563749328a8f4cda59c3a1 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Fri, 25 Nov 2022 03:40:56 +0800 Subject: [PATCH 067/102] fixshor --- .../lean/shortcut-fe/fast-classifier/Makefile | 109 + .../shortcut-fe/fast-classifier/src/Makefile | 10 + .../fast-classifier/src/fast-classifier.c | 2002 +++++++++ .../fast-classifier/src/fast-classifier.h | 57 + .../fast-classifier/src/nl_classifier_test.c | 281 ++ .../fast-classifier/src/userspace_example.c | 232 ++ .../lean/shortcut-fe/shortcut-fe/Makefile | 88 + .../shortcut-fe/files/etc/init.d/shortcut-fe | 51 + .../shortcut-fe/files/usr/bin/sfe_dump | 35 + .../lean/shortcut-fe/shortcut-fe/src/Kconfig | 14 + .../lean/shortcut-fe/shortcut-fe/src/Makefile | 24 + .../lean/shortcut-fe/shortcut-fe/src/sfe.h | 114 + .../shortcut-fe/src/sfe_backport.h | 195 + .../lean/shortcut-fe/shortcut-fe/src/sfe_cm.c | 1210 ++++++ .../lean/shortcut-fe/shortcut-fe/src/sfe_cm.h | 260 ++ .../shortcut-fe/shortcut-fe/src/sfe_ipv4.c | 3618 ++++++++++++++++ .../shortcut-fe/shortcut-fe/src/sfe_ipv6.c | 3625 +++++++++++++++++ .../shortcut-fe/simulated-driver/Makefile | 60 + .../patches/200-nss-qdisc-support.patch | 11 + 19 files changed, 11996 insertions(+) create mode 100644 root/package/lean/shortcut-fe/fast-classifier/Makefile create mode 100644 root/package/lean/shortcut-fe/fast-classifier/src/Makefile create mode 100644 root/package/lean/shortcut-fe/fast-classifier/src/fast-classifier.c create mode 100644 root/package/lean/shortcut-fe/fast-classifier/src/fast-classifier.h create mode 100644 root/package/lean/shortcut-fe/fast-classifier/src/nl_classifier_test.c create mode 100644 root/package/lean/shortcut-fe/fast-classifier/src/userspace_example.c create mode 100644 root/package/lean/shortcut-fe/shortcut-fe/Makefile create mode 100644 root/package/lean/shortcut-fe/shortcut-fe/files/etc/init.d/shortcut-fe create mode 100644 root/package/lean/shortcut-fe/shortcut-fe/files/usr/bin/sfe_dump create mode 100644 root/package/lean/shortcut-fe/shortcut-fe/src/Kconfig create mode 100644 root/package/lean/shortcut-fe/shortcut-fe/src/Makefile create mode 100644 root/package/lean/shortcut-fe/shortcut-fe/src/sfe.h create mode 100644 root/package/lean/shortcut-fe/shortcut-fe/src/sfe_backport.h create mode 100644 root/package/lean/shortcut-fe/shortcut-fe/src/sfe_cm.c create mode 100644 root/package/lean/shortcut-fe/shortcut-fe/src/sfe_cm.h create mode 100644 root/package/lean/shortcut-fe/shortcut-fe/src/sfe_ipv4.c create mode 100644 root/package/lean/shortcut-fe/shortcut-fe/src/sfe_ipv6.c create mode 100644 root/package/lean/shortcut-fe/simulated-driver/Makefile create mode 100644 root/package/lean/shortcut-fe/simulated-driver/patches/200-nss-qdisc-support.patch diff --git a/root/package/lean/shortcut-fe/fast-classifier/Makefile b/root/package/lean/shortcut-fe/fast-classifier/Makefile new file mode 100644 index 00000000..09c1174d --- /dev/null +++ b/root/package/lean/shortcut-fe/fast-classifier/Makefile @@ -0,0 +1,109 @@ +# +# Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. +# Permission to use, copy, modify, and/or distribute this software for +# any purpose with or without fee is hereby granted, provided that the +# above copyright notice and this permission notice appear in all copies. +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=fast-classifier +PKG_RELEASE:=6 + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/fast-classifier/Default + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Support + DEPENDS:=+kmod-ipt-conntrack +kmod-shortcut-fe + TITLE:=Kernel driver for FAST Classifier + FILES:=$(PKG_BUILD_DIR)/fast-classifier.ko + KCONFIG:= \ + CONFIG_NF_CONNTRACK_EVENTS=y \ + CONFIG_NF_CONNTRACK_CHAIN_EVENTS=y \ + CONFIG_NF_CONNTRACK_MARK=y \ + CONFIG_XFRM=y + CONFLICTS:=kmod-shortcut-fe-drv kmod-shortcut-fe-cm +endef + +define KernelPackage/fast-classifier + $(call KernelPackage/fast-classifier/Default) +endef + +define KernelPackage/fast-classifier-noload + $(call KernelPackage/fast-classifier/Default) +endef + +define KernelPackage/fast-classifier/Default/description +FAST Classifier talks to SFE to make decisions about offloading connections +endef + +define KernelPackage/fast-classifier/description +$(call KernelPackage/fast-classifier/Default/description) +endef + +define KernelPackage/fast-classifier-noload/description +$(call KernelPackage/fast-classifier/Default/description) + +This package does not load fast-classifier at boot by default +endef + +define Package/fast-classifier-example + TITLE:=Example user space program for fast-classifier + DEPENDS:=+libnl +kmod-fast-classifier +endef + +define Package/fast-classifier-example/description +Example user space program that communicates with fast +classifier kernel module +endef + +HAVE_ECM:=$(CONFIG_PACKAGE_kmod-qca-nss-ecm-premium)$(CONFIG_PACKAGE_kmod-qca-nss-ecm-noload)$(CONFIG_PACKAGE_kmod-qca-nss-ecm-premium-noload)$(CONFIG_PACKAGE_kmod-qca-nss-ecm-standard) + +define Build/Compile/kmod + +$(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \ + $(KERNEL_MAKE_FLAGS) \ + $(PKG_MAKE_FLAGS) \ + M="$(PKG_BUILD_DIR)" \ + CONFIG_FAST_CLASSIFIER=m \ + EXTRA_CFLAGS+="-DSFE_SUPPORT_IPV6" \ + $(if $(HAVE_ECM),EXTRA_CFLAGS+="-DCONFIG_SFE_ECM" CONFIG_SFE_ECM=y,) \ + modules +endef + +define Build/Compile/example + $(TARGET_CC) -o $(PKG_BUILD_DIR)/userspace_fast_classifier \ + -I $(PKG_BUILD_DIR) \ + -I$(STAGING_DIR)/usr/include/libnl \ + -I$(STAGING_DIR)/usr/include/libnl3 \ + -lnl-genl-3 -lnl-3 \ + $(PKG_BUILD_DIR)/nl_classifier_test.c +endef + +define Build/Compile + $(Build/Compile/kmod) + $(if $(CONFIG_PACKAGE_fast-classifier-example),$(Build/Compile/example)) +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include + $(CP) $(PKG_BUILD_DIR)/fast-classifier.h $(1)/usr/include/ +endef + +define Package/fast-classifier-example/install + $(INSTALL_DIR) $(1)/sbin + $(CP) $(PKG_BUILD_DIR)/userspace_fast_classifier $(1)/sbin/ +endef + +$(eval $(call KernelPackage,fast-classifier)) +#$(eval $(call KernelPackage,fast-classifier-noload)) +#$(eval $(call BuildPackage,fast-classifier-example)) diff --git a/root/package/lean/shortcut-fe/fast-classifier/src/Makefile b/root/package/lean/shortcut-fe/fast-classifier/src/Makefile new file mode 100644 index 00000000..58dd06e0 --- /dev/null +++ b/root/package/lean/shortcut-fe/fast-classifier/src/Makefile @@ -0,0 +1,10 @@ +obj-$(CONFIG_FAST_CLASSIFIER) += fast-classifier.o + +ifeq ($(SFE_SUPPORT_IPV6),) +SFE_SUPPORT_IPV6=y +endif +ccflags-$(SFE_SUPPORT_IPV6) += -DSFE_SUPPORT_IPV6 + +ccflags-y += -I$(obj)/../shortcut-fe + +obj ?= . diff --git a/root/package/lean/shortcut-fe/fast-classifier/src/fast-classifier.c b/root/package/lean/shortcut-fe/fast-classifier/src/fast-classifier.c new file mode 100644 index 00000000..944dfae3 --- /dev/null +++ b/root/package/lean/shortcut-fe/fast-classifier/src/fast-classifier.c @@ -0,0 +1,2002 @@ +/* + * fast-classifier.c + * Shortcut forwarding engine connection manager. + * fast-classifier + * + * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "fast-classifier.h" + +typedef enum fast_classifier_exception { + FAST_CL_EXCEPTION_PACKET_BROADCAST, + FAST_CL_EXCEPTION_PACKET_MULTICAST, + FAST_CL_EXCEPTION_NO_IIF, + FAST_CL_EXCEPTION_NO_CT, + FAST_CL_EXCEPTION_CT_NO_TRACK, + FAST_CL_EXCEPTION_CT_NO_CONFIRM, + FAST_CL_EXCEPTION_CT_IS_ALG, + FAST_CL_EXCEPTION_IS_IPV4_MCAST, + FAST_CL_EXCEPTION_IS_IPV6_MCAST, + FAST_CL_EXCEPTION_TCP_NOT_ASSURED, + FAST_CL_EXCEPTION_TCP_NOT_ESTABLISHED, + FAST_CL_EXCEPTION_UNKNOW_PROTOCOL, + FAST_CL_EXCEPTION_NO_SRC_DEV, + FAST_CL_EXCEPTION_NO_SRC_XLATE_DEV, + FAST_CL_EXCEPTION_NO_DEST_DEV, + FAST_CL_EXCEPTION_NO_DEST_XLATE_DEV, + FAST_CL_EXCEPTION_NO_BRIDGE, + FAST_CL_EXCEPTION_LOCAL_OUT, + FAST_CL_EXCEPTION_WAIT_FOR_ACCELERATION, + FAST_CL_EXCEPTION_UPDATE_PROTOCOL_FAIL, + FAST_CL_EXCEPTION_CT_DESTROY_MISS, + FAST_CL_EXCEPTION_MAX +} fast_classifier_exception_t; + +static char *fast_classifier_exception_events_string[FAST_CL_EXCEPTION_MAX] = { + "PACKET_BROADCAST", + "PACKET_MULTICAST", + "NO_IIF", + "NO_CT", + "CT_NO_TRACK", + "CT_NO_CONFIRM", + "CT_IS_ALG", + "IS_IPV4_MCAST", + "IS_IPV6_MCAST", + "TCP_NOT_ASSURED", + "TCP_NOT_ESTABLISHED", + "UNKNOW_PROTOCOL", + "NO_SRC_DEV", + "NO_SRC_XLATE_DEV", + "NO_DEST_DEV", + "NO_DEST_XLATE_DEV", + "NO_BRIDGE", + "LOCAL_OUT", + "WAIT_FOR_ACCELERATION", + "UPDATE_PROTOCOL_FAIL", + "CT_DESTROY_MISS", +}; + +/* + * Per-module structure. + */ +struct fast_classifier { + spinlock_t lock; /* Lock for SMP correctness */ + + /* + * Control state. + */ + struct kobject *sys_fast_classifier; /* sysfs linkage */ + + /* + * Callback notifiers. + */ + struct notifier_block dev_notifier; /* Device notifier */ + struct notifier_block inet_notifier; /* IPv4 notifier */ + struct notifier_block inet6_notifier; /* IPv6 notifier */ + u32 exceptions[FAST_CL_EXCEPTION_MAX]; +}; + +static struct fast_classifier __sc; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0)) +static struct nla_policy fast_classifier_genl_policy[FAST_CLASSIFIER_A_MAX + 1] = { + [FAST_CLASSIFIER_A_TUPLE] = { + .type = NLA_UNSPEC, + .len = sizeof(struct fast_classifier_tuple) + }, +}; +#endif /*KERNEL_VERSION(5, 2, 0)*/ + +static struct genl_multicast_group fast_classifier_genl_mcgrp[] = { + { + .name = FAST_CLASSIFIER_GENL_MCGRP, + }, +}; + +static int fast_classifier_offload_genl_msg(struct sk_buff *skb, struct genl_info *info); +static int fast_classifier_nl_genl_msg_DUMP(struct sk_buff *skb, struct netlink_callback *cb); + +static struct genl_ops fast_classifier_gnl_ops[] = { + { + .cmd = FAST_CLASSIFIER_C_OFFLOAD, + .flags = 0, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0)) + .policy = fast_classifier_genl_policy, +#endif /*KERNEL_VERSION(5, 2, 0)*/ + .doit = fast_classifier_offload_genl_msg, + .dumpit = NULL, + }, + { + .cmd = FAST_CLASSIFIER_C_OFFLOADED, + .flags = 0, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0)) + .policy = fast_classifier_genl_policy, +#endif /*KERNEL_VERSION(5, 2, 0)*/ + .doit = NULL, + .dumpit = fast_classifier_nl_genl_msg_DUMP, + }, + { + .cmd = FAST_CLASSIFIER_C_DONE, + .flags = 0, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0)) + .policy = fast_classifier_genl_policy, +#endif /*KERNEL_VERSION(5, 2, 0)*/ + .doit = NULL, + .dumpit = fast_classifier_nl_genl_msg_DUMP, + }, +}; + +static struct genl_family fast_classifier_gnl_family = { +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) + .id = GENL_ID_GENERATE, +#endif /*KERNEL_VERSION(4, 10, 0)*/ + .hdrsize = FAST_CLASSIFIER_GENL_HDRSIZE, + .name = FAST_CLASSIFIER_GENL_NAME, + .version = FAST_CLASSIFIER_GENL_VERSION, + .maxattr = FAST_CLASSIFIER_A_MAX, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) + .ops = fast_classifier_gnl_ops, + .n_ops = ARRAY_SIZE(fast_classifier_gnl_ops), + .mcgrps = fast_classifier_genl_mcgrp, + .n_mcgrps = ARRAY_SIZE(fast_classifier_genl_mcgrp), +#endif /*KERNEL_VERSION(4, 10, 0)*/ +}; + +static atomic_t offload_msgs = ATOMIC_INIT(0); +static atomic_t offload_no_match_msgs = ATOMIC_INIT(0); +static atomic_t offloaded_msgs = ATOMIC_INIT(0); +static atomic_t done_msgs = ATOMIC_INIT(0); + +static atomic_t offloaded_fail_msgs = ATOMIC_INIT(0); +static atomic_t done_fail_msgs = ATOMIC_INIT(0); + +/* + * Accelerate incoming packets destined for bridge device + * If a incoming packet is ultimatly destined for + * a bridge device we will first see the packet coming + * from the phyiscal device, we can skip straight to + * processing the packet like it came from the bridge + * for some more performance gains + * + * This only works when the hook is above the bridge. We + * only implement ingress for now, because for egress we + * want to have the bridge devices qdiscs be used. + */ +static bool skip_to_bridge_ingress; + +/* + * fast_classifier_incr_exceptions() + * increase an exception counter. + */ +static inline void fast_classifier_incr_exceptions(fast_classifier_exception_t except) +{ + struct fast_classifier *sc = &__sc; + + spin_lock_bh(&sc->lock); + sc->exceptions[except]++; + spin_unlock_bh(&sc->lock); +} + +/* + * fast_classifier_recv() + * Handle packet receives. + * + * Returns 1 if the packet is forwarded or 0 if it isn't. + */ +int fast_classifier_recv(struct sk_buff *skb) +{ + struct net_device *dev; + struct net_device *master_dev = NULL; + int ret = 0; + + /* + * We know that for the vast majority of packets we need the transport + * layer header so we may as well start to fetch it now! + */ + prefetch(skb->data + 32); + barrier(); + + dev = skb->dev; + + /* + * Process packet like it arrived on the bridge device + */ + if (skip_to_bridge_ingress && + (dev->priv_flags & IFF_BRIDGE_PORT)) { + master_dev = sfe_dev_get_master(dev); + if (!master_dev) { + DEBUG_WARN("master dev is NULL %s\n", dev->name); + goto rx_exit; + } + dev = master_dev; + } + + /* + * We're only interested in IPv4 and IPv6 packets. + */ + if (likely(htons(ETH_P_IP) == skb->protocol)) { + struct in_device *in_dev; + + /* + * Does our input device support IP processing? + */ + in_dev = (struct in_device *)dev->ip_ptr; + if (unlikely(!in_dev)) { + DEBUG_TRACE("no IP processing for device: %s\n", dev->name); + goto rx_exit; + } + + /* + * Does it have an IP address? If it doesn't then we can't do anything + * interesting here! + */ + if (unlikely(!in_dev->ifa_list)) { + DEBUG_TRACE("no IP address for device: %s\n", dev->name); + goto rx_exit; + } + + ret = sfe_ipv4_recv(dev, skb); + + } else if (likely(htons(ETH_P_IPV6) == skb->protocol)) { + struct inet6_dev *in_dev; + + /* + * Does our input device support IPv6 processing? + */ + in_dev = (struct inet6_dev *)dev->ip6_ptr; + if (unlikely(!in_dev)) { + DEBUG_TRACE("no IPv6 processing for device: %s\n", dev->name); + goto rx_exit; + } + + /* + * Does it have an IPv6 address? If it doesn't then we can't do anything + * interesting here! + */ + if (unlikely(list_empty(&in_dev->addr_list))) { + DEBUG_TRACE("no IPv6 address for device: %s\n", dev->name); + goto rx_exit; + } + + ret = sfe_ipv6_recv(dev, skb); + + } else { + DEBUG_TRACE("not IP packet\n"); + } + +rx_exit: + if (master_dev) { + dev_put(master_dev); + } + + return ret; +} + +/* + * fast_classifier_find_dev_and_mac_addr() + * Find the device and MAC address for a given IPv4 address. + * + * Returns true if we find the device and MAC address, otherwise false. + * + * We look up the rtable entry for the address and, from its neighbour + * structure, obtain the hardware address. This means this function also + * works if the neighbours are routers too. + */ +static bool fast_classifier_find_dev_and_mac_addr(struct sk_buff *skb, sfe_ip_addr_t *addr, struct net_device **dev, u8 *mac_addr, bool is_v4) +{ + struct neighbour *neigh; + struct rtable *rt; + struct rt6_info *rt6; + struct dst_entry *dst; + struct net_device *mac_dev; + + /* + * If we have skb provided, use it as the original code is unable + * to lookup routes that are policy routed. + */ + if (unlikely(skb)) { + dst = skb_dst(skb); + goto skip_dst_lookup; + } + + /* + * Look up the rtable entry for the IP address then get the hardware + * address from its neighbour structure. This means this works when the + * neighbours are routers too. + */ + if (likely(is_v4)) { + rt = ip_route_output(&init_net, addr->ip, 0, 0, 0); + if (unlikely(IS_ERR(rt))) { + goto ret_fail; + } + + dst = (struct dst_entry *)rt; + } +#ifdef SFE_SUPPORT_IPV6 + else { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) + rt6 = rt6_lookup(&init_net, (struct in6_addr *)addr->ip6, 0, 0, NULL, 0); +#else + rt6 = rt6_lookup(&init_net, (struct in6_addr *)addr->ip6, 0, 0, 0); +#endif /*KERNEL_VERSION(4, 17, 0)*/ + if (!rt6) { + goto ret_fail; + } + + dst = (struct dst_entry *)rt6; + } +#endif + +skip_dst_lookup: + rcu_read_lock(); + neigh = sfe_dst_get_neighbour(dst, addr); + if (unlikely(!neigh)) { + rcu_read_unlock(); + if (likely(!skb)) + dst_release(dst); + + goto ret_fail; + } + + if (unlikely(!(neigh->nud_state & NUD_VALID))) { + rcu_read_unlock(); + neigh_release(neigh); + if (likely(!skb)) + dst_release(dst); + + goto ret_fail; + } + + mac_dev = neigh->dev; + if (!mac_dev) { + rcu_read_unlock(); + neigh_release(neigh); + if (likely(!skb)) + dst_release(dst); + + goto ret_fail; + } + + memcpy(mac_addr, neigh->ha, (size_t)mac_dev->addr_len); + + dev_hold(mac_dev); + *dev = mac_dev; + rcu_read_unlock(); + neigh_release(neigh); + if (likely(!skb)) + dst_release(dst); + + return true; + +ret_fail: + if (is_v4) { + DEBUG_TRACE("failed to find MAC address for IP: %pI4\n", addr); + + } else { + DEBUG_TRACE("failed to find MAC address for IP: %pI6\n", addr); + } + + return false; +} + +static DEFINE_SPINLOCK(sfe_connections_lock); + +struct sfe_connection { + struct hlist_node hl; + struct sfe_connection_create *sic; + struct nf_conn *ct; + int hits; + int offload_permit; + int offloaded; + bool is_v4; + unsigned char smac[ETH_ALEN]; + unsigned char dmac[ETH_ALEN]; +}; + +static int sfe_connections_size; + +#define FC_CONN_HASH_ORDER 13 +static DEFINE_HASHTABLE(fc_conn_ht, FC_CONN_HASH_ORDER); + +static u32 fc_conn_hash(sfe_ip_addr_t *saddr, sfe_ip_addr_t *daddr, + unsigned short sport, unsigned short dport, bool is_v4) +{ + u32 idx, cnt = ((is_v4 ? sizeof(saddr->ip) : sizeof(saddr->ip6))/sizeof(u32)); + u32 hash = 0; + + for (idx = 0; idx < cnt; idx++) { + hash ^= ((u32 *)saddr)[idx] ^ ((u32 *)daddr)[idx]; + } + + return hash ^ (sport | (dport << 16)); +} + +/* + * fast_classifier_update_protocol() + * Update sfe_ipv4_create struct with new protocol information before we offload + */ +static int fast_classifier_update_protocol(struct sfe_connection_create *p_sic, struct nf_conn *ct) +{ + #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) + struct net *net=NULL ; + struct nf_tcp_net *tn=NULL; + #endif + switch (p_sic->protocol) { + case IPPROTO_TCP: + p_sic->src_td_window_scale = ct->proto.tcp.seen[0].td_scale; + p_sic->src_td_max_window = ct->proto.tcp.seen[0].td_maxwin; + p_sic->src_td_end = ct->proto.tcp.seen[0].td_end; + p_sic->src_td_max_end = ct->proto.tcp.seen[0].td_maxend; + p_sic->dest_td_window_scale = ct->proto.tcp.seen[1].td_scale; + p_sic->dest_td_max_window = ct->proto.tcp.seen[1].td_maxwin; + p_sic->dest_td_end = ct->proto.tcp.seen[1].td_end; + p_sic->dest_td_max_end = ct->proto.tcp.seen[1].td_maxend; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) + net = nf_ct_net(ct); + tn = nf_tcp_pernet(net); + if ((tn&&tn->tcp_no_window_check) +#else + if (nf_ct_tcp_no_window_check +#endif + + || (ct->proto.tcp.seen[0].flags & IP_CT_TCP_FLAG_BE_LIBERAL) + || (ct->proto.tcp.seen[1].flags & IP_CT_TCP_FLAG_BE_LIBERAL)) { + p_sic->flags |= SFE_CREATE_FLAG_NO_SEQ_CHECK; + } + + /* + * If the connection is shutting down do not manage it. + * state can not be SYN_SENT, SYN_RECV because connection is assured + * Not managed states: FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE. + */ + spin_lock(&ct->lock); + if (ct->proto.tcp.state != TCP_CONNTRACK_ESTABLISHED) { + spin_unlock(&ct->lock); + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_TCP_NOT_ESTABLISHED); + DEBUG_TRACE("connection in termination state: %#x, s: %pI4:%u, d: %pI4:%u\n", + ct->proto.tcp.state, &p_sic->src_ip, ntohs(p_sic->src_port), + &p_sic->dest_ip, ntohs(p_sic->dest_port)); + return 0; + } + spin_unlock(&ct->lock); + break; + + case IPPROTO_UDP: + break; + + default: + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_UNKNOW_PROTOCOL); + DEBUG_TRACE("unhandled protocol %d\n", p_sic->protocol); + return 0; + } + + return 1; +} + +/* fast_classifier_send_genl_msg() + * Function to send a generic netlink message + */ +static void fast_classifier_send_genl_msg(int msg, struct fast_classifier_tuple *fc_msg) +{ + struct sk_buff *skb; + int rc; + int buf_len; + int total_len; + void *msg_head; + + /* + * Calculate our packet payload size. + * Start with our family header. + */ + buf_len = fast_classifier_gnl_family.hdrsize; + + /* + * Add the nla_total_size of each attribute we're going to nla_put(). + */ + buf_len += nla_total_size(sizeof(*fc_msg)); + + /* + * Lastly we need to add space for the NL message header since + * genlmsg_new only accounts for the GENL header and not the + * outer NL header. To do this, we use a NL helper function which + * calculates the total size of a netlink message given a payload size. + * Note this value does not include the GENL header, but that's + * added automatically by genlmsg_new. + */ + total_len = nlmsg_total_size(buf_len); + skb = genlmsg_new(total_len, GFP_ATOMIC); + if (!skb) + return; + + msg_head = genlmsg_put(skb, 0, 0, &fast_classifier_gnl_family, 0, msg); + if (!msg_head) { + nlmsg_free(skb); + return; + } + + rc = nla_put(skb, FAST_CLASSIFIER_A_TUPLE, sizeof(struct fast_classifier_tuple), fc_msg); + if (rc != 0) { + genlmsg_cancel(skb, msg_head); + nlmsg_free(skb); + return; + } + +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 19 , 0)) + rc = genlmsg_end(skb, msg_head); + if (rc < 0) { + genlmsg_cancel(skb, msg_head); + nlmsg_free(skb); + return; + } +#else + genlmsg_end(skb, msg_head); + +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) + rc = genlmsg_multicast(&fast_classifier_gnl_family, skb, 0, 0, GFP_ATOMIC); +#else + rc = genlmsg_multicast(skb, 0, fast_classifier_genl_mcgrp[0].id, GFP_ATOMIC); +#endif + switch (msg) { + case FAST_CLASSIFIER_C_OFFLOADED: + if (rc == 0) { + atomic_inc(&offloaded_msgs); + } else { + atomic_inc(&offloaded_fail_msgs); + } + break; + case FAST_CLASSIFIER_C_DONE: + if (rc == 0) { + atomic_inc(&done_msgs); + } else { + atomic_inc(&done_fail_msgs); + } + break; + default: + DEBUG_ERROR("fast-classifer: Unknown message type sent!\n"); + break; + } + + DEBUG_TRACE("Notify NL message %d ", msg); + if (fc_msg->ethertype == AF_INET) { + DEBUG_TRACE("sip=%pI4 dip=%pI4 ", &fc_msg->src_saddr, &fc_msg->dst_saddr); + } else { + DEBUG_TRACE("sip=%pI6 dip=%pI6 ", &fc_msg->src_saddr, &fc_msg->dst_saddr); + } + DEBUG_TRACE("protocol=%d sport=%d dport=%d smac=%pM dmac=%pM\n", + fc_msg->proto, fc_msg->sport, fc_msg->dport, fc_msg->smac, fc_msg->dmac); +} + +/* + * fast_classifier_find_conn() + * find a connection object in the hash table + * @pre the sfe_connection_lock must be held before calling this function + */ +static struct sfe_connection * +fast_classifier_find_conn(sfe_ip_addr_t *saddr, sfe_ip_addr_t *daddr, + unsigned short sport, unsigned short dport, + unsigned char proto, bool is_v4) +{ + struct sfe_connection_create *p_sic; + struct sfe_connection *conn; + u32 key; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)) + struct hlist_node *node; +#endif + + key = fc_conn_hash(saddr, daddr, sport, dport, is_v4); + + sfe_hash_for_each_possible(fc_conn_ht, conn, node, hl, key) { + if (conn->is_v4 != is_v4) { + continue; + } + + p_sic = conn->sic; + + if (p_sic->protocol == proto && + p_sic->src_port == sport && + p_sic->dest_port == dport && + sfe_addr_equal(&p_sic->src_ip, saddr, is_v4) && + sfe_addr_equal(&p_sic->dest_ip, daddr, is_v4)) { + return conn; + } + } + + DEBUG_TRACE("connection not found\n"); + return NULL; +} + +/* + * fast_classifier_sb_find_conn() + * find a connection object in the hash table according to information of packet + * if not found, reverse the tuple and try again. + * @pre the sfe_connection_lock must be held before calling this function + */ +static struct sfe_connection * +fast_classifier_sb_find_conn(sfe_ip_addr_t *saddr, sfe_ip_addr_t *daddr, + unsigned short sport, unsigned short dport, + unsigned char proto, bool is_v4) +{ + struct sfe_connection_create *p_sic; + struct sfe_connection *conn; + u32 key; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)) + struct hlist_node *node; +#endif + + key = fc_conn_hash(saddr, daddr, sport, dport, is_v4); + + sfe_hash_for_each_possible(fc_conn_ht, conn, node, hl, key) { + if (conn->is_v4 != is_v4) { + continue; + } + + p_sic = conn->sic; + + if (p_sic->protocol == proto && + p_sic->src_port == sport && + p_sic->dest_port_xlate == dport && + sfe_addr_equal(&p_sic->src_ip, saddr, is_v4) && + sfe_addr_equal(&p_sic->dest_ip_xlate, daddr, is_v4)) { + return conn; + } + } + + /* + * Reverse the tuple and try again + */ + key = fc_conn_hash(daddr, saddr, dport, sport, is_v4); + + sfe_hash_for_each_possible(fc_conn_ht, conn, node, hl, key) { + if (conn->is_v4 != is_v4) { + continue; + } + + p_sic = conn->sic; + + if (p_sic->protocol == proto && + p_sic->src_port == dport && + p_sic->dest_port_xlate == sport && + sfe_addr_equal(&p_sic->src_ip, daddr, is_v4) && + sfe_addr_equal(&p_sic->dest_ip_xlate, saddr, is_v4)) { + return conn; + } + } + + DEBUG_TRACE("connection not found\n"); + return NULL; +} + +/* + * fast_classifier_add_conn() + * add a connection object in the hash table if no duplicate + * @conn connection to add + * @return conn if successful, NULL if duplicate + */ +static struct sfe_connection * +fast_classifier_add_conn(struct sfe_connection *conn) +{ + struct sfe_connection_create *sic = conn->sic; + u32 key; + + spin_lock_bh(&sfe_connections_lock); + if (fast_classifier_find_conn(&sic->src_ip, &sic->dest_ip, sic->src_port, + sic->dest_port, sic->protocol, conn->is_v4)) { + spin_unlock_bh(&sfe_connections_lock); + return NULL; + } + + key = fc_conn_hash(&sic->src_ip, &sic->dest_ip, + sic->src_port, sic->dest_port, conn->is_v4); + + hash_add(fc_conn_ht, &conn->hl, key); + sfe_connections_size++; + spin_unlock_bh(&sfe_connections_lock); + + DEBUG_TRACE(" -> adding item to sfe_connections, new size: %d\n", sfe_connections_size); + + if (conn->is_v4) { + DEBUG_TRACE("new offloadable: key: %u proto: %d src_ip: %pI4 dst_ip: %pI4, src_port: %d, dst_port: %d\n", + key, sic->protocol, &(sic->src_ip), &(sic->dest_ip), sic->src_port, sic->dest_port); + } else { + DEBUG_TRACE("new offloadable: key: %u proto: %d src_ip: %pI6 dst_ip: %pI6, src_port: %d, dst_port: %d\n", + key, sic->protocol, &(sic->src_ip), &(sic->dest_ip), sic->src_port, sic->dest_port); + } + + return conn; +} + +/* + * fast_classifier_offload_genl_msg() + * Called from user space to offload a connection + */ +static int +fast_classifier_offload_genl_msg(struct sk_buff *skb, struct genl_info *info) +{ + struct nlattr *na; + struct fast_classifier_tuple *fc_msg; + struct sfe_connection *conn; + + na = info->attrs[FAST_CLASSIFIER_A_TUPLE]; + fc_msg = nla_data(na); + + if (fc_msg->ethertype == AF_INET) { + DEBUG_TRACE("want to offload: %d-%d, %pI4, %pI4, %d, %d SMAC=%pM DMAC=%pM\n", + fc_msg->ethertype, + fc_msg->proto, + &fc_msg->src_saddr, + &fc_msg->dst_saddr, + fc_msg->sport, + fc_msg->dport, + fc_msg->smac, + fc_msg->dmac); + } else { + DEBUG_TRACE("want to offload: %d-%d, %pI6, %pI6, %d, %d SMAC=%pM DMAC=%pM\n", + fc_msg->ethertype, + fc_msg->proto, + &fc_msg->src_saddr, + &fc_msg->dst_saddr, + fc_msg->sport, + fc_msg->dport, + fc_msg->smac, + fc_msg->dmac); + } + + spin_lock_bh(&sfe_connections_lock); + conn = fast_classifier_sb_find_conn((sfe_ip_addr_t *)&fc_msg->src_saddr, + (sfe_ip_addr_t *)&fc_msg->dst_saddr, + fc_msg->sport, + fc_msg->dport, + fc_msg->proto, + (fc_msg->ethertype == AF_INET)); + if (!conn) { + spin_unlock_bh(&sfe_connections_lock); + DEBUG_TRACE("REQUEST OFFLOAD NO MATCH\n"); + atomic_inc(&offload_no_match_msgs); + return 0; + } + + conn->offload_permit = 1; + spin_unlock_bh(&sfe_connections_lock); + atomic_inc(&offload_msgs); + + DEBUG_TRACE("INFO: calling sfe rule creation!\n"); + return 0; +} + +/* + * fast_classifier_nl_genl_msg_DUMP() + * ignore fast_classifier_messages OFFLOADED and DONE + */ +static int fast_classifier_nl_genl_msg_DUMP(struct sk_buff *skb, + struct netlink_callback *cb) +{ + return 0; +} + +/* auto offload connection once we have this many packets*/ +static int offload_at_pkts = 128; + +/* + * fast_classifier_post_routing() + * Called for packets about to leave the box - either locally generated or forwarded from another interface + */ +static unsigned int fast_classifier_post_routing(struct sk_buff *skb, bool is_v4) +{ + int ret; + struct sfe_connection_create sic; + struct sfe_connection_create *p_sic; + struct net_device *in; + struct nf_conn *ct; + enum ip_conntrack_info ctinfo; + struct net_device *dev; + struct net_device *src_dev; + struct net_device *dest_dev; + struct net_device *src_dev_tmp; + struct net_device *dest_dev_tmp; + struct net_device *src_br_dev = NULL; + struct net_device *dest_br_dev = NULL; + struct nf_conntrack_tuple orig_tuple; + struct nf_conntrack_tuple reply_tuple; + struct sfe_connection *conn; + struct sk_buff *tmp_skb = NULL; + + /* + * Don't process broadcast or multicast packets. + */ + if (unlikely(skb->pkt_type == PACKET_BROADCAST)) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_PACKET_BROADCAST); + DEBUG_TRACE("broadcast, ignoring\n"); + return NF_ACCEPT; + } + if (unlikely(skb->pkt_type == PACKET_MULTICAST)) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_PACKET_MULTICAST); + DEBUG_TRACE("multicast, ignoring\n"); + return NF_ACCEPT; + } + + /* + * Don't process packets that are not being forwarded. + */ + in = dev_get_by_index(&init_net, skb->skb_iif); + if (!in) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_NO_IIF); + DEBUG_TRACE("packet not forwarding\n"); + return NF_ACCEPT; + } + + dev_put(in); + + /* + * Don't process packets that aren't being tracked by conntrack. + */ + ct = nf_ct_get(skb, &ctinfo); + if (unlikely(!ct)) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_NO_CT); + DEBUG_TRACE("no conntrack connection, ignoring\n"); + return NF_ACCEPT; + } + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) + /* + * Don't process untracked connections. + */ + if (unlikely(nf_ct_is_untracked(ct))) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_CT_NO_TRACK); + DEBUG_TRACE("untracked connection\n"); + return NF_ACCEPT; + } +#endif /*KERNEL_VERSION(4, 12, 0)*/ + + /* + * Unconfirmed connection may be dropped by Linux at the final step, + * So we don't process unconfirmed connections. + */ + if (!nf_ct_is_confirmed(ct)) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_CT_NO_CONFIRM); + DEBUG_TRACE("unconfirmed connection\n"); + return NF_ACCEPT; + } + + /* + * Don't process connections that require support from a 'helper' (typically a NAT ALG). + */ + if (unlikely(nfct_help(ct))) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_CT_IS_ALG); + DEBUG_TRACE("connection has helper\n"); + return NF_ACCEPT; + } + + memset(&sic, 0, sizeof(sic)); + + /* + * Look up the details of our connection in conntrack. + * + * Note that the data we get from conntrack is for the "ORIGINAL" direction + * but our packet may actually be in the "REPLY" direction. + */ + orig_tuple = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; + reply_tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple; + sic.protocol = (s32)orig_tuple.dst.protonum; + + sic.flags = 0; + + /* + * Get addressing information, non-NAT first + */ + if (likely(is_v4)) { + u32 dscp; + + sic.src_ip.ip = (__be32)orig_tuple.src.u3.ip; + sic.dest_ip.ip = (__be32)orig_tuple.dst.u3.ip; + + if (ipv4_is_multicast(sic.src_ip.ip) || ipv4_is_multicast(sic.dest_ip.ip)) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_IS_IPV4_MCAST); + DEBUG_TRACE("multicast address\n"); + return NF_ACCEPT; + } + + /* + * NAT'ed addresses - note these are as seen from the 'reply' direction + * When NAT does not apply to this connection these will be identical to the above. + */ + sic.src_ip_xlate.ip = (__be32)reply_tuple.dst.u3.ip; + sic.dest_ip_xlate.ip = (__be32)reply_tuple.src.u3.ip; + + dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT; + if (dscp) { + sic.dest_dscp = dscp; + sic.src_dscp = sic.dest_dscp; + sic.flags |= SFE_CREATE_FLAG_REMARK_DSCP; + } + } else { + u32 dscp; + + sic.src_ip.ip6[0] = *((struct sfe_ipv6_addr *)&orig_tuple.src.u3.in6); + sic.dest_ip.ip6[0] = *((struct sfe_ipv6_addr *)&orig_tuple.dst.u3.in6); + + if (ipv6_addr_is_multicast((struct in6_addr *)sic.src_ip.ip6) || + ipv6_addr_is_multicast((struct in6_addr *)sic.dest_ip.ip6)) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_IS_IPV6_MCAST); + DEBUG_TRACE("multicast address\n"); + return NF_ACCEPT; + } + + /* + * NAT'ed addresses - note these are as seen from the 'reply' direction + * When NAT does not apply to this connection these will be identical to the above. + */ + sic.src_ip_xlate.ip6[0] = *((struct sfe_ipv6_addr *)&reply_tuple.dst.u3.in6); + sic.dest_ip_xlate.ip6[0] = *((struct sfe_ipv6_addr *)&reply_tuple.src.u3.in6); + + dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT; + if (dscp) { + sic.dest_dscp = dscp; + sic.src_dscp = sic.dest_dscp; + sic.flags |= SFE_CREATE_FLAG_REMARK_DSCP; + } + } + + switch (sic.protocol) { + case IPPROTO_TCP: + sic.src_port = orig_tuple.src.u.tcp.port; + sic.dest_port = orig_tuple.dst.u.tcp.port; + sic.src_port_xlate = reply_tuple.dst.u.tcp.port; + sic.dest_port_xlate = reply_tuple.src.u.tcp.port; + + /* + * Don't try to manage a non-established connection. + */ + if (!test_bit(IPS_ASSURED_BIT, &ct->status)) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_TCP_NOT_ASSURED); + DEBUG_TRACE("non-established connection\n"); + return NF_ACCEPT; + } + + break; + + case IPPROTO_UDP: + sic.src_port = orig_tuple.src.u.udp.port; + sic.dest_port = orig_tuple.dst.u.udp.port; + sic.src_port_xlate = reply_tuple.dst.u.udp.port; + sic.dest_port_xlate = reply_tuple.src.u.udp.port; + + /* + * Somehow, SFE is not playing nice with IPSec traffic. + * Do not accelerate for now. + */ + if (ntohs(sic.dest_port) == 4500 || ntohs(sic.dest_port) == 500) { + if (likely(is_v4)) + DEBUG_TRACE("quarkysg:: IPsec bypass: %pI4:%d(%pI4:%d) to %pI4:%d(%pI4:%d)\n", + &sic.src_ip.ip, ntohs(sic.src_port), &sic.src_ip_xlate.ip, ntohs(sic.src_port_xlate), + &sic.dest_ip.ip, ntohs(sic.dest_port), &sic.dest_ip_xlate.ip, ntohs(sic.dest_port_xlate)); + else + DEBUG_TRACE("quarkysg:: IPsec bypass: %pI6:%d to %pI6:%d\n", + &sic.src_ip.ip6, ntohs(sic.src_port), &sic.dest_ip.ip6, ntohs(sic.dest_port)); + return NF_ACCEPT; + } + break; + + default: + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_UNKNOW_PROTOCOL); + DEBUG_TRACE("unhandled protocol %d\n", sic.protocol); + return NF_ACCEPT; + } + +#ifdef CONFIG_XFRM + sic.original_accel = 1; + sic.reply_accel = 1; +#endif + + /* + * Get QoS information + */ + if (skb->priority) { + sic.dest_priority = skb->priority; + sic.src_priority = sic.dest_priority; + sic.flags |= SFE_CREATE_FLAG_REMARK_PRIORITY; + } + + if (is_v4) { + DEBUG_TRACE("POST_ROUTE: checking new connection: %d src_ip: %pI4 dst_ip: %pI4, src_port: %d, dst_port: %d\n", + sic.protocol, &sic.src_ip, &sic.dest_ip, sic.src_port, sic.dest_port); + } else { + DEBUG_TRACE("POST_ROUTE: checking new connection: %d src_ip: %pI6 dst_ip: %pI6, src_port: %d, dst_port: %d\n", + sic.protocol, &sic.src_ip, &sic.dest_ip, sic.src_port, sic.dest_port); + } + + /* + * If we already have this connection in our list, skip it + * XXX: this may need to be optimized + */ + spin_lock_bh(&sfe_connections_lock); + + conn = fast_classifier_find_conn(&sic.src_ip, &sic.dest_ip, sic.src_port, sic.dest_port, sic.protocol, is_v4); + if (conn) { + conn->hits++; + + if (!conn->offloaded) { + if (conn->offload_permit || conn->hits >= offload_at_pkts) { + DEBUG_TRACE("OFFLOADING CONNECTION, TOO MANY HITS\n"); + + if (fast_classifier_update_protocol(conn->sic, conn->ct) == 0) { + spin_unlock_bh(&sfe_connections_lock); + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_UPDATE_PROTOCOL_FAIL); + DEBUG_TRACE("UNKNOWN PROTOCOL OR CONNECTION CLOSING, SKIPPING\n"); + return NF_ACCEPT; + } + + DEBUG_TRACE("INFO: calling sfe rule creation!\n"); + spin_unlock_bh(&sfe_connections_lock); + + ret = is_v4 ? sfe_ipv4_create_rule(conn->sic) : sfe_ipv6_create_rule(conn->sic); + if ((ret == 0) || (ret == -EADDRINUSE)) { + struct fast_classifier_tuple fc_msg; + + if (is_v4) { + fc_msg.ethertype = AF_INET; + fc_msg.src_saddr.in = *((struct in_addr *)&sic.src_ip); + fc_msg.dst_saddr.in = *((struct in_addr *)&sic.dest_ip_xlate); + } else { + fc_msg.ethertype = AF_INET6; + fc_msg.src_saddr.in6 = *((struct in6_addr *)&sic.src_ip); + fc_msg.dst_saddr.in6 = *((struct in6_addr *)&sic.dest_ip_xlate); + } + + fc_msg.proto = sic.protocol; + fc_msg.sport = sic.src_port; + fc_msg.dport = sic.dest_port_xlate; + memcpy(fc_msg.smac, conn->smac, ETH_ALEN); + memcpy(fc_msg.dmac, conn->dmac, ETH_ALEN); + fast_classifier_send_genl_msg(FAST_CLASSIFIER_C_OFFLOADED, &fc_msg); + conn->offloaded = 1; + } + + return NF_ACCEPT; + } + } + + spin_unlock_bh(&sfe_connections_lock); + if (conn->offloaded) { + is_v4 ? sfe_ipv4_update_rule(conn->sic) : sfe_ipv6_update_rule(conn->sic); + } + + DEBUG_TRACE("FOUND, SKIPPING\n"); + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_WAIT_FOR_ACCELERATION); + return NF_ACCEPT; + } + + spin_unlock_bh(&sfe_connections_lock); + + /* + * Get the net device and MAC addresses that correspond to the various source and + * destination host addresses. + */ + if (!fast_classifier_find_dev_and_mac_addr(NULL, &sic.src_ip, &src_dev_tmp, sic.src_mac, is_v4)) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_NO_SRC_DEV); + return NF_ACCEPT; + } + src_dev = src_dev_tmp; + + if (!fast_classifier_find_dev_and_mac_addr(NULL, &sic.src_ip_xlate, &dev, sic.src_mac_xlate, is_v4)) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_NO_SRC_XLATE_DEV); + goto done1; + } + dev_put(dev); + + if (unlikely(!is_v4)) + tmp_skb = skb; + + if (!fast_classifier_find_dev_and_mac_addr(tmp_skb, &sic.dest_ip, &dev, sic.dest_mac, is_v4)) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_NO_DEST_DEV); + goto done1; + } + dev_put(dev); + + if (!fast_classifier_find_dev_and_mac_addr(skb, &sic.dest_ip_xlate, &dest_dev_tmp, sic.dest_mac_xlate, is_v4)) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_NO_DEST_XLATE_DEV); + goto done1; + } + dest_dev = dest_dev_tmp; + + /* + * Our devices may actually be part of a bridge interface. If that's + * the case then find the bridge interface instead. + */ + if (src_dev->priv_flags & IFF_BRIDGE_PORT) { + src_br_dev = sfe_dev_get_master(src_dev); + if (!src_br_dev) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_NO_BRIDGE); + DEBUG_TRACE("no bridge found for: %s\n", src_dev->name); + goto done2; + } + src_dev = src_br_dev; + } + + if (dest_dev->priv_flags & IFF_BRIDGE_PORT) { + dest_br_dev = sfe_dev_get_master(dest_dev); + if (!dest_br_dev) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_NO_BRIDGE); + DEBUG_TRACE("no bridge found for: %s\n", dest_dev->name); + goto done3; + } + dest_dev = dest_br_dev; + } + + sic.src_dev = src_dev; + sic.dest_dev = dest_dev; + + sic.src_mtu = src_dev->mtu; + sic.dest_mtu = dest_dev->mtu; + + if (skb->mark) { + DEBUG_TRACE("SKB MARK NON ZERO %x\n", skb->mark); + } + sic.mark = skb->mark; + + conn = kmalloc(sizeof(*conn), GFP_ATOMIC); + if (!conn) { + printk(KERN_CRIT "ERROR: no memory for sfe\n"); + goto done4; + } + conn->hits = 0; + conn->offload_permit = 0; + conn->offloaded = 0; + conn->is_v4 = is_v4; + DEBUG_TRACE("Source MAC=%pM\n", sic.src_mac); + memcpy(conn->smac, sic.src_mac, ETH_ALEN); + memcpy(conn->dmac, sic.dest_mac_xlate, ETH_ALEN); + + p_sic = kmalloc(sizeof(*p_sic), GFP_ATOMIC); + if (!p_sic) { + printk(KERN_CRIT "ERROR: no memory for sfe\n"); + kfree(conn); + goto done4; + } + + memcpy(p_sic, &sic, sizeof(sic)); + conn->sic = p_sic; + conn->ct = ct; + + if (!fast_classifier_add_conn(conn)) { + kfree(conn->sic); + kfree(conn); + } + + /* + * If we had bridge ports then release them too. + */ +done4: + if (dest_br_dev) { + dev_put(dest_br_dev); + } +done3: + if (src_br_dev) { + dev_put(src_br_dev); + } +done2: + dev_put(dest_dev_tmp); +done1: + dev_put(src_dev_tmp); + + return NF_ACCEPT; +} + +/* + * fast_classifier_ipv4_post_routing_hook() + * Called for packets about to leave the box - either locally generated or forwarded from another interface + */ +fast_classifier_ipv4_post_routing_hook(hooknum, ops, skb, in_unused, out, okfn) +{ + return fast_classifier_post_routing(skb, true); +} + +/* + * fast_classifier_ipv6_post_routing_hook() + * Called for packets about to leave the box - either locally generated or forwarded from another interface + */ +fast_classifier_ipv6_post_routing_hook(hooknum, ops, skb, in_unused, out, okfn) +{ + return fast_classifier_post_routing(skb, false); +} + +/* + * fast_classifier_update_mark() + * updates the mark for a fast-classifier connection + */ +static void fast_classifier_update_mark(struct sfe_connection_mark *mark, bool is_v4) +{ + struct sfe_connection *conn; + + spin_lock_bh(&sfe_connections_lock); + + conn = fast_classifier_find_conn(&mark->src_ip, &mark->dest_ip, + mark->src_port, mark->dest_port, + mark->protocol, is_v4); + if (conn) { + conn->sic->mark = mark->mark; + } + + spin_unlock_bh(&sfe_connections_lock); +} + +#ifdef CONFIG_NF_CONNTRACK_EVENTS +/* + * fast_classifier_conntrack_event() + * Callback event invoked when a conntrack connection's state changes. + */ +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS +static int fast_classifier_conntrack_event(struct notifier_block *this, + unsigned long events, void *ptr) +#else +static int fast_classifier_conntrack_event(unsigned int events, struct nf_ct_event *item) +#endif +{ +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS + struct nf_ct_event *item = ptr; +#endif + struct sfe_connection_destroy sid; + struct nf_conn *ct = item->ct; + struct nf_conntrack_tuple orig_tuple; + struct sfe_connection *conn; + struct fast_classifier_tuple fc_msg; + int offloaded = 0; + bool is_v4; + + /* + * If we don't have a conntrack entry then we're done. + */ + if (unlikely(!ct)) { + DEBUG_WARN("no ct in conntrack event callback\n"); + return NOTIFY_DONE; + } + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) + /* + * If this is an untracked connection then we can't have any state either. + */ + if (unlikely(nf_ct_is_untracked(ct))) { + DEBUG_TRACE("ignoring untracked conn\n"); + return NOTIFY_DONE; + } +#endif /*KERNEL_VERSION(4, 12, 0)*/ + + orig_tuple = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; + sid.protocol = (s32)orig_tuple.dst.protonum; + + /* + * Extract information from the conntrack connection. We're only interested + * in nominal connection information (i.e. we're ignoring any NAT information). + */ + if (likely(nf_ct_l3num(ct) == AF_INET)) { + sid.src_ip.ip = (__be32)orig_tuple.src.u3.ip; + sid.dest_ip.ip = (__be32)orig_tuple.dst.u3.ip; + is_v4 = true; + } else if (likely(nf_ct_l3num(ct) == AF_INET6)) { + sid.src_ip.ip6[0] = *((struct sfe_ipv6_addr *)&orig_tuple.src.u3.in6); + sid.dest_ip.ip6[0] = *((struct sfe_ipv6_addr *)&orig_tuple.dst.u3.in6); + is_v4 = false; + } else { + DEBUG_TRACE("ignoring non-IPv4 and non-IPv6 connection\n"); + return NOTIFY_DONE; + } + + switch (sid.protocol) { + case IPPROTO_TCP: + sid.src_port = orig_tuple.src.u.tcp.port; + sid.dest_port = orig_tuple.dst.u.tcp.port; + break; + + case IPPROTO_UDP: + sid.src_port = orig_tuple.src.u.udp.port; + sid.dest_port = orig_tuple.dst.u.udp.port; + break; + + default: + DEBUG_TRACE("unhandled protocol: %d\n", sid.protocol); + return NOTIFY_DONE; + } + + /* + * Check for an updated mark + */ + if ((events & (1 << IPCT_MARK)) && (ct->mark != 0)) { + struct sfe_connection_mark mark; + + mark.protocol = sid.protocol; + mark.src_ip = sid.src_ip; + mark.dest_ip = sid.dest_ip; + mark.src_port = sid.src_port; + mark.dest_port = sid.dest_port; + mark.mark = ct->mark; + + is_v4 ? sfe_ipv4_mark_rule(&mark) : sfe_ipv6_mark_rule(&mark); + fast_classifier_update_mark(&mark, is_v4); + } + + /* + * We're only interested in destroy events at this point + */ + if (unlikely(!(events & (1 << IPCT_DESTROY)))) { + DEBUG_TRACE("ignoring non-destroy event\n"); + return NOTIFY_DONE; + } + + if (is_v4) { + DEBUG_TRACE("Try to clean up: proto: %d src_ip: %pI4 dst_ip: %pI4, src_port: %d, dst_port: %d\n", + sid.protocol, &sid.src_ip, &sid.dest_ip, ntohs(sid.src_port), ntohs(sid.dest_port)); + } else { + DEBUG_TRACE("Try to clean up: proto: %d src_ip: %pI6 dst_ip: %pI6, src_port: %d, dst_port: %d\n", + sid.protocol, &sid.src_ip, &sid.dest_ip, ntohs(sid.src_port), ntohs(sid.dest_port)); + } + + spin_lock_bh(&sfe_connections_lock); + + conn = fast_classifier_find_conn(&sid.src_ip, &sid.dest_ip, sid.src_port, sid.dest_port, sid.protocol, is_v4); + if (conn && conn->offloaded) { + if (is_v4) { + fc_msg.ethertype = AF_INET; + fc_msg.src_saddr.in = *((struct in_addr *)&conn->sic->src_ip); + fc_msg.dst_saddr.in = *((struct in_addr *)&conn->sic->dest_ip_xlate); + } else { + fc_msg.ethertype = AF_INET6; + fc_msg.src_saddr.in6 = *((struct in6_addr *)&conn->sic->src_ip); + fc_msg.dst_saddr.in6 = *((struct in6_addr *)&conn->sic->dest_ip_xlate); + } + + fc_msg.proto = conn->sic->protocol; + fc_msg.sport = conn->sic->src_port; + fc_msg.dport = conn->sic->dest_port_xlate; + memcpy(fc_msg.smac, conn->smac, ETH_ALEN); + memcpy(fc_msg.dmac, conn->dmac, ETH_ALEN); + offloaded = 1; + } + + if (conn) { + DEBUG_TRACE("Free connection\n"); + + hash_del(&conn->hl); + sfe_connections_size--; + kfree(conn->sic); + kfree(conn); + } else { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_CT_DESTROY_MISS); + } + + spin_unlock_bh(&sfe_connections_lock); + + is_v4 ? sfe_ipv4_destroy_rule(&sid) : sfe_ipv6_destroy_rule(&sid); + + if (offloaded) { + fast_classifier_send_genl_msg(FAST_CLASSIFIER_C_DONE, &fc_msg); + } + + return NOTIFY_DONE; +} + +/* + * Netfilter conntrack event system to monitor connection tracking changes + */ +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS +static struct notifier_block fast_classifier_conntrack_notifier = { + .notifier_call = fast_classifier_conntrack_event, +}; +#else +static struct nf_ct_event_notifier fast_classifier_conntrack_notifier = { + .fcn = fast_classifier_conntrack_event, +}; +#endif +#endif + +/* + * Structure to establish a hook into the post routing netfilter point - this + * will pick up local outbound and packets going from one interface to another. + * + * Note: see include/linux/netfilter_ipv4.h for info related to priority levels. + * We want to examine packets after NAT translation and any ALG processing. + */ +static struct nf_hook_ops fast_classifier_ops_post_routing[] __read_mostly = { + SFE_IPV4_NF_POST_ROUTING_HOOK(__fast_classifier_ipv4_post_routing_hook), + SFE_IPV6_NF_POST_ROUTING_HOOK(__fast_classifier_ipv6_post_routing_hook), +}; + +/* + * fast_classifier_sync_rule() + * Synchronize a connection's state. + */ +static void fast_classifier_sync_rule(struct sfe_connection_sync *sis) +{ + struct nf_conntrack_tuple_hash *h; + struct nf_conntrack_tuple tuple; + struct nf_conn *ct; + SFE_NF_CONN_ACCT(acct); + + /* + * Create a tuple so as to be able to look up a connection + */ + memset(&tuple, 0, sizeof(tuple)); + tuple.src.u.all = (__be16)sis->src_port; + tuple.dst.dir = IP_CT_DIR_ORIGINAL; + tuple.dst.protonum = (u8)sis->protocol; + tuple.dst.u.all = (__be16)sis->dest_port; + + if (sis->is_v6) { + tuple.src.u3.in6 = *((struct in6_addr *)sis->src_ip.ip6); + tuple.dst.u3.in6 = *((struct in6_addr *)sis->dest_ip.ip6); + tuple.src.l3num = AF_INET6; + + DEBUG_TRACE("update connection - p: %d, s: %pI6:%u, d: %pI6:%u\n", + (int)tuple.dst.protonum, + &tuple.src.u3.in6, (unsigned int)ntohs(tuple.src.u.all), + &tuple.dst.u3.in6, (unsigned int)ntohs(tuple.dst.u.all)); + } else { + tuple.src.u3.ip = sis->src_ip.ip; + tuple.dst.u3.ip = sis->dest_ip.ip; + tuple.src.l3num = AF_INET; + + DEBUG_TRACE("update connection - p: %d, s: %pI4:%u, d: %pI4:%u\n", + (int)tuple.dst.protonum, + &tuple.src.u3.ip, (unsigned int)ntohs(tuple.src.u.all), + &tuple.dst.u3.ip, (unsigned int)ntohs(tuple.dst.u.all)); + } + + /* + * Update packet count for ingress on bridge device + */ + if (skip_to_bridge_ingress) { + struct rtnl_link_stats64 nlstats; + nlstats.tx_packets = 0; + nlstats.tx_bytes = 0; + + if (sis->src_dev && IFF_EBRIDGE && + (sis->src_new_packet_count || sis->src_new_byte_count)) { + nlstats.rx_packets = sis->src_new_packet_count; + nlstats.rx_bytes = sis->src_new_byte_count; + spin_lock_bh(&sfe_connections_lock); + br_dev_update_stats(sis->src_dev, &nlstats); + spin_unlock_bh(&sfe_connections_lock); + } + if (sis->dest_dev && IFF_EBRIDGE && + (sis->dest_new_packet_count || sis->dest_new_byte_count)) { + nlstats.rx_packets = sis->dest_new_packet_count; + nlstats.rx_bytes = sis->dest_new_byte_count; + spin_lock_bh(&sfe_connections_lock); + br_dev_update_stats(sis->dest_dev, &nlstats); + spin_unlock_bh(&sfe_connections_lock); + } + } + + /* + * Look up conntrack connection + */ + h = nf_conntrack_find_get(&init_net, SFE_NF_CT_DEFAULT_ZONE, &tuple); + if (unlikely(!h)) { + DEBUG_TRACE("no connection found\n"); + return; + } + + ct = nf_ct_tuplehash_to_ctrack(h); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)) + NF_CT_ASSERT(ct->timeout.data == (unsigned long)ct); +#endif /*KERNEL_VERSION(4, 9, 0)*/ + + /* + * Only update if this is not a fixed timeout + */ + if (!test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) { + spin_lock_bh(&ct->lock); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) + ct->timeout += sis->delta_jiffies; +#else + ct->timeout.expires += sis->delta_jiffies; +#endif /*KERNEL_VERSION(4, 9, 0)*/ + spin_unlock_bh(&ct->lock); + } + + acct = nf_conn_acct_find(ct); + if (acct) { + spin_lock_bh(&ct->lock); + atomic64_add(sis->src_new_packet_count, &SFE_ACCT_COUNTER(acct)[IP_CT_DIR_ORIGINAL].packets); + atomic64_add(sis->src_new_byte_count, &SFE_ACCT_COUNTER(acct)[IP_CT_DIR_ORIGINAL].bytes); + atomic64_add(sis->dest_new_packet_count, &SFE_ACCT_COUNTER(acct)[IP_CT_DIR_REPLY].packets); + atomic64_add(sis->dest_new_byte_count, &SFE_ACCT_COUNTER(acct)[IP_CT_DIR_REPLY].bytes); + spin_unlock_bh(&ct->lock); + } + + switch (sis->protocol) { + case IPPROTO_TCP: + spin_lock_bh(&ct->lock); + if (ct->proto.tcp.seen[0].td_maxwin < sis->src_td_max_window) { + ct->proto.tcp.seen[0].td_maxwin = sis->src_td_max_window; + } + if ((s32)(ct->proto.tcp.seen[0].td_end - sis->src_td_end) < 0) { + ct->proto.tcp.seen[0].td_end = sis->src_td_end; + } + if ((s32)(ct->proto.tcp.seen[0].td_maxend - sis->src_td_max_end) < 0) { + ct->proto.tcp.seen[0].td_maxend = sis->src_td_max_end; + } + if (ct->proto.tcp.seen[1].td_maxwin < sis->dest_td_max_window) { + ct->proto.tcp.seen[1].td_maxwin = sis->dest_td_max_window; + } + if ((s32)(ct->proto.tcp.seen[1].td_end - sis->dest_td_end) < 0) { + ct->proto.tcp.seen[1].td_end = sis->dest_td_end; + } + if ((s32)(ct->proto.tcp.seen[1].td_maxend - sis->dest_td_max_end) < 0) { + ct->proto.tcp.seen[1].td_maxend = sis->dest_td_max_end; + } + spin_unlock_bh(&ct->lock); + break; + } + + /* + * Release connection + */ + nf_ct_put(ct); +} + +/* + * fast_classifier_device_event() + */ +static int fast_classifier_device_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct net_device *dev = SFE_DEV_EVENT_PTR(ptr); + + if (dev && (event == NETDEV_DOWN)) { + sfe_ipv4_destroy_all_rules_for_dev(dev); + sfe_ipv6_destroy_all_rules_for_dev(dev); + } + + return NOTIFY_DONE; +} + +/* + * fast_classifier_inet_event() + */ +static int fast_classifier_inet_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev; + + if (dev && (event == NETDEV_DOWN)) { + sfe_ipv4_destroy_all_rules_for_dev(dev); + } + + return NOTIFY_DONE; +} + +/* + * fast_classifier_inet6_event() + */ +static int fast_classifier_inet6_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct net_device *dev = ((struct inet6_ifaddr *)ptr)->idev->dev; + + if (dev && (event == NETDEV_DOWN)) { + sfe_ipv6_destroy_all_rules_for_dev(dev); + } + + return NOTIFY_DONE; +} + +/* + * fast_classifier_get_offload_at_pkts() + */ +static ssize_t fast_classifier_get_offload_at_pkts(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, (ssize_t)PAGE_SIZE, "%d\n", offload_at_pkts); +} + +/* + * fast_classifier_set_offload_at_pkts() + */ +static ssize_t fast_classifier_set_offload_at_pkts(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + long new; + int ret; + + ret = kstrtol(buf, 0, &new); + if (ret == -EINVAL || ((int)new != new)) + return -EINVAL; + + offload_at_pkts = new; + + return size; +} + +/* + * fast_classifier_get_debug_info() + */ +static ssize_t fast_classifier_get_debug_info(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + size_t len = 0; + struct sfe_connection *conn; + u32 i; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)) + struct hlist_node *node; +#endif + + spin_lock_bh(&sfe_connections_lock); + len += scnprintf(buf, PAGE_SIZE - len, "size=%d offload=%d offload_no_match=%d" + " offloaded=%d done=%d offloaded_fail=%d done_fail=%d\n", + sfe_connections_size, + atomic_read(&offload_msgs), + atomic_read(&offload_no_match_msgs), + atomic_read(&offloaded_msgs), + atomic_read(&done_msgs), + atomic_read(&offloaded_fail_msgs), + atomic_read(&done_fail_msgs)); + sfe_hash_for_each(fc_conn_ht, i, node, conn, hl) { + len += scnprintf(buf + len, PAGE_SIZE - len, + (conn->is_v4 ? "o=%d, p=%d [%pM]:%pI4:%u %pI4:%u:[%pM] m=%08x h=%d\n" : "o=%d, p=%d [%pM]:%pI6:%u %pI6:%u:[%pM] m=%08x h=%d\n"), + conn->offloaded, + conn->sic->protocol, + conn->sic->src_mac, + &conn->sic->src_ip, + ntohs(conn->sic->src_port), + &conn->sic->dest_ip, + ntohs(conn->sic->dest_port), + conn->sic->dest_mac_xlate, + conn->sic->mark, + conn->hits); + } + spin_unlock_bh(&sfe_connections_lock); + + return len; +} + +/* + * fast_classifier_get_skip_bridge_ingress() + */ +static ssize_t fast_classifier_get_skip_bridge_ingress(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, (ssize_t)PAGE_SIZE, "%d\n", skip_to_bridge_ingress); +} + +/* + * fast_classifier_set_skip_bridge_ingress() + */ +static ssize_t fast_classifier_set_skip_bridge_ingress(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + long new; + int ret; + + ret = kstrtol(buf, 0, &new); + if (ret == -EINVAL || ((int)new != new)) + return -EINVAL; + + skip_to_bridge_ingress = new ? 1 : 0; + + return size; +} + +/* + * fast_classifier_get_exceptions + * dump exception counters + */ +static ssize_t fast_classifier_get_exceptions(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int idx, len; + struct fast_classifier *sc = &__sc; + + spin_lock_bh(&sc->lock); + for (len = 0, idx = 0; idx < FAST_CL_EXCEPTION_MAX; idx++) { + if (sc->exceptions[idx]) { + len += snprintf(buf + len, (ssize_t)(PAGE_SIZE - len), "%s = %d\n", fast_classifier_exception_events_string[idx], sc->exceptions[idx]); + } + } + spin_unlock_bh(&sc->lock); + + return len; +} + +/* + * sysfs attributes. + */ +static const struct device_attribute fast_classifier_offload_at_pkts_attr = + __ATTR(offload_at_pkts, S_IWUSR | S_IRUGO, fast_classifier_get_offload_at_pkts, fast_classifier_set_offload_at_pkts); +static const struct device_attribute fast_classifier_debug_info_attr = + __ATTR(debug_info, S_IRUGO, fast_classifier_get_debug_info, NULL); +static const struct device_attribute fast_classifier_skip_bridge_ingress = + __ATTR(skip_to_bridge_ingress, S_IWUSR | S_IRUGO, fast_classifier_get_skip_bridge_ingress, fast_classifier_set_skip_bridge_ingress); +static const struct device_attribute fast_classifier_exceptions_attr = + __ATTR(exceptions, S_IRUGO, fast_classifier_get_exceptions, NULL); + +/* + * fast_classifier_init() + */ +static int __init fast_classifier_init(void) +{ + struct fast_classifier *sc = &__sc; + int result = -1; +#ifdef CONFIG_SFE_ECM + int (*fast_recv)(struct sk_buff *skb); +#endif + + printk(KERN_ALERT "fast-classifier: starting up\n"); + DEBUG_INFO("SFE CM init\n"); + + hash_init(fc_conn_ht); + + /* + * Create sys/fast_classifier + */ + sc->sys_fast_classifier = kobject_create_and_add("fast_classifier", NULL); + if (!sc->sys_fast_classifier) { + DEBUG_ERROR("failed to register fast_classifier\n"); + goto exit1; + } + + result = sysfs_create_file(sc->sys_fast_classifier, &fast_classifier_offload_at_pkts_attr.attr); + if (result) { + DEBUG_ERROR("failed to register offload at pkgs: %d\n", result); + goto exit2; + } + + result = sysfs_create_file(sc->sys_fast_classifier, &fast_classifier_debug_info_attr.attr); + if (result) { + DEBUG_ERROR("failed to register debug dev: %d\n", result); + sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_offload_at_pkts_attr.attr); + goto exit2; + } + + result = sysfs_create_file(sc->sys_fast_classifier, &fast_classifier_skip_bridge_ingress.attr); + if (result) { + DEBUG_ERROR("failed to register skip bridge on ingress: %d\n", result); + sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_offload_at_pkts_attr.attr); + sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_debug_info_attr.attr); + goto exit2; + } + + result = sysfs_create_file(sc->sys_fast_classifier, &fast_classifier_exceptions_attr.attr); + if (result) { + DEBUG_ERROR("failed to register exceptions file: %d\n", result); + sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_offload_at_pkts_attr.attr); + sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_debug_info_attr.attr); + sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_skip_bridge_ingress.attr); + goto exit2; + } + + sc->dev_notifier.notifier_call = fast_classifier_device_event; + sc->dev_notifier.priority = 1; + register_netdevice_notifier(&sc->dev_notifier); + + sc->inet_notifier.notifier_call = fast_classifier_inet_event; + sc->inet_notifier.priority = 1; + register_inetaddr_notifier(&sc->inet_notifier); + + sc->inet6_notifier.notifier_call = fast_classifier_inet6_event; + sc->inet6_notifier.priority = 1; + register_inet6addr_notifier(&sc->inet6_notifier); + + /* + * Register our netfilter hooks. + */ + result = nf_register_net_hooks(&init_net, fast_classifier_ops_post_routing, ARRAY_SIZE(fast_classifier_ops_post_routing)); + if (result < 0) { + DEBUG_ERROR("can't register nf post routing hook: %d\n", result); + goto exit3; + } + +#ifdef CONFIG_NF_CONNTRACK_EVENTS + /* + * Register a notifier hook to get fast notifications of expired connections. + */ +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS + result = nf_conntrack_register_chain_notifier(&init_net, &fast_classifier_conntrack_notifier); +#else + result = nf_conntrack_register_notifier(&init_net, &fast_classifier_conntrack_notifier); +#endif + if (result < 0) { + DEBUG_ERROR("can't register nf notifier hook: %d\n", result); + goto exit4; + } +#endif + + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) + result = genl_register_family(&fast_classifier_gnl_family); + if (result) { + DEBUG_ERROR("failed to register genl family: %d\n", result); + goto exit5; + } +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) + result = genl_register_family_with_ops_groups(&fast_classifier_gnl_family, + fast_classifier_gnl_ops, + fast_classifier_genl_mcgrp); + if (result) { + DEBUG_ERROR("failed to register genl ops: %d\n", result); + goto exit5; + } +#else + result = genl_register_family(&fast_classifier_gnl_family); + if (result) { + printk(KERN_CRIT "unable to register genl family\n"); + goto exit5; + } + + result = genl_register_ops(&fast_classifier_gnl_family, fast_classifier_gnl_ops); + if (result) { + printk(KERN_CRIT "unable to register ops\n"); + goto exit6; + } + + result = genl_register_mc_group(&fast_classifier_gnl_family, + fast_classifier_genl_mcgrp); + if (result) { + printk(KERN_CRIT "unable to register multicast group\n"); + goto exit6; + } +#endif + + printk(KERN_ALERT "fast-classifier: registered\n"); + + spin_lock_init(&sc->lock); + + /* + * Hook the receive path in the network stack. + */ +#ifdef CONFIG_SFE_ECM + rcu_read_lock(); + fast_recv = rcu_dereference(athrs_fast_nat_recv); + rcu_read_unlock(); + if (!fast_recv) { + BUG_ON(athrs_fast_nat_recv); + } +#else + BUG_ON(athrs_fast_nat_recv); +#endif + RCU_INIT_POINTER(athrs_fast_nat_recv, fast_classifier_recv); + + /* + * Hook the shortcut sync callback. + */ + sfe_ipv4_register_sync_rule_callback(fast_classifier_sync_rule); + sfe_ipv6_register_sync_rule_callback(fast_classifier_sync_rule); + return 0; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)) +exit6: + genl_unregister_family(&fast_classifier_gnl_family); +#endif + +exit5: +#ifdef CONFIG_NF_CONNTRACK_EVENTS +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS + nf_conntrack_unregister_chain_notifier(&init_net, &fast_classifier_conntrack_notifier); +#else + nf_conntrack_unregister_notifier(&init_net, &fast_classifier_conntrack_notifier); +#endif + +exit4: +#endif + nf_unregister_net_hooks(&init_net, fast_classifier_ops_post_routing, ARRAY_SIZE(fast_classifier_ops_post_routing)); + +exit3: + unregister_inetaddr_notifier(&sc->inet_notifier); + unregister_inet6addr_notifier(&sc->inet6_notifier); + unregister_netdevice_notifier(&sc->dev_notifier); + sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_offload_at_pkts_attr.attr); + sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_debug_info_attr.attr); + sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_skip_bridge_ingress.attr); + sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_exceptions_attr.attr); + +exit2: + kobject_put(sc->sys_fast_classifier); + +exit1: + return result; +} + +/* + * fast_classifier_exit() + */ +static void __exit fast_classifier_exit(void) +{ + struct fast_classifier *sc = &__sc; + int result = -1; + + DEBUG_INFO("SFE CM exit\n"); + printk(KERN_ALERT "fast-classifier: shutting down\n"); + + /* + * Unregister our sync callback. + */ + sfe_ipv4_register_sync_rule_callback(NULL); + sfe_ipv6_register_sync_rule_callback(NULL); + + /* + * Unregister our receive callback. + */ + RCU_INIT_POINTER(athrs_fast_nat_recv, NULL); + + /* + * Wait for all callbacks to complete. + */ + rcu_barrier(); + + /* + * Destroy all connections. + */ + sfe_ipv4_destroy_all_rules_for_dev(NULL); + sfe_ipv6_destroy_all_rules_for_dev(NULL); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)) + result = genl_unregister_ops(&fast_classifier_gnl_family, fast_classifier_gnl_ops); + if (result != 0) { + printk(KERN_CRIT "Unable to unreigster genl_ops\n"); + } +#endif + + result = genl_unregister_family(&fast_classifier_gnl_family); + if (result != 0) { + printk(KERN_CRIT "Unable to unregister genl_family\n"); + } + +#ifdef CONFIG_NF_CONNTRACK_EVENTS +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS + nf_conntrack_unregister_chain_notifier(&init_net, &fast_classifier_conntrack_notifier); +#else + nf_conntrack_unregister_notifier(&init_net, &fast_classifier_conntrack_notifier); +#endif +#endif + nf_unregister_net_hooks(&init_net, fast_classifier_ops_post_routing, ARRAY_SIZE(fast_classifier_ops_post_routing)); + + unregister_inet6addr_notifier(&sc->inet6_notifier); + unregister_inetaddr_notifier(&sc->inet_notifier); + unregister_netdevice_notifier(&sc->dev_notifier); + + kobject_put(sc->sys_fast_classifier); +} + +module_init(fast_classifier_init) +module_exit(fast_classifier_exit) + +MODULE_DESCRIPTION("Shortcut Forwarding Engine - Connection Manager"); +MODULE_LICENSE("Dual BSD/GPL"); + diff --git a/root/package/lean/shortcut-fe/fast-classifier/src/fast-classifier.h b/root/package/lean/shortcut-fe/fast-classifier/src/fast-classifier.h new file mode 100644 index 00000000..6b7a18cf --- /dev/null +++ b/root/package/lean/shortcut-fe/fast-classifier/src/fast-classifier.h @@ -0,0 +1,57 @@ +/* + * User space header to send message to the fast classifier + * + * Copyright (c) 2013,2016 The Linux Foundation. All rights reserved. + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#define FAST_CLASSIFIER_GENL_VERSION (1) +#define FAST_CLASSIFIER_GENL_NAME "FC" +#define FAST_CLASSIFIER_GENL_MCGRP "FC_MCGRP" +#define FAST_CLASSIFIER_GENL_HDRSIZE (0) + +enum { + FAST_CLASSIFIER_A_UNSPEC, + FAST_CLASSIFIER_A_TUPLE, + __FAST_CLASSIFIER_A_MAX, +}; + +#define FAST_CLASSIFIER_A_MAX (__FAST_CLASSIFIER_A_MAX - 1) + +enum { + FAST_CLASSIFIER_C_UNSPEC, + FAST_CLASSIFIER_C_OFFLOAD, + FAST_CLASSIFIER_C_OFFLOADED, + FAST_CLASSIFIER_C_DONE, + __FAST_CLASSIFIER_C_MAX, +}; + +#define FAST_CLASSIFIER_C_MAX (__FAST_CLASSIFIER_C_MAX - 1) + +struct fast_classifier_tuple { + unsigned short ethertype; + unsigned char proto; + union { + struct in_addr in; + struct in6_addr in6; + } src_saddr; + union { + struct in_addr in; + struct in6_addr in6; + } dst_saddr; + unsigned short sport; + unsigned short dport; + unsigned char smac[ETH_ALEN]; + unsigned char dmac[ETH_ALEN]; +}; diff --git a/root/package/lean/shortcut-fe/fast-classifier/src/nl_classifier_test.c b/root/package/lean/shortcut-fe/fast-classifier/src/nl_classifier_test.c new file mode 100644 index 00000000..63941796 --- /dev/null +++ b/root/package/lean/shortcut-fe/fast-classifier/src/nl_classifier_test.c @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include + +#define NL_CLASSIFIER_GENL_VERSION 1 +#define NL_CLASSIFIER_GENL_FAMILY "FC" +#define NL_CLASSIFIER_GENL_GROUP "FC_MCGRP" +#define NL_CLASSIFIER_GENL_HDRSIZE 0 + +enum NL_CLASSIFIER_CMD { + NL_CLASSIFIER_CMD_UNSPEC, + NL_CLASSIFIER_CMD_ACCEL, + NL_CLASSIFIER_CMD_ACCEL_OK, + NL_CLASSIFIER_CMD_CONNECTION_CLOSED, + NL_CLASSIFIER_CMD_MAX, +}; + +enum NL_CLASSIFIER_ATTR { + NL_CLASSIFIER_ATTR_UNSPEC, + NL_CLASSIFIER_ATTR_TUPLE, + NL_CLASSIFIER_ATTR_MAX, +}; + +union nl_classifier_tuple_ip { + struct in_addr in; + struct in6_addr in6; +}; + +struct nl_classifier_tuple { + unsigned short af; + unsigned char proto; + union nl_classifier_tuple_ip src_ip; + union nl_classifier_tuple_ip dst_ip; + unsigned short sport; + unsigned short dport; + unsigned char smac[6]; + unsigned char dmac[6]; +}; + +struct nl_classifier_instance { + struct nl_sock *sock; + int family_id; + int group_id; + int stop; +}; + +struct nl_classifier_instance nl_cls_inst; + +static struct nla_policy nl_classifier_genl_policy[(NL_CLASSIFIER_ATTR_MAX+1)] = { + [NL_CLASSIFIER_ATTR_TUPLE] = { .type = NLA_UNSPEC }, +}; + +void nl_classifier_dump_nl_tuple(struct nl_classifier_tuple *tuple) +{ + char ip_str[64]; + + printf("protocol = %s\n", (tuple->proto == IPPROTO_UDP) ? "udp" : ((tuple->proto == IPPROTO_TCP) ? "tcp" : "unknown")); + printf("source ip = %s\n", inet_ntop(tuple->af, &tuple->src_ip, ip_str, sizeof(ip_str))); + printf("destination ip = %s\n", inet_ntop(tuple->af, &tuple->dst_ip, ip_str, sizeof(ip_str))); + printf("source port = %d\n", ntohs(tuple->sport)); + printf("destination port = %d\n", ntohs(tuple->dport)); +} + +int nl_classifier_msg_recv(struct nl_msg *msg, void *arg) +{ + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct genlmsghdr *gnlh = nlmsg_data(nlh); + struct nlattr *attrs[(NL_CLASSIFIER_ATTR_MAX+1)]; + + genlmsg_parse(nlh, NL_CLASSIFIER_GENL_HDRSIZE, attrs, NL_CLASSIFIER_ATTR_MAX, nl_classifier_genl_policy); + + switch (gnlh->cmd) { + case NL_CLASSIFIER_CMD_ACCEL_OK: + printf("Acceleration successful:\n"); + nl_classifier_dump_nl_tuple(nla_data(attrs[NL_CLASSIFIER_ATTR_TUPLE])); + return NL_OK; + case NL_CLASSIFIER_CMD_CONNECTION_CLOSED: + printf("Connection is closed:\n"); + nl_classifier_dump_nl_tuple(nla_data(attrs[NL_CLASSIFIER_ATTR_TUPLE])); + return NL_OK; + default: + printf("nl classifier received unknow message %d\n", gnlh->cmd); + } + + return NL_SKIP; +} + +void nl_classifier_offload(struct nl_classifier_instance *inst, + unsigned char proto, unsigned long *src_saddr, + unsigned long *dst_saddr, unsigned short sport, + unsigned short dport, int af) +{ + struct nl_msg *msg; + int ret; + struct nl_classifier_tuple classifier_msg; + + memset(&classifier_msg, 0, sizeof(classifier_msg)); + classifier_msg.af = af; + classifier_msg.proto = proto; + memcpy(&classifier_msg.src_ip, src_saddr, (af == AF_INET ? 4 : 16)); + memcpy(&classifier_msg.dst_ip, dst_saddr, (af == AF_INET ? 4 : 16)); + classifier_msg.sport = sport; + classifier_msg.dport = dport; + + msg = nlmsg_alloc(); + if (!msg) { + printf("Unable to allocate message\n"); + return; + } + + genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, inst->family_id, + NL_CLASSIFIER_GENL_HDRSIZE, NLM_F_REQUEST, + NL_CLASSIFIER_CMD_ACCEL, NL_CLASSIFIER_GENL_VERSION); + nla_put(msg, NL_CLASSIFIER_ATTR_TUPLE, sizeof(classifier_msg), &classifier_msg); + + ret = nl_send_auto(inst->sock, msg); + if (ret < 0) { + printf("send netlink message failed.\n"); + nlmsg_free(msg); + return; + } + + nlmsg_free(msg); + printf("nl classifier offload connection successful\n"); +} + +int nl_classifier_init(struct nl_classifier_instance *inst) +{ + int ret; + + inst->sock = nl_socket_alloc(); + if (!inst->sock) { + printf("Unable to allocation socket.\n"); + return -1; + } + genl_connect(inst->sock); + + inst->family_id = genl_ctrl_resolve(inst->sock, NL_CLASSIFIER_GENL_FAMILY); + if (inst->family_id < 0) { + printf("Unable to resolve family %s\n", NL_CLASSIFIER_GENL_FAMILY); + goto init_failed; + } + + inst->group_id = genl_ctrl_resolve_grp(inst->sock, NL_CLASSIFIER_GENL_FAMILY, NL_CLASSIFIER_GENL_GROUP); + if (inst->group_id < 0) { + printf("Unable to resolve mcast group %s\n", NL_CLASSIFIER_GENL_GROUP); + goto init_failed; + } + + ret = nl_socket_add_membership(inst->sock, inst->group_id); + if (ret < 0) { + printf("Unable to add membership\n"); + goto init_failed; + } + + nl_socket_disable_seq_check(inst->sock); + nl_socket_modify_cb(inst->sock, NL_CB_VALID, NL_CB_CUSTOM, nl_classifier_msg_recv, NULL); + + printf("nl classifier init successful\n"); + return 0; + +init_failed: + if (inst->sock) { + nl_close(inst->sock); + nl_socket_free(inst->sock); + inst->sock = NULL; + } + return -1; +} + +void nl_classifier_exit(struct nl_classifier_instance *inst) +{ + if (inst->sock) { + nl_close(inst->sock); + nl_socket_free(inst->sock); + inst->sock = NULL; + } + printf("nl classifier exit successful\n"); +} + +int nl_classifier_parse_arg(int argc, char *argv[], unsigned char *proto, unsigned long *src_saddr, + unsigned long *dst_saddr, unsigned short *sport, unsigned short *dport, int *af) +{ + int ret; + unsigned short port; + + if (argc < 7) { + printf("help: nl_classifier \n"); + return -1; + } + + if (0 == strncmp(argv[1], "v4", 2)) { + *af = AF_INET; + } else if (0 == strncmp(argv[1], "v6", 2)) { + *af = AF_INET6; + } else { + printf("Address family is not supported"); + return -1; + } + + if (0 == strncmp(argv[2], "udp", 3)) { + *proto = IPPROTO_UDP; + } else if (0 == strncmp(argv[2], "tcp", 3)) { + *proto = IPPROTO_TCP; + } else { + printf("Protocol is not supported"); + return -1; + } + + ret = inet_pton(*af, argv[3], src_saddr); + if (ret <= 0) { + printf("source ip has wrong format\n"); + return -1; + } + + ret = inet_pton(*af, argv[4], dst_saddr); + if (ret <= 0) { + printf("destination ip has wrong format\n"); + return -1; + } + + port = strtol(argv[5], NULL, 0); + *sport = htons(port); + port = strtol(argv[6], NULL, 0); + *dport = htons(port); + + printf("nl classifier parse arguments successful\n"); + return 0; +} + +int main(int argc, char *argv[]) +{ + struct nl_classifier_instance *inst = &nl_cls_inst; + unsigned char proto; + unsigned long src_addr[4]; + unsigned long dst_addr[4]; + unsigned short sport; + unsigned short dport; + int af; + int ret; + + ret = nl_classifier_parse_arg(argc, argv, &proto, src_addr, dst_addr, &sport, &dport, &af); + if (ret < 0) { + printf("Failed to parse arguments\n"); + return ret; + } + + ret = nl_classifier_init(inst); + if (ret < 0) { + printf("Unable to init generic netlink\n"); + return ret; + } + + nl_classifier_offload(inst, proto, src_addr, dst_addr, sport, dport, af); + + /* main loop to listen on message */ + while (!inst->stop) { + nl_recvmsgs_default(inst->sock); + } + + nl_classifier_exit(inst); + + return 0; +} diff --git a/root/package/lean/shortcut-fe/fast-classifier/src/userspace_example.c b/root/package/lean/shortcut-fe/fast-classifier/src/userspace_example.c new file mode 100644 index 00000000..4f4113d9 --- /dev/null +++ b/root/package/lean/shortcut-fe/fast-classifier/src/userspace_example.c @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2013,2016 The Linux Foundation. All rights reserved. + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#include + +static struct nl_sock *sock; +static struct nl_sock *sock_event; +static int family; +static int grp_id; + +static struct nla_policy fast_classifier_genl_policy[FAST_CLASSIFIER_A_MAX + 1] = { + [FAST_CLASSIFIER_A_TUPLE] = { .type = NLA_UNSPEC }, +}; + +void dump_fc_tuple(struct fast_classifier_tuple *fc_msg) +{ + char src_str[INET_ADDRSTRLEN]; + char dst_str[INET_ADDRSTRLEN]; + + printf("TUPLE: %d, %s, %s, %d, %d" + " SMAC=%02x:%02x:%02x:%02x:%02x:%02x", + " DMAC=%02x:%02x:%02x:%02x:%02x:%02x\n", + fc_msg->proto, + inet_ntop(AF_INET, + &fc_msg->src_saddr.in.s_addr, + src_str, + INET_ADDRSTRLEN), + inet_ntop(AF_INET, + &fc_msg->dst_saddr.in.s_addr, + dst_str, + INET_ADDRSTRLEN), + fc_msg->sport, fc_msg->dport, + fc_msg->smac[0], fc_msg->smac[1], fc_msg->smac[2], + fc_msg->smac[3], fc_msg->smac[4], fc_msg->smac[5], + fc_msg->dmac[0], fc_msg->dmac[1], fc_msg->dmac[2], + fc_msg->dmac[3], fc_msg->dmac[4], fc_msg->dmac[5]); +} + +static int parse_cb(struct nl_msg *msg, void *arg) +{ + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct genlmsghdr *gnlh = nlmsg_data(nlh); + struct nlattr *attrs[FAST_CLASSIFIER_A_MAX]; + + genlmsg_parse(nlh, 0, attrs, FAST_CLASSIFIER_A_MAX, fast_classifier_genl_policy); + + switch (gnlh->cmd) { + case FAST_CLASSIFIER_C_OFFLOADED: + printf("Got a offloaded message\n"); + dump_fc_tuple(nla_data(attrs[FAST_CLASSIFIER_A_TUPLE])); + return NL_OK; + case FAST_CLASSIFIER_C_DONE: + printf("Got a done message\n"); + dump_fc_tuple(nla_data(attrs[FAST_CLASSIFIER_A_TUPLE])); + return NL_OK; + } + + return NL_SKIP; +} + +int fast_classifier_init(void) +{ + int err; + + sock = nl_socket_alloc(); + if (!sock) { + printf("Unable to allocation socket.\n"); + return -1; + } + genl_connect(sock); + + sock_event = nl_socket_alloc(); + if (!sock_event) { + nl_close(sock); + nl_socket_free(sock); + printf("Unable to allocation socket.\n"); + return -1; + } + genl_connect(sock_event); + + family = genl_ctrl_resolve(sock, FAST_CLASSIFIER_GENL_NAME); + if (family < 0) { + nl_close(sock_event); + nl_close(sock); + nl_socket_free(sock); + nl_socket_free(sock_event); + printf("Unable to resolve family\n"); + return -1; + } + + grp_id = genl_ctrl_resolve_grp(sock, FAST_CLASSIFIER_GENL_NAME, + FAST_CLASSIFIER_GENL_MCGRP); + if (grp_id < 0) { + printf("Unable to resolve mcast group\n"); + return -1; + } + + err = nl_socket_add_membership(sock_event, grp_id); + if (err < 0) { + printf("Unable to add membership\n"); + return -1; + } + + nl_socket_disable_seq_check(sock_event); + nl_socket_modify_cb(sock_event, NL_CB_VALID, NL_CB_CUSTOM, parse_cb, NULL); + + return 0; +} + +void fast_classifier_close(void) +{ + nl_close(sock_event); + nl_close(sock); + nl_socket_free(sock_event); + nl_socket_free(sock); +} + +void fast_classifier_ipv4_offload(unsigned char proto, unsigned long src_saddr, + unsigned long dst_saddr, unsigned short sport, + unsigned short dport) +{ + struct nl_msg *msg; + int ret; +#ifdef DEBUG + char src_str[INET_ADDRSTRLEN]; + char dst_str[INET_ADDRSTRLEN]; +#endif + struct fast_classifier_tuple fc_msg; + +#ifdef DEBUG + printf("DEBUG: would offload: %d, %s, %s, %d, %d\n", proto, + inet_ntop(AF_INET, &src_saddr, src_str, INET_ADDRSTRLEN), + inet_ntop(AF_INET, &dst_saddr, dst_str, INET_ADDRSTRLEN), + sport, dport); +#endif + + fc_msg.proto = proto; + fc_msg.src_saddr.in.s_addr = src_saddr; + fc_msg.dst_saddr.in.s_addr = dst_saddr; + fc_msg.sport = sport; + fc_msg.dport = dport; + fc_msg.smac[0] = 'a'; + fc_msg.smac[1] = 'b'; + fc_msg.smac[2] = 'c'; + fc_msg.smac[3] = 'd'; + fc_msg.smac[4] = 'e'; + fc_msg.smac[5] = 'f'; + fc_msg.dmac[0] = 'f'; + fc_msg.dmac[1] = 'e'; + fc_msg.dmac[2] = 'd'; + fc_msg.dmac[3] = 'c'; + fc_msg.dmac[4] = 'b'; + fc_msg.dmac[5] = 'a'; + + if (fast_classifier_init() < 0) { + printf("Unable to init generic netlink\n"); + exit(1); + } + + msg = nlmsg_alloc(); + if (!msg) { + nl_socket_free(sock); + printf("Unable to allocate message\n"); + return; + } + + genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, + FAST_CLASSIFIER_GENL_HDRSIZE, NLM_F_REQUEST, + FAST_CLASSIFIER_C_OFFLOAD, FAST_CLASSIFIER_GENL_VERSION); + nla_put(msg, 1, sizeof(fc_msg), &fc_msg); + + ret = nl_send_auto_complete(sock, msg); + + nlmsg_free(msg); + if (ret < 0) { + printf("nlmsg_free failed"); + nl_close(sock); + nl_socket_free(sock); + return; + } + + ret = nl_wait_for_ack(sock); + if (ret < 0) { + printf("wait for ack failed"); + nl_close(sock); + nl_socket_free(sock); + return; + } +} + +void fast_classifier_listen_for_messages(void) +{ + printf("waiting for netlink events\n"); + + while (1) { + nl_recvmsgs_default(sock_event); + } +} + +int main(int argc, char *argv[]) +{ + if (fast_classifier_init() < 0) { + printf("Unable to init generic netlink\n"); + exit(1); + } + + fast_classifier_ipv4_offload('a', 0, 0, 0, 0); + + /* this never returns */ + fast_classifier_listen_for_messages(); + + fast_classifier_close(); + + return 0; +} diff --git a/root/package/lean/shortcut-fe/shortcut-fe/Makefile b/root/package/lean/shortcut-fe/shortcut-fe/Makefile new file mode 100644 index 00000000..dd53042e --- /dev/null +++ b/root/package/lean/shortcut-fe/shortcut-fe/Makefile @@ -0,0 +1,88 @@ +# +# Copyright (c) 2013-2018, 2020 The Linux Foundation. All rights reserved. +# Permission to use, copy, modify, and/or distribute this software for +# any purpose with or without fee is hereby granted, provided that the +# above copyright notice and this permission notice appear in all copies. +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=shortcut-fe +PKG_RELEASE:=8 + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/shortcut-fe + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Support + DEPENDS:=@IPV6 +kmod-nf-conntrack + TITLE:=Kernel driver for SFE + FILES:= \ + $(PKG_BUILD_DIR)/shortcut-fe.ko \ + $(PKG_BUILD_DIR)/shortcut-fe-ipv6.ko + KCONFIG:= \ + CONFIG_NF_CONNTRACK_EVENTS=y \ + CONFIG_NF_CONNTRACK_TIMEOUT=y \ + CONFIG_SHORTCUT_FE=y \ + CONFIG_XFRM=y + PROVIDES:=$(PKG_NAME) + AUTOLOAD:=$(call AutoLoad,09,shortcut-fe shortcut-fe-ipv6) +endef + +define KernelPackage/shortcut-fe/Description +Shortcut is an in-Linux-kernel IP packet forwarding engine. +endef + +define KernelPackage/shortcut-fe/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) ./files/usr/bin/sfe_dump $(1)/usr/bin +endef + +HAVE_ECM:=$(CONFIG_PACKAGE_kmod-qca-nss-ecm-premium)$(CONFIG_PACKAGE_kmod-qca-nss-ecm-noload)$(CONFIG_PACKAGE_kmod-qca-nss-ecm-premium-noload)$(CONFIG_PACKAGE_kmod-qca-nss-ecm-standard) + +define KernelPackage/shortcut-fe-cm + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Support + DEPENDS:=+kmod-ipt-conntrack +kmod-shortcut-fe + TITLE:=Kernel driver for SFE + FILES:=$(PKG_BUILD_DIR)/shortcut-fe-cm.ko + KCONFIG:= \ + CONFIG_NF_CONNTRACK_CHAIN_EVENTS=y \ + CONFIG_NF_CONNTRACK_EVENTS=y \ + CONFIG_XFRM=y + CONFLICTS:=kmod-shortcut-fe-drv +endef + +define KernelPackage/shortcut-fe-cm/Description +Simple connection manager for the Shortcut forwarding engine. +endef + +define Build/Compile + $(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \ + $(KERNEL_MAKE_FLAGS) \ + $(PKG_MAKE_FLAGS) \ + M="$(PKG_BUILD_DIR)" \ + EXTRA_CFLAGS+="-DSFE_SUPPORT_IPV6" SFE_SUPPORT_IPV6=y \ + $(if $(HAVE_ECM),EXTRA_CFLAGS+="-DCONFIG_SFE_ECM" CONFIG_SFE_ECM=y,) \ + modules +endef + +ifneq ($(CONFIG_PACKAGE_kmod-shortcut-fe)$(CONFIG_PACKAGE_kmod-shortcut-fe-cm),) +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include/shortcut-fe + $(CP) -rf $(PKG_BUILD_DIR)/sfe.h $(1)/usr/include/shortcut-fe +endef +endif + +$(eval $(call KernelPackage,shortcut-fe)) +$(eval $(call KernelPackage,shortcut-fe-cm)) diff --git a/root/package/lean/shortcut-fe/shortcut-fe/files/etc/init.d/shortcut-fe b/root/package/lean/shortcut-fe/shortcut-fe/files/etc/init.d/shortcut-fe new file mode 100644 index 00000000..838512a3 --- /dev/null +++ b/root/package/lean/shortcut-fe/shortcut-fe/files/etc/init.d/shortcut-fe @@ -0,0 +1,51 @@ +#!/bin/sh /etc/rc.common +# +# Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. +# Permission to use, copy, modify, and/or distribute this software for +# any purpose with or without fee is hereby granted, provided that the +# above copyright notice and this permission notice appear in all copies. +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +#SFE connection manager has a lower priority, it should be started after other connection manager +#to detect the existence of connection manager with higher priority +START=70 + +have_cm() { + [ -d "/sys/kernel/debug/ecm" ] && echo 1 && return + + echo 0 +} + +#load shortcut-fe and connection manager +load_sfe() { + local kernel_version=$(uname -r) + + [ -d "/sys/module/shortcut_fe" ] || insmod /lib/modules/$kernel_version/shortcut-fe.ko + [ -d "/sys/module/shortcut_fe_ipv6" ] || insmod /lib/modules/$kernel_version/shortcut-fe-ipv6.ko + + [ -e "/lib/modules/$kernel_version/shortcut-fe-cm.ko" ] && { + [ -d /sys/module/shortcut_fe_cm ] || insmod /lib/modules/$kernel_version/shortcut-fe-cm.ko + } + [ -e "/lib/modules/$kernel_version/fast-classifier.ko" ] && { + [ -d /sys/module/fast_classifier ] || insmod /lib/modules/$kernel_version/fast-classifier.ko + } +} + +start() { + [ "$(have_cm)" = "0" ] && load_sfe +} + +stop() { + [ -d "/sys/module/shortcut_fe_cm" ] && rmmod shortcut_fe_cm + [ -d "/sys/module/shortcut_fe_ipv6" ] && rmmod shortcut_fe_ipv6 + [ -d "/sys/module/shortcut_fe" ] && rmmod shortcut_fe + [ -d "/sys/module/shortcut_fe_drv" ] && rmmod shortcut_fe_drv + [ -d "/sys/module/fast_classifier" ] && rmmod fast_classifier +} diff --git a/root/package/lean/shortcut-fe/shortcut-fe/files/usr/bin/sfe_dump b/root/package/lean/shortcut-fe/shortcut-fe/files/usr/bin/sfe_dump new file mode 100644 index 00000000..2a224e0c --- /dev/null +++ b/root/package/lean/shortcut-fe/shortcut-fe/files/usr/bin/sfe_dump @@ -0,0 +1,35 @@ +#!/bin/sh +# +# Copyright (c) 2015 The Linux Foundation. All rights reserved. +# Permission to use, copy, modify, and/or distribute this software for +# any purpose with or without fee is hereby granted, provided that the +# above copyright notice and this permission notice appear in all copies. +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +#@sfe_dump +#@example : sfe_dump (ipv4|ipv6) +sfe_dump(){ + [ -e "/dev/sfe_ipv4" ] || { + dev_num=$(cat /sys/sfe_ipv4/debug_dev) + mknod /dev/sfe_ipv4 c $dev_num 0 + } + [ -e "/dev/sfe_ipv6" ] || { + dev_num=$(cat /sys/sfe_ipv6/debug_dev) + mknod /dev/sfe_ipv6 c $dev_num 0 + } + cat /dev/sfe_$1 +} + +if [ -z "$1" ]; then + sfe_dump ipv4 + sfe_dump ipv6 +else + sfe_dump $1 +fi diff --git a/root/package/lean/shortcut-fe/shortcut-fe/src/Kconfig b/root/package/lean/shortcut-fe/shortcut-fe/src/Kconfig new file mode 100644 index 00000000..487f1e06 --- /dev/null +++ b/root/package/lean/shortcut-fe/shortcut-fe/src/Kconfig @@ -0,0 +1,14 @@ +# +# Shortcut forwarding engine +# + +config SHORTCUT_FE + tristate "Shortcut Forwarding Engine" + depends on NF_CONNTRACK + ---help--- + Shortcut is a fast in-kernel packet forwarding engine. + + To compile this code as a module, choose M here: the module will be + called shortcut-fe. + + If unsure, say N. diff --git a/root/package/lean/shortcut-fe/shortcut-fe/src/Makefile b/root/package/lean/shortcut-fe/shortcut-fe/src/Makefile new file mode 100644 index 00000000..991a20ec --- /dev/null +++ b/root/package/lean/shortcut-fe/shortcut-fe/src/Makefile @@ -0,0 +1,24 @@ +# +# Makefile for Shortcut FE. +# + +obj-m += shortcut-fe.o + +ifdef SFE_SUPPORT_IPV6 +obj-m += shortcut-fe-ipv6.o +endif + +obj-m += shortcut-fe-cm.o + +shortcut-fe-objs := \ + sfe_ipv4.o + +ifdef SFE_SUPPORT_IPV6 +shortcut-fe-ipv6-objs := \ + sfe_ipv6.o +endif + +shortcut-fe-cm-objs := \ + sfe_cm.o + +ccflags-y += -Werror -Wall diff --git a/root/package/lean/shortcut-fe/shortcut-fe/src/sfe.h b/root/package/lean/shortcut-fe/shortcut-fe/src/sfe.h new file mode 100644 index 00000000..279e7b3d --- /dev/null +++ b/root/package/lean/shortcut-fe/shortcut-fe/src/sfe.h @@ -0,0 +1,114 @@ +/* + * sfe.h + * Shortcut forwarding engine. + * + * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved. + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +/* + * The following are debug macros used throughout the SFE. + * + * The DEBUG_LEVEL enables the followings based on its value, + * when dynamic debug option is disabled. + * + * 0 = OFF + * 1 = ASSERTS / ERRORS + * 2 = 1 + WARN + * 3 = 2 + INFO + * 4 = 3 + TRACE + */ +#define DEBUG_LEVEL 2 + +#if (DEBUG_LEVEL < 1) +#define DEBUG_ASSERT(s, ...) +#define DEBUG_ERROR(s, ...) +#else +#define DEBUG_ASSERT(c, s, ...) if (!(c)) { pr_emerg("ASSERT: %s:%d:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__); BUG(); } +#define DEBUG_ERROR(s, ...) pr_err("%s:%d:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#endif + +#if defined(CONFIG_DYNAMIC_DEBUG) +/* + * Compile messages for dynamic enable/disable + */ +#define DEBUG_WARN(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define DEBUG_INFO(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define DEBUG_TRACE(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#else + +/* + * Statically compile messages at different levels + */ +#if (DEBUG_LEVEL < 2) +#define DEBUG_WARN(s, ...) +#else +#define DEBUG_WARN(s, ...) pr_warn("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#endif + +#if (DEBUG_LEVEL < 3) +#define DEBUG_INFO(s, ...) +#else +#define DEBUG_INFO(s, ...) pr_notice("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#endif + +#if (DEBUG_LEVEL < 4) +#define DEBUG_TRACE(s, ...) +#else +#define DEBUG_TRACE(s, ...) pr_info("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#endif +#endif + +#ifdef CONFIG_NF_FLOW_COOKIE +typedef int (*flow_cookie_set_func_t)(u32 protocol, __be32 src_ip, __be16 src_port, + __be32 dst_ip, __be16 dst_port, u16 flow_cookie); +/* + * sfe_register_flow_cookie_cb + * register a function in SFE to let SFE use this function to configure flow cookie for a flow + * + * Hardware driver which support flow cookie should register a callback function in SFE. Then SFE + * can use this function to configure flow cookie for a flow. + * return: 0, success; !=0, fail + */ +int sfe_register_flow_cookie_cb(flow_cookie_set_func_t cb); + +/* + * sfe_unregister_flow_cookie_cb + * unregister function which is used to configure flow cookie for a flow + * + * return: 0, success; !=0, fail + */ +int sfe_unregister_flow_cookie_cb(flow_cookie_set_func_t cb); + +typedef int (*sfe_ipv6_flow_cookie_set_func_t)(u32 protocol, __be32 src_ip[4], __be16 src_port, + __be32 dst_ip[4], __be16 dst_port, u16 flow_cookie); + +/* + * sfe_ipv6_register_flow_cookie_cb + * register a function in SFE to let SFE use this function to configure flow cookie for a flow + * + * Hardware driver which support flow cookie should register a callback function in SFE. Then SFE + * can use this function to configure flow cookie for a flow. + * return: 0, success; !=0, fail + */ +int sfe_ipv6_register_flow_cookie_cb(sfe_ipv6_flow_cookie_set_func_t cb); + +/* + * sfe_ipv6_unregister_flow_cookie_cb + * unregister function which is used to configure flow cookie for a flow + * + * return: 0, success; !=0, fail + */ +int sfe_ipv6_unregister_flow_cookie_cb(sfe_ipv6_flow_cookie_set_func_t cb); + +#endif /*CONFIG_NF_FLOW_COOKIE*/ diff --git a/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_backport.h b/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_backport.h new file mode 100644 index 00000000..d2d60c73 --- /dev/null +++ b/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_backport.h @@ -0,0 +1,195 @@ +/* + * sfe_backport.h + * Shortcut forwarding engine compatible header file. + * + * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) +#include +#else +enum udp_conntrack { + UDP_CT_UNREPLIED, + UDP_CT_REPLIED, + UDP_CT_MAX +}; + +static inline unsigned int * +nf_ct_timeout_lookup(struct net *net, struct nf_conn *ct, + struct nf_conntrack_l4proto *l4proto) +{ +#ifdef CONFIG_NF_CONNTRACK_TIMEOUT + struct nf_conn_timeout *timeout_ext; + unsigned int *timeouts; + + timeout_ext = nf_ct_timeout_find(ct); + if (timeout_ext) + timeouts = NF_CT_TIMEOUT_EXT_DATA(timeout_ext); + else + timeouts = l4proto->get_timeouts(net); + + return timeouts; +#else + return l4proto->get_timeouts(net); +#endif /*CONFIG_NF_CONNTRACK_TIMEOUT*/ +} +#endif /*KERNEL_VERSION(3, 7, 0)*/ +#endif /*KERNEL_VERSION(3, 4, 0)*/ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) +#define sfe_define_post_routing_hook(FN_NAME, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ +static unsigned int FN_NAME(void *priv, \ + struct sk_buff *SKB, \ + const struct nf_hook_state *state) +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) +#define sfe_define_post_routing_hook(FN_NAME, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ +static unsigned int FN_NAME(const struct nf_hook_ops *OPS, \ + struct sk_buff *SKB, \ + const struct net_device *UNUSED, \ + const struct net_device *OUT, \ + int (*OKFN)(struct sk_buff *)) +#else +#define sfe_define_post_routing_hook(FN_NAME, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ +static unsigned int FN_NAME(unsigned int HOOKNUM, \ + struct sk_buff *SKB, \ + const struct net_device *UNUSED, \ + const struct net_device *OUT, \ + int (*OKFN)(struct sk_buff *)) +#endif + +#define sfe_cm_ipv4_post_routing_hook(HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ + sfe_define_post_routing_hook(__sfe_cm_ipv4_post_routing_hook, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) +#define sfe_cm_ipv6_post_routing_hook(HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ + sfe_define_post_routing_hook(__sfe_cm_ipv6_post_routing_hook, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) +#define fast_classifier_ipv4_post_routing_hook(HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ + sfe_define_post_routing_hook(__fast_classifier_ipv4_post_routing_hook, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) +#define fast_classifier_ipv6_post_routing_hook(HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ + sfe_define_post_routing_hook(__fast_classifier_ipv6_post_routing_hook, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) +#define SFE_IPV4_NF_POST_ROUTING_HOOK(fn) \ + { \ + .hook = fn, \ + .pf = NFPROTO_IPV4, \ + .hooknum = NF_INET_POST_ROUTING, \ + .priority = NF_IP_PRI_NAT_SRC + 1, \ + } +#else +#define SFE_IPV4_NF_POST_ROUTING_HOOK(fn) \ + { \ + .hook = fn, \ + .owner = THIS_MODULE, \ + .pf = NFPROTO_IPV4, \ + .hooknum = NF_INET_POST_ROUTING, \ + .priority = NF_IP_PRI_NAT_SRC + 1, \ + } +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) +#define SFE_IPV6_NF_POST_ROUTING_HOOK(fn) \ + { \ + .hook = fn, \ + .pf = NFPROTO_IPV6, \ + .hooknum = NF_INET_POST_ROUTING, \ + .priority = NF_IP_PRI_NAT_SRC + 1, \ + } +#else +#define SFE_IPV6_NF_POST_ROUTING_HOOK(fn) \ + { \ + .hook = fn, \ + .owner = THIS_MODULE, \ + .pf = NFPROTO_IPV6, \ + .hooknum = NF_INET_POST_ROUTING, \ + .priority = NF_IP6_PRI_NAT_SRC + 1, \ + } +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0)) +#define SFE_NF_CT_DEFAULT_ZONE (&nf_ct_zone_dflt) +#else +#define SFE_NF_CT_DEFAULT_ZONE NF_CT_DEFAULT_ZONE +#endif + +/* + * sfe_dev_get_master + * get master of bridge port, and hold it + */ +static inline struct net_device *sfe_dev_get_master(struct net_device *dev) +{ + struct net_device *master; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) + rcu_read_lock(); + master = netdev_master_upper_dev_get_rcu(dev); + if (master) + dev_hold(master); + + rcu_read_unlock(); +#else + master = dev->master; + if (master) + dev_hold(master); +#endif + return master; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) +#define SFE_DEV_EVENT_PTR(PTR) netdev_notifier_info_to_dev(PTR) +#else +#define SFE_DEV_EVENT_PTR(PTR) (struct net_device *)(PTR) +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) +#define SFE_NF_CONN_ACCT(NM) struct nf_conn_acct *NM +#else +#define SFE_NF_CONN_ACCT(NM) struct nf_conn_counter *NM +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) +#define SFE_ACCT_COUNTER(NM) ((NM)->counter) +#else +#define SFE_ACCT_COUNTER(NM) (NM) +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) +#define sfe_hash_for_each_possible(name, obj, node, member, key) \ + hash_for_each_possible(name, obj, member, key) +#else +#define sfe_hash_for_each_possible(name, obj, node, member, key) \ + hash_for_each_possible(name, obj, node, member, key) +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) +#define sfe_hash_for_each(name, bkt, node, obj, member) \ + hash_for_each(name, bkt, obj, member) +#else +#define sfe_hash_for_each(name, bkt, node, obj, member) \ + hash_for_each(name, bkt, node, obj, member) +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) +#define sfe_dst_get_neighbour(dst, daddr) dst_neigh_lookup(dst, addr) +#else +static inline struct neighbour * +sfe_dst_get_neighbour(struct dst_entry *dst, void *daddr) +{ + struct neighbour *neigh = dst_get_neighbour_noref(dst); + + if (neigh) + neigh_hold(neigh); + + return neigh; +} +#endif diff --git a/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_cm.c b/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_cm.c new file mode 100644 index 00000000..2d3f79a0 --- /dev/null +++ b/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_cm.c @@ -0,0 +1,1210 @@ +/* + * sfe-cm.c + * Shortcut forwarding engine connection manager. + * + * Copyright (c) 2013-2018, 2020 The Linux Foundation. All rights reserved. + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sfe.h" +#include "sfe_cm.h" +#include "sfe_backport.h" + +typedef enum sfe_cm_exception { + SFE_CM_EXCEPTION_PACKET_BROADCAST, + SFE_CM_EXCEPTION_PACKET_MULTICAST, + SFE_CM_EXCEPTION_NO_IIF, + SFE_CM_EXCEPTION_NO_CT, + SFE_CM_EXCEPTION_CT_NO_TRACK, + SFE_CM_EXCEPTION_CT_NO_CONFIRM, + SFE_CM_EXCEPTION_CT_IS_ALG, + SFE_CM_EXCEPTION_IS_IPV4_MCAST, + SFE_CM_EXCEPTION_IS_IPV6_MCAST, + SFE_CM_EXCEPTION_TCP_NOT_ASSURED, + SFE_CM_EXCEPTION_TCP_NOT_ESTABLISHED, + SFE_CM_EXCEPTION_UNKNOW_PROTOCOL, + SFE_CM_EXCEPTION_NO_SRC_DEV, + SFE_CM_EXCEPTION_NO_SRC_XLATE_DEV, + SFE_CM_EXCEPTION_NO_DEST_DEV, + SFE_CM_EXCEPTION_NO_DEST_XLATE_DEV, + SFE_CM_EXCEPTION_NO_BRIDGE, + SFE_CM_EXCEPTION_LOCAL_OUT, + SFE_CM_EXCEPTION_MAX +} sfe_cm_exception_t; + +static char *sfe_cm_exception_events_string[SFE_CM_EXCEPTION_MAX] = { + "PACKET_BROADCAST", + "PACKET_MULTICAST", + "NO_IIF", + "NO_CT", + "CT_NO_TRACK", + "CT_NO_CONFIRM", + "CT_IS_ALG", + "IS_IPV4_MCAST", + "IS_IPV6_MCAST", + "TCP_NOT_ASSURED", + "TCP_NOT_ESTABLISHED", + "UNKNOW_PROTOCOL", + "NO_SRC_DEV", + "NO_SRC_XLATE_DEV", + "NO_DEST_DEV", + "NO_DEST_XLATE_DEV", + "NO_BRIDGE", + "LOCAL_OUT" +}; + +/* + * Per-module structure. + */ +struct sfe_cm { + spinlock_t lock; /* Lock for SMP correctness */ + + /* + * Control state. + */ + struct kobject *sys_sfe_cm; /* sysfs linkage */ + + /* + * Callback notifiers. + */ + struct notifier_block dev_notifier; /* Device notifier */ + struct notifier_block inet_notifier; /* IPv4 notifier */ + struct notifier_block inet6_notifier; /* IPv6 notifier */ + u32 exceptions[SFE_CM_EXCEPTION_MAX]; +}; + +static struct sfe_cm __sc; + +/* + * sfe_cm_incr_exceptions() + * increase an exception counter. + */ +static inline void sfe_cm_incr_exceptions(sfe_cm_exception_t except) +{ + struct sfe_cm *sc = &__sc; + + spin_lock_bh(&sc->lock); + sc->exceptions[except]++; + spin_unlock_bh(&sc->lock); +} + +/* + * sfe_cm_recv() + * Handle packet receives. + * + * Returns 1 if the packet is forwarded or 0 if it isn't. + */ +int sfe_cm_recv(struct sk_buff *skb) +{ + struct net_device *dev; + + /* + * We know that for the vast majority of packets we need the transport + * layer header so we may as well start to fetch it now! + */ + prefetch(skb->data + 32); + barrier(); + + dev = skb->dev; + + /* + * We're only interested in IPv4 and IPv6 packets. + */ + if (likely(htons(ETH_P_IP) == skb->protocol)) { + struct in_device *in_dev; + + /* + * Does our input device support IP processing? + */ + in_dev = (struct in_device *)dev->ip_ptr; + if (unlikely(!in_dev)) { + DEBUG_TRACE("no IP processing for device: %s\n", dev->name); + return 0; + } + + /* + * Does it have an IP address? If it doesn't then we can't do anything + * interesting here! + */ + if (unlikely(!in_dev->ifa_list)) { + DEBUG_TRACE("no IP address for device: %s\n", dev->name); + return 0; + } + + return sfe_ipv4_recv(dev, skb); + } + + if (likely(htons(ETH_P_IPV6) == skb->protocol)) { + struct inet6_dev *in_dev; + + /* + * Does our input device support IPv6 processing? + */ + in_dev = (struct inet6_dev *)dev->ip6_ptr; + if (unlikely(!in_dev)) { + DEBUG_TRACE("no IPv6 processing for device: %s\n", dev->name); + return 0; + } + + /* + * Does it have an IPv6 address? If it doesn't then we can't do anything + * interesting here! + */ + if (unlikely(list_empty(&in_dev->addr_list))) { + DEBUG_TRACE("no IPv6 address for device: %s\n", dev->name); + return 0; + } + + return sfe_ipv6_recv(dev, skb); + } + + DEBUG_TRACE("not IP packet\n"); + return 0; +} + +/* + * sfe_cm_find_dev_and_mac_addr() + * Find the device and MAC address for a given IPv4/IPv6 address. + * + * Returns true if we find the device and MAC address, otherwise false. + * + * We look up the rtable entry for the address and, from its neighbour + * structure, obtain the hardware address. This means this function also + * works if the neighbours are routers too. + */ +static bool sfe_cm_find_dev_and_mac_addr(struct sk_buff *skb, sfe_ip_addr_t *addr, struct net_device **dev, u8 *mac_addr, int is_v4) +{ + struct neighbour *neigh; + struct rtable *rt; + struct rt6_info *rt6; + struct dst_entry *dst; + struct net_device *mac_dev; + + /* + * If we have skb provided, use it as the original code is unable + * to lookup routes that are policy routed. + */ + if (unlikely(skb)) { + dst = skb_dst(skb); + goto skip_dst_lookup; + } + + /* + * Look up the rtable entry for the IP address then get the hardware + * address from its neighbour structure. This means this work when the + * neighbours are routers too. + */ + if (likely(is_v4)) { + rt = ip_route_output(&init_net, addr->ip, 0, 0, 0); + if (unlikely(IS_ERR(rt))) { + goto ret_fail; + } + + dst = (struct dst_entry *)rt; + } else { +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0)) + rt6 = rt6_lookup(&init_net, (struct in6_addr *)addr->ip6, 0, 0, 0); +#else + rt6 = rt6_lookup(&init_net, (struct in6_addr *)addr->ip6, 0, 0, NULL, 0); +#endif + if (!rt6) { + goto ret_fail; + } + + dst = (struct dst_entry *)rt6; + } + +skip_dst_lookup: + rcu_read_lock(); + neigh = sfe_dst_get_neighbour(dst, addr); + if (unlikely(!neigh)) { + rcu_read_unlock(); + if (likely(!skb)) + dst_release(dst); + goto ret_fail; + } + + if (unlikely(!(neigh->nud_state & NUD_VALID))) { + rcu_read_unlock(); + neigh_release(neigh); + if (likely(!skb)) + dst_release(dst); + goto ret_fail; + } + + mac_dev = neigh->dev; + if (!mac_dev) { + rcu_read_unlock(); + neigh_release(neigh); + if (likely(!skb)) + dst_release(dst); + goto ret_fail; + } + + memcpy(mac_addr, neigh->ha, (size_t)mac_dev->addr_len); + + dev_hold(mac_dev); + *dev = mac_dev; + rcu_read_unlock(); + neigh_release(neigh); + if (likely(!skb)) + dst_release(dst); + + return true; + +ret_fail: + if (is_v4) { + DEBUG_TRACE("failed to find MAC address for IP: %pI4\n", &addr->ip); + + } else { + DEBUG_TRACE("failed to find MAC address for IP: %pI6\n", addr->ip6); + } + + return false; +} + +/* + * sfe_cm_post_routing() + * Called for packets about to leave the box - either locally generated or forwarded from another interface + */ +static unsigned int sfe_cm_post_routing(struct sk_buff *skb, int is_v4) +{ + struct sfe_connection_create sic; + struct net_device *in; + struct nf_conn *ct; + enum ip_conntrack_info ctinfo; + struct net_device *dev; + struct net_device *src_dev; + struct net_device *dest_dev; + struct net_device *src_dev_tmp; + struct net_device *dest_dev_tmp; + struct net_device *src_br_dev = NULL; + struct net_device *dest_br_dev = NULL; + struct nf_conntrack_tuple orig_tuple; + struct nf_conntrack_tuple reply_tuple; + struct sk_buff *tmp_skb = NULL; + SFE_NF_CONN_ACCT(acct); + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) + struct net *net=NULL; + struct nf_tcp_net *tn=NULL; + #endif + + /* + * Don't process broadcast or multicast packets. + */ + if (unlikely(skb->pkt_type == PACKET_BROADCAST)) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_PACKET_BROADCAST); + DEBUG_TRACE("broadcast, ignoring\n"); + return NF_ACCEPT; + } + if (unlikely(skb->pkt_type == PACKET_MULTICAST)) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_PACKET_MULTICAST); + DEBUG_TRACE("multicast, ignoring\n"); + return NF_ACCEPT; + } + +#ifdef CONFIG_XFRM + /* + * Packet to xfrm for encapsulation, we can't process it + */ + if (unlikely(skb_dst(skb)->xfrm)) { + DEBUG_TRACE("packet to xfrm, ignoring\n"); + return NF_ACCEPT; + } +#endif + + /* + * Don't process locally generated packets. + */ + if (skb->sk) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_LOCAL_OUT); + DEBUG_TRACE("skip local out packet\n"); + return NF_ACCEPT; + } + + /* + * Don't process packets that are not being forwarded. + */ + in = dev_get_by_index(&init_net, skb->skb_iif); + if (!in) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_IIF); + DEBUG_TRACE("packet not forwarding\n"); + return NF_ACCEPT; + } + + dev_put(in); + + /* + * Don't process packets that aren't being tracked by conntrack. + */ + ct = nf_ct_get(skb, &ctinfo); + if (unlikely(!ct)) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_CT); + DEBUG_TRACE("no conntrack connection, ignoring\n"); + return NF_ACCEPT; + } + + /* + * Don't process untracked connections. + */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) + if (unlikely(nf_ct_is_untracked(ct))) { +#else + if (unlikely(ctinfo == IP_CT_UNTRACKED)) { +#endif + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_CT_NO_TRACK); + DEBUG_TRACE("untracked connection\n"); + return NF_ACCEPT; + } + + /* + * Unconfirmed connection may be dropped by Linux at the final step, + * So we don't process unconfirmed connections. + */ + if (!nf_ct_is_confirmed(ct)) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_CT_NO_CONFIRM); + DEBUG_TRACE("unconfirmed connection\n"); + return NF_ACCEPT; + } + + /* + * Don't process connections that require support from a 'helper' (typically a NAT ALG). + */ + if (unlikely(nfct_help(ct))) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_CT_IS_ALG); + DEBUG_TRACE("connection has helper\n"); + return NF_ACCEPT; + } + + /* + * Check if the acceleration of a flow could be rejected quickly. + */ + acct = nf_conn_acct_find(ct); + if (acct) { + long long packets = atomic64_read(&SFE_ACCT_COUNTER(acct)[CTINFO2DIR(ctinfo)].packets); + if ((packets > 0xff) && (packets & 0xff)) { + /* + * Connection hits slow path at least 256 times, so it must be not able to accelerate. + * But we also give it a chance to walk through ECM every 256 packets + */ + return NF_ACCEPT; + } + } + + /* + * Look up the details of our connection in conntrack. + * + * Note that the data we get from conntrack is for the "ORIGINAL" direction + * but our packet may actually be in the "REPLY" direction. + */ + orig_tuple = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; + reply_tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple; + sic.protocol = (s32)orig_tuple.dst.protonum; + + sic.flags = 0; + + /* + * Get addressing information, non-NAT first + */ + if (likely(is_v4)) { + u32 dscp; + + sic.src_ip.ip = (__be32)orig_tuple.src.u3.ip; + sic.dest_ip.ip = (__be32)orig_tuple.dst.u3.ip; + + if (ipv4_is_multicast(sic.src_ip.ip) || ipv4_is_multicast(sic.dest_ip.ip)) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_IS_IPV4_MCAST); + DEBUG_TRACE("multicast address\n"); + return NF_ACCEPT; + } + + /* + * NAT'ed addresses - note these are as seen from the 'reply' direction + * When NAT does not apply to this connection these will be identical to the above. + */ + sic.src_ip_xlate.ip = (__be32)reply_tuple.dst.u3.ip; + sic.dest_ip_xlate.ip = (__be32)reply_tuple.src.u3.ip; + + dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT; + if (dscp) { + sic.dest_dscp = dscp; + sic.src_dscp = sic.dest_dscp; + sic.flags |= SFE_CREATE_FLAG_REMARK_DSCP; + } + } else { + u32 dscp; + + sic.src_ip.ip6[0] = *((struct sfe_ipv6_addr *)&orig_tuple.src.u3.in6); + sic.dest_ip.ip6[0] = *((struct sfe_ipv6_addr *)&orig_tuple.dst.u3.in6); + + if (ipv6_addr_is_multicast((struct in6_addr *)sic.src_ip.ip6) || + ipv6_addr_is_multicast((struct in6_addr *)sic.dest_ip.ip6)) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_IS_IPV6_MCAST); + DEBUG_TRACE("multicast address\n"); + return NF_ACCEPT; + } + + /* + * NAT'ed addresses - note these are as seen from the 'reply' direction + * When NAT does not apply to this connection these will be identical to the above. + */ + sic.src_ip_xlate.ip6[0] = *((struct sfe_ipv6_addr *)&reply_tuple.dst.u3.in6); + sic.dest_ip_xlate.ip6[0] = *((struct sfe_ipv6_addr *)&reply_tuple.src.u3.in6); + + dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT; + if (dscp) { + sic.dest_dscp = dscp; + sic.src_dscp = sic.dest_dscp; + sic.flags |= SFE_CREATE_FLAG_REMARK_DSCP; + } + } + + switch (sic.protocol) { + case IPPROTO_TCP: + sic.src_port = orig_tuple.src.u.tcp.port; + sic.dest_port = orig_tuple.dst.u.tcp.port; + sic.src_port_xlate = reply_tuple.dst.u.tcp.port; + sic.dest_port_xlate = reply_tuple.src.u.tcp.port; + sic.src_td_window_scale = ct->proto.tcp.seen[0].td_scale; + sic.src_td_max_window = ct->proto.tcp.seen[0].td_maxwin; + sic.src_td_end = ct->proto.tcp.seen[0].td_end; + sic.src_td_max_end = ct->proto.tcp.seen[0].td_maxend; + sic.dest_td_window_scale = ct->proto.tcp.seen[1].td_scale; + sic.dest_td_max_window = ct->proto.tcp.seen[1].td_maxwin; + sic.dest_td_end = ct->proto.tcp.seen[1].td_end; + sic.dest_td_max_end = ct->proto.tcp.seen[1].td_maxend; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) + net = nf_ct_net(ct); + tn = nf_tcp_pernet(net); + if ((tn&&tn->tcp_no_window_check) +#else + if (nf_ct_tcp_no_window_check +#endif + || (ct->proto.tcp.seen[0].flags & IP_CT_TCP_FLAG_BE_LIBERAL) + || (ct->proto.tcp.seen[1].flags & IP_CT_TCP_FLAG_BE_LIBERAL)) { + sic.flags |= SFE_CREATE_FLAG_NO_SEQ_CHECK; + } + + /* + * Don't try to manage a non-established connection. + */ + if (!test_bit(IPS_ASSURED_BIT, &ct->status)) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_TCP_NOT_ASSURED); + DEBUG_TRACE("non-established connection\n"); + return NF_ACCEPT; + } + + /* + * If the connection is shutting down do not manage it. + * state can not be SYN_SENT, SYN_RECV because connection is assured + * Not managed states: FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE. + */ + spin_lock_bh(&ct->lock); + if (ct->proto.tcp.state != TCP_CONNTRACK_ESTABLISHED) { + spin_unlock_bh(&ct->lock); + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_TCP_NOT_ESTABLISHED); + DEBUG_TRACE("connection in termination state: %#x, s: %pI4:%u, d: %pI4:%u\n", + ct->proto.tcp.state, &sic.src_ip, ntohs(sic.src_port), + &sic.dest_ip, ntohs(sic.dest_port)); + return NF_ACCEPT; + } + spin_unlock_bh(&ct->lock); + + /* + * Somehow, SFE is not playing nice with IPSec traffic. + * Do not accelerate for now. + */ + if (ntohs(sic.dest_port) == 4500 || ntohs(sic.dest_port) == 500) { + if (likely(is_v4)) + DEBUG_TRACE("IPsec bypass: %pI4:%d(%pI4:%d) to %pI4:%d(%pI4:%d)\n", + &sic.src_ip.ip, ntohs(sic.src_port), &sic.src_ip_xlate.ip, ntohs(sic.src_port_xlate), + &sic.dest_ip.ip, ntohs(sic.dest_port), &sic.dest_ip_xlate.ip, ntohs(sic.dest_port_xlate)); + else + DEBUG_TRACE("IPsec bypass: %pI6:%d to %pI6:%d\n", + &sic.src_ip.ip6, ntohs(sic.src_port), &sic.dest_ip.ip6, ntohs(sic.dest_port)); + return NF_ACCEPT; + } + break; + + case IPPROTO_UDP: + sic.src_port = orig_tuple.src.u.udp.port; + sic.dest_port = orig_tuple.dst.u.udp.port; + sic.src_port_xlate = reply_tuple.dst.u.udp.port; + sic.dest_port_xlate = reply_tuple.src.u.udp.port; + break; + + default: + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_UNKNOW_PROTOCOL); + DEBUG_TRACE("unhandled protocol %d\n", sic.protocol); + return NF_ACCEPT; + } + +#ifdef CONFIG_XFRM + sic.original_accel = 1; + sic.reply_accel = 1; + + /* + * For packets de-capsulated from xfrm, we still can accelerate it + * on the direction we just received the packet. + */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)) + if (unlikely(skb->sp)) { +#else + if (unlikely(secpath_exists(skb))) { +#endif + if (sic.protocol == IPPROTO_TCP && + !(sic.flags & SFE_CREATE_FLAG_NO_SEQ_CHECK)) { + return NF_ACCEPT; + } + + if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) { + sic.reply_accel = 0; + } else { + sic.original_accel = 0; + } + } +#endif + + /* + * Get QoS information + */ + if (skb->priority) { + sic.dest_priority = skb->priority; + sic.src_priority = sic.dest_priority; + sic.flags |= SFE_CREATE_FLAG_REMARK_PRIORITY; + } + + /* + * Get the net device and MAC addresses that correspond to the various source and + * destination host addresses. + */ + if (!sfe_cm_find_dev_and_mac_addr(NULL, &sic.src_ip, &src_dev_tmp, sic.src_mac, is_v4)) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_SRC_DEV); + return NF_ACCEPT; + } + src_dev = src_dev_tmp; + + if (!sfe_cm_find_dev_and_mac_addr(NULL, &sic.src_ip_xlate, &dev, sic.src_mac_xlate, is_v4)) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_SRC_XLATE_DEV); + goto done1; + } + dev_put(dev); + /* Somehow, for IPv6, we need this workaround as well */ + if (unlikely(!is_v4)) + tmp_skb = skb; + if (!sfe_cm_find_dev_and_mac_addr(tmp_skb, &sic.dest_ip, &dev, sic.dest_mac, is_v4)) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_DEST_DEV); + goto done1; + } + dev_put(dev); + + if (!sfe_cm_find_dev_and_mac_addr(skb, &sic.dest_ip_xlate, &dest_dev_tmp, sic.dest_mac_xlate, is_v4)) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_DEST_XLATE_DEV); + goto done1; + } + dest_dev = dest_dev_tmp; + + /* + * Our devices may actually be part of a bridge interface. If that's + * the case then find the bridge interface instead. + */ + if (src_dev->priv_flags & IFF_BRIDGE_PORT) { + src_br_dev = sfe_dev_get_master(src_dev); + if (!src_br_dev) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_BRIDGE); + DEBUG_TRACE("no bridge found for: %s\n", src_dev->name); + goto done2; + } + src_dev = src_br_dev; + } + + if (dest_dev->priv_flags & IFF_BRIDGE_PORT) { + dest_br_dev = sfe_dev_get_master(dest_dev); + if (!dest_br_dev) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_BRIDGE); + DEBUG_TRACE("no bridge found for: %s\n", dest_dev->name); + goto done3; + } + dest_dev = dest_br_dev; + } + + sic.src_dev = src_dev; + sic.dest_dev = dest_dev; + + sic.src_mtu = src_dev->mtu; + sic.dest_mtu = dest_dev->mtu; + + if (likely(is_v4)) { + sfe_ipv4_create_rule(&sic); + } else { + sfe_ipv6_create_rule(&sic); + } + + /* + * If we had bridge ports then release them too. + */ + if (dest_br_dev) { + dev_put(dest_br_dev); + } +done3: + if (src_br_dev) { + dev_put(src_br_dev); + } +done2: + dev_put(dest_dev_tmp); +done1: + dev_put(src_dev_tmp); + + return NF_ACCEPT; +} + +/* + * sfe_cm_ipv4_post_routing_hook() + * Called for packets about to leave the box - either locally generated or forwarded from another interface + */ +sfe_cm_ipv4_post_routing_hook(hooknum, ops, skb, in_unused, out, okfn) +{ + return sfe_cm_post_routing(skb, true); +} + +/* + * sfe_cm_ipv6_post_routing_hook() + * Called for packets about to leave the box - either locally generated or forwarded from another interface + */ +sfe_cm_ipv6_post_routing_hook(hooknum, ops, skb, in_unused, out, okfn) +{ + return sfe_cm_post_routing(skb, false); +} + +#ifdef CONFIG_NF_CONNTRACK_EVENTS +/* + * sfe_cm_conntrack_event() + * Callback event invoked when a conntrack connection's state changes. + */ +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS +static int sfe_cm_conntrack_event(struct notifier_block *this, + unsigned long events, void *ptr) +#else +static int sfe_cm_conntrack_event(unsigned int events, struct nf_ct_event *item) +#endif +{ +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS + struct nf_ct_event *item = ptr; +#endif + struct sfe_connection_destroy sid; + struct nf_conn *ct = item->ct; + struct nf_conntrack_tuple orig_tuple; + + /* + * If we don't have a conntrack entry then we're done. + */ + if (unlikely(!ct)) { + DEBUG_WARN("no ct in conntrack event callback\n"); + return NOTIFY_DONE; + } + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) + if (unlikely(nf_ct_is_untracked(ct))) { + DEBUG_TRACE("ignoring untracked conn\n"); + return NOTIFY_DONE; + } +#endif + + /* + * We're only interested in destroy events. + */ + if (unlikely(!(events & (1 << IPCT_DESTROY)))) { + DEBUG_TRACE("ignoring non-destroy event\n"); + return NOTIFY_DONE; + } + + orig_tuple = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; + sid.protocol = (s32)orig_tuple.dst.protonum; + + /* + * Extract information from the conntrack connection. We're only interested + * in nominal connection information (i.e. we're ignoring any NAT information). + */ + switch (sid.protocol) { + case IPPROTO_TCP: + sid.src_port = orig_tuple.src.u.tcp.port; + sid.dest_port = orig_tuple.dst.u.tcp.port; + break; + + case IPPROTO_UDP: + sid.src_port = orig_tuple.src.u.udp.port; + sid.dest_port = orig_tuple.dst.u.udp.port; + break; + + default: + DEBUG_TRACE("unhandled protocol: %d\n", sid.protocol); + return NOTIFY_DONE; + } + + if (likely(nf_ct_l3num(ct) == AF_INET)) { + sid.src_ip.ip = (__be32)orig_tuple.src.u3.ip; + sid.dest_ip.ip = (__be32)orig_tuple.dst.u3.ip; + + sfe_ipv4_destroy_rule(&sid); + } else if (likely(nf_ct_l3num(ct) == AF_INET6)) { + sid.src_ip.ip6[0] = *((struct sfe_ipv6_addr *)&orig_tuple.src.u3.in6); + sid.dest_ip.ip6[0] = *((struct sfe_ipv6_addr *)&orig_tuple.dst.u3.in6); + + sfe_ipv6_destroy_rule(&sid); + } else { + DEBUG_TRACE("ignoring non-IPv4 and non-IPv6 connection\n"); + } + + return NOTIFY_DONE; +} + +/* + * Netfilter conntrack event system to monitor connection tracking changes + */ +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS +static struct notifier_block sfe_cm_conntrack_notifier = { + .notifier_call = sfe_cm_conntrack_event, +}; +#else +static struct nf_ct_event_notifier sfe_cm_conntrack_notifier = { + .fcn = sfe_cm_conntrack_event, +}; +#endif +#endif + +/* + * Structure to establish a hook into the post routing netfilter point - this + * will pick up local outbound and packets going from one interface to another. + * + * Note: see include/linux/netfilter_ipv4.h for info related to priority levels. + * We want to examine packets after NAT translation and any ALG processing. + */ +static struct nf_hook_ops sfe_cm_ops_post_routing[] __read_mostly = { + SFE_IPV4_NF_POST_ROUTING_HOOK(__sfe_cm_ipv4_post_routing_hook), +#ifdef SFE_SUPPORT_IPV6 + SFE_IPV6_NF_POST_ROUTING_HOOK(__sfe_cm_ipv6_post_routing_hook), +#endif +}; + +/* + * sfe_cm_sync_rule() + * Synchronize a connection's state. + */ +static void sfe_cm_sync_rule(struct sfe_connection_sync *sis) +{ + struct nf_conntrack_tuple_hash *h; + struct nf_conntrack_tuple tuple; + struct nf_conn *ct; + SFE_NF_CONN_ACCT(acct); + + /* + * Create a tuple so as to be able to look up a connection + */ + memset(&tuple, 0, sizeof(tuple)); + tuple.src.u.all = (__be16)sis->src_port; + tuple.dst.dir = IP_CT_DIR_ORIGINAL; + tuple.dst.protonum = (u8)sis->protocol; + tuple.dst.u.all = (__be16)sis->dest_port; + + if (sis->is_v6) { + tuple.src.u3.in6 = *((struct in6_addr *)sis->src_ip.ip6); + tuple.dst.u3.in6 = *((struct in6_addr *)sis->dest_ip.ip6); + tuple.src.l3num = AF_INET6; + + DEBUG_TRACE("update connection - p: %d, s: %pI6:%u, d: %pI6:%u\n", + (int)tuple.dst.protonum, + &tuple.src.u3.in6, (unsigned int)ntohs(tuple.src.u.all), + &tuple.dst.u3.in6, (unsigned int)ntohs(tuple.dst.u.all)); + } else { + tuple.src.u3.ip = sis->src_ip.ip; + tuple.dst.u3.ip = sis->dest_ip.ip; + tuple.src.l3num = AF_INET; + + DEBUG_TRACE("update connection - p: %d, s: %pI4:%u, d: %pI4:%u\n", + (int)tuple.dst.protonum, + &tuple.src.u3.ip, (unsigned int)ntohs(tuple.src.u.all), + &tuple.dst.u3.ip, (unsigned int)ntohs(tuple.dst.u.all)); + } + + /* + * Look up conntrack connection + */ + h = nf_conntrack_find_get(&init_net, SFE_NF_CT_DEFAULT_ZONE, &tuple); + if (unlikely(!h)) { + DEBUG_TRACE("no connection found\n"); + return; + } + + ct = nf_ct_tuplehash_to_ctrack(h); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)) + NF_CT_ASSERT(ct->timeout.data == (unsigned long)ct); +#endif + /* + * Only update if this is not a fixed timeout + */ + if (!test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) { + spin_lock_bh(&ct->lock); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)) + ct->timeout.expires += sis->delta_jiffies; +#else + ct->timeout += sis->delta_jiffies; +#endif + spin_unlock_bh(&ct->lock); + } + + acct = nf_conn_acct_find(ct); + if (acct) { + spin_lock_bh(&ct->lock); + atomic64_add(sis->src_new_packet_count, &SFE_ACCT_COUNTER(acct)[IP_CT_DIR_ORIGINAL].packets); + atomic64_add(sis->src_new_byte_count, &SFE_ACCT_COUNTER(acct)[IP_CT_DIR_ORIGINAL].bytes); + atomic64_add(sis->dest_new_packet_count, &SFE_ACCT_COUNTER(acct)[IP_CT_DIR_REPLY].packets); + atomic64_add(sis->dest_new_byte_count, &SFE_ACCT_COUNTER(acct)[IP_CT_DIR_REPLY].bytes); + spin_unlock_bh(&ct->lock); + } + + switch (sis->protocol) { + case IPPROTO_TCP: + spin_lock_bh(&ct->lock); + if (ct->proto.tcp.seen[0].td_maxwin < sis->src_td_max_window) { + ct->proto.tcp.seen[0].td_maxwin = sis->src_td_max_window; + } + if ((s32)(ct->proto.tcp.seen[0].td_end - sis->src_td_end) < 0) { + ct->proto.tcp.seen[0].td_end = sis->src_td_end; + } + if ((s32)(ct->proto.tcp.seen[0].td_maxend - sis->src_td_max_end) < 0) { + ct->proto.tcp.seen[0].td_maxend = sis->src_td_max_end; + } + if (ct->proto.tcp.seen[1].td_maxwin < sis->dest_td_max_window) { + ct->proto.tcp.seen[1].td_maxwin = sis->dest_td_max_window; + } + if ((s32)(ct->proto.tcp.seen[1].td_end - sis->dest_td_end) < 0) { + ct->proto.tcp.seen[1].td_end = sis->dest_td_end; + } + if ((s32)(ct->proto.tcp.seen[1].td_maxend - sis->dest_td_max_end) < 0) { + ct->proto.tcp.seen[1].td_maxend = sis->dest_td_max_end; + } + spin_unlock_bh(&ct->lock); + break; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) + case IPPROTO_UDP: + /* + * In Linux connection track, UDP flow has two timeout values: + * /proc/sys/net/netfilter/nf_conntrack_udp_timeout: + * this is for uni-direction UDP flow, normally its value is 60 seconds + * /proc/sys/net/netfilter/nf_conntrack_udp_timeout_stream: + * this is for bi-direction UDP flow, normally its value is 180 seconds + * + * Linux will update timer of UDP flow to stream timeout once it seen packets + * in reply direction. But if flow is accelerated by NSS or SFE, Linux won't + * see any packets. So we have to do the same thing in our stats sync message. + */ + if (!test_bit(IPS_ASSURED_BIT, &ct->status) && acct) { + u_int64_t reply_pkts = atomic64_read(&SFE_ACCT_COUNTER(acct)[IP_CT_DIR_REPLY].packets); + + if (reply_pkts != 0) { + unsigned int *timeouts; + struct nf_conntrack_l4proto *l4proto __maybe_unused; + set_bit(IPS_SEEN_REPLY_BIT, &ct->status); + set_bit(IPS_ASSURED_BIT, &ct->status); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)) + l4proto = __nf_ct_l4proto_find((sis->is_v6 ? AF_INET6 : AF_INET), IPPROTO_UDP); + timeouts = nf_ct_timeout_lookup(&init_net, ct, l4proto); + spin_lock_bh(&ct->lock); + ct->timeout.expires = jiffies + timeouts[UDP_CT_REPLIED]; + spin_unlock_bh(&ct->lock); +#else + timeouts = nf_ct_timeout_lookup(ct); + if (!timeouts) { + timeouts = nf_udp_pernet(nf_ct_net(ct))->timeouts; + } + + spin_lock_bh(&ct->lock); + ct->timeout = jiffies + timeouts[UDP_CT_REPLIED]; + spin_unlock_bh(&ct->lock); +#endif + } + } + break; +#endif /*KERNEL_VERSION(3, 4, 0)*/ + } + + /* + * Release connection + */ + nf_ct_put(ct); +} + +/* + * sfe_cm_device_event() + */ +int sfe_cm_device_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct net_device *dev = SFE_DEV_EVENT_PTR(ptr); + + if (dev && (event == NETDEV_DOWN)) { + sfe_ipv4_destroy_all_rules_for_dev(dev); + sfe_ipv6_destroy_all_rules_for_dev(dev); + } + + return NOTIFY_DONE; +} + +/* + * sfe_cm_inet_event() + */ +static int sfe_cm_inet_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev; + + if (dev && (event == NETDEV_DOWN)) { + sfe_ipv4_destroy_all_rules_for_dev(dev); + } + + return NOTIFY_DONE; +} + +/* + * sfe_cm_inet6_event() + */ +static int sfe_cm_inet6_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct net_device *dev = ((struct inet6_ifaddr *)ptr)->idev->dev; + + if (dev && (event == NETDEV_DOWN)) { + sfe_ipv6_destroy_all_rules_for_dev(dev); + } + + return NOTIFY_DONE; +} + +/* + * sfe_cm_get_exceptions + * dump exception counters + */ +static ssize_t sfe_cm_get_exceptions(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int idx, len; + struct sfe_cm *sc = &__sc; + + spin_lock_bh(&sc->lock); + for (len = 0, idx = 0; idx < SFE_CM_EXCEPTION_MAX; idx++) { + if (sc->exceptions[idx]) { + len += snprintf(buf + len, (ssize_t)(PAGE_SIZE - len), "%s = %d\n", sfe_cm_exception_events_string[idx], sc->exceptions[idx]); + } + } + spin_unlock_bh(&sc->lock); + + return len; +} + +/* + * sysfs attributes. + */ +static const struct device_attribute sfe_cm_exceptions_attr = + __ATTR(exceptions, S_IRUGO, sfe_cm_get_exceptions, NULL); + +/* + * sfe_cm_init() + */ +static int __init sfe_cm_init(void) +{ + struct sfe_cm *sc = &__sc; + int result = -1; +#ifdef CONFIG_SFE_ECM + int (*fast_recv)(struct sk_buff *skb); +#endif + + DEBUG_INFO("SFE CM init\n"); + + /* + * Create sys/sfe_cm + */ + sc->sys_sfe_cm = kobject_create_and_add("sfe_cm", NULL); + if (!sc->sys_sfe_cm) { + DEBUG_ERROR("failed to register sfe_cm\n"); + goto exit1; + } + + /* + * Create sys/sfe_cm/exceptions + */ + result = sysfs_create_file(sc->sys_sfe_cm, &sfe_cm_exceptions_attr.attr); + if (result) { + DEBUG_ERROR("failed to register exceptions file: %d\n", result); + goto exit2; + } + + sc->dev_notifier.notifier_call = sfe_cm_device_event; + sc->dev_notifier.priority = 1; + register_netdevice_notifier(&sc->dev_notifier); + + sc->inet_notifier.notifier_call = sfe_cm_inet_event; + sc->inet_notifier.priority = 1; + register_inetaddr_notifier(&sc->inet_notifier); + + sc->inet6_notifier.notifier_call = sfe_cm_inet6_event; + sc->inet6_notifier.priority = 1; + register_inet6addr_notifier(&sc->inet6_notifier); + /* + * Register our netfilter hooks. + */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)) + result = nf_register_hooks(sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing)); +#else + result = nf_register_net_hooks(&init_net, sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing)); +#endif + if (result < 0) { + DEBUG_ERROR("can't register nf post routing hook: %d\n", result); + goto exit3; + } + + /* + * Register a notifier hook to get fast notifications of expired connections. + * Note: In CONFIG_NF_CONNTRACK_CHAIN_EVENTS enabled case, nf_conntrack_register_notifier() + * function always returns 0. + */ +#ifdef CONFIG_NF_CONNTRACK_EVENTS +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS + result = nf_conntrack_register_chain_notifier(&init_net, &sfe_cm_conntrack_notifier); +#else + result = nf_conntrack_register_notifier(&init_net, &sfe_cm_conntrack_notifier); +#endif + if (result < 0) { + DEBUG_ERROR("can't register nf notifier hook: %d\n", result); + goto exit4; + } +#endif + spin_lock_init(&sc->lock); + + /* + * Hook the receive path in the network stack. + */ +#ifdef CONFIG_SFE_ECM + rcu_read_lock(); + fast_recv = rcu_dereference(athrs_fast_nat_recv); + rcu_read_unlock(); + if (!fast_recv) { + BUG_ON(athrs_fast_nat_recv); + } +#else + BUG_ON(athrs_fast_nat_recv); +#endif + RCU_INIT_POINTER(athrs_fast_nat_recv, sfe_cm_recv); + + /* + * Hook the shortcut sync callback. + */ + sfe_ipv4_register_sync_rule_callback(sfe_cm_sync_rule); + sfe_ipv6_register_sync_rule_callback(sfe_cm_sync_rule); + return 0; + +#ifdef CONFIG_NF_CONNTRACK_EVENTS +exit4: +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)) + nf_unregister_hooks(sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing)); +#else + nf_unregister_net_hooks(&init_net, sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing)); +#endif + +#endif +#endif +exit3: + unregister_inet6addr_notifier(&sc->inet6_notifier); + unregister_inetaddr_notifier(&sc->inet_notifier); + unregister_netdevice_notifier(&sc->dev_notifier); +exit2: + kobject_put(sc->sys_sfe_cm); + +exit1: + return result; +} + +/* + * sfe_cm_exit() + */ +static void __exit sfe_cm_exit(void) +{ + struct sfe_cm *sc = &__sc; + + DEBUG_INFO("SFE CM exit\n"); + + /* + * Unregister our sync callback. + */ + sfe_ipv4_register_sync_rule_callback(NULL); + sfe_ipv6_register_sync_rule_callback(NULL); + + /* + * Unregister our receive callback. + */ + RCU_INIT_POINTER(athrs_fast_nat_recv, NULL); + + /* + * Wait for all callbacks to complete. + */ + rcu_barrier(); + + /* + * Destroy all connections. + */ + sfe_ipv4_destroy_all_rules_for_dev(NULL); + sfe_ipv6_destroy_all_rules_for_dev(NULL); + +#ifdef CONFIG_NF_CONNTRACK_EVENTS +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS + nf_conntrack_unregister_chain_notifier(&init_net, &sfe_cm_conntrack_notifier); +#else + nf_conntrack_unregister_notifier(&init_net, &sfe_cm_conntrack_notifier); +#endif +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)) + nf_unregister_hooks(sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing)); +#else + nf_unregister_net_hooks(&init_net, sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing)); +#endif + unregister_inet6addr_notifier(&sc->inet6_notifier); + unregister_inetaddr_notifier(&sc->inet_notifier); + unregister_netdevice_notifier(&sc->dev_notifier); + + kobject_put(sc->sys_sfe_cm); +} + +module_init(sfe_cm_init) +module_exit(sfe_cm_exit) + +MODULE_DESCRIPTION("Shortcut Forwarding Engine - Connection Manager"); +MODULE_LICENSE("Dual BSD/GPL"); + diff --git a/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_cm.h b/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_cm.h new file mode 100644 index 00000000..124c86f4 --- /dev/null +++ b/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_cm.h @@ -0,0 +1,260 @@ +/* + * sfe_cm.h + * Shortcut forwarding engine. + * + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * connection flags. + */ +#define SFE_CREATE_FLAG_NO_SEQ_CHECK BIT(0) + /* Indicates that we should not check sequence numbers */ +#define SFE_CREATE_FLAG_REMARK_PRIORITY BIT(1) + /* Indicates that we should remark priority of skb */ +#define SFE_CREATE_FLAG_REMARK_DSCP BIT(2) + /* Indicates that we should remark DSCP of packet */ + +/* + * IPv6 address structure + */ +struct sfe_ipv6_addr { + __be32 addr[4]; +}; + +typedef union { + __be32 ip; + struct sfe_ipv6_addr ip6[1]; +} sfe_ip_addr_t; + +/* + * connection creation structure. + */ +struct sfe_connection_create { + int protocol; + struct net_device *src_dev; + struct net_device *dest_dev; + u32 flags; + u32 src_mtu; + u32 dest_mtu; + sfe_ip_addr_t src_ip; + sfe_ip_addr_t src_ip_xlate; + sfe_ip_addr_t dest_ip; + sfe_ip_addr_t dest_ip_xlate; + __be16 src_port; + __be16 src_port_xlate; + __be16 dest_port; + __be16 dest_port_xlate; + u8 src_mac[ETH_ALEN]; + u8 src_mac_xlate[ETH_ALEN]; + u8 dest_mac[ETH_ALEN]; + u8 dest_mac_xlate[ETH_ALEN]; + u8 src_td_window_scale; + u32 src_td_max_window; + u32 src_td_end; + u32 src_td_max_end; + u8 dest_td_window_scale; + u32 dest_td_max_window; + u32 dest_td_end; + u32 dest_td_max_end; + u32 mark; +#ifdef CONFIG_XFRM + u32 original_accel; + u32 reply_accel; +#endif + u32 src_priority; + u32 dest_priority; + u32 src_dscp; + u32 dest_dscp; +}; + +/* + * connection destruction structure. + */ +struct sfe_connection_destroy { + int protocol; + sfe_ip_addr_t src_ip; + sfe_ip_addr_t dest_ip; + __be16 src_port; + __be16 dest_port; +}; + +typedef enum sfe_sync_reason { + SFE_SYNC_REASON_STATS, /* Sync is to synchronize stats */ + SFE_SYNC_REASON_FLUSH, /* Sync is to flush a entry */ + SFE_SYNC_REASON_DESTROY /* Sync is to destroy a entry(requested by connection manager) */ +} sfe_sync_reason_t; + +/* + * Structure used to sync connection stats/state back within the system. + * + * NOTE: The addresses here are NON-NAT addresses, i.e. the true endpoint addressing. + * 'src' is the creator of the connection. + */ +struct sfe_connection_sync { + struct net_device *src_dev; + struct net_device *dest_dev; + int is_v6; /* Is it for ipv6? */ + int protocol; /* IP protocol number (IPPROTO_...) */ + sfe_ip_addr_t src_ip; /* Non-NAT source address, i.e. the creator of the connection */ + sfe_ip_addr_t src_ip_xlate; /* NATed source address */ + __be16 src_port; /* Non-NAT source port */ + __be16 src_port_xlate; /* NATed source port */ + sfe_ip_addr_t dest_ip; /* Non-NAT destination address, i.e. to whom the connection was created */ + sfe_ip_addr_t dest_ip_xlate; /* NATed destination address */ + __be16 dest_port; /* Non-NAT destination port */ + __be16 dest_port_xlate; /* NATed destination port */ + u32 src_td_max_window; + u32 src_td_end; + u32 src_td_max_end; + u64 src_packet_count; + u64 src_byte_count; + u32 src_new_packet_count; + u32 src_new_byte_count; + u32 dest_td_max_window; + u32 dest_td_end; + u32 dest_td_max_end; + u64 dest_packet_count; + u64 dest_byte_count; + u32 dest_new_packet_count; + u32 dest_new_byte_count; + u32 reason; /* reason for stats sync message, i.e. destroy, flush, period sync */ + u64 delta_jiffies; /* Time to be added to the current timeout to keep the connection alive */ +}; + +/* + * connection mark structure + */ +struct sfe_connection_mark { + int protocol; + sfe_ip_addr_t src_ip; + sfe_ip_addr_t dest_ip; + __be16 src_port; + __be16 dest_port; + u32 mark; +}; + +/* + * Expose the hook for the receive processing. + */ +extern int (*athrs_fast_nat_recv)(struct sk_buff *skb); + +/* + * Expose what should be a static flag in the TCP connection tracker. + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0) +extern int nf_ct_tcp_no_window_check; +#endif +/* + * This callback will be called in a timer + * at 100 times per second to sync stats back to + * Linux connection track. + * + * A RCU lock is taken to prevent this callback + * from unregistering. + */ +typedef void (*sfe_sync_rule_callback_t)(struct sfe_connection_sync *); + +/* + * IPv4 APIs used by connection manager + */ +int sfe_ipv4_recv(struct net_device *dev, struct sk_buff *skb); +int sfe_ipv4_create_rule(struct sfe_connection_create *sic); +void sfe_ipv4_destroy_rule(struct sfe_connection_destroy *sid); +void sfe_ipv4_destroy_all_rules_for_dev(struct net_device *dev); +void sfe_ipv4_register_sync_rule_callback(sfe_sync_rule_callback_t callback); +void sfe_ipv4_update_rule(struct sfe_connection_create *sic); +void sfe_ipv4_mark_rule(struct sfe_connection_mark *mark); + +#ifdef SFE_SUPPORT_IPV6 +/* + * IPv6 APIs used by connection manager + */ +int sfe_ipv6_recv(struct net_device *dev, struct sk_buff *skb); +int sfe_ipv6_create_rule(struct sfe_connection_create *sic); +void sfe_ipv6_destroy_rule(struct sfe_connection_destroy *sid); +void sfe_ipv6_destroy_all_rules_for_dev(struct net_device *dev); +void sfe_ipv6_register_sync_rule_callback(sfe_sync_rule_callback_t callback); +void sfe_ipv6_update_rule(struct sfe_connection_create *sic); +void sfe_ipv6_mark_rule(struct sfe_connection_mark *mark); +#else +static inline int sfe_ipv6_recv(struct net_device *dev, struct sk_buff *skb) +{ + return 0; +} + +static inline int sfe_ipv6_create_rule(struct sfe_connection_create *sic) +{ + return 0; +} + +static inline void sfe_ipv6_destroy_rule(struct sfe_connection_destroy *sid) +{ + return; +} + +static inline void sfe_ipv6_destroy_all_rules_for_dev(struct net_device *dev) +{ + return; +} + +static inline void sfe_ipv6_register_sync_rule_callback(sfe_sync_rule_callback_t callback) +{ + return; +} + +static inline void sfe_ipv6_update_rule(struct sfe_connection_create *sic) +{ + return; +} + +static inline void sfe_ipv6_mark_rule(struct sfe_connection_mark *mark) +{ + return; +} +#endif + +/* + * sfe_ipv6_addr_equal() + * compare ipv6 address + * + * return: 1, equal; 0, no equal + */ +static inline int sfe_ipv6_addr_equal(struct sfe_ipv6_addr *a, + struct sfe_ipv6_addr *b) +{ + return a->addr[0] == b->addr[0] && + a->addr[1] == b->addr[1] && + a->addr[2] == b->addr[2] && + a->addr[3] == b->addr[3]; +} + +/* + * sfe_ipv4_addr_equal() + * compare ipv4 address + * + * return: 1, equal; 0, no equal + */ +#define sfe_ipv4_addr_equal(a, b) ((u32)(a) == (u32)(b)) + +/* + * sfe_addr_equal() + * compare ipv4 or ipv6 address + * + * return: 1, equal; 0, no equal + */ +static inline int sfe_addr_equal(sfe_ip_addr_t *a, + sfe_ip_addr_t *b, int is_v4) +{ + return is_v4 ? sfe_ipv4_addr_equal(a->ip, b->ip) : sfe_ipv6_addr_equal(a->ip6, b->ip6); +} diff --git a/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_ipv4.c b/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_ipv4.c new file mode 100644 index 00000000..cdcdd66d --- /dev/null +++ b/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_ipv4.c @@ -0,0 +1,3618 @@ +/* + * sfe_ipv4.c + * Shortcut forwarding engine - IPv4 edition. + * + * Copyright (c) 2013-2016, 2019-2020 The Linux Foundation. All rights reserved. + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "sfe.h" +#include "sfe_cm.h" + +/* + * By default Linux IP header and transport layer header structures are + * unpacked, assuming that such headers should be 32-bit aligned. + * Unfortunately some wireless adaptors can't cope with this requirement and + * some CPUs can't handle misaligned accesses. For those platforms we + * define SFE_IPV4_UNALIGNED_IP_HEADER and mark the structures as packed. + * When we do this the compiler will generate slightly worse code than for the + * aligned case (on most platforms) but will be much quicker than fixing + * things up in an unaligned trap handler. + */ +#define SFE_IPV4_UNALIGNED_IP_HEADER 1 +#if SFE_IPV4_UNALIGNED_IP_HEADER +#define SFE_IPV4_UNALIGNED_STRUCT __attribute__((packed)) +#else +#define SFE_IPV4_UNALIGNED_STRUCT +#endif + +/* + * An Ethernet header, but with an optional "packed" attribute to + * help with performance on some platforms (see the definition of + * SFE_IPV4_UNALIGNED_STRUCT) + */ +struct sfe_ipv4_eth_hdr { + __be16 h_dest[ETH_ALEN / 2]; + __be16 h_source[ETH_ALEN / 2]; + __be16 h_proto; +} SFE_IPV4_UNALIGNED_STRUCT; + +#define SFE_IPV4_DSCP_MASK 0x3 +#define SFE_IPV4_DSCP_SHIFT 2 + +/* + * An IPv4 header, but with an optional "packed" attribute to + * help with performance on some platforms (see the definition of + * SFE_IPV4_UNALIGNED_STRUCT) + */ +struct sfe_ipv4_ip_hdr { +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u8 ihl:4, + version:4; +#elif defined (__BIG_ENDIAN_BITFIELD) + __u8 version:4, + ihl:4; +#else +#error "Please fix " +#endif + __u8 tos; + __be16 tot_len; + __be16 id; + __be16 frag_off; + __u8 ttl; + __u8 protocol; + __sum16 check; + __be32 saddr; + __be32 daddr; + + /* + * The options start here. + */ +} SFE_IPV4_UNALIGNED_STRUCT; + +/* + * A UDP header, but with an optional "packed" attribute to + * help with performance on some platforms (see the definition of + * SFE_IPV4_UNALIGNED_STRUCT) + */ +struct sfe_ipv4_udp_hdr { + __be16 source; + __be16 dest; + __be16 len; + __sum16 check; +} SFE_IPV4_UNALIGNED_STRUCT; + +/* + * A TCP header, but with an optional "packed" attribute to + * help with performance on some platforms (see the definition of + * SFE_IPV4_UNALIGNED_STRUCT) + */ +struct sfe_ipv4_tcp_hdr { + __be16 source; + __be16 dest; + __be32 seq; + __be32 ack_seq; +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u16 res1:4, + doff:4, + fin:1, + syn:1, + rst:1, + psh:1, + ack:1, + urg:1, + ece:1, + cwr:1; +#elif defined(__BIG_ENDIAN_BITFIELD) + __u16 doff:4, + res1:4, + cwr:1, + ece:1, + urg:1, + ack:1, + psh:1, + rst:1, + syn:1, + fin:1; +#else +#error "Adjust your defines" +#endif + __be16 window; + __sum16 check; + __be16 urg_ptr; +} SFE_IPV4_UNALIGNED_STRUCT; + +/* + * Specifies the lower bound on ACK numbers carried in the TCP header + */ +#define SFE_IPV4_TCP_MAX_ACK_WINDOW 65520 + +/* + * IPv4 TCP connection match additional data. + */ +struct sfe_ipv4_tcp_connection_match { + u8 win_scale; /* Window scale */ + u32 max_win; /* Maximum window size seen */ + u32 end; /* Sequence number of the next byte to send (seq + segment length) */ + u32 max_end; /* Sequence number of the last byte to ack */ +}; + +/* + * Bit flags for IPv4 connection matching entry. + */ +#define SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_SRC (1<<0) + /* Perform source translation */ +#define SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_DEST (1<<1) + /* Perform destination translation */ +#define SFE_IPV4_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK (1<<2) + /* Ignore TCP sequence numbers */ +#define SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR (1<<3) + /* Fast Ethernet header write */ +#define SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_L2_HDR (1<<4) + /* Fast Ethernet header write */ +#define SFE_IPV4_CONNECTION_MATCH_FLAG_PRIORITY_REMARK (1<<5) + /* remark priority of SKB */ +#define SFE_IPV4_CONNECTION_MATCH_FLAG_DSCP_REMARK (1<<6) + /* remark DSCP of packet */ + +/* + * IPv4 connection matching structure. + */ +struct sfe_ipv4_connection_match { + /* + * References to other objects. + */ + struct sfe_ipv4_connection_match *next; + struct sfe_ipv4_connection_match *prev; + struct sfe_ipv4_connection *connection; + struct sfe_ipv4_connection_match *counter_match; + /* Matches the flow in the opposite direction as the one in *connection */ + struct sfe_ipv4_connection_match *active_next; + struct sfe_ipv4_connection_match *active_prev; + bool active; /* Flag to indicate if we're on the active list */ + + /* + * Characteristics that identify flows that match this rule. + */ + struct net_device *match_dev; /* Network device */ + u8 match_protocol; /* Protocol */ + __be32 match_src_ip; /* Source IP address */ + __be32 match_dest_ip; /* Destination IP address */ + __be16 match_src_port; /* Source port/connection ident */ + __be16 match_dest_port; /* Destination port/connection ident */ + + /* + * Control the operations of the match. + */ + u32 flags; /* Bit flags */ +#ifdef CONFIG_NF_FLOW_COOKIE + u32 flow_cookie; /* used flow cookie, for debug */ +#endif +#ifdef CONFIG_XFRM + u32 flow_accel; /* The flow accelerated or not */ +#endif + + /* + * Connection state that we track once we match. + */ + union { /* Protocol-specific state */ + struct sfe_ipv4_tcp_connection_match tcp; + } protocol_state; + /* + * Stats recorded in a sync period. These stats will be added to + * rx_packet_count64/rx_byte_count64 after a sync period. + */ + u32 rx_packet_count; + u32 rx_byte_count; + + /* + * Packet translation information. + */ + __be32 xlate_src_ip; /* Address after source translation */ + __be16 xlate_src_port; /* Port/connection ident after source translation */ + u16 xlate_src_csum_adjustment; + /* Transport layer checksum adjustment after source translation */ + u16 xlate_src_partial_csum_adjustment; + /* Transport layer pseudo header checksum adjustment after source translation */ + + __be32 xlate_dest_ip; /* Address after destination translation */ + __be16 xlate_dest_port; /* Port/connection ident after destination translation */ + u16 xlate_dest_csum_adjustment; + /* Transport layer checksum adjustment after destination translation */ + u16 xlate_dest_partial_csum_adjustment; + /* Transport layer pseudo header checksum adjustment after destination translation */ + + /* + * QoS information + */ + u32 priority; + u32 dscp; + + /* + * Packet transmit information. + */ + struct net_device *xmit_dev; /* Network device on which to transmit */ + unsigned short int xmit_dev_mtu; + /* Interface MTU */ + u16 xmit_dest_mac[ETH_ALEN / 2]; + /* Destination MAC address to use when forwarding */ + u16 xmit_src_mac[ETH_ALEN / 2]; + /* Source MAC address to use when forwarding */ + + /* + * Summary stats. + */ + u64 rx_packet_count64; + u64 rx_byte_count64; +}; + +/* + * Per-connection data structure. + */ +struct sfe_ipv4_connection { + struct sfe_ipv4_connection *next; + /* Pointer to the next entry in a hash chain */ + struct sfe_ipv4_connection *prev; + /* Pointer to the previous entry in a hash chain */ + int protocol; /* IP protocol number */ + __be32 src_ip; /* Src IP addr pre-translation */ + __be32 src_ip_xlate; /* Src IP addr post-translation */ + __be32 dest_ip; /* Dest IP addr pre-translation */ + __be32 dest_ip_xlate; /* Dest IP addr post-translation */ + __be16 src_port; /* Src port pre-translation */ + __be16 src_port_xlate; /* Src port post-translation */ + __be16 dest_port; /* Dest port pre-translation */ + __be16 dest_port_xlate; /* Dest port post-translation */ + struct sfe_ipv4_connection_match *original_match; + /* Original direction matching structure */ + struct net_device *original_dev; + /* Original direction source device */ + struct sfe_ipv4_connection_match *reply_match; + /* Reply direction matching structure */ + struct net_device *reply_dev; /* Reply direction source device */ + u64 last_sync_jiffies; /* Jiffies count for the last sync */ + struct sfe_ipv4_connection *all_connections_next; + /* Pointer to the next entry in the list of all connections */ + struct sfe_ipv4_connection *all_connections_prev; + /* Pointer to the previous entry in the list of all connections */ + u32 mark; /* mark for outgoing packet */ + u32 debug_read_seq; /* sequence number for debug dump */ +}; + +/* + * IPv4 connections and hash table size information. + */ +#define SFE_IPV4_CONNECTION_HASH_SHIFT 12 +#define SFE_IPV4_CONNECTION_HASH_SIZE (1 << SFE_IPV4_CONNECTION_HASH_SHIFT) +#define SFE_IPV4_CONNECTION_HASH_MASK (SFE_IPV4_CONNECTION_HASH_SIZE - 1) + +#ifdef CONFIG_NF_FLOW_COOKIE +#define SFE_FLOW_COOKIE_SIZE 2048 +#define SFE_FLOW_COOKIE_MASK 0x7ff + +struct sfe_flow_cookie_entry { + struct sfe_ipv4_connection_match *match; + unsigned long last_clean_time; +}; +#endif + +enum sfe_ipv4_exception_events { + SFE_IPV4_EXCEPTION_EVENT_UDP_HEADER_INCOMPLETE, + SFE_IPV4_EXCEPTION_EVENT_UDP_NO_CONNECTION, + SFE_IPV4_EXCEPTION_EVENT_UDP_IP_OPTIONS_OR_INITIAL_FRAGMENT, + SFE_IPV4_EXCEPTION_EVENT_UDP_SMALL_TTL, + SFE_IPV4_EXCEPTION_EVENT_UDP_NEEDS_FRAGMENTATION, + SFE_IPV4_EXCEPTION_EVENT_TCP_HEADER_INCOMPLETE, + SFE_IPV4_EXCEPTION_EVENT_TCP_NO_CONNECTION_SLOW_FLAGS, + SFE_IPV4_EXCEPTION_EVENT_TCP_NO_CONNECTION_FAST_FLAGS, + SFE_IPV4_EXCEPTION_EVENT_TCP_IP_OPTIONS_OR_INITIAL_FRAGMENT, + SFE_IPV4_EXCEPTION_EVENT_TCP_SMALL_TTL, + SFE_IPV4_EXCEPTION_EVENT_TCP_NEEDS_FRAGMENTATION, + SFE_IPV4_EXCEPTION_EVENT_TCP_FLAGS, + SFE_IPV4_EXCEPTION_EVENT_TCP_SEQ_EXCEEDS_RIGHT_EDGE, + SFE_IPV4_EXCEPTION_EVENT_TCP_SMALL_DATA_OFFS, + SFE_IPV4_EXCEPTION_EVENT_TCP_BAD_SACK, + SFE_IPV4_EXCEPTION_EVENT_TCP_BIG_DATA_OFFS, + SFE_IPV4_EXCEPTION_EVENT_TCP_SEQ_BEFORE_LEFT_EDGE, + SFE_IPV4_EXCEPTION_EVENT_TCP_ACK_EXCEEDS_RIGHT_EDGE, + SFE_IPV4_EXCEPTION_EVENT_TCP_ACK_BEFORE_LEFT_EDGE, + SFE_IPV4_EXCEPTION_EVENT_ICMP_HEADER_INCOMPLETE, + SFE_IPV4_EXCEPTION_EVENT_ICMP_UNHANDLED_TYPE, + SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_HEADER_INCOMPLETE, + SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_NON_V4, + SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_IP_OPTIONS_INCOMPLETE, + SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_UDP_HEADER_INCOMPLETE, + SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_TCP_HEADER_INCOMPLETE, + SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_UNHANDLED_PROTOCOL, + SFE_IPV4_EXCEPTION_EVENT_ICMP_NO_CONNECTION, + SFE_IPV4_EXCEPTION_EVENT_ICMP_FLUSHED_CONNECTION, + SFE_IPV4_EXCEPTION_EVENT_HEADER_INCOMPLETE, + SFE_IPV4_EXCEPTION_EVENT_BAD_TOTAL_LENGTH, + SFE_IPV4_EXCEPTION_EVENT_NON_V4, + SFE_IPV4_EXCEPTION_EVENT_NON_INITIAL_FRAGMENT, + SFE_IPV4_EXCEPTION_EVENT_DATAGRAM_INCOMPLETE, + SFE_IPV4_EXCEPTION_EVENT_IP_OPTIONS_INCOMPLETE, + SFE_IPV4_EXCEPTION_EVENT_UNHANDLED_PROTOCOL, + SFE_IPV4_EXCEPTION_EVENT_CLONED_SKB_UNSHARE_ERROR, + SFE_IPV4_EXCEPTION_EVENT_LAST +}; + +static char *sfe_ipv4_exception_events_string[SFE_IPV4_EXCEPTION_EVENT_LAST] = { + "UDP_HEADER_INCOMPLETE", + "UDP_NO_CONNECTION", + "UDP_IP_OPTIONS_OR_INITIAL_FRAGMENT", + "UDP_SMALL_TTL", + "UDP_NEEDS_FRAGMENTATION", + "TCP_HEADER_INCOMPLETE", + "TCP_NO_CONNECTION_SLOW_FLAGS", + "TCP_NO_CONNECTION_FAST_FLAGS", + "TCP_IP_OPTIONS_OR_INITIAL_FRAGMENT", + "TCP_SMALL_TTL", + "TCP_NEEDS_FRAGMENTATION", + "TCP_FLAGS", + "TCP_SEQ_EXCEEDS_RIGHT_EDGE", + "TCP_SMALL_DATA_OFFS", + "TCP_BAD_SACK", + "TCP_BIG_DATA_OFFS", + "TCP_SEQ_BEFORE_LEFT_EDGE", + "TCP_ACK_EXCEEDS_RIGHT_EDGE", + "TCP_ACK_BEFORE_LEFT_EDGE", + "ICMP_HEADER_INCOMPLETE", + "ICMP_UNHANDLED_TYPE", + "ICMP_IPV4_HEADER_INCOMPLETE", + "ICMP_IPV4_NON_V4", + "ICMP_IPV4_IP_OPTIONS_INCOMPLETE", + "ICMP_IPV4_UDP_HEADER_INCOMPLETE", + "ICMP_IPV4_TCP_HEADER_INCOMPLETE", + "ICMP_IPV4_UNHANDLED_PROTOCOL", + "ICMP_NO_CONNECTION", + "ICMP_FLUSHED_CONNECTION", + "HEADER_INCOMPLETE", + "BAD_TOTAL_LENGTH", + "NON_V4", + "NON_INITIAL_FRAGMENT", + "DATAGRAM_INCOMPLETE", + "IP_OPTIONS_INCOMPLETE", + "UNHANDLED_PROTOCOL", + "CLONED_SKB_UNSHARE_ERROR" +}; + +/* + * Per-module structure. + */ +struct sfe_ipv4 { + spinlock_t lock; /* Lock for SMP correctness */ + struct sfe_ipv4_connection_match *active_head; + /* Head of the list of recently active connections */ + struct sfe_ipv4_connection_match *active_tail; + /* Tail of the list of recently active connections */ + struct sfe_ipv4_connection *all_connections_head; + /* Head of the list of all connections */ + struct sfe_ipv4_connection *all_connections_tail; + /* Tail of the list of all connections */ + unsigned int num_connections; /* Number of connections */ + struct timer_list timer; /* Timer used for periodic sync ops */ + sfe_sync_rule_callback_t __rcu sync_rule_callback; + /* Callback function registered by a connection manager for stats syncing */ + struct sfe_ipv4_connection *conn_hash[SFE_IPV4_CONNECTION_HASH_SIZE]; + /* Connection hash table */ + struct sfe_ipv4_connection_match *conn_match_hash[SFE_IPV4_CONNECTION_HASH_SIZE]; + /* Connection match hash table */ +#ifdef CONFIG_NF_FLOW_COOKIE + struct sfe_flow_cookie_entry sfe_flow_cookie_table[SFE_FLOW_COOKIE_SIZE]; + /* flow cookie table*/ + flow_cookie_set_func_t flow_cookie_set_func; + /* function used to configure flow cookie in hardware*/ + int flow_cookie_enable; + /* Enable/disable flow cookie at runtime */ +#endif + + /* + * Stats recorded in a sync period. These stats will be added to + * connection_xxx64 after a sync period. + */ + u32 connection_create_requests; + /* Number of IPv4 connection create requests */ + u32 connection_create_collisions; + /* Number of IPv4 connection create requests that collided with existing hash table entries */ + u32 connection_destroy_requests; + /* Number of IPv4 connection destroy requests */ + u32 connection_destroy_misses; + /* Number of IPv4 connection destroy requests that missed our hash table */ + u32 connection_match_hash_hits; + /* Number of IPv4 connection match hash hits */ + u32 connection_match_hash_reorders; + /* Number of IPv4 connection match hash reorders */ + u32 connection_flushes; /* Number of IPv4 connection flushes */ + u32 packets_forwarded; /* Number of IPv4 packets forwarded */ + u32 packets_not_forwarded; /* Number of IPv4 packets not forwarded */ + u32 exception_events[SFE_IPV4_EXCEPTION_EVENT_LAST]; + + /* + * Summary statistics. + */ + u64 connection_create_requests64; + /* Number of IPv4 connection create requests */ + u64 connection_create_collisions64; + /* Number of IPv4 connection create requests that collided with existing hash table entries */ + u64 connection_destroy_requests64; + /* Number of IPv4 connection destroy requests */ + u64 connection_destroy_misses64; + /* Number of IPv4 connection destroy requests that missed our hash table */ + u64 connection_match_hash_hits64; + /* Number of IPv4 connection match hash hits */ + u64 connection_match_hash_reorders64; + /* Number of IPv4 connection match hash reorders */ + u64 connection_flushes64; /* Number of IPv4 connection flushes */ + u64 packets_forwarded64; /* Number of IPv4 packets forwarded */ + u64 packets_not_forwarded64; + /* Number of IPv4 packets not forwarded */ + u64 exception_events64[SFE_IPV4_EXCEPTION_EVENT_LAST]; + + /* + * Control state. + */ + struct kobject *sys_sfe_ipv4; /* sysfs linkage */ + int debug_dev; /* Major number of the debug char device */ + u32 debug_read_seq; /* sequence number for debug dump */ +}; + +/* + * Enumeration of the XML output. + */ +enum sfe_ipv4_debug_xml_states { + SFE_IPV4_DEBUG_XML_STATE_START, + SFE_IPV4_DEBUG_XML_STATE_CONNECTIONS_START, + SFE_IPV4_DEBUG_XML_STATE_CONNECTIONS_CONNECTION, + SFE_IPV4_DEBUG_XML_STATE_CONNECTIONS_END, + SFE_IPV4_DEBUG_XML_STATE_EXCEPTIONS_START, + SFE_IPV4_DEBUG_XML_STATE_EXCEPTIONS_EXCEPTION, + SFE_IPV4_DEBUG_XML_STATE_EXCEPTIONS_END, + SFE_IPV4_DEBUG_XML_STATE_STATS, + SFE_IPV4_DEBUG_XML_STATE_END, + SFE_IPV4_DEBUG_XML_STATE_DONE +}; + +/* + * XML write state. + */ +struct sfe_ipv4_debug_xml_write_state { + enum sfe_ipv4_debug_xml_states state; + /* XML output file state machine state */ + int iter_exception; /* Next exception iterator */ +}; + +typedef bool (*sfe_ipv4_debug_xml_write_method_t)(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv4_debug_xml_write_state *ws); + +static struct sfe_ipv4 __si; + +/* + * sfe_ipv4_gen_ip_csum() + * Generate the IP checksum for an IPv4 header. + * + * Note that this function assumes that we have only 20 bytes of IP header. + */ +static inline u16 sfe_ipv4_gen_ip_csum(struct sfe_ipv4_ip_hdr *iph) +{ + u32 sum; + u16 *i = (u16 *)iph; + + iph->check = 0; + + /* + * Generate the sum. + */ + sum = i[0] + i[1] + i[2] + i[3] + i[4] + i[5] + i[6] + i[7] + i[8] + i[9]; + + /* + * Fold it to ones-complement form. + */ + sum = (sum & 0xffff) + (sum >> 16); + sum = (sum & 0xffff) + (sum >> 16); + + return (u16)sum ^ 0xffff; +} + +/* + * sfe_ipv4_get_connection_match_hash() + * Generate the hash used in connection match lookups. + */ +static inline unsigned int sfe_ipv4_get_connection_match_hash(struct net_device *dev, u8 protocol, + __be32 src_ip, __be16 src_port, + __be32 dest_ip, __be16 dest_port) +{ + size_t dev_addr = (size_t)dev; + u32 hash = ((u32)dev_addr) ^ ntohl(src_ip ^ dest_ip) ^ protocol ^ ntohs(src_port ^ dest_port); + return ((hash >> SFE_IPV4_CONNECTION_HASH_SHIFT) ^ hash) & SFE_IPV4_CONNECTION_HASH_MASK; +} + +/* + * sfe_ipv4_find_sfe_ipv4_connection_match() + * Get the IPv4 flow match info that corresponds to a particular 5-tuple. + * + * On entry we must be holding the lock that protects the hash table. + */ +static struct sfe_ipv4_connection_match * +sfe_ipv4_find_sfe_ipv4_connection_match(struct sfe_ipv4 *si, struct net_device *dev, u8 protocol, + __be32 src_ip, __be16 src_port, + __be32 dest_ip, __be16 dest_port) +{ + struct sfe_ipv4_connection_match *cm; + struct sfe_ipv4_connection_match *head; + unsigned int conn_match_idx; + + conn_match_idx = sfe_ipv4_get_connection_match_hash(dev, protocol, src_ip, src_port, dest_ip, dest_port); + cm = si->conn_match_hash[conn_match_idx]; + + /* + * If we don't have anything in this chain then bail. + */ + if (unlikely(!cm)) { + return NULL; + } + + /* + * Hopefully the first entry is the one we want. + */ + if ((cm->match_src_port == src_port) + && (cm->match_dest_port == dest_port) + && (cm->match_src_ip == src_ip) + && (cm->match_dest_ip == dest_ip) + && (cm->match_protocol == protocol) + && (cm->match_dev == dev)) { + si->connection_match_hash_hits++; + return cm; + } + + /* + * Unfortunately we didn't find it at head, so we search it in chain and + * move matching entry to the top of the hash chain. We presume that this + * will be reused again very quickly. + */ + head = cm; + do { + cm = cm->next; + } while (cm && (cm->match_src_port != src_port + || cm->match_dest_port != dest_port + || cm->match_src_ip != src_ip + || cm->match_dest_ip != dest_ip + || cm->match_protocol != protocol + || cm->match_dev != dev)); + + /* + * Not found then we're done. + */ + if (unlikely(!cm)) { + return NULL; + } + + /* + * We found a match so move it. + */ + if (cm->next) { + cm->next->prev = cm->prev; + } + cm->prev->next = cm->next; + cm->prev = NULL; + cm->next = head; + head->prev = cm; + si->conn_match_hash[conn_match_idx] = cm; + si->connection_match_hash_reorders++; + + return cm; +} + +/* + * sfe_ipv4_connection_match_update_summary_stats() + * Update the summary stats for a connection match entry. + */ +static inline void sfe_ipv4_connection_match_update_summary_stats(struct sfe_ipv4_connection_match *cm) +{ + cm->rx_packet_count64 += cm->rx_packet_count; + cm->rx_packet_count = 0; + cm->rx_byte_count64 += cm->rx_byte_count; + cm->rx_byte_count = 0; +} + +/* + * sfe_ipv4_connection_match_compute_translations() + * Compute port and address translations for a connection match entry. + */ +static void sfe_ipv4_connection_match_compute_translations(struct sfe_ipv4_connection_match *cm) +{ + /* + * Before we insert the entry look to see if this is tagged as doing address + * translations. If it is then work out the adjustment that we need to apply + * to the transport checksum. + */ + if (cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_SRC) { + /* + * Precompute an incremental checksum adjustment so we can + * edit packets in this stream very quickly. The algorithm is from RFC1624. + */ + u16 src_ip_hi = cm->match_src_ip >> 16; + u16 src_ip_lo = cm->match_src_ip & 0xffff; + u32 xlate_src_ip = ~cm->xlate_src_ip; + u16 xlate_src_ip_hi = xlate_src_ip >> 16; + u16 xlate_src_ip_lo = xlate_src_ip & 0xffff; + u16 xlate_src_port = ~cm->xlate_src_port; + u32 adj; + + /* + * When we compute this fold it down to a 16-bit offset + * as that way we can avoid having to do a double + * folding of the twos-complement result because the + * addition of 2 16-bit values cannot cause a double + * wrap-around! + */ + adj = src_ip_hi + src_ip_lo + cm->match_src_port + + xlate_src_ip_hi + xlate_src_ip_lo + xlate_src_port; + adj = (adj & 0xffff) + (adj >> 16); + adj = (adj & 0xffff) + (adj >> 16); + cm->xlate_src_csum_adjustment = (u16)adj; + + } + + if (cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_DEST) { + /* + * Precompute an incremental checksum adjustment so we can + * edit packets in this stream very quickly. The algorithm is from RFC1624. + */ + u16 dest_ip_hi = cm->match_dest_ip >> 16; + u16 dest_ip_lo = cm->match_dest_ip & 0xffff; + u32 xlate_dest_ip = ~cm->xlate_dest_ip; + u16 xlate_dest_ip_hi = xlate_dest_ip >> 16; + u16 xlate_dest_ip_lo = xlate_dest_ip & 0xffff; + u16 xlate_dest_port = ~cm->xlate_dest_port; + u32 adj; + + /* + * When we compute this fold it down to a 16-bit offset + * as that way we can avoid having to do a double + * folding of the twos-complement result because the + * addition of 2 16-bit values cannot cause a double + * wrap-around! + */ + adj = dest_ip_hi + dest_ip_lo + cm->match_dest_port + + xlate_dest_ip_hi + xlate_dest_ip_lo + xlate_dest_port; + adj = (adj & 0xffff) + (adj >> 16); + adj = (adj & 0xffff) + (adj >> 16); + cm->xlate_dest_csum_adjustment = (u16)adj; + } + + if (cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_SRC) { + u32 adj = ~cm->match_src_ip + cm->xlate_src_ip; + if (adj < cm->xlate_src_ip) { + adj++; + } + + adj = (adj & 0xffff) + (adj >> 16); + adj = (adj & 0xffff) + (adj >> 16); + cm->xlate_src_partial_csum_adjustment = (u16)adj; + } + + if (cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_DEST) { + u32 adj = ~cm->match_dest_ip + cm->xlate_dest_ip; + if (adj < cm->xlate_dest_ip) { + adj++; + } + + adj = (adj & 0xffff) + (adj >> 16); + adj = (adj & 0xffff) + (adj >> 16); + cm->xlate_dest_partial_csum_adjustment = (u16)adj; + } + +} + +/* + * sfe_ipv4_update_summary_stats() + * Update the summary stats. + */ +static void sfe_ipv4_update_summary_stats(struct sfe_ipv4 *si) +{ + int i; + + si->connection_create_requests64 += si->connection_create_requests; + si->connection_create_requests = 0; + si->connection_create_collisions64 += si->connection_create_collisions; + si->connection_create_collisions = 0; + si->connection_destroy_requests64 += si->connection_destroy_requests; + si->connection_destroy_requests = 0; + si->connection_destroy_misses64 += si->connection_destroy_misses; + si->connection_destroy_misses = 0; + si->connection_match_hash_hits64 += si->connection_match_hash_hits; + si->connection_match_hash_hits = 0; + si->connection_match_hash_reorders64 += si->connection_match_hash_reorders; + si->connection_match_hash_reorders = 0; + si->connection_flushes64 += si->connection_flushes; + si->connection_flushes = 0; + si->packets_forwarded64 += si->packets_forwarded; + si->packets_forwarded = 0; + si->packets_not_forwarded64 += si->packets_not_forwarded; + si->packets_not_forwarded = 0; + + for (i = 0; i < SFE_IPV4_EXCEPTION_EVENT_LAST; i++) { + si->exception_events64[i] += si->exception_events[i]; + si->exception_events[i] = 0; + } +} + +/* + * sfe_ipv4_insert_sfe_ipv4_connection_match() + * Insert a connection match into the hash. + * + * On entry we must be holding the lock that protects the hash table. + */ +static inline void sfe_ipv4_insert_sfe_ipv4_connection_match(struct sfe_ipv4 *si, + struct sfe_ipv4_connection_match *cm) +{ + struct sfe_ipv4_connection_match **hash_head; + struct sfe_ipv4_connection_match *prev_head; + unsigned int conn_match_idx + = sfe_ipv4_get_connection_match_hash(cm->match_dev, cm->match_protocol, + cm->match_src_ip, cm->match_src_port, + cm->match_dest_ip, cm->match_dest_port); + + hash_head = &si->conn_match_hash[conn_match_idx]; + prev_head = *hash_head; + cm->prev = NULL; + if (prev_head) { + prev_head->prev = cm; + } + + cm->next = prev_head; + *hash_head = cm; + +#ifdef CONFIG_NF_FLOW_COOKIE + if (!si->flow_cookie_enable) + return; + + /* + * Configure hardware to put a flow cookie in packet of this flow, + * then we can accelerate the lookup process when we received this packet. + */ + for (conn_match_idx = 1; conn_match_idx < SFE_FLOW_COOKIE_SIZE; conn_match_idx++) { + struct sfe_flow_cookie_entry *entry = &si->sfe_flow_cookie_table[conn_match_idx]; + + if ((NULL == entry->match) && time_is_before_jiffies(entry->last_clean_time + HZ)) { + flow_cookie_set_func_t func; + + rcu_read_lock(); + func = rcu_dereference(si->flow_cookie_set_func); + if (func) { + if (!func(cm->match_protocol, cm->match_src_ip, cm->match_src_port, + cm->match_dest_ip, cm->match_dest_port, conn_match_idx)) { + entry->match = cm; + cm->flow_cookie = conn_match_idx; + } + } + rcu_read_unlock(); + + break; + } + } +#endif +} + +/* + * sfe_ipv4_remove_sfe_ipv4_connection_match() + * Remove a connection match object from the hash. + * + * On entry we must be holding the lock that protects the hash table. + */ +static inline void sfe_ipv4_remove_sfe_ipv4_connection_match(struct sfe_ipv4 *si, struct sfe_ipv4_connection_match *cm) +{ +#ifdef CONFIG_NF_FLOW_COOKIE + if (si->flow_cookie_enable) { + /* + * Tell hardware that we no longer need a flow cookie in packet of this flow + */ + unsigned int conn_match_idx; + + for (conn_match_idx = 1; conn_match_idx < SFE_FLOW_COOKIE_SIZE; conn_match_idx++) { + struct sfe_flow_cookie_entry *entry = &si->sfe_flow_cookie_table[conn_match_idx]; + + if (cm == entry->match) { + flow_cookie_set_func_t func; + + rcu_read_lock(); + func = rcu_dereference(si->flow_cookie_set_func); + if (func) { + func(cm->match_protocol, cm->match_src_ip, cm->match_src_port, + cm->match_dest_ip, cm->match_dest_port, 0); + } + rcu_read_unlock(); + + cm->flow_cookie = 0; + entry->match = NULL; + entry->last_clean_time = jiffies; + break; + } + } + } +#endif + + /* + * Unlink the connection match entry from the hash. + */ + if (cm->prev) { + cm->prev->next = cm->next; + } else { + unsigned int conn_match_idx + = sfe_ipv4_get_connection_match_hash(cm->match_dev, cm->match_protocol, + cm->match_src_ip, cm->match_src_port, + cm->match_dest_ip, cm->match_dest_port); + si->conn_match_hash[conn_match_idx] = cm->next; + } + + if (cm->next) { + cm->next->prev = cm->prev; + } + + /* + * If the connection match entry is in the active list remove it. + */ + if (cm->active) { + if (likely(cm->active_prev)) { + cm->active_prev->active_next = cm->active_next; + } else { + si->active_head = cm->active_next; + } + + if (likely(cm->active_next)) { + cm->active_next->active_prev = cm->active_prev; + } else { + si->active_tail = cm->active_prev; + } + } +} + +/* + * sfe_ipv4_get_connection_hash() + * Generate the hash used in connection lookups. + */ +static inline unsigned int sfe_ipv4_get_connection_hash(u8 protocol, __be32 src_ip, __be16 src_port, + __be32 dest_ip, __be16 dest_port) +{ + u32 hash = ntohl(src_ip ^ dest_ip) ^ protocol ^ ntohs(src_port ^ dest_port); + return ((hash >> SFE_IPV4_CONNECTION_HASH_SHIFT) ^ hash) & SFE_IPV4_CONNECTION_HASH_MASK; +} + +/* + * sfe_ipv4_find_sfe_ipv4_connection() + * Get the IPv4 connection info that corresponds to a particular 5-tuple. + * + * On entry we must be holding the lock that protects the hash table. + */ +static inline struct sfe_ipv4_connection *sfe_ipv4_find_sfe_ipv4_connection(struct sfe_ipv4 *si, u32 protocol, + __be32 src_ip, __be16 src_port, + __be32 dest_ip, __be16 dest_port) +{ + struct sfe_ipv4_connection *c; + unsigned int conn_idx = sfe_ipv4_get_connection_hash(protocol, src_ip, src_port, dest_ip, dest_port); + c = si->conn_hash[conn_idx]; + + /* + * If we don't have anything in this chain then bale. + */ + if (unlikely(!c)) { + return NULL; + } + + /* + * Hopefully the first entry is the one we want. + */ + if ((c->src_port == src_port) + && (c->dest_port == dest_port) + && (c->src_ip == src_ip) + && (c->dest_ip == dest_ip) + && (c->protocol == protocol)) { + return c; + } + + /* + * Unfortunately we didn't find it at head, so we search it in chain. + */ + do { + c = c->next; + } while (c && (c->src_port != src_port + || c->dest_port != dest_port + || c->src_ip != src_ip + || c->dest_ip != dest_ip + || c->protocol != protocol)); + + /* + * Will need connection entry for next create/destroy metadata, + * So no need to re-order entry for these requests + */ + return c; +} + +/* + * sfe_ipv4_mark_rule() + * Updates the mark for a current offloaded connection + * + * Will take hash lock upon entry + */ +void sfe_ipv4_mark_rule(struct sfe_connection_mark *mark) +{ + struct sfe_ipv4 *si = &__si; + struct sfe_ipv4_connection *c; + + spin_lock_bh(&si->lock); + c = sfe_ipv4_find_sfe_ipv4_connection(si, mark->protocol, + mark->src_ip.ip, mark->src_port, + mark->dest_ip.ip, mark->dest_port); + if (c) { + WARN_ON((0 != c->mark) && (0 == mark->mark)); + c->mark = mark->mark; + } + spin_unlock_bh(&si->lock); + + if (c) { + DEBUG_TRACE("Matching connection found for mark, " + "setting from %08x to %08x\n", + c->mark, mark->mark); + } +} + +/* + * sfe_ipv4_insert_sfe_ipv4_connection() + * Insert a connection into the hash. + * + * On entry we must be holding the lock that protects the hash table. + */ +static void sfe_ipv4_insert_sfe_ipv4_connection(struct sfe_ipv4 *si, struct sfe_ipv4_connection *c) +{ + struct sfe_ipv4_connection **hash_head; + struct sfe_ipv4_connection *prev_head; + unsigned int conn_idx; + + /* + * Insert entry into the connection hash. + */ + conn_idx = sfe_ipv4_get_connection_hash(c->protocol, c->src_ip, c->src_port, + c->dest_ip, c->dest_port); + hash_head = &si->conn_hash[conn_idx]; + prev_head = *hash_head; + c->prev = NULL; + if (prev_head) { + prev_head->prev = c; + } + + c->next = prev_head; + *hash_head = c; + + /* + * Insert entry into the "all connections" list. + */ + if (si->all_connections_tail) { + c->all_connections_prev = si->all_connections_tail; + si->all_connections_tail->all_connections_next = c; + } else { + c->all_connections_prev = NULL; + si->all_connections_head = c; + } + + si->all_connections_tail = c; + c->all_connections_next = NULL; + si->num_connections++; + + /* + * Insert the connection match objects too. + */ + sfe_ipv4_insert_sfe_ipv4_connection_match(si, c->original_match); + sfe_ipv4_insert_sfe_ipv4_connection_match(si, c->reply_match); +} + +/* + * sfe_ipv4_remove_sfe_ipv4_connection() + * Remove a sfe_ipv4_connection object from the hash. + * + * On entry we must be holding the lock that protects the hash table. + */ +static void sfe_ipv4_remove_sfe_ipv4_connection(struct sfe_ipv4 *si, struct sfe_ipv4_connection *c) +{ + /* + * Remove the connection match objects. + */ + sfe_ipv4_remove_sfe_ipv4_connection_match(si, c->reply_match); + sfe_ipv4_remove_sfe_ipv4_connection_match(si, c->original_match); + + /* + * Unlink the connection. + */ + if (c->prev) { + c->prev->next = c->next; + } else { + unsigned int conn_idx = sfe_ipv4_get_connection_hash(c->protocol, c->src_ip, c->src_port, + c->dest_ip, c->dest_port); + si->conn_hash[conn_idx] = c->next; + } + + if (c->next) { + c->next->prev = c->prev; + } + + /* + * Unlink connection from all_connections list + */ + if (c->all_connections_prev) { + c->all_connections_prev->all_connections_next = c->all_connections_next; + } else { + si->all_connections_head = c->all_connections_next; + } + + if (c->all_connections_next) { + c->all_connections_next->all_connections_prev = c->all_connections_prev; + } else { + si->all_connections_tail = c->all_connections_prev; + } + + si->num_connections--; +} + +/* + * sfe_ipv4_sync_sfe_ipv4_connection() + * Sync a connection. + * + * On entry to this function we expect that the lock for the connection is either + * already held or isn't required. + */ +static void sfe_ipv4_gen_sync_sfe_ipv4_connection(struct sfe_ipv4 *si, struct sfe_ipv4_connection *c, + struct sfe_connection_sync *sis, sfe_sync_reason_t reason, + u64 now_jiffies) +{ + struct sfe_ipv4_connection_match *original_cm; + struct sfe_ipv4_connection_match *reply_cm; + + /* + * Fill in the update message. + */ + sis->is_v6 = 0; + sis->protocol = c->protocol; + sis->src_ip.ip = c->src_ip; + sis->src_ip_xlate.ip = c->src_ip_xlate; + sis->dest_ip.ip = c->dest_ip; + sis->dest_ip_xlate.ip = c->dest_ip_xlate; + sis->src_port = c->src_port; + sis->src_port_xlate = c->src_port_xlate; + sis->dest_port = c->dest_port; + sis->dest_port_xlate = c->dest_port_xlate; + + original_cm = c->original_match; + reply_cm = c->reply_match; + sis->src_td_max_window = original_cm->protocol_state.tcp.max_win; + sis->src_td_end = original_cm->protocol_state.tcp.end; + sis->src_td_max_end = original_cm->protocol_state.tcp.max_end; + sis->dest_td_max_window = reply_cm->protocol_state.tcp.max_win; + sis->dest_td_end = reply_cm->protocol_state.tcp.end; + sis->dest_td_max_end = reply_cm->protocol_state.tcp.max_end; + + sis->src_new_packet_count = original_cm->rx_packet_count; + sis->src_new_byte_count = original_cm->rx_byte_count; + sis->dest_new_packet_count = reply_cm->rx_packet_count; + sis->dest_new_byte_count = reply_cm->rx_byte_count; + + sfe_ipv4_connection_match_update_summary_stats(original_cm); + sfe_ipv4_connection_match_update_summary_stats(reply_cm); + + sis->src_dev = original_cm->match_dev; + sis->src_packet_count = original_cm->rx_packet_count64; + sis->src_byte_count = original_cm->rx_byte_count64; + + sis->dest_dev = reply_cm->match_dev; + sis->dest_packet_count = reply_cm->rx_packet_count64; + sis->dest_byte_count = reply_cm->rx_byte_count64; + + sis->reason = reason; + + /* + * Get the time increment since our last sync. + */ + sis->delta_jiffies = now_jiffies - c->last_sync_jiffies; + c->last_sync_jiffies = now_jiffies; +} + +/* + * sfe_ipv4_flush_sfe_ipv4_connection() + * Flush a connection and free all associated resources. + * + * We need to be called with bottom halves disabled locally as we need to acquire + * the connection hash lock and release it again. In general we're actually called + * from within a BH and so we're fine, but we're also called when connections are + * torn down. + */ +static void sfe_ipv4_flush_sfe_ipv4_connection(struct sfe_ipv4 *si, + struct sfe_ipv4_connection *c, + sfe_sync_reason_t reason) +{ + struct sfe_connection_sync sis; + u64 now_jiffies; + sfe_sync_rule_callback_t sync_rule_callback; + + rcu_read_lock(); + spin_lock_bh(&si->lock); + si->connection_flushes++; + sync_rule_callback = rcu_dereference(si->sync_rule_callback); + spin_unlock_bh(&si->lock); + + if (sync_rule_callback) { + /* + * Generate a sync message and then sync. + */ + now_jiffies = get_jiffies_64(); + sfe_ipv4_gen_sync_sfe_ipv4_connection(si, c, &sis, reason, now_jiffies); + sync_rule_callback(&sis); + } + + rcu_read_unlock(); + + /* + * Release our hold of the source and dest devices and free the memory + * for our connection objects. + */ + dev_put(c->original_dev); + dev_put(c->reply_dev); + kfree(c->original_match); + kfree(c->reply_match); + kfree(c); +} + +/* + * sfe_ipv4_recv_udp() + * Handle UDP packet receives and forwarding. + */ +static int sfe_ipv4_recv_udp(struct sfe_ipv4 *si, struct sk_buff *skb, struct net_device *dev, + unsigned int len, struct sfe_ipv4_ip_hdr *iph, unsigned int ihl, bool flush_on_find) +{ + struct sfe_ipv4_udp_hdr *udph; + __be32 src_ip; + __be32 dest_ip; + __be16 src_port; + __be16 dest_port; + struct sfe_ipv4_connection_match *cm; + u8 ttl; + struct net_device *xmit_dev; + + /* + * Is our packet too short to contain a valid UDP header? + */ + if (unlikely(!pskb_may_pull(skb, (sizeof(struct sfe_ipv4_udp_hdr) + ihl)))) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_UDP_HEADER_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("packet too short for UDP header\n"); + return 0; + } + + /* + * Read the IP address and port information. Read the IP header data first + * because we've almost certainly got that in the cache. We may not yet have + * the UDP header cached though so allow more time for any prefetching. + */ + src_ip = iph->saddr; + dest_ip = iph->daddr; + + udph = (struct sfe_ipv4_udp_hdr *)(skb->data + ihl); + src_port = udph->source; + dest_port = udph->dest; + + spin_lock_bh(&si->lock); + + /* + * Look for a connection match. + */ +#ifdef CONFIG_NF_FLOW_COOKIE + cm = si->sfe_flow_cookie_table[skb->flow_cookie & SFE_FLOW_COOKIE_MASK].match; + if (unlikely(!cm)) { + cm = sfe_ipv4_find_sfe_ipv4_connection_match(si, dev, IPPROTO_UDP, src_ip, src_port, dest_ip, dest_port); + } +#else + cm = sfe_ipv4_find_sfe_ipv4_connection_match(si, dev, IPPROTO_UDP, src_ip, src_port, dest_ip, dest_port); +#endif + if (unlikely(!cm)) { + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_UDP_NO_CONNECTION]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("no connection found\n"); + return 0; + } + + /* + * If our packet has beern marked as "flush on find" we can't actually + * forward it in the fast path, but now that we've found an associated + * connection we can flush that out before we process the packet. + */ + if (unlikely(flush_on_find)) { + struct sfe_ipv4_connection *c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_UDP_IP_OPTIONS_OR_INITIAL_FRAGMENT]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("flush on find\n"); + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + +#ifdef CONFIG_XFRM + /* + * We can't accelerate the flow on this direction, just let it go + * through the slow path. + */ + if (unlikely(!cm->flow_accel)) { + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + return 0; + } +#endif + + /* + * Does our TTL allow forwarding? + */ + ttl = iph->ttl; + if (unlikely(ttl < 2)) { + struct sfe_ipv4_connection *c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_UDP_SMALL_TTL]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("ttl too low\n"); + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * If our packet is larger than the MTU of the transmit interface then + * we can't forward it easily. + */ + if (unlikely(len > cm->xmit_dev_mtu)) { + struct sfe_ipv4_connection *c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_UDP_NEEDS_FRAGMENTATION]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("larger than mtu\n"); + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * From this point on we're good to modify the packet. + */ + + /* + * Check if skb was cloned. If it was, unshare it. Because + * the data area is going to be written in this path and we don't want to + * change the cloned skb's data section. + */ + if (unlikely(skb_cloned(skb))) { + DEBUG_TRACE("%px: skb is a cloned skb\n", skb); + skb = skb_unshare(skb, GFP_ATOMIC); + if (!skb) { + DEBUG_WARN("Failed to unshare the cloned skb\n"); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_CLONED_SKB_UNSHARE_ERROR]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + return 0; + } + + /* + * Update the iph and udph pointers with the unshared skb's data area. + */ + iph = (struct sfe_ipv4_ip_hdr *)skb->data; + udph = (struct sfe_ipv4_udp_hdr *)(skb->data + ihl); + } + + /* + * Update DSCP + */ + if (unlikely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_DSCP_REMARK)) { + iph->tos = (iph->tos & SFE_IPV4_DSCP_MASK) | cm->dscp; + } + + /* + * Decrement our TTL. + */ + iph->ttl = ttl - 1; + + /* + * Do we have to perform translations of the source address/port? + */ + if (unlikely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_SRC)) { + u16 udp_csum; + + iph->saddr = cm->xlate_src_ip; + udph->source = cm->xlate_src_port; + + /* + * Do we have a non-zero UDP checksum? If we do then we need + * to update it. + */ + udp_csum = udph->check; + if (likely(udp_csum)) { + u32 sum; + + if (unlikely(skb->ip_summed == CHECKSUM_PARTIAL)) { + sum = udp_csum + cm->xlate_src_partial_csum_adjustment; + } else { + sum = udp_csum + cm->xlate_src_csum_adjustment; + } + + sum = (sum & 0xffff) + (sum >> 16); + udph->check = (u16)sum; + } + } + + /* + * Do we have to perform translations of the destination address/port? + */ + if (unlikely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_DEST)) { + u16 udp_csum; + + iph->daddr = cm->xlate_dest_ip; + udph->dest = cm->xlate_dest_port; + + /* + * Do we have a non-zero UDP checksum? If we do then we need + * to update it. + */ + udp_csum = udph->check; + if (likely(udp_csum)) { + u32 sum; + + if (unlikely(skb->ip_summed == CHECKSUM_PARTIAL)) { + sum = udp_csum + cm->xlate_dest_partial_csum_adjustment; + } else { + sum = udp_csum + cm->xlate_dest_csum_adjustment; + } + + sum = (sum & 0xffff) + (sum >> 16); + udph->check = (u16)sum; + } + } + + /* + * Replace the IP checksum. + */ + iph->check = sfe_ipv4_gen_ip_csum(iph); + + /* + * Update traffic stats. + */ + cm->rx_packet_count++; + cm->rx_byte_count += len; + + /* + * If we're not already on the active list then insert ourselves at the tail + * of the current list. + */ + if (unlikely(!cm->active)) { + cm->active = true; + cm->active_prev = si->active_tail; + if (likely(si->active_tail)) { + si->active_tail->active_next = cm; + } else { + si->active_head = cm; + } + si->active_tail = cm; + } + + xmit_dev = cm->xmit_dev; + skb->dev = xmit_dev; + + /* + * Check to see if we need to write a header. + */ + if (likely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_L2_HDR)) { + if (unlikely(!(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR))) { + dev_hard_header(skb, xmit_dev, ETH_P_IP, + cm->xmit_dest_mac, cm->xmit_src_mac, len); + } else { + /* + * For the simple case we write this really fast. + */ + struct sfe_ipv4_eth_hdr *eth = (struct sfe_ipv4_eth_hdr *)__skb_push(skb, ETH_HLEN); + eth->h_proto = htons(ETH_P_IP); + eth->h_dest[0] = cm->xmit_dest_mac[0]; + eth->h_dest[1] = cm->xmit_dest_mac[1]; + eth->h_dest[2] = cm->xmit_dest_mac[2]; + eth->h_source[0] = cm->xmit_src_mac[0]; + eth->h_source[1] = cm->xmit_src_mac[1]; + eth->h_source[2] = cm->xmit_src_mac[2]; + } + } + + /* + * Update priority of skb. + */ + if (unlikely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_PRIORITY_REMARK)) { + skb->priority = cm->priority; + } + + /* + * Mark outgoing packet. + */ + skb->mark = cm->connection->mark; + if (skb->mark) { + DEBUG_TRACE("SKB MARK is NON ZERO %x\n", skb->mark); + } + + si->packets_forwarded++; + spin_unlock_bh(&si->lock); + + /* + * We're going to check for GSO flags when we transmit the packet so + * start fetching the necessary cache line now. + */ + prefetch(skb_shinfo(skb)); + + /* + * Mark that this packet has been fast forwarded. + */ + skb->fast_forwarded = 1; + + /* + * Send the packet on its way. + */ + dev_queue_xmit(skb); + + return 1; +} + +/* + * sfe_ipv4_process_tcp_option_sack() + * Parse TCP SACK option and update ack according + */ +static bool sfe_ipv4_process_tcp_option_sack(const struct sfe_ipv4_tcp_hdr *th, const u32 data_offs, + u32 *ack) +{ + u32 length = sizeof(struct sfe_ipv4_tcp_hdr); + u8 *ptr = (u8 *)th + length; + + /* + * Ignore processing if TCP packet has only TIMESTAMP option. + */ + if (likely(data_offs == length + TCPOLEN_TIMESTAMP + 1 + 1) + && likely(ptr[0] == TCPOPT_NOP) + && likely(ptr[1] == TCPOPT_NOP) + && likely(ptr[2] == TCPOPT_TIMESTAMP) + && likely(ptr[3] == TCPOLEN_TIMESTAMP)) { + return true; + } + + /* + * TCP options. Parse SACK option. + */ + while (length < data_offs) { + u8 size; + u8 kind; + + ptr = (u8 *)th + length; + kind = *ptr; + + /* + * NOP, for padding + * Not in the switch because to fast escape and to not calculate size + */ + if (kind == TCPOPT_NOP) { + length++; + continue; + } + + if (kind == TCPOPT_SACK) { + u32 sack = 0; + u8 re = 1 + 1; + + size = *(ptr + 1); + if ((size < (1 + 1 + TCPOLEN_SACK_PERBLOCK)) + || ((size - (1 + 1)) % (TCPOLEN_SACK_PERBLOCK)) + || (size > (data_offs - length))) { + return false; + } + + re += 4; + while (re < size) { + u32 sack_re; + u8 *sptr = ptr + re; + sack_re = (sptr[0] << 24) | (sptr[1] << 16) | (sptr[2] << 8) | sptr[3]; + if (sack_re > sack) { + sack = sack_re; + } + re += TCPOLEN_SACK_PERBLOCK; + } + if (sack > *ack) { + *ack = sack; + } + length += size; + continue; + } + if (kind == TCPOPT_EOL) { + return true; + } + size = *(ptr + 1); + if (size < 2) { + return false; + } + length += size; + } + + return true; +} + +/* + * sfe_ipv4_recv_tcp() + * Handle TCP packet receives and forwarding. + */ +static int sfe_ipv4_recv_tcp(struct sfe_ipv4 *si, struct sk_buff *skb, struct net_device *dev, + unsigned int len, struct sfe_ipv4_ip_hdr *iph, unsigned int ihl, bool flush_on_find) +{ + struct sfe_ipv4_tcp_hdr *tcph; + __be32 src_ip; + __be32 dest_ip; + __be16 src_port; + __be16 dest_port; + struct sfe_ipv4_connection_match *cm; + struct sfe_ipv4_connection_match *counter_cm; + u8 ttl; + u32 flags; + struct net_device *xmit_dev; + + /* + * Is our packet too short to contain a valid UDP header? + */ + if (unlikely(!pskb_may_pull(skb, (sizeof(struct sfe_ipv4_tcp_hdr) + ihl)))) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_HEADER_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("packet too short for TCP header\n"); + return 0; + } + + /* + * Read the IP address and port information. Read the IP header data first + * because we've almost certainly got that in the cache. We may not yet have + * the TCP header cached though so allow more time for any prefetching. + */ + src_ip = iph->saddr; + dest_ip = iph->daddr; + + tcph = (struct sfe_ipv4_tcp_hdr *)(skb->data + ihl); + src_port = tcph->source; + dest_port = tcph->dest; + flags = tcp_flag_word(tcph); + + spin_lock_bh(&si->lock); + + /* + * Look for a connection match. + */ +#ifdef CONFIG_NF_FLOW_COOKIE + cm = si->sfe_flow_cookie_table[skb->flow_cookie & SFE_FLOW_COOKIE_MASK].match; + if (unlikely(!cm)) { + cm = sfe_ipv4_find_sfe_ipv4_connection_match(si, dev, IPPROTO_TCP, src_ip, src_port, dest_ip, dest_port); + } +#else + cm = sfe_ipv4_find_sfe_ipv4_connection_match(si, dev, IPPROTO_TCP, src_ip, src_port, dest_ip, dest_port); +#endif + if (unlikely(!cm)) { + /* + * We didn't get a connection but as TCP is connection-oriented that + * may be because this is a non-fast connection (not running established). + * For diagnostic purposes we differentiate this here. + */ + if (likely((flags & (TCP_FLAG_SYN | TCP_FLAG_RST | TCP_FLAG_FIN | TCP_FLAG_ACK)) == TCP_FLAG_ACK)) { + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_NO_CONNECTION_FAST_FLAGS]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("no connection found - fast flags\n"); + return 0; + } + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_NO_CONNECTION_SLOW_FLAGS]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("no connection found - slow flags: 0x%x\n", + flags & (TCP_FLAG_SYN | TCP_FLAG_RST | TCP_FLAG_FIN | TCP_FLAG_ACK)); + return 0; + } + + /* + * If our packet has beern marked as "flush on find" we can't actually + * forward it in the fast path, but now that we've found an associated + * connection we can flush that out before we process the packet. + */ + if (unlikely(flush_on_find)) { + struct sfe_ipv4_connection *c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_IP_OPTIONS_OR_INITIAL_FRAGMENT]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("flush on find\n"); + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + +#ifdef CONFIG_XFRM + /* + * We can't accelerate the flow on this direction, just let it go + * through the slow path. + */ + if (unlikely(!cm->flow_accel)) { + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + return 0; + } +#endif + /* + * Does our TTL allow forwarding? + */ + ttl = iph->ttl; + if (unlikely(ttl < 2)) { + struct sfe_ipv4_connection *c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_SMALL_TTL]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("ttl too low\n"); + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * If our packet is larger than the MTU of the transmit interface then + * we can't forward it easily. + */ + if (unlikely((len > cm->xmit_dev_mtu) && !skb_is_gso(skb))) { + struct sfe_ipv4_connection *c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_NEEDS_FRAGMENTATION]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("larger than mtu\n"); + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * Look at our TCP flags. Anything missing an ACK or that has RST, SYN or FIN + * set is not a fast path packet. + */ + if (unlikely((flags & (TCP_FLAG_SYN | TCP_FLAG_RST | TCP_FLAG_FIN | TCP_FLAG_ACK)) != TCP_FLAG_ACK)) { + struct sfe_ipv4_connection *c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_FLAGS]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("TCP flags: 0x%x are not fast\n", + flags & (TCP_FLAG_SYN | TCP_FLAG_RST | TCP_FLAG_FIN | TCP_FLAG_ACK)); + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + counter_cm = cm->counter_match; + + /* + * Are we doing sequence number checking? + */ + if (likely(!(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK))) { + u32 seq; + u32 ack; + u32 sack; + u32 data_offs; + u32 end; + u32 left_edge; + u32 scaled_win; + u32 max_end; + + /* + * Is our sequence fully past the right hand edge of the window? + */ + seq = ntohl(tcph->seq); + if (unlikely((s32)(seq - (cm->protocol_state.tcp.max_end + 1)) > 0)) { + struct sfe_ipv4_connection *c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_SEQ_EXCEEDS_RIGHT_EDGE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("seq: %u exceeds right edge: %u\n", + seq, cm->protocol_state.tcp.max_end + 1); + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * Check that our TCP data offset isn't too short. + */ + data_offs = tcph->doff << 2; + if (unlikely(data_offs < sizeof(struct sfe_ipv4_tcp_hdr))) { + struct sfe_ipv4_connection *c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_SMALL_DATA_OFFS]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("TCP data offset: %u, too small\n", data_offs); + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * Update ACK according to any SACK option. + */ + ack = ntohl(tcph->ack_seq); + sack = ack; + if (unlikely(!sfe_ipv4_process_tcp_option_sack(tcph, data_offs, &sack))) { + struct sfe_ipv4_connection *c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_BAD_SACK]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("TCP option SACK size is wrong\n"); + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * Check that our TCP data offset isn't past the end of the packet. + */ + data_offs += sizeof(struct sfe_ipv4_ip_hdr); + if (unlikely(len < data_offs)) { + struct sfe_ipv4_connection *c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_BIG_DATA_OFFS]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("TCP data offset: %u, past end of packet: %u\n", + data_offs, len); + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + end = seq + len - data_offs; + + /* + * Is our sequence fully before the left hand edge of the window? + */ + if (unlikely((s32)(end - (cm->protocol_state.tcp.end + - counter_cm->protocol_state.tcp.max_win - 1)) < 0)) { + struct sfe_ipv4_connection *c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_SEQ_BEFORE_LEFT_EDGE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("seq: %u before left edge: %u\n", + end, cm->protocol_state.tcp.end - counter_cm->protocol_state.tcp.max_win - 1); + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * Are we acking data that is to the right of what has been sent? + */ + if (unlikely((s32)(sack - (counter_cm->protocol_state.tcp.end + 1)) > 0)) { + struct sfe_ipv4_connection *c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_ACK_EXCEEDS_RIGHT_EDGE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("ack: %u exceeds right edge: %u\n", + sack, counter_cm->protocol_state.tcp.end + 1); + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * Is our ack too far before the left hand edge of the window? + */ + left_edge = counter_cm->protocol_state.tcp.end + - cm->protocol_state.tcp.max_win + - SFE_IPV4_TCP_MAX_ACK_WINDOW + - 1; + if (unlikely((s32)(sack - left_edge) < 0)) { + struct sfe_ipv4_connection *c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_ACK_BEFORE_LEFT_EDGE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("ack: %u before left edge: %u\n", sack, left_edge); + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * Have we just seen the largest window size yet for this connection? If yes + * then we need to record the new value. + */ + scaled_win = ntohs(tcph->window) << cm->protocol_state.tcp.win_scale; + scaled_win += (sack - ack); + if (unlikely(cm->protocol_state.tcp.max_win < scaled_win)) { + cm->protocol_state.tcp.max_win = scaled_win; + } + + /* + * If our sequence and/or ack numbers have advanced then record the new state. + */ + if (likely((s32)(end - cm->protocol_state.tcp.end) >= 0)) { + cm->protocol_state.tcp.end = end; + } + + max_end = sack + scaled_win; + if (likely((s32)(max_end - counter_cm->protocol_state.tcp.max_end) >= 0)) { + counter_cm->protocol_state.tcp.max_end = max_end; + } + } + + /* + * From this point on we're good to modify the packet. + */ + + /* + * Check if skb was cloned. If it was, unshare it. Because + * the data area is going to be written in this path and we don't want to + * change the cloned skb's data section. + */ + if (unlikely(skb_cloned(skb))) { + DEBUG_TRACE("%px: skb is a cloned skb\n", skb); + skb = skb_unshare(skb, GFP_ATOMIC); + if (!skb) { + DEBUG_WARN("Failed to unshare the cloned skb\n"); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_CLONED_SKB_UNSHARE_ERROR]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + return 0; + } + + /* + * Update the iph and tcph pointers with the unshared skb's data area. + */ + iph = (struct sfe_ipv4_ip_hdr *)skb->data; + tcph = (struct sfe_ipv4_tcp_hdr *)(skb->data + ihl); + } + + /* + * Update DSCP + */ + if (unlikely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_DSCP_REMARK)) { + iph->tos = (iph->tos & SFE_IPV4_DSCP_MASK) | cm->dscp; + } + + /* + * Decrement our TTL. + */ + iph->ttl = ttl - 1; + + /* + * Do we have to perform translations of the source address/port? + */ + if (unlikely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_SRC)) { + u16 tcp_csum; + u32 sum; + + iph->saddr = cm->xlate_src_ip; + tcph->source = cm->xlate_src_port; + + /* + * Do we have a non-zero UDP checksum? If we do then we need + * to update it. + */ + tcp_csum = tcph->check; + if (unlikely(skb->ip_summed == CHECKSUM_PARTIAL)) { + sum = tcp_csum + cm->xlate_src_partial_csum_adjustment; + } else { + sum = tcp_csum + cm->xlate_src_csum_adjustment; + } + + sum = (sum & 0xffff) + (sum >> 16); + tcph->check = (u16)sum; + } + + /* + * Do we have to perform translations of the destination address/port? + */ + if (unlikely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_DEST)) { + u16 tcp_csum; + u32 sum; + + iph->daddr = cm->xlate_dest_ip; + tcph->dest = cm->xlate_dest_port; + + /* + * Do we have a non-zero UDP checksum? If we do then we need + * to update it. + */ + tcp_csum = tcph->check; + if (unlikely(skb->ip_summed == CHECKSUM_PARTIAL)) { + sum = tcp_csum + cm->xlate_dest_partial_csum_adjustment; + } else { + sum = tcp_csum + cm->xlate_dest_csum_adjustment; + } + + sum = (sum & 0xffff) + (sum >> 16); + tcph->check = (u16)sum; + } + + /* + * Replace the IP checksum. + */ + iph->check = sfe_ipv4_gen_ip_csum(iph); + + /* + * Update traffic stats. + */ + cm->rx_packet_count++; + cm->rx_byte_count += len; + + /* + * If we're not already on the active list then insert ourselves at the tail + * of the current list. + */ + if (unlikely(!cm->active)) { + cm->active = true; + cm->active_prev = si->active_tail; + if (likely(si->active_tail)) { + si->active_tail->active_next = cm; + } else { + si->active_head = cm; + } + si->active_tail = cm; + } + + xmit_dev = cm->xmit_dev; + skb->dev = xmit_dev; + + /* + * Check to see if we need to write a header. + */ + if (likely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_L2_HDR)) { + if (unlikely(!(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR))) { + dev_hard_header(skb, xmit_dev, ETH_P_IP, + cm->xmit_dest_mac, cm->xmit_src_mac, len); + } else { + /* + * For the simple case we write this really fast. + */ + struct sfe_ipv4_eth_hdr *eth = (struct sfe_ipv4_eth_hdr *)__skb_push(skb, ETH_HLEN); + eth->h_proto = htons(ETH_P_IP); + eth->h_dest[0] = cm->xmit_dest_mac[0]; + eth->h_dest[1] = cm->xmit_dest_mac[1]; + eth->h_dest[2] = cm->xmit_dest_mac[2]; + eth->h_source[0] = cm->xmit_src_mac[0]; + eth->h_source[1] = cm->xmit_src_mac[1]; + eth->h_source[2] = cm->xmit_src_mac[2]; + } + } + + /* + * Update priority of skb. + */ + if (unlikely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_PRIORITY_REMARK)) { + skb->priority = cm->priority; + } + + /* + * Mark outgoing packet + */ + skb->mark = cm->connection->mark; + if (skb->mark) { + DEBUG_TRACE("SKB MARK is NON ZERO %x\n", skb->mark); + } + + si->packets_forwarded++; + spin_unlock_bh(&si->lock); + + /* + * We're going to check for GSO flags when we transmit the packet so + * start fetching the necessary cache line now. + */ + prefetch(skb_shinfo(skb)); + + /* + * Mark that this packet has been fast forwarded. + */ + skb->fast_forwarded = 1; + + /* + * Send the packet on its way. + */ + dev_queue_xmit(skb); + + return 1; +} + +/* + * sfe_ipv4_recv_icmp() + * Handle ICMP packet receives. + * + * ICMP packets aren't handled as a "fast path" and always have us process them + * through the default Linux stack. What we do need to do is look for any errors + * about connections we are handling in the fast path. If we find any such + * connections then we want to flush their state so that the ICMP error path + * within Linux has all of the correct state should it need it. + */ +static int sfe_ipv4_recv_icmp(struct sfe_ipv4 *si, struct sk_buff *skb, struct net_device *dev, + unsigned int len, struct sfe_ipv4_ip_hdr *iph, unsigned int ihl) +{ + struct icmphdr *icmph; + struct sfe_ipv4_ip_hdr *icmp_iph; + unsigned int icmp_ihl_words; + unsigned int icmp_ihl; + u32 *icmp_trans_h; + struct sfe_ipv4_udp_hdr *icmp_udph; + struct sfe_ipv4_tcp_hdr *icmp_tcph; + __be32 src_ip; + __be32 dest_ip; + __be16 src_port; + __be16 dest_port; + struct sfe_ipv4_connection_match *cm; + struct sfe_ipv4_connection *c; + u32 pull_len = sizeof(struct icmphdr) + ihl; + + /* + * Is our packet too short to contain a valid ICMP header? + */ + len -= ihl; + if (!pskb_may_pull(skb, pull_len)) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_HEADER_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("packet too short for ICMP header\n"); + return 0; + } + + /* + * We only handle "destination unreachable" and "time exceeded" messages. + */ + icmph = (struct icmphdr *)(skb->data + ihl); + if ((icmph->type != ICMP_DEST_UNREACH) + && (icmph->type != ICMP_TIME_EXCEEDED)) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_UNHANDLED_TYPE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("unhandled ICMP type: 0x%x\n", icmph->type); + return 0; + } + + /* + * Do we have the full embedded IP header? + */ + len -= sizeof(struct icmphdr); + pull_len += sizeof(struct sfe_ipv4_ip_hdr); + if (!pskb_may_pull(skb, pull_len)) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_HEADER_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("Embedded IP header not complete\n"); + return 0; + } + + /* + * Is our embedded IP version wrong? + */ + icmp_iph = (struct sfe_ipv4_ip_hdr *)(icmph + 1); + if (unlikely(icmp_iph->version != 4)) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_NON_V4]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("IP version: %u\n", icmp_iph->version); + return 0; + } + + /* + * Do we have the full embedded IP header, including any options? + */ + icmp_ihl_words = icmp_iph->ihl; + icmp_ihl = icmp_ihl_words << 2; + pull_len += icmp_ihl - sizeof(struct sfe_ipv4_ip_hdr); + if (!pskb_may_pull(skb, pull_len)) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_IP_OPTIONS_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("Embedded header not large enough for IP options\n"); + return 0; + } + + len -= icmp_ihl; + icmp_trans_h = ((u32 *)icmp_iph) + icmp_ihl_words; + + /* + * Handle the embedded transport layer header. + */ + switch (icmp_iph->protocol) { + case IPPROTO_UDP: + /* + * We should have 8 bytes of UDP header - that's enough to identify + * the connection. + */ + pull_len += 8; + if (!pskb_may_pull(skb, pull_len)) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_UDP_HEADER_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("Incomplete embedded UDP header\n"); + return 0; + } + + icmp_udph = (struct sfe_ipv4_udp_hdr *)icmp_trans_h; + src_port = icmp_udph->source; + dest_port = icmp_udph->dest; + break; + + case IPPROTO_TCP: + /* + * We should have 8 bytes of TCP header - that's enough to identify + * the connection. + */ + pull_len += 8; + if (!pskb_may_pull(skb, pull_len)) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_TCP_HEADER_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("Incomplete embedded TCP header\n"); + return 0; + } + + icmp_tcph = (struct sfe_ipv4_tcp_hdr *)icmp_trans_h; + src_port = icmp_tcph->source; + dest_port = icmp_tcph->dest; + break; + + default: + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_UNHANDLED_PROTOCOL]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("Unhandled embedded IP protocol: %u\n", icmp_iph->protocol); + return 0; + } + + src_ip = icmp_iph->saddr; + dest_ip = icmp_iph->daddr; + + spin_lock_bh(&si->lock); + + /* + * Look for a connection match. Note that we reverse the source and destination + * here because our embedded message contains a packet that was sent in the + * opposite direction to the one in which we just received it. It will have + * been sent on the interface from which we received it though so that's still + * ok to use. + */ + cm = sfe_ipv4_find_sfe_ipv4_connection_match(si, dev, icmp_iph->protocol, dest_ip, dest_port, src_ip, src_port); + if (unlikely(!cm)) { + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_NO_CONNECTION]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("no connection found\n"); + return 0; + } + + /* + * We found a connection so now remove it from the connection list and flush + * its state. + */ + c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_FLUSHED_CONNECTION]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; +} + +/* + * sfe_ipv4_recv() + * Handle packet receives and forwaring. + * + * Returns 1 if the packet is forwarded or 0 if it isn't. + */ +int sfe_ipv4_recv(struct net_device *dev, struct sk_buff *skb) +{ + struct sfe_ipv4 *si = &__si; + unsigned int len; + unsigned int tot_len; + unsigned int frag_off; + unsigned int ihl; + bool flush_on_find; + bool ip_options; + struct sfe_ipv4_ip_hdr *iph; + u32 protocol; + + /* + * Check that we have space for an IP header here. + */ + len = skb->len; + if (unlikely(!pskb_may_pull(skb, sizeof(struct sfe_ipv4_ip_hdr)))) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_HEADER_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("len: %u is too short\n", len); + return 0; + } + + /* + * Check that our "total length" is large enough for an IP header. + */ + iph = (struct sfe_ipv4_ip_hdr *)skb->data; + tot_len = ntohs(iph->tot_len); + if (unlikely(tot_len < sizeof(struct sfe_ipv4_ip_hdr))) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_BAD_TOTAL_LENGTH]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("tot_len: %u is too short\n", tot_len); + return 0; + } + + /* + * Is our IP version wrong? + */ + if (unlikely(iph->version != 4)) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_NON_V4]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("IP version: %u\n", iph->version); + return 0; + } + + /* + * Does our datagram fit inside the skb? + */ + if (unlikely(tot_len > len)) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_DATAGRAM_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("tot_len: %u, exceeds len: %u\n", tot_len, len); + return 0; + } + + /* + * Do we have a non-initial fragment? + */ + frag_off = ntohs(iph->frag_off); + if (unlikely(frag_off & IP_OFFSET)) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_NON_INITIAL_FRAGMENT]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("non-initial fragment\n"); + return 0; + } + + /* + * If we have a (first) fragment then mark it to cause any connection to flush. + */ + flush_on_find = unlikely(frag_off & IP_MF) ? true : false; + + /* + * Do we have any IP options? That's definite a slow path! If we do have IP + * options we need to recheck our header size. + */ + ihl = iph->ihl << 2; + ip_options = unlikely(ihl != sizeof(struct sfe_ipv4_ip_hdr)) ? true : false; + if (unlikely(ip_options)) { + if (unlikely(len < ihl)) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_IP_OPTIONS_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("len: %u is too short for header of size: %u\n", len, ihl); + return 0; + } + + flush_on_find = true; + } + + protocol = iph->protocol; + if (IPPROTO_UDP == protocol) { + return sfe_ipv4_recv_udp(si, skb, dev, len, iph, ihl, flush_on_find); + } + + if (IPPROTO_TCP == protocol) { + return sfe_ipv4_recv_tcp(si, skb, dev, len, iph, ihl, flush_on_find); + } + + if (IPPROTO_ICMP == protocol) { + return sfe_ipv4_recv_icmp(si, skb, dev, len, iph, ihl); + } + + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_UNHANDLED_PROTOCOL]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("not UDP, TCP or ICMP: %u\n", protocol); + return 0; +} + +static void +sfe_ipv4_update_tcp_state(struct sfe_ipv4_connection *c, + struct sfe_connection_create *sic) +{ + struct sfe_ipv4_connection_match *orig_cm; + struct sfe_ipv4_connection_match *repl_cm; + struct sfe_ipv4_tcp_connection_match *orig_tcp; + struct sfe_ipv4_tcp_connection_match *repl_tcp; + + orig_cm = c->original_match; + repl_cm = c->reply_match; + orig_tcp = &orig_cm->protocol_state.tcp; + repl_tcp = &repl_cm->protocol_state.tcp; + + /* update orig */ + if (orig_tcp->max_win < sic->src_td_max_window) { + orig_tcp->max_win = sic->src_td_max_window; + } + if ((s32)(orig_tcp->end - sic->src_td_end) < 0) { + orig_tcp->end = sic->src_td_end; + } + if ((s32)(orig_tcp->max_end - sic->src_td_max_end) < 0) { + orig_tcp->max_end = sic->src_td_max_end; + } + + /* update reply */ + if (repl_tcp->max_win < sic->dest_td_max_window) { + repl_tcp->max_win = sic->dest_td_max_window; + } + if ((s32)(repl_tcp->end - sic->dest_td_end) < 0) { + repl_tcp->end = sic->dest_td_end; + } + if ((s32)(repl_tcp->max_end - sic->dest_td_max_end) < 0) { + repl_tcp->max_end = sic->dest_td_max_end; + } + + /* update match flags */ + orig_cm->flags &= ~SFE_IPV4_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; + repl_cm->flags &= ~SFE_IPV4_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; + if (sic->flags & SFE_CREATE_FLAG_NO_SEQ_CHECK) { + orig_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; + repl_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; + } +} + +static void +sfe_ipv4_update_protocol_state(struct sfe_ipv4_connection *c, + struct sfe_connection_create *sic) +{ + switch (sic->protocol) { + case IPPROTO_TCP: + sfe_ipv4_update_tcp_state(c, sic); + break; + } +} + +void sfe_ipv4_update_rule(struct sfe_connection_create *sic) +{ + struct sfe_ipv4_connection *c; + struct sfe_ipv4 *si = &__si; + + spin_lock_bh(&si->lock); + + c = sfe_ipv4_find_sfe_ipv4_connection(si, + sic->protocol, + sic->src_ip.ip, + sic->src_port, + sic->dest_ip.ip, + sic->dest_port); + if (c != NULL) { + sfe_ipv4_update_protocol_state(c, sic); + } + + spin_unlock_bh(&si->lock); +} + +/* + * sfe_ipv4_create_rule() + * Create a forwarding rule. + */ +int sfe_ipv4_create_rule(struct sfe_connection_create *sic) +{ + struct sfe_ipv4 *si = &__si; + struct sfe_ipv4_connection *c; + struct sfe_ipv4_connection_match *original_cm; + struct sfe_ipv4_connection_match *reply_cm; + struct net_device *dest_dev; + struct net_device *src_dev; + + dest_dev = sic->dest_dev; + src_dev = sic->src_dev; + + if (unlikely((dest_dev->reg_state != NETREG_REGISTERED) || + (src_dev->reg_state != NETREG_REGISTERED))) { + return -EINVAL; + } + + spin_lock_bh(&si->lock); + si->connection_create_requests++; + + /* + * Check to see if there is already a flow that matches the rule we're + * trying to create. If there is then we can't create a new one. + */ + c = sfe_ipv4_find_sfe_ipv4_connection(si, + sic->protocol, + sic->src_ip.ip, + sic->src_port, + sic->dest_ip.ip, + sic->dest_port); + if (c != NULL) { + si->connection_create_collisions++; + + /* + * If we already have the flow then it's likely that this + * request to create the connection rule contains more + * up-to-date information. Check and update accordingly. + */ + sfe_ipv4_update_protocol_state(c, sic); + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("connection already exists - mark: %08x, p: %d\n" + " s: %s:%pxM:%pI4:%u, d: %s:%pxM:%pI4:%u\n", + sic->mark, sic->protocol, + sic->src_dev->name, sic->src_mac, &sic->src_ip.ip, ntohs(sic->src_port), + sic->dest_dev->name, sic->dest_mac, &sic->dest_ip.ip, ntohs(sic->dest_port)); + return -EADDRINUSE; + } + + /* + * Allocate the various connection tracking objects. + */ + c = (struct sfe_ipv4_connection *)kmalloc(sizeof(struct sfe_ipv4_connection), GFP_ATOMIC); + if (unlikely(!c)) { + spin_unlock_bh(&si->lock); + return -ENOMEM; + } + + original_cm = (struct sfe_ipv4_connection_match *)kmalloc(sizeof(struct sfe_ipv4_connection_match), GFP_ATOMIC); + if (unlikely(!original_cm)) { + spin_unlock_bh(&si->lock); + kfree(c); + return -ENOMEM; + } + + reply_cm = (struct sfe_ipv4_connection_match *)kmalloc(sizeof(struct sfe_ipv4_connection_match), GFP_ATOMIC); + if (unlikely(!reply_cm)) { + spin_unlock_bh(&si->lock); + kfree(original_cm); + kfree(c); + return -ENOMEM; + } + + /* + * Fill in the "original" direction connection matching object. + * Note that the transmit MAC address is "dest_mac_xlate" because + * we always know both ends of a connection by their translated + * addresses and not their public addresses. + */ + original_cm->match_dev = src_dev; + original_cm->match_protocol = sic->protocol; + original_cm->match_src_ip = sic->src_ip.ip; + original_cm->match_src_port = sic->src_port; + original_cm->match_dest_ip = sic->dest_ip.ip; + original_cm->match_dest_port = sic->dest_port; + original_cm->xlate_src_ip = sic->src_ip_xlate.ip; + original_cm->xlate_src_port = sic->src_port_xlate; + original_cm->xlate_dest_ip = sic->dest_ip_xlate.ip; + original_cm->xlate_dest_port = sic->dest_port_xlate; + original_cm->rx_packet_count = 0; + original_cm->rx_packet_count64 = 0; + original_cm->rx_byte_count = 0; + original_cm->rx_byte_count64 = 0; + original_cm->xmit_dev = dest_dev; + original_cm->xmit_dev_mtu = sic->dest_mtu; + memcpy(original_cm->xmit_src_mac, dest_dev->dev_addr, ETH_ALEN); + memcpy(original_cm->xmit_dest_mac, sic->dest_mac_xlate, ETH_ALEN); + original_cm->connection = c; + original_cm->counter_match = reply_cm; + original_cm->flags = 0; + if (sic->flags & SFE_CREATE_FLAG_REMARK_PRIORITY) { + original_cm->priority = sic->src_priority; + original_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_PRIORITY_REMARK; + } + if (sic->flags & SFE_CREATE_FLAG_REMARK_DSCP) { + original_cm->dscp = sic->src_dscp << SFE_IPV4_DSCP_SHIFT; + original_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_DSCP_REMARK; + } +#ifdef CONFIG_NF_FLOW_COOKIE + original_cm->flow_cookie = 0; +#endif +#ifdef CONFIG_XFRM + original_cm->flow_accel = sic->original_accel; +#endif + original_cm->active_next = NULL; + original_cm->active_prev = NULL; + original_cm->active = false; + + /* + * For PPP links we don't write an L2 header. For everything else we do. + */ + if (!(dest_dev->flags & IFF_POINTOPOINT)) { + original_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_L2_HDR; + + /* + * If our dev writes Ethernet headers then we can write a really fast + * version. + */ + if (dest_dev->header_ops) { + if (dest_dev->header_ops->create == eth_header) { + original_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR; + } + } + } + + /* + * Fill in the "reply" direction connection matching object. + */ + reply_cm->match_dev = dest_dev; + reply_cm->match_protocol = sic->protocol; + reply_cm->match_src_ip = sic->dest_ip_xlate.ip; + reply_cm->match_src_port = sic->dest_port_xlate; + reply_cm->match_dest_ip = sic->src_ip_xlate.ip; + reply_cm->match_dest_port = sic->src_port_xlate; + reply_cm->xlate_src_ip = sic->dest_ip.ip; + reply_cm->xlate_src_port = sic->dest_port; + reply_cm->xlate_dest_ip = sic->src_ip.ip; + reply_cm->xlate_dest_port = sic->src_port; + reply_cm->rx_packet_count = 0; + reply_cm->rx_packet_count64 = 0; + reply_cm->rx_byte_count = 0; + reply_cm->rx_byte_count64 = 0; + reply_cm->xmit_dev = src_dev; + reply_cm->xmit_dev_mtu = sic->src_mtu; + memcpy(reply_cm->xmit_src_mac, src_dev->dev_addr, ETH_ALEN); + memcpy(reply_cm->xmit_dest_mac, sic->src_mac, ETH_ALEN); + reply_cm->connection = c; + reply_cm->counter_match = original_cm; + reply_cm->flags = 0; + if (sic->flags & SFE_CREATE_FLAG_REMARK_PRIORITY) { + reply_cm->priority = sic->dest_priority; + reply_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_PRIORITY_REMARK; + } + if (sic->flags & SFE_CREATE_FLAG_REMARK_DSCP) { + reply_cm->dscp = sic->dest_dscp << SFE_IPV4_DSCP_SHIFT; + reply_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_DSCP_REMARK; + } +#ifdef CONFIG_NF_FLOW_COOKIE + reply_cm->flow_cookie = 0; +#endif +#ifdef CONFIG_XFRM + reply_cm->flow_accel = sic->reply_accel; +#endif + reply_cm->active_next = NULL; + reply_cm->active_prev = NULL; + reply_cm->active = false; + + /* + * For PPP links we don't write an L2 header. For everything else we do. + */ + if (!(src_dev->flags & IFF_POINTOPOINT)) { + reply_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_L2_HDR; + + /* + * If our dev writes Ethernet headers then we can write a really fast + * version. + */ + if (src_dev->header_ops) { + if (src_dev->header_ops->create == eth_header) { + reply_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR; + } + } + } + + + if (sic->dest_ip.ip != sic->dest_ip_xlate.ip || sic->dest_port != sic->dest_port_xlate) { + original_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_DEST; + reply_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_SRC; + } + + if (sic->src_ip.ip != sic->src_ip_xlate.ip || sic->src_port != sic->src_port_xlate) { + original_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_SRC; + reply_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_DEST; + } + + c->protocol = sic->protocol; + c->src_ip = sic->src_ip.ip; + c->src_ip_xlate = sic->src_ip_xlate.ip; + c->src_port = sic->src_port; + c->src_port_xlate = sic->src_port_xlate; + c->original_dev = src_dev; + c->original_match = original_cm; + c->dest_ip = sic->dest_ip.ip; + c->dest_ip_xlate = sic->dest_ip_xlate.ip; + c->dest_port = sic->dest_port; + c->dest_port_xlate = sic->dest_port_xlate; + c->reply_dev = dest_dev; + c->reply_match = reply_cm; + c->mark = sic->mark; + c->debug_read_seq = 0; + c->last_sync_jiffies = get_jiffies_64(); + + /* + * Take hold of our source and dest devices for the duration of the connection. + */ + dev_hold(c->original_dev); + dev_hold(c->reply_dev); + + /* + * Initialize the protocol-specific information that we track. + */ + switch (sic->protocol) { + case IPPROTO_TCP: + original_cm->protocol_state.tcp.win_scale = sic->src_td_window_scale; + original_cm->protocol_state.tcp.max_win = sic->src_td_max_window ? sic->src_td_max_window : 1; + original_cm->protocol_state.tcp.end = sic->src_td_end; + original_cm->protocol_state.tcp.max_end = sic->src_td_max_end; + reply_cm->protocol_state.tcp.win_scale = sic->dest_td_window_scale; + reply_cm->protocol_state.tcp.max_win = sic->dest_td_max_window ? sic->dest_td_max_window : 1; + reply_cm->protocol_state.tcp.end = sic->dest_td_end; + reply_cm->protocol_state.tcp.max_end = sic->dest_td_max_end; + if (sic->flags & SFE_CREATE_FLAG_NO_SEQ_CHECK) { + original_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; + reply_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; + } + break; + } + + sfe_ipv4_connection_match_compute_translations(original_cm); + sfe_ipv4_connection_match_compute_translations(reply_cm); + sfe_ipv4_insert_sfe_ipv4_connection(si, c); + + spin_unlock_bh(&si->lock); + + /* + * We have everything we need! + */ + DEBUG_INFO("new connection - mark: %08x, p: %d\n" + " s: %s:%pxM(%pxM):%pI4(%pI4):%u(%u)\n" + " d: %s:%pxM(%pxM):%pI4(%pI4):%u(%u)\n", + sic->mark, sic->protocol, + sic->src_dev->name, sic->src_mac, sic->src_mac_xlate, + &sic->src_ip.ip, &sic->src_ip_xlate.ip, ntohs(sic->src_port), ntohs(sic->src_port_xlate), + dest_dev->name, sic->dest_mac, sic->dest_mac_xlate, + &sic->dest_ip.ip, &sic->dest_ip_xlate.ip, ntohs(sic->dest_port), ntohs(sic->dest_port_xlate)); + + return 0; +} + +/* + * sfe_ipv4_destroy_rule() + * Destroy a forwarding rule. + */ +void sfe_ipv4_destroy_rule(struct sfe_connection_destroy *sid) +{ + struct sfe_ipv4 *si = &__si; + struct sfe_ipv4_connection *c; + + spin_lock_bh(&si->lock); + si->connection_destroy_requests++; + + /* + * Check to see if we have a flow that matches the rule we're trying + * to destroy. If there isn't then we can't destroy it. + */ + c = sfe_ipv4_find_sfe_ipv4_connection(si, sid->protocol, sid->src_ip.ip, sid->src_port, + sid->dest_ip.ip, sid->dest_port); + if (!c) { + si->connection_destroy_misses++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("connection does not exist - p: %d, s: %pI4:%u, d: %pI4:%u\n", + sid->protocol, &sid->src_ip, ntohs(sid->src_port), + &sid->dest_ip, ntohs(sid->dest_port)); + return; + } + + /* + * Remove our connection details from the hash tables. + */ + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + spin_unlock_bh(&si->lock); + + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_DESTROY); + + DEBUG_INFO("connection destroyed - p: %d, s: %pI4:%u, d: %pI4:%u\n", + sid->protocol, &sid->src_ip.ip, ntohs(sid->src_port), + &sid->dest_ip.ip, ntohs(sid->dest_port)); +} + +/* + * sfe_ipv4_register_sync_rule_callback() + * Register a callback for rule synchronization. + */ +void sfe_ipv4_register_sync_rule_callback(sfe_sync_rule_callback_t sync_rule_callback) +{ + struct sfe_ipv4 *si = &__si; + + spin_lock_bh(&si->lock); + rcu_assign_pointer(si->sync_rule_callback, sync_rule_callback); + spin_unlock_bh(&si->lock); +} + +/* + * sfe_ipv4_get_debug_dev() + */ +static ssize_t sfe_ipv4_get_debug_dev(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct sfe_ipv4 *si = &__si; + ssize_t count; + int num; + + spin_lock_bh(&si->lock); + num = si->debug_dev; + spin_unlock_bh(&si->lock); + + count = snprintf(buf, (ssize_t)PAGE_SIZE, "%d\n", num); + return count; +} + +/* + * sysfs attributes. + */ +static const struct device_attribute sfe_ipv4_debug_dev_attr = + __ATTR(debug_dev, S_IWUSR | S_IRUGO, sfe_ipv4_get_debug_dev, NULL); + +/* + * sfe_ipv4_destroy_all_rules_for_dev() + * Destroy all connections that match a particular device. + * + * If we pass dev as NULL then this destroys all connections. + */ +void sfe_ipv4_destroy_all_rules_for_dev(struct net_device *dev) +{ + struct sfe_ipv4 *si = &__si; + struct sfe_ipv4_connection *c; + +another_round: + spin_lock_bh(&si->lock); + + for (c = si->all_connections_head; c; c = c->all_connections_next) { + /* + * Does this connection relate to the device we are destroying? + */ + if (!dev + || (dev == c->original_dev) + || (dev == c->reply_dev)) { + break; + } + } + + if (c) { + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + } + + spin_unlock_bh(&si->lock); + + if (c) { + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_DESTROY); + goto another_round; + } +} + +/* + * sfe_ipv4_periodic_sync() + */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) +static void sfe_ipv4_periodic_sync(unsigned long arg) +#else +static void sfe_ipv4_periodic_sync(struct timer_list *tl) +#endif +{ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) + struct sfe_ipv4 *si = (struct sfe_ipv4 *)arg; +#else + struct sfe_ipv4 *si = from_timer(si, tl, timer); +#endif + u64 now_jiffies; + int quota; + sfe_sync_rule_callback_t sync_rule_callback; + + now_jiffies = get_jiffies_64(); + + rcu_read_lock(); + sync_rule_callback = rcu_dereference(si->sync_rule_callback); + if (!sync_rule_callback) { + rcu_read_unlock(); + goto done; + } + + spin_lock_bh(&si->lock); + sfe_ipv4_update_summary_stats(si); + + /* + * Get an estimate of the number of connections to parse in this sync. + */ + quota = (si->num_connections + 63) / 64; + + /* + * Walk the "active" list and sync the connection state. + */ + while (quota--) { + struct sfe_ipv4_connection_match *cm; + struct sfe_ipv4_connection_match *counter_cm; + struct sfe_ipv4_connection *c; + struct sfe_connection_sync sis; + + cm = si->active_head; + if (!cm) { + break; + } + + /* + * There's a possibility that our counter match is in the active list too. + * If it is then remove it. + */ + counter_cm = cm->counter_match; + if (counter_cm->active) { + counter_cm->active = false; + + /* + * We must have a connection preceding this counter match + * because that's the one that got us to this point, so we don't have + * to worry about removing the head of the list. + */ + counter_cm->active_prev->active_next = counter_cm->active_next; + + if (likely(counter_cm->active_next)) { + counter_cm->active_next->active_prev = counter_cm->active_prev; + } else { + si->active_tail = counter_cm->active_prev; + } + + counter_cm->active_next = NULL; + counter_cm->active_prev = NULL; + } + + /* + * Now remove the head of the active scan list. + */ + cm->active = false; + si->active_head = cm->active_next; + if (likely(cm->active_next)) { + cm->active_next->active_prev = NULL; + } else { + si->active_tail = NULL; + } + cm->active_next = NULL; + + /* + * Sync the connection state. + */ + c = cm->connection; + sfe_ipv4_gen_sync_sfe_ipv4_connection(si, c, &sis, SFE_SYNC_REASON_STATS, now_jiffies); + + /* + * We don't want to be holding the lock when we sync! + */ + spin_unlock_bh(&si->lock); + sync_rule_callback(&sis); + spin_lock_bh(&si->lock); + } + + spin_unlock_bh(&si->lock); + rcu_read_unlock(); + +done: + mod_timer(&si->timer, jiffies + ((HZ + 99) / 100)); +} + +#define CHAR_DEV_MSG_SIZE 768 + +/* + * sfe_ipv4_debug_dev_read_start() + * Generate part of the XML output. + */ +static bool sfe_ipv4_debug_dev_read_start(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv4_debug_xml_write_state *ws) +{ + int bytes_read; + + si->debug_read_seq++; + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\n"); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + ws->state++; + return true; +} + +/* + * sfe_ipv4_debug_dev_read_connections_start() + * Generate part of the XML output. + */ +static bool sfe_ipv4_debug_dev_read_connections_start(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv4_debug_xml_write_state *ws) +{ + int bytes_read; + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n"); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + ws->state++; + return true; +} + +/* + * sfe_ipv4_debug_dev_read_connections_connection() + * Generate part of the XML output. + */ +static bool sfe_ipv4_debug_dev_read_connections_connection(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv4_debug_xml_write_state *ws) +{ + struct sfe_ipv4_connection *c; + struct sfe_ipv4_connection_match *original_cm; + struct sfe_ipv4_connection_match *reply_cm; + int bytes_read; + int protocol; + struct net_device *src_dev; + __be32 src_ip; + __be32 src_ip_xlate; + __be16 src_port; + __be16 src_port_xlate; + u64 src_rx_packets; + u64 src_rx_bytes; + struct net_device *dest_dev; + __be32 dest_ip; + __be32 dest_ip_xlate; + __be16 dest_port; + __be16 dest_port_xlate; + u64 dest_rx_packets; + u64 dest_rx_bytes; + u64 last_sync_jiffies; + u32 mark, src_priority, dest_priority, src_dscp, dest_dscp; +#ifdef CONFIG_NF_FLOW_COOKIE + int src_flow_cookie, dst_flow_cookie; +#endif + + spin_lock_bh(&si->lock); + + for (c = si->all_connections_head; c; c = c->all_connections_next) { + if (c->debug_read_seq < si->debug_read_seq) { + c->debug_read_seq = si->debug_read_seq; + break; + } + } + + /* + * If there were no connections then move to the next state. + */ + if (!c) { + spin_unlock_bh(&si->lock); + ws->state++; + return true; + } + + original_cm = c->original_match; + reply_cm = c->reply_match; + + protocol = c->protocol; + src_dev = c->original_dev; + src_ip = c->src_ip; + src_ip_xlate = c->src_ip_xlate; + src_port = c->src_port; + src_port_xlate = c->src_port_xlate; + src_priority = original_cm->priority; + src_dscp = original_cm->dscp >> SFE_IPV4_DSCP_SHIFT; + + sfe_ipv4_connection_match_update_summary_stats(original_cm); + sfe_ipv4_connection_match_update_summary_stats(reply_cm); + + src_rx_packets = original_cm->rx_packet_count64; + src_rx_bytes = original_cm->rx_byte_count64; + dest_dev = c->reply_dev; + dest_ip = c->dest_ip; + dest_ip_xlate = c->dest_ip_xlate; + dest_port = c->dest_port; + dest_port_xlate = c->dest_port_xlate; + dest_priority = reply_cm->priority; + dest_dscp = reply_cm->dscp >> SFE_IPV4_DSCP_SHIFT; + dest_rx_packets = reply_cm->rx_packet_count64; + dest_rx_bytes = reply_cm->rx_byte_count64; + last_sync_jiffies = get_jiffies_64() - c->last_sync_jiffies; + mark = c->mark; +#ifdef CONFIG_NF_FLOW_COOKIE + src_flow_cookie = original_cm->flow_cookie; + dst_flow_cookie = reply_cm->flow_cookie; +#endif + spin_unlock_bh(&si->lock); + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\t\n", + protocol, + src_dev->name, + &src_ip, &src_ip_xlate, + ntohs(src_port), ntohs(src_port_xlate), + src_priority, src_dscp, + src_rx_packets, src_rx_bytes, + dest_dev->name, + &dest_ip, &dest_ip_xlate, + ntohs(dest_port), ntohs(dest_port_xlate), + dest_priority, dest_dscp, + dest_rx_packets, dest_rx_bytes, +#ifdef CONFIG_NF_FLOW_COOKIE + src_flow_cookie, dst_flow_cookie, +#endif + last_sync_jiffies, mark); + + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + return true; +} + +/* + * sfe_ipv4_debug_dev_read_connections_end() + * Generate part of the XML output. + */ +static bool sfe_ipv4_debug_dev_read_connections_end(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv4_debug_xml_write_state *ws) +{ + int bytes_read; + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n"); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + ws->state++; + return true; +} + +/* + * sfe_ipv4_debug_dev_read_exceptions_start() + * Generate part of the XML output. + */ +static bool sfe_ipv4_debug_dev_read_exceptions_start(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv4_debug_xml_write_state *ws) +{ + int bytes_read; + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n"); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + ws->state++; + return true; +} + +/* + * sfe_ipv4_debug_dev_read_exceptions_exception() + * Generate part of the XML output. + */ +static bool sfe_ipv4_debug_dev_read_exceptions_exception(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv4_debug_xml_write_state *ws) +{ + u64 ct; + + spin_lock_bh(&si->lock); + ct = si->exception_events64[ws->iter_exception]; + spin_unlock_bh(&si->lock); + + if (ct) { + int bytes_read; + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, + "\t\t\n", + sfe_ipv4_exception_events_string[ws->iter_exception], + ct); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + } + + ws->iter_exception++; + if (ws->iter_exception >= SFE_IPV4_EXCEPTION_EVENT_LAST) { + ws->iter_exception = 0; + ws->state++; + } + + return true; +} + +/* + * sfe_ipv4_debug_dev_read_exceptions_end() + * Generate part of the XML output. + */ +static bool sfe_ipv4_debug_dev_read_exceptions_end(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv4_debug_xml_write_state *ws) +{ + int bytes_read; + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n"); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + ws->state++; + return true; +} + +/* + * sfe_ipv4_debug_dev_read_stats() + * Generate part of the XML output. + */ +static bool sfe_ipv4_debug_dev_read_stats(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv4_debug_xml_write_state *ws) +{ + int bytes_read; + unsigned int num_connections; + u64 packets_forwarded; + u64 packets_not_forwarded; + u64 connection_create_requests; + u64 connection_create_collisions; + u64 connection_destroy_requests; + u64 connection_destroy_misses; + u64 connection_flushes; + u64 connection_match_hash_hits; + u64 connection_match_hash_reorders; + + spin_lock_bh(&si->lock); + sfe_ipv4_update_summary_stats(si); + + num_connections = si->num_connections; + packets_forwarded = si->packets_forwarded64; + packets_not_forwarded = si->packets_not_forwarded64; + connection_create_requests = si->connection_create_requests64; + connection_create_collisions = si->connection_create_collisions64; + connection_destroy_requests = si->connection_destroy_requests64; + connection_destroy_misses = si->connection_destroy_misses64; + connection_flushes = si->connection_flushes64; + connection_match_hash_hits = si->connection_match_hash_hits64; + connection_match_hash_reorders = si->connection_match_hash_reorders64; + spin_unlock_bh(&si->lock); + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n", + num_connections, + packets_forwarded, + packets_not_forwarded, + connection_create_requests, + connection_create_collisions, + connection_destroy_requests, + connection_destroy_misses, + connection_flushes, + connection_match_hash_hits, + connection_match_hash_reorders); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + ws->state++; + return true; +} + +/* + * sfe_ipv4_debug_dev_read_end() + * Generate part of the XML output. + */ +static bool sfe_ipv4_debug_dev_read_end(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv4_debug_xml_write_state *ws) +{ + int bytes_read; + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\n"); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + ws->state++; + return true; +} + +/* + * Array of write functions that write various XML elements that correspond to + * our XML output state machine. + */ +static sfe_ipv4_debug_xml_write_method_t sfe_ipv4_debug_xml_write_methods[SFE_IPV4_DEBUG_XML_STATE_DONE] = { + sfe_ipv4_debug_dev_read_start, + sfe_ipv4_debug_dev_read_connections_start, + sfe_ipv4_debug_dev_read_connections_connection, + sfe_ipv4_debug_dev_read_connections_end, + sfe_ipv4_debug_dev_read_exceptions_start, + sfe_ipv4_debug_dev_read_exceptions_exception, + sfe_ipv4_debug_dev_read_exceptions_end, + sfe_ipv4_debug_dev_read_stats, + sfe_ipv4_debug_dev_read_end, +}; + +/* + * sfe_ipv4_debug_dev_read() + * Send info to userspace upon read request from user + */ +static ssize_t sfe_ipv4_debug_dev_read(struct file *filp, char *buffer, size_t length, loff_t *offset) +{ + char msg[CHAR_DEV_MSG_SIZE]; + int total_read = 0; + struct sfe_ipv4_debug_xml_write_state *ws; + struct sfe_ipv4 *si = &__si; + + ws = (struct sfe_ipv4_debug_xml_write_state *)filp->private_data; + while ((ws->state != SFE_IPV4_DEBUG_XML_STATE_DONE) && (length > CHAR_DEV_MSG_SIZE)) { + if ((sfe_ipv4_debug_xml_write_methods[ws->state])(si, buffer, msg, &length, &total_read, ws)) { + continue; + } + } + + return total_read; +} + +/* + * sfe_ipv4_debug_dev_write() + * Write to char device resets some stats + */ +static ssize_t sfe_ipv4_debug_dev_write(struct file *filp, const char *buffer, size_t length, loff_t *offset) +{ + struct sfe_ipv4 *si = &__si; + + spin_lock_bh(&si->lock); + sfe_ipv4_update_summary_stats(si); + + si->packets_forwarded64 = 0; + si->packets_not_forwarded64 = 0; + si->connection_create_requests64 = 0; + si->connection_create_collisions64 = 0; + si->connection_destroy_requests64 = 0; + si->connection_destroy_misses64 = 0; + si->connection_flushes64 = 0; + si->connection_match_hash_hits64 = 0; + si->connection_match_hash_reorders64 = 0; + spin_unlock_bh(&si->lock); + + return length; +} + +/* + * sfe_ipv4_debug_dev_open() + */ +static int sfe_ipv4_debug_dev_open(struct inode *inode, struct file *file) +{ + struct sfe_ipv4_debug_xml_write_state *ws; + + ws = (struct sfe_ipv4_debug_xml_write_state *)file->private_data; + if (!ws) { + ws = kzalloc(sizeof(struct sfe_ipv4_debug_xml_write_state), GFP_KERNEL); + if (!ws) { + return -ENOMEM; + } + + ws->state = SFE_IPV4_DEBUG_XML_STATE_START; + file->private_data = ws; + } + + return 0; +} + +/* + * sfe_ipv4_debug_dev_release() + */ +static int sfe_ipv4_debug_dev_release(struct inode *inode, struct file *file) +{ + struct sfe_ipv4_debug_xml_write_state *ws; + + ws = (struct sfe_ipv4_debug_xml_write_state *)file->private_data; + if (ws) { + /* + * We've finished with our output so free the write state. + */ + kfree(ws); + } + + return 0; +} + +/* + * File operations used in the debug char device + */ +static struct file_operations sfe_ipv4_debug_dev_fops = { + .read = sfe_ipv4_debug_dev_read, + .write = sfe_ipv4_debug_dev_write, + .open = sfe_ipv4_debug_dev_open, + .release = sfe_ipv4_debug_dev_release +}; + +#ifdef CONFIG_NF_FLOW_COOKIE +/* + * sfe_register_flow_cookie_cb + * register a function in SFE to let SFE use this function to configure flow cookie for a flow + * + * Hardware driver which support flow cookie should register a callback function in SFE. Then SFE + * can use this function to configure flow cookie for a flow. + * return: 0, success; !=0, fail + */ +int sfe_register_flow_cookie_cb(flow_cookie_set_func_t cb) +{ + struct sfe_ipv4 *si = &__si; + + BUG_ON(!cb); + + if (si->flow_cookie_set_func) { + return -1; + } + + rcu_assign_pointer(si->flow_cookie_set_func, cb); + return 0; +} + +/* + * sfe_unregister_flow_cookie_cb + * unregister function which is used to configure flow cookie for a flow + * + * return: 0, success; !=0, fail + */ +int sfe_unregister_flow_cookie_cb(flow_cookie_set_func_t cb) +{ + struct sfe_ipv4 *si = &__si; + + RCU_INIT_POINTER(si->flow_cookie_set_func, NULL); + return 0; +} + +/* + * sfe_ipv4_get_flow_cookie() + */ +static ssize_t sfe_ipv4_get_flow_cookie(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct sfe_ipv4 *si = &__si; + return snprintf(buf, (ssize_t)PAGE_SIZE, "%d\n", si->flow_cookie_enable); +} + +/* + * sfe_ipv4_set_flow_cookie() + */ +static ssize_t sfe_ipv4_set_flow_cookie(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct sfe_ipv4 *si = &__si; + strict_strtol(buf, 0, (long int *)&si->flow_cookie_enable); + + return size; +} + +/* + * sysfs attributes. + */ +static const struct device_attribute sfe_ipv4_flow_cookie_attr = + __ATTR(flow_cookie_enable, S_IWUSR | S_IRUGO, sfe_ipv4_get_flow_cookie, sfe_ipv4_set_flow_cookie); +#endif /*CONFIG_NF_FLOW_COOKIE*/ + +/* + * sfe_ipv4_init() + */ +static int __init sfe_ipv4_init(void) +{ + struct sfe_ipv4 *si = &__si; + int result = -1; + + DEBUG_INFO("SFE IPv4 init\n"); + + /* + * Create sys/sfe_ipv4 + */ + si->sys_sfe_ipv4 = kobject_create_and_add("sfe_ipv4", NULL); + if (!si->sys_sfe_ipv4) { + DEBUG_ERROR("failed to register sfe_ipv4\n"); + goto exit1; + } + + /* + * Create files, one for each parameter supported by this module. + */ + result = sysfs_create_file(si->sys_sfe_ipv4, &sfe_ipv4_debug_dev_attr.attr); + if (result) { + DEBUG_ERROR("failed to register debug dev file: %d\n", result); + goto exit2; + } + +#ifdef CONFIG_NF_FLOW_COOKIE + result = sysfs_create_file(si->sys_sfe_ipv4, &sfe_ipv4_flow_cookie_attr.attr); + if (result) { + DEBUG_ERROR("failed to register flow cookie enable file: %d\n", result); + goto exit3; + } +#endif /* CONFIG_NF_FLOW_COOKIE */ + + /* + * Register our debug char device. + */ + result = register_chrdev(0, "sfe_ipv4", &sfe_ipv4_debug_dev_fops); + if (result < 0) { + DEBUG_ERROR("Failed to register chrdev: %d\n", result); + goto exit4; + } + + si->debug_dev = result; + + /* + * Create a timer to handle periodic statistics. + */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) + setup_timer(&si->timer, sfe_ipv4_periodic_sync, (unsigned long)si); +#else + timer_setup(&si->timer, sfe_ipv4_periodic_sync, 0); +#endif + mod_timer(&si->timer, jiffies + ((HZ + 99) / 100)); + + spin_lock_init(&si->lock); + + return 0; + +exit4: +#ifdef CONFIG_NF_FLOW_COOKIE + sysfs_remove_file(si->sys_sfe_ipv4, &sfe_ipv4_flow_cookie_attr.attr); + +exit3: +#endif /* CONFIG_NF_FLOW_COOKIE */ + sysfs_remove_file(si->sys_sfe_ipv4, &sfe_ipv4_debug_dev_attr.attr); + +exit2: + kobject_put(si->sys_sfe_ipv4); + +exit1: + return result; +} + +/* + * sfe_ipv4_exit() + */ +static void __exit sfe_ipv4_exit(void) +{ + struct sfe_ipv4 *si = &__si; + + DEBUG_INFO("SFE IPv4 exit\n"); + + /* + * Destroy all connections. + */ + sfe_ipv4_destroy_all_rules_for_dev(NULL); + + del_timer_sync(&si->timer); + + unregister_chrdev(si->debug_dev, "sfe_ipv4"); + +#ifdef CONFIG_NF_FLOW_COOKIE + sysfs_remove_file(si->sys_sfe_ipv4, &sfe_ipv4_flow_cookie_attr.attr); +#endif /* CONFIG_NF_FLOW_COOKIE */ + sysfs_remove_file(si->sys_sfe_ipv4, &sfe_ipv4_debug_dev_attr.attr); + + kobject_put(si->sys_sfe_ipv4); + +} + +module_init(sfe_ipv4_init) +module_exit(sfe_ipv4_exit) + +EXPORT_SYMBOL(sfe_ipv4_recv); +EXPORT_SYMBOL(sfe_ipv4_create_rule); +EXPORT_SYMBOL(sfe_ipv4_destroy_rule); +EXPORT_SYMBOL(sfe_ipv4_destroy_all_rules_for_dev); +EXPORT_SYMBOL(sfe_ipv4_register_sync_rule_callback); +EXPORT_SYMBOL(sfe_ipv4_mark_rule); +EXPORT_SYMBOL(sfe_ipv4_update_rule); +#ifdef CONFIG_NF_FLOW_COOKIE +EXPORT_SYMBOL(sfe_register_flow_cookie_cb); +EXPORT_SYMBOL(sfe_unregister_flow_cookie_cb); +#endif + +MODULE_DESCRIPTION("Shortcut Forwarding Engine - IPv4 edition"); +MODULE_LICENSE("Dual BSD/GPL"); + diff --git a/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_ipv6.c b/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_ipv6.c new file mode 100644 index 00000000..ae330669 --- /dev/null +++ b/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_ipv6.c @@ -0,0 +1,3625 @@ +/* + * sfe_ipv6.c + * Shortcut forwarding engine - IPv6 support. + * + * Copyright (c) 2015-2016, 2019-2020 The Linux Foundation. All rights reserved. + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "sfe.h" +#include "sfe_cm.h" + +/* + * By default Linux IP header and transport layer header structures are + * unpacked, assuming that such headers should be 32-bit aligned. + * Unfortunately some wireless adaptors can't cope with this requirement and + * some CPUs can't handle misaligned accesses. For those platforms we + * define SFE_IPV6_UNALIGNED_IP_HEADER and mark the structures as packed. + * When we do this the compiler will generate slightly worse code than for the + * aligned case (on most platforms) but will be much quicker than fixing + * things up in an unaligned trap handler. + */ +#define SFE_IPV6_UNALIGNED_IP_HEADER 1 +#if SFE_IPV6_UNALIGNED_IP_HEADER +#define SFE_IPV6_UNALIGNED_STRUCT __attribute__((packed)) +#else +#define SFE_IPV6_UNALIGNED_STRUCT +#endif + +#define CHAR_DEV_MSG_SIZE 768 + +/* + * An Ethernet header, but with an optional "packed" attribute to + * help with performance on some platforms (see the definition of + * SFE_IPV6_UNALIGNED_STRUCT) + */ +struct sfe_ipv6_eth_hdr { + __be16 h_dest[ETH_ALEN / 2]; + __be16 h_source[ETH_ALEN / 2]; + __be16 h_proto; +} SFE_IPV6_UNALIGNED_STRUCT; + +#define SFE_IPV6_DSCP_MASK 0xf03f +#define SFE_IPV6_DSCP_SHIFT 2 + +/* + * An IPv6 header, but with an optional "packed" attribute to + * help with performance on some platforms (see the definition of + * SFE_IPV6_UNALIGNED_STRUCT) + */ +struct sfe_ipv6_ip_hdr { +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u8 priority:4, + version:4; +#elif defined(__BIG_ENDIAN_BITFIELD) + __u8 version:4, + priority:4; +#else +#error "Please fix " +#endif + __u8 flow_lbl[3]; + __be16 payload_len; + __u8 nexthdr; + __u8 hop_limit; + struct sfe_ipv6_addr saddr; + struct sfe_ipv6_addr daddr; + + /* + * The extension header start here. + */ +} SFE_IPV6_UNALIGNED_STRUCT; + +#define SFE_IPV6_EXT_HDR_HOP 0 +#define SFE_IPV6_EXT_HDR_ROUTING 43 +#define SFE_IPV6_EXT_HDR_FRAG 44 +#define SFE_IPV6_EXT_HDR_ESP 50 +#define SFE_IPV6_EXT_HDR_AH 51 +#define SFE_IPV6_EXT_HDR_NONE 59 +#define SFE_IPV6_EXT_HDR_DST 60 +#define SFE_IPV6_EXT_HDR_MH 135 + +/* + * fragmentation header + */ + +struct sfe_ipv6_frag_hdr { + __u8 nexthdr; + __u8 reserved; + __be16 frag_off; + __be32 identification; +}; + +#define SFE_IPV6_FRAG_OFFSET 0xfff8 + +/* + * generic IPv6 extension header + */ +struct sfe_ipv6_ext_hdr { + __u8 next_hdr; + __u8 hdr_len; + __u8 padding[6]; +} SFE_IPV6_UNALIGNED_STRUCT; + +/* + * A UDP header, but with an optional "packed" attribute to + * help with performance on some platforms (see the definition of + * SFE_IPV6_UNALIGNED_STRUCT) + */ +struct sfe_ipv6_udp_hdr { + __be16 source; + __be16 dest; + __be16 len; + __sum16 check; +} SFE_IPV6_UNALIGNED_STRUCT; + +/* + * A TCP header, but with an optional "packed" attribute to + * help with performance on some platforms (see the definition of + * SFE_IPV6_UNALIGNED_STRUCT) + */ +struct sfe_ipv6_tcp_hdr { + __be16 source; + __be16 dest; + __be32 seq; + __be32 ack_seq; +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u16 res1:4, + doff:4, + fin:1, + syn:1, + rst:1, + psh:1, + ack:1, + urg:1, + ece:1, + cwr:1; +#elif defined(__BIG_ENDIAN_BITFIELD) + __u16 doff:4, + res1:4, + cwr:1, + ece:1, + urg:1, + ack:1, + psh:1, + rst:1, + syn:1, + fin:1; +#else +#error "Adjust your defines" +#endif + __be16 window; + __sum16 check; + __be16 urg_ptr; +} SFE_IPV6_UNALIGNED_STRUCT; + +/* + * Specifies the lower bound on ACK numbers carried in the TCP header + */ +#define SFE_IPV6_TCP_MAX_ACK_WINDOW 65520 + +/* + * IPv6 TCP connection match additional data. + */ +struct sfe_ipv6_tcp_connection_match { + u8 win_scale; /* Window scale */ + u32 max_win; /* Maximum window size seen */ + u32 end; /* Sequence number of the next byte to send (seq + segment length) */ + u32 max_end; /* Sequence number of the last byte to ack */ +}; + +/* + * Bit flags for IPv6 connection matching entry. + */ +#define SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_SRC (1<<0) + /* Perform source translation */ +#define SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_DEST (1<<1) + /* Perform destination translation */ +#define SFE_IPV6_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK (1<<2) + /* Ignore TCP sequence numbers */ +#define SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR (1<<3) + /* Fast Ethernet header write */ +#define SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_L2_HDR (1<<4) + /* Fast Ethernet header write */ +#define SFE_IPV6_CONNECTION_MATCH_FLAG_PRIORITY_REMARK (1<<5) + /* remark priority of SKB */ +#define SFE_IPV6_CONNECTION_MATCH_FLAG_DSCP_REMARK (1<<6) + /* remark DSCP of packet */ + +/* + * IPv6 connection matching structure. + */ +struct sfe_ipv6_connection_match { + /* + * References to other objects. + */ + struct sfe_ipv6_connection_match *next; + struct sfe_ipv6_connection_match *prev; + struct sfe_ipv6_connection *connection; + struct sfe_ipv6_connection_match *counter_match; + /* Matches the flow in the opposite direction as the one in connection */ + struct sfe_ipv6_connection_match *active_next; + struct sfe_ipv6_connection_match *active_prev; + bool active; /* Flag to indicate if we're on the active list */ + + /* + * Characteristics that identify flows that match this rule. + */ + struct net_device *match_dev; /* Network device */ + u8 match_protocol; /* Protocol */ + struct sfe_ipv6_addr match_src_ip[1]; /* Source IP address */ + struct sfe_ipv6_addr match_dest_ip[1]; /* Destination IP address */ + __be16 match_src_port; /* Source port/connection ident */ + __be16 match_dest_port; /* Destination port/connection ident */ + + /* + * Control the operations of the match. + */ + u32 flags; /* Bit flags */ +#ifdef CONFIG_NF_FLOW_COOKIE + u32 flow_cookie; /* used flow cookie, for debug */ +#endif +#ifdef CONFIG_XFRM + u32 flow_accel; /* The flow accelerated or not */ +#endif + + /* + * Connection state that we track once we match. + */ + union { /* Protocol-specific state */ + struct sfe_ipv6_tcp_connection_match tcp; + } protocol_state; + /* + * Stats recorded in a sync period. These stats will be added to + * rx_packet_count64/rx_byte_count64 after a sync period. + */ + u32 rx_packet_count; + u32 rx_byte_count; + + /* + * Packet translation information. + */ + struct sfe_ipv6_addr xlate_src_ip[1]; /* Address after source translation */ + __be16 xlate_src_port; /* Port/connection ident after source translation */ + u16 xlate_src_csum_adjustment; + /* Transport layer checksum adjustment after source translation */ + struct sfe_ipv6_addr xlate_dest_ip[1]; /* Address after destination translation */ + __be16 xlate_dest_port; /* Port/connection ident after destination translation */ + u16 xlate_dest_csum_adjustment; + /* Transport layer checksum adjustment after destination translation */ + + /* + * QoS information + */ + u32 priority; + u32 dscp; + + /* + * Packet transmit information. + */ + struct net_device *xmit_dev; /* Network device on which to transmit */ + unsigned short int xmit_dev_mtu; + /* Interface MTU */ + u16 xmit_dest_mac[ETH_ALEN / 2]; + /* Destination MAC address to use when forwarding */ + u16 xmit_src_mac[ETH_ALEN / 2]; + /* Source MAC address to use when forwarding */ + + /* + * Summary stats. + */ + u64 rx_packet_count64; + u64 rx_byte_count64; +}; + +/* + * Per-connection data structure. + */ +struct sfe_ipv6_connection { + struct sfe_ipv6_connection *next; + /* Pointer to the next entry in a hash chain */ + struct sfe_ipv6_connection *prev; + /* Pointer to the previous entry in a hash chain */ + int protocol; /* IP protocol number */ + struct sfe_ipv6_addr src_ip[1]; /* Src IP addr pre-translation */ + struct sfe_ipv6_addr src_ip_xlate[1]; /* Src IP addr post-translation */ + struct sfe_ipv6_addr dest_ip[1]; /* Dest IP addr pre-translation */ + struct sfe_ipv6_addr dest_ip_xlate[1]; /* Dest IP addr post-translation */ + __be16 src_port; /* Src port pre-translation */ + __be16 src_port_xlate; /* Src port post-translation */ + __be16 dest_port; /* Dest port pre-translation */ + __be16 dest_port_xlate; /* Dest port post-translation */ + struct sfe_ipv6_connection_match *original_match; + /* Original direction matching structure */ + struct net_device *original_dev; + /* Original direction source device */ + struct sfe_ipv6_connection_match *reply_match; + /* Reply direction matching structure */ + struct net_device *reply_dev; /* Reply direction source device */ + u64 last_sync_jiffies; /* Jiffies count for the last sync */ + struct sfe_ipv6_connection *all_connections_next; + /* Pointer to the next entry in the list of all connections */ + struct sfe_ipv6_connection *all_connections_prev; + /* Pointer to the previous entry in the list of all connections */ + u32 mark; /* mark for outgoing packet */ + u32 debug_read_seq; /* sequence number for debug dump */ +}; + +/* + * IPv6 connections and hash table size information. + */ +#define SFE_IPV6_CONNECTION_HASH_SHIFT 12 +#define SFE_IPV6_CONNECTION_HASH_SIZE (1 << SFE_IPV6_CONNECTION_HASH_SHIFT) +#define SFE_IPV6_CONNECTION_HASH_MASK (SFE_IPV6_CONNECTION_HASH_SIZE - 1) + +#ifdef CONFIG_NF_FLOW_COOKIE +#define SFE_FLOW_COOKIE_SIZE 2048 +#define SFE_FLOW_COOKIE_MASK 0x7ff + +struct sfe_ipv6_flow_cookie_entry { + struct sfe_ipv6_connection_match *match; + unsigned long last_clean_time; +}; +#endif + +enum sfe_ipv6_exception_events { + SFE_IPV6_EXCEPTION_EVENT_UDP_HEADER_INCOMPLETE, + SFE_IPV6_EXCEPTION_EVENT_UDP_NO_CONNECTION, + SFE_IPV6_EXCEPTION_EVENT_UDP_IP_OPTIONS_OR_INITIAL_FRAGMENT, + SFE_IPV6_EXCEPTION_EVENT_UDP_SMALL_TTL, + SFE_IPV6_EXCEPTION_EVENT_UDP_NEEDS_FRAGMENTATION, + SFE_IPV6_EXCEPTION_EVENT_TCP_HEADER_INCOMPLETE, + SFE_IPV6_EXCEPTION_EVENT_TCP_NO_CONNECTION_SLOW_FLAGS, + SFE_IPV6_EXCEPTION_EVENT_TCP_NO_CONNECTION_FAST_FLAGS, + SFE_IPV6_EXCEPTION_EVENT_TCP_IP_OPTIONS_OR_INITIAL_FRAGMENT, + SFE_IPV6_EXCEPTION_EVENT_TCP_SMALL_TTL, + SFE_IPV6_EXCEPTION_EVENT_TCP_NEEDS_FRAGMENTATION, + SFE_IPV6_EXCEPTION_EVENT_TCP_FLAGS, + SFE_IPV6_EXCEPTION_EVENT_TCP_SEQ_EXCEEDS_RIGHT_EDGE, + SFE_IPV6_EXCEPTION_EVENT_TCP_SMALL_DATA_OFFS, + SFE_IPV6_EXCEPTION_EVENT_TCP_BAD_SACK, + SFE_IPV6_EXCEPTION_EVENT_TCP_BIG_DATA_OFFS, + SFE_IPV6_EXCEPTION_EVENT_TCP_SEQ_BEFORE_LEFT_EDGE, + SFE_IPV6_EXCEPTION_EVENT_TCP_ACK_EXCEEDS_RIGHT_EDGE, + SFE_IPV6_EXCEPTION_EVENT_TCP_ACK_BEFORE_LEFT_EDGE, + SFE_IPV6_EXCEPTION_EVENT_ICMP_HEADER_INCOMPLETE, + SFE_IPV6_EXCEPTION_EVENT_ICMP_UNHANDLED_TYPE, + SFE_IPV6_EXCEPTION_EVENT_ICMP_IPV6_HEADER_INCOMPLETE, + SFE_IPV6_EXCEPTION_EVENT_ICMP_IPV6_NON_V6, + SFE_IPV6_EXCEPTION_EVENT_ICMP_IPV6_IP_OPTIONS_INCOMPLETE, + SFE_IPV6_EXCEPTION_EVENT_ICMP_IPV6_UDP_HEADER_INCOMPLETE, + SFE_IPV6_EXCEPTION_EVENT_ICMP_IPV6_TCP_HEADER_INCOMPLETE, + SFE_IPV6_EXCEPTION_EVENT_ICMP_IPV6_UNHANDLED_PROTOCOL, + SFE_IPV6_EXCEPTION_EVENT_ICMP_NO_CONNECTION, + SFE_IPV6_EXCEPTION_EVENT_ICMP_FLUSHED_CONNECTION, + SFE_IPV6_EXCEPTION_EVENT_HEADER_INCOMPLETE, + SFE_IPV6_EXCEPTION_EVENT_BAD_TOTAL_LENGTH, + SFE_IPV6_EXCEPTION_EVENT_NON_V6, + SFE_IPV6_EXCEPTION_EVENT_NON_INITIAL_FRAGMENT, + SFE_IPV6_EXCEPTION_EVENT_DATAGRAM_INCOMPLETE, + SFE_IPV6_EXCEPTION_EVENT_IP_OPTIONS_INCOMPLETE, + SFE_IPV6_EXCEPTION_EVENT_UNHANDLED_PROTOCOL, + SFE_IPV6_EXCEPTION_EVENT_FLOW_COOKIE_ADD_FAIL, + SFE_IPV6_EXCEPTION_EVENT_CLONED_SKB_UNSHARE_ERROR, + SFE_IPV6_EXCEPTION_EVENT_LAST +}; + +static char *sfe_ipv6_exception_events_string[SFE_IPV6_EXCEPTION_EVENT_LAST] = { + "UDP_HEADER_INCOMPLETE", + "UDP_NO_CONNECTION", + "UDP_IP_OPTIONS_OR_INITIAL_FRAGMENT", + "UDP_SMALL_TTL", + "UDP_NEEDS_FRAGMENTATION", + "TCP_HEADER_INCOMPLETE", + "TCP_NO_CONNECTION_SLOW_FLAGS", + "TCP_NO_CONNECTION_FAST_FLAGS", + "TCP_IP_OPTIONS_OR_INITIAL_FRAGMENT", + "TCP_SMALL_TTL", + "TCP_NEEDS_FRAGMENTATION", + "TCP_FLAGS", + "TCP_SEQ_EXCEEDS_RIGHT_EDGE", + "TCP_SMALL_DATA_OFFS", + "TCP_BAD_SACK", + "TCP_BIG_DATA_OFFS", + "TCP_SEQ_BEFORE_LEFT_EDGE", + "TCP_ACK_EXCEEDS_RIGHT_EDGE", + "TCP_ACK_BEFORE_LEFT_EDGE", + "ICMP_HEADER_INCOMPLETE", + "ICMP_UNHANDLED_TYPE", + "ICMP_IPV6_HEADER_INCOMPLETE", + "ICMP_IPV6_NON_V6", + "ICMP_IPV6_IP_OPTIONS_INCOMPLETE", + "ICMP_IPV6_UDP_HEADER_INCOMPLETE", + "ICMP_IPV6_TCP_HEADER_INCOMPLETE", + "ICMP_IPV6_UNHANDLED_PROTOCOL", + "ICMP_NO_CONNECTION", + "ICMP_FLUSHED_CONNECTION", + "HEADER_INCOMPLETE", + "BAD_TOTAL_LENGTH", + "NON_V6", + "NON_INITIAL_FRAGMENT", + "DATAGRAM_INCOMPLETE", + "IP_OPTIONS_INCOMPLETE", + "UNHANDLED_PROTOCOL", + "FLOW_COOKIE_ADD_FAIL", + "CLONED_SKB_UNSHARE_ERROR" +}; + +/* + * Per-module structure. + */ +struct sfe_ipv6 { + spinlock_t lock; /* Lock for SMP correctness */ + struct sfe_ipv6_connection_match *active_head; + /* Head of the list of recently active connections */ + struct sfe_ipv6_connection_match *active_tail; + /* Tail of the list of recently active connections */ + struct sfe_ipv6_connection *all_connections_head; + /* Head of the list of all connections */ + struct sfe_ipv6_connection *all_connections_tail; + /* Tail of the list of all connections */ + unsigned int num_connections; /* Number of connections */ + struct timer_list timer; /* Timer used for periodic sync ops */ + sfe_sync_rule_callback_t __rcu sync_rule_callback; + /* Callback function registered by a connection manager for stats syncing */ + struct sfe_ipv6_connection *conn_hash[SFE_IPV6_CONNECTION_HASH_SIZE]; + /* Connection hash table */ + struct sfe_ipv6_connection_match *conn_match_hash[SFE_IPV6_CONNECTION_HASH_SIZE]; + /* Connection match hash table */ +#ifdef CONFIG_NF_FLOW_COOKIE + struct sfe_ipv6_flow_cookie_entry sfe_flow_cookie_table[SFE_FLOW_COOKIE_SIZE]; + /* flow cookie table*/ + sfe_ipv6_flow_cookie_set_func_t flow_cookie_set_func; + /* function used to configure flow cookie in hardware*/ + int flow_cookie_enable; + /* Enable/disable flow cookie at runtime */ +#endif + + /* + * Stats recorded in a sync period. These stats will be added to + * connection_xxx64 after a sync period. + */ + u32 connection_create_requests; + /* Number of IPv6 connection create requests */ + u32 connection_create_collisions; + /* Number of IPv6 connection create requests that collided with existing hash table entries */ + u32 connection_destroy_requests; + /* Number of IPv6 connection destroy requests */ + u32 connection_destroy_misses; + /* Number of IPv6 connection destroy requests that missed our hash table */ + u32 connection_match_hash_hits; + /* Number of IPv6 connection match hash hits */ + u32 connection_match_hash_reorders; + /* Number of IPv6 connection match hash reorders */ + u32 connection_flushes; /* Number of IPv6 connection flushes */ + u32 packets_forwarded; /* Number of IPv6 packets forwarded */ + u32 packets_not_forwarded; /* Number of IPv6 packets not forwarded */ + u32 exception_events[SFE_IPV6_EXCEPTION_EVENT_LAST]; + + /* + * Summary statistics. + */ + u64 connection_create_requests64; + /* Number of IPv6 connection create requests */ + u64 connection_create_collisions64; + /* Number of IPv6 connection create requests that collided with existing hash table entries */ + u64 connection_destroy_requests64; + /* Number of IPv6 connection destroy requests */ + u64 connection_destroy_misses64; + /* Number of IPv6 connection destroy requests that missed our hash table */ + u64 connection_match_hash_hits64; + /* Number of IPv6 connection match hash hits */ + u64 connection_match_hash_reorders64; + /* Number of IPv6 connection match hash reorders */ + u64 connection_flushes64; /* Number of IPv6 connection flushes */ + u64 packets_forwarded64; /* Number of IPv6 packets forwarded */ + u64 packets_not_forwarded64; + /* Number of IPv6 packets not forwarded */ + u64 exception_events64[SFE_IPV6_EXCEPTION_EVENT_LAST]; + + /* + * Control state. + */ + struct kobject *sys_sfe_ipv6; /* sysfs linkage */ + int debug_dev; /* Major number of the debug char device */ + u32 debug_read_seq; /* sequence number for debug dump */ +}; + +/* + * Enumeration of the XML output. + */ +enum sfe_ipv6_debug_xml_states { + SFE_IPV6_DEBUG_XML_STATE_START, + SFE_IPV6_DEBUG_XML_STATE_CONNECTIONS_START, + SFE_IPV6_DEBUG_XML_STATE_CONNECTIONS_CONNECTION, + SFE_IPV6_DEBUG_XML_STATE_CONNECTIONS_END, + SFE_IPV6_DEBUG_XML_STATE_EXCEPTIONS_START, + SFE_IPV6_DEBUG_XML_STATE_EXCEPTIONS_EXCEPTION, + SFE_IPV6_DEBUG_XML_STATE_EXCEPTIONS_END, + SFE_IPV6_DEBUG_XML_STATE_STATS, + SFE_IPV6_DEBUG_XML_STATE_END, + SFE_IPV6_DEBUG_XML_STATE_DONE +}; + +/* + * XML write state. + */ +struct sfe_ipv6_debug_xml_write_state { + enum sfe_ipv6_debug_xml_states state; + /* XML output file state machine state */ + int iter_exception; /* Next exception iterator */ +}; + +typedef bool (*sfe_ipv6_debug_xml_write_method_t)(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv6_debug_xml_write_state *ws); + +static struct sfe_ipv6 __si6; + +/* + * sfe_ipv6_get_debug_dev() + */ +static ssize_t sfe_ipv6_get_debug_dev(struct device *dev, struct device_attribute *attr, char *buf); + +/* + * sysfs attributes. + */ +static const struct device_attribute sfe_ipv6_debug_dev_attr = + __ATTR(debug_dev, S_IWUSR | S_IRUGO, sfe_ipv6_get_debug_dev, NULL); + +/* + * sfe_ipv6_is_ext_hdr() + * check if we recognize ipv6 extension header + */ +static inline bool sfe_ipv6_is_ext_hdr(u8 hdr) +{ + return (hdr == SFE_IPV6_EXT_HDR_HOP) || + (hdr == SFE_IPV6_EXT_HDR_ROUTING) || + (hdr == SFE_IPV6_EXT_HDR_FRAG) || + (hdr == SFE_IPV6_EXT_HDR_AH) || + (hdr == SFE_IPV6_EXT_HDR_DST) || + (hdr == SFE_IPV6_EXT_HDR_MH); +} + +/* + * sfe_ipv6_change_dsfield() + * change dscp field in IPv6 packet + */ +static inline void sfe_ipv6_change_dsfield(struct sfe_ipv6_ip_hdr *iph, u8 dscp) +{ + __be16 *p = (__be16 *)iph; + + *p = ((*p & htons(SFE_IPV6_DSCP_MASK)) | htons((u16)dscp << 4)); +} + +/* + * sfe_ipv6_get_connection_match_hash() + * Generate the hash used in connection match lookups. + */ +static inline unsigned int sfe_ipv6_get_connection_match_hash(struct net_device *dev, u8 protocol, + struct sfe_ipv6_addr *src_ip, __be16 src_port, + struct sfe_ipv6_addr *dest_ip, __be16 dest_port) +{ + u32 idx, hash = 0; + size_t dev_addr = (size_t)dev; + + for (idx = 0; idx < 4; idx++) { + hash ^= src_ip->addr[idx] ^ dest_ip->addr[idx]; + } + hash = ((u32)dev_addr) ^ hash ^ protocol ^ ntohs(src_port ^ dest_port); + return ((hash >> SFE_IPV6_CONNECTION_HASH_SHIFT) ^ hash) & SFE_IPV6_CONNECTION_HASH_MASK; +} + +/* + * sfe_ipv6_find_connection_match() + * Get the IPv6 flow match info that corresponds to a particular 5-tuple. + * + * On entry we must be holding the lock that protects the hash table. + */ +static struct sfe_ipv6_connection_match * +sfe_ipv6_find_connection_match(struct sfe_ipv6 *si, struct net_device *dev, u8 protocol, + struct sfe_ipv6_addr *src_ip, __be16 src_port, + struct sfe_ipv6_addr *dest_ip, __be16 dest_port) +{ + struct sfe_ipv6_connection_match *cm; + struct sfe_ipv6_connection_match *head; + unsigned int conn_match_idx; + + conn_match_idx = sfe_ipv6_get_connection_match_hash(dev, protocol, src_ip, src_port, dest_ip, dest_port); + cm = si->conn_match_hash[conn_match_idx]; + + /* + * If we don't have anything in this chain then bail. + */ + if (unlikely(!cm)) { + return NULL; + } + + /* + * Hopefully the first entry is the one we want. + */ + if ((cm->match_src_port == src_port) + && (cm->match_dest_port == dest_port) + && (sfe_ipv6_addr_equal(cm->match_src_ip, src_ip)) + && (sfe_ipv6_addr_equal(cm->match_dest_ip, dest_ip)) + && (cm->match_protocol == protocol) + && (cm->match_dev == dev)) { + si->connection_match_hash_hits++; + return cm; + } + + /* + * Unfortunately we didn't find it at head, so we search it in chain and + * move matching entry to the top of the hash chain. We presume that this + * will be reused again very quickly. + */ + head = cm; + do { + cm = cm->next; + } while (cm && (cm->match_src_port != src_port + || cm->match_dest_port != dest_port + || !sfe_ipv6_addr_equal(cm->match_src_ip, src_ip) + || !sfe_ipv6_addr_equal(cm->match_dest_ip, dest_ip) + || cm->match_protocol != protocol + || cm->match_dev != dev)); + + /* + * Not found then we're done. + */ + if (unlikely(!cm)) { + return NULL; + } + + /* + * We found a match so move it. + */ + if (cm->next) { + cm->next->prev = cm->prev; + } + cm->prev->next = cm->next; + cm->prev = NULL; + cm->next = head; + head->prev = cm; + si->conn_match_hash[conn_match_idx] = cm; + si->connection_match_hash_reorders++; + + return cm; +} + +/* + * sfe_ipv6_connection_match_update_summary_stats() + * Update the summary stats for a connection match entry. + */ +static inline void sfe_ipv6_connection_match_update_summary_stats(struct sfe_ipv6_connection_match *cm) +{ + cm->rx_packet_count64 += cm->rx_packet_count; + cm->rx_packet_count = 0; + cm->rx_byte_count64 += cm->rx_byte_count; + cm->rx_byte_count = 0; +} + +/* + * sfe_ipv6_connection_match_compute_translations() + * Compute port and address translations for a connection match entry. + */ +static void sfe_ipv6_connection_match_compute_translations(struct sfe_ipv6_connection_match *cm) +{ + u32 diff[9]; + u32 *idx_32; + u16 *idx_16; + + /* + * Before we insert the entry look to see if this is tagged as doing address + * translations. If it is then work out the adjustment that we need to apply + * to the transport checksum. + */ + if (cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_SRC) { + u32 adj = 0; + u32 carry = 0; + + /* + * Precompute an incremental checksum adjustment so we can + * edit packets in this stream very quickly. The algorithm is from RFC1624. + */ + idx_32 = diff; + *(idx_32++) = cm->match_src_ip->addr[0]; + *(idx_32++) = cm->match_src_ip->addr[1]; + *(idx_32++) = cm->match_src_ip->addr[2]; + *(idx_32++) = cm->match_src_ip->addr[3]; + + idx_16 = (u16 *)idx_32; + *(idx_16++) = cm->match_src_port; + *(idx_16++) = ~cm->xlate_src_port; + idx_32 = (u32 *)idx_16; + + *(idx_32++) = ~cm->xlate_src_ip->addr[0]; + *(idx_32++) = ~cm->xlate_src_ip->addr[1]; + *(idx_32++) = ~cm->xlate_src_ip->addr[2]; + *(idx_32++) = ~cm->xlate_src_ip->addr[3]; + + /* + * When we compute this fold it down to a 16-bit offset + * as that way we can avoid having to do a double + * folding of the twos-complement result because the + * addition of 2 16-bit values cannot cause a double + * wrap-around! + */ + for (idx_32 = diff; idx_32 < diff + 9; idx_32++) { + u32 w = *idx_32; + adj += carry; + adj += w; + carry = (w > adj); + } + adj += carry; + adj = (adj & 0xffff) + (adj >> 16); + adj = (adj & 0xffff) + (adj >> 16); + cm->xlate_src_csum_adjustment = (u16)adj; + } + + if (cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_DEST) { + u32 adj = 0; + u32 carry = 0; + + /* + * Precompute an incremental checksum adjustment so we can + * edit packets in this stream very quickly. The algorithm is from RFC1624. + */ + idx_32 = diff; + *(idx_32++) = cm->match_dest_ip->addr[0]; + *(idx_32++) = cm->match_dest_ip->addr[1]; + *(idx_32++) = cm->match_dest_ip->addr[2]; + *(idx_32++) = cm->match_dest_ip->addr[3]; + + idx_16 = (u16 *)idx_32; + *(idx_16++) = cm->match_dest_port; + *(idx_16++) = ~cm->xlate_dest_port; + idx_32 = (u32 *)idx_16; + + *(idx_32++) = ~cm->xlate_dest_ip->addr[0]; + *(idx_32++) = ~cm->xlate_dest_ip->addr[1]; + *(idx_32++) = ~cm->xlate_dest_ip->addr[2]; + *(idx_32++) = ~cm->xlate_dest_ip->addr[3]; + + /* + * When we compute this fold it down to a 16-bit offset + * as that way we can avoid having to do a double + * folding of the twos-complement result because the + * addition of 2 16-bit values cannot cause a double + * wrap-around! + */ + for (idx_32 = diff; idx_32 < diff + 9; idx_32++) { + u32 w = *idx_32; + adj += carry; + adj += w; + carry = (w > adj); + } + adj += carry; + adj = (adj & 0xffff) + (adj >> 16); + adj = (adj & 0xffff) + (adj >> 16); + cm->xlate_dest_csum_adjustment = (u16)adj; + } +} + +/* + * sfe_ipv6_update_summary_stats() + * Update the summary stats. + */ +static void sfe_ipv6_update_summary_stats(struct sfe_ipv6 *si) +{ + int i; + + si->connection_create_requests64 += si->connection_create_requests; + si->connection_create_requests = 0; + si->connection_create_collisions64 += si->connection_create_collisions; + si->connection_create_collisions = 0; + si->connection_destroy_requests64 += si->connection_destroy_requests; + si->connection_destroy_requests = 0; + si->connection_destroy_misses64 += si->connection_destroy_misses; + si->connection_destroy_misses = 0; + si->connection_match_hash_hits64 += si->connection_match_hash_hits; + si->connection_match_hash_hits = 0; + si->connection_match_hash_reorders64 += si->connection_match_hash_reorders; + si->connection_match_hash_reorders = 0; + si->connection_flushes64 += si->connection_flushes; + si->connection_flushes = 0; + si->packets_forwarded64 += si->packets_forwarded; + si->packets_forwarded = 0; + si->packets_not_forwarded64 += si->packets_not_forwarded; + si->packets_not_forwarded = 0; + + for (i = 0; i < SFE_IPV6_EXCEPTION_EVENT_LAST; i++) { + si->exception_events64[i] += si->exception_events[i]; + si->exception_events[i] = 0; + } +} + +/* + * sfe_ipv6_insert_connection_match() + * Insert a connection match into the hash. + * + * On entry we must be holding the lock that protects the hash table. + */ +static inline void sfe_ipv6_insert_connection_match(struct sfe_ipv6 *si, + struct sfe_ipv6_connection_match *cm) +{ + struct sfe_ipv6_connection_match **hash_head; + struct sfe_ipv6_connection_match *prev_head; + unsigned int conn_match_idx + = sfe_ipv6_get_connection_match_hash(cm->match_dev, cm->match_protocol, + cm->match_src_ip, cm->match_src_port, + cm->match_dest_ip, cm->match_dest_port); + + hash_head = &si->conn_match_hash[conn_match_idx]; + prev_head = *hash_head; + cm->prev = NULL; + if (prev_head) { + prev_head->prev = cm; + } + + cm->next = prev_head; + *hash_head = cm; + +#ifdef CONFIG_NF_FLOW_COOKIE + if (!si->flow_cookie_enable || !(cm->flags & (SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_SRC | SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_DEST))) + return; + + /* + * Configure hardware to put a flow cookie in packet of this flow, + * then we can accelerate the lookup process when we received this packet. + */ + for (conn_match_idx = 1; conn_match_idx < SFE_FLOW_COOKIE_SIZE; conn_match_idx++) { + struct sfe_ipv6_flow_cookie_entry *entry = &si->sfe_flow_cookie_table[conn_match_idx]; + + if ((NULL == entry->match) && time_is_before_jiffies(entry->last_clean_time + HZ)) { + sfe_ipv6_flow_cookie_set_func_t func; + + rcu_read_lock(); + func = rcu_dereference(si->flow_cookie_set_func); + if (func) { + if (!func(cm->match_protocol, cm->match_src_ip->addr, cm->match_src_port, + cm->match_dest_ip->addr, cm->match_dest_port, conn_match_idx)) { + entry->match = cm; + cm->flow_cookie = conn_match_idx; + } else { + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_FLOW_COOKIE_ADD_FAIL]++; + } + } + rcu_read_unlock(); + + break; + } + } +#endif +} + +/* + * sfe_ipv6_remove_connection_match() + * Remove a connection match object from the hash. + * + * On entry we must be holding the lock that protects the hash table. + */ +static inline void sfe_ipv6_remove_connection_match(struct sfe_ipv6 *si, struct sfe_ipv6_connection_match *cm) +{ +#ifdef CONFIG_NF_FLOW_COOKIE + if (si->flow_cookie_enable) { + /* + * Tell hardware that we no longer need a flow cookie in packet of this flow + */ + unsigned int conn_match_idx; + + for (conn_match_idx = 1; conn_match_idx < SFE_FLOW_COOKIE_SIZE; conn_match_idx++) { + struct sfe_ipv6_flow_cookie_entry *entry = &si->sfe_flow_cookie_table[conn_match_idx]; + + if (cm == entry->match) { + sfe_ipv6_flow_cookie_set_func_t func; + + rcu_read_lock(); + func = rcu_dereference(si->flow_cookie_set_func); + if (func) { + func(cm->match_protocol, cm->match_src_ip->addr, cm->match_src_port, + cm->match_dest_ip->addr, cm->match_dest_port, 0); + } + rcu_read_unlock(); + + cm->flow_cookie = 0; + entry->match = NULL; + entry->last_clean_time = jiffies; + break; + } + } + } +#endif + + /* + * Unlink the connection match entry from the hash. + */ + if (cm->prev) { + cm->prev->next = cm->next; + } else { + unsigned int conn_match_idx + = sfe_ipv6_get_connection_match_hash(cm->match_dev, cm->match_protocol, + cm->match_src_ip, cm->match_src_port, + cm->match_dest_ip, cm->match_dest_port); + si->conn_match_hash[conn_match_idx] = cm->next; + } + + if (cm->next) { + cm->next->prev = cm->prev; + } + + /* + * If the connection match entry is in the active list remove it. + */ + if (cm->active) { + if (likely(cm->active_prev)) { + cm->active_prev->active_next = cm->active_next; + } else { + si->active_head = cm->active_next; + } + + if (likely(cm->active_next)) { + cm->active_next->active_prev = cm->active_prev; + } else { + si->active_tail = cm->active_prev; + } + } +} + +/* + * sfe_ipv6_get_connection_hash() + * Generate the hash used in connection lookups. + */ +static inline unsigned int sfe_ipv6_get_connection_hash(u8 protocol, struct sfe_ipv6_addr *src_ip, __be16 src_port, + struct sfe_ipv6_addr *dest_ip, __be16 dest_port) +{ + u32 idx, hash = 0; + + for (idx = 0; idx < 4; idx++) { + hash ^= src_ip->addr[idx] ^ dest_ip->addr[idx]; + } + hash = hash ^ protocol ^ ntohs(src_port ^ dest_port); + return ((hash >> SFE_IPV6_CONNECTION_HASH_SHIFT) ^ hash) & SFE_IPV6_CONNECTION_HASH_MASK; +} + +/* + * sfe_ipv6_find_connection() + * Get the IPv6 connection info that corresponds to a particular 5-tuple. + * + * On entry we must be holding the lock that protects the hash table. + */ +static inline struct sfe_ipv6_connection *sfe_ipv6_find_connection(struct sfe_ipv6 *si, u32 protocol, + struct sfe_ipv6_addr *src_ip, __be16 src_port, + struct sfe_ipv6_addr *dest_ip, __be16 dest_port) +{ + struct sfe_ipv6_connection *c; + unsigned int conn_idx = sfe_ipv6_get_connection_hash(protocol, src_ip, src_port, dest_ip, dest_port); + c = si->conn_hash[conn_idx]; + + /* + * If we don't have anything in this chain then bale. + */ + if (unlikely(!c)) { + return NULL; + } + + /* + * Hopefully the first entry is the one we want. + */ + if ((c->src_port == src_port) + && (c->dest_port == dest_port) + && (sfe_ipv6_addr_equal(c->src_ip, src_ip)) + && (sfe_ipv6_addr_equal(c->dest_ip, dest_ip)) + && (c->protocol == protocol)) { + return c; + } + + /* + * Unfortunately we didn't find it at head, so we search it in chain. + */ + do { + c = c->next; + } while (c && (c->src_port != src_port + || c->dest_port != dest_port + || !sfe_ipv6_addr_equal(c->src_ip, src_ip) + || !sfe_ipv6_addr_equal(c->dest_ip, dest_ip) + || c->protocol != protocol)); + + /* + * Will need connection entry for next create/destroy metadata, + * So no need to re-order entry for these requests + */ + return c; +} + +/* + * sfe_ipv6_mark_rule() + * Updates the mark for a current offloaded connection + * + * Will take hash lock upon entry + */ +void sfe_ipv6_mark_rule(struct sfe_connection_mark *mark) +{ + struct sfe_ipv6 *si = &__si6; + struct sfe_ipv6_connection *c; + + spin_lock_bh(&si->lock); + c = sfe_ipv6_find_connection(si, mark->protocol, + mark->src_ip.ip6, mark->src_port, + mark->dest_ip.ip6, mark->dest_port); + if (c) { + WARN_ON((0 != c->mark) && (0 == mark->mark)); + c->mark = mark->mark; + } + spin_unlock_bh(&si->lock); + + if (c) { + DEBUG_TRACE("Matching connection found for mark, " + "setting from %08x to %08x\n", + c->mark, mark->mark); + } +} + +/* + * sfe_ipv6_insert_connection() + * Insert a connection into the hash. + * + * On entry we must be holding the lock that protects the hash table. + */ +static void sfe_ipv6_insert_connection(struct sfe_ipv6 *si, struct sfe_ipv6_connection *c) +{ + struct sfe_ipv6_connection **hash_head; + struct sfe_ipv6_connection *prev_head; + unsigned int conn_idx; + + /* + * Insert entry into the connection hash. + */ + conn_idx = sfe_ipv6_get_connection_hash(c->protocol, c->src_ip, c->src_port, + c->dest_ip, c->dest_port); + hash_head = &si->conn_hash[conn_idx]; + prev_head = *hash_head; + c->prev = NULL; + if (prev_head) { + prev_head->prev = c; + } + + c->next = prev_head; + *hash_head = c; + + /* + * Insert entry into the "all connections" list. + */ + if (si->all_connections_tail) { + c->all_connections_prev = si->all_connections_tail; + si->all_connections_tail->all_connections_next = c; + } else { + c->all_connections_prev = NULL; + si->all_connections_head = c; + } + + si->all_connections_tail = c; + c->all_connections_next = NULL; + si->num_connections++; + + /* + * Insert the connection match objects too. + */ + sfe_ipv6_insert_connection_match(si, c->original_match); + sfe_ipv6_insert_connection_match(si, c->reply_match); +} + +/* + * sfe_ipv6_remove_connection() + * Remove a sfe_ipv6_connection object from the hash. + * + * On entry we must be holding the lock that protects the hash table. + */ +static void sfe_ipv6_remove_connection(struct sfe_ipv6 *si, struct sfe_ipv6_connection *c) +{ + /* + * Remove the connection match objects. + */ + sfe_ipv6_remove_connection_match(si, c->reply_match); + sfe_ipv6_remove_connection_match(si, c->original_match); + + /* + * Unlink the connection. + */ + if (c->prev) { + c->prev->next = c->next; + } else { + unsigned int conn_idx = sfe_ipv6_get_connection_hash(c->protocol, c->src_ip, c->src_port, + c->dest_ip, c->dest_port); + si->conn_hash[conn_idx] = c->next; + } + + if (c->next) { + c->next->prev = c->prev; + } + + /* + * Unlink connection from all_connections list + */ + if (c->all_connections_prev) { + c->all_connections_prev->all_connections_next = c->all_connections_next; + } else { + si->all_connections_head = c->all_connections_next; + } + + if (c->all_connections_next) { + c->all_connections_next->all_connections_prev = c->all_connections_prev; + } else { + si->all_connections_tail = c->all_connections_prev; + } + + si->num_connections--; +} + +/* + * sfe_ipv6_gen_sync_connection() + * Sync a connection. + * + * On entry to this function we expect that the lock for the connection is either + * already held or isn't required. + */ +static void sfe_ipv6_gen_sync_connection(struct sfe_ipv6 *si, struct sfe_ipv6_connection *c, + struct sfe_connection_sync *sis, sfe_sync_reason_t reason, + u64 now_jiffies) +{ + struct sfe_ipv6_connection_match *original_cm; + struct sfe_ipv6_connection_match *reply_cm; + + /* + * Fill in the update message. + */ + sis->is_v6 = 1; + sis->protocol = c->protocol; + sis->src_ip.ip6[0] = c->src_ip[0]; + sis->src_ip_xlate.ip6[0] = c->src_ip_xlate[0]; + sis->dest_ip.ip6[0] = c->dest_ip[0]; + sis->dest_ip_xlate.ip6[0] = c->dest_ip_xlate[0]; + sis->src_port = c->src_port; + sis->src_port_xlate = c->src_port_xlate; + sis->dest_port = c->dest_port; + sis->dest_port_xlate = c->dest_port_xlate; + + original_cm = c->original_match; + reply_cm = c->reply_match; + sis->src_td_max_window = original_cm->protocol_state.tcp.max_win; + sis->src_td_end = original_cm->protocol_state.tcp.end; + sis->src_td_max_end = original_cm->protocol_state.tcp.max_end; + sis->dest_td_max_window = reply_cm->protocol_state.tcp.max_win; + sis->dest_td_end = reply_cm->protocol_state.tcp.end; + sis->dest_td_max_end = reply_cm->protocol_state.tcp.max_end; + + sis->src_new_packet_count = original_cm->rx_packet_count; + sis->src_new_byte_count = original_cm->rx_byte_count; + sis->dest_new_packet_count = reply_cm->rx_packet_count; + sis->dest_new_byte_count = reply_cm->rx_byte_count; + + sfe_ipv6_connection_match_update_summary_stats(original_cm); + sfe_ipv6_connection_match_update_summary_stats(reply_cm); + + sis->src_dev = original_cm->match_dev; + sis->src_packet_count = original_cm->rx_packet_count64; + sis->src_byte_count = original_cm->rx_byte_count64; + + sis->dest_dev = reply_cm->match_dev; + sis->dest_packet_count = reply_cm->rx_packet_count64; + sis->dest_byte_count = reply_cm->rx_byte_count64; + + sis->reason = reason; + + /* + * Get the time increment since our last sync. + */ + sis->delta_jiffies = now_jiffies - c->last_sync_jiffies; + c->last_sync_jiffies = now_jiffies; +} + +/* + * sfe_ipv6_flush_connection() + * Flush a connection and free all associated resources. + * + * We need to be called with bottom halves disabled locally as we need to acquire + * the connection hash lock and release it again. In general we're actually called + * from within a BH and so we're fine, but we're also called when connections are + * torn down. + */ +static void sfe_ipv6_flush_connection(struct sfe_ipv6 *si, + struct sfe_ipv6_connection *c, + sfe_sync_reason_t reason) +{ + struct sfe_connection_sync sis; + u64 now_jiffies; + sfe_sync_rule_callback_t sync_rule_callback; + + rcu_read_lock(); + spin_lock_bh(&si->lock); + si->connection_flushes++; + sync_rule_callback = rcu_dereference(si->sync_rule_callback); + spin_unlock_bh(&si->lock); + + if (sync_rule_callback) { + /* + * Generate a sync message and then sync. + */ + now_jiffies = get_jiffies_64(); + sfe_ipv6_gen_sync_connection(si, c, &sis, reason, now_jiffies); + sync_rule_callback(&sis); + } + + rcu_read_unlock(); + + /* + * Release our hold of the source and dest devices and free the memory + * for our connection objects. + */ + dev_put(c->original_dev); + dev_put(c->reply_dev); + kfree(c->original_match); + kfree(c->reply_match); + kfree(c); +} + +/* + * sfe_ipv6_recv_udp() + * Handle UDP packet receives and forwarding. + */ +static int sfe_ipv6_recv_udp(struct sfe_ipv6 *si, struct sk_buff *skb, struct net_device *dev, + unsigned int len, struct sfe_ipv6_ip_hdr *iph, unsigned int ihl, bool flush_on_find) +{ + struct sfe_ipv6_udp_hdr *udph; + struct sfe_ipv6_addr *src_ip; + struct sfe_ipv6_addr *dest_ip; + __be16 src_port; + __be16 dest_port; + struct sfe_ipv6_connection_match *cm; + struct net_device *xmit_dev; + + /* + * Is our packet too short to contain a valid UDP header? + */ + if (!pskb_may_pull(skb, (sizeof(struct sfe_ipv6_udp_hdr) + ihl))) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_UDP_HEADER_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("packet too short for UDP header\n"); + return 0; + } + + /* + * Read the IP address and port information. Read the IP header data first + * because we've almost certainly got that in the cache. We may not yet have + * the UDP header cached though so allow more time for any prefetching. + */ + src_ip = &iph->saddr; + dest_ip = &iph->daddr; + + udph = (struct sfe_ipv6_udp_hdr *)(skb->data + ihl); + src_port = udph->source; + dest_port = udph->dest; + + spin_lock_bh(&si->lock); + + /* + * Look for a connection match. + */ +#ifdef CONFIG_NF_FLOW_COOKIE + cm = si->sfe_flow_cookie_table[skb->flow_cookie & SFE_FLOW_COOKIE_MASK].match; + if (unlikely(!cm)) { + cm = sfe_ipv6_find_connection_match(si, dev, IPPROTO_UDP, src_ip, src_port, dest_ip, dest_port); + } +#else + cm = sfe_ipv6_find_connection_match(si, dev, IPPROTO_UDP, src_ip, src_port, dest_ip, dest_port); +#endif + if (unlikely(!cm)) { + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_UDP_NO_CONNECTION]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("no connection found\n"); + return 0; + } + + /* + * If our packet has beern marked as "flush on find" we can't actually + * forward it in the fast path, but now that we've found an associated + * connection we can flush that out before we process the packet. + */ + if (unlikely(flush_on_find)) { + struct sfe_ipv6_connection *c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_UDP_IP_OPTIONS_OR_INITIAL_FRAGMENT]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("flush on find\n"); + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + +#ifdef CONFIG_XFRM + /* + * We can't accelerate the flow on this direction, just let it go + * through the slow path. + */ + if (unlikely(!cm->flow_accel)) { + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + return 0; + } +#endif + + /* + * Does our hop_limit allow forwarding? + */ + if (unlikely(iph->hop_limit < 2)) { + struct sfe_ipv6_connection *c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_UDP_SMALL_TTL]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("hop_limit too low\n"); + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * If our packet is larger than the MTU of the transmit interface then + * we can't forward it easily. + */ + if (unlikely(len > cm->xmit_dev_mtu)) { + struct sfe_ipv6_connection *c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_UDP_NEEDS_FRAGMENTATION]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("larger than mtu\n"); + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * From this point on we're good to modify the packet. + */ + + /* + * Check if skb was cloned. If it was, unshare it. Because + * the data area is going to be written in this path and we don't want to + * change the cloned skb's data section. + */ + if (unlikely(skb_cloned(skb))) { + DEBUG_TRACE("%px: skb is a cloned skb\n", skb); + skb = skb_unshare(skb, GFP_ATOMIC); + if (!skb) { + DEBUG_WARN("Failed to unshare the cloned skb\n"); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_CLONED_SKB_UNSHARE_ERROR]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + return 0; + } + + /* + * Update the iph and udph pointers with the unshared skb's data area. + */ + iph = (struct sfe_ipv6_ip_hdr *)skb->data; + udph = (struct sfe_ipv6_udp_hdr *)(skb->data + ihl); + } + + /* + * Update DSCP + */ + if (unlikely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_DSCP_REMARK)) { + sfe_ipv6_change_dsfield(iph, cm->dscp); + } + + /* + * Decrement our hop_limit. + */ + iph->hop_limit -= 1; + + /* + * Do we have to perform translations of the source address/port? + */ + if (unlikely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_SRC)) { + u16 udp_csum; + + iph->saddr = cm->xlate_src_ip[0]; + udph->source = cm->xlate_src_port; + + /* + * Do we have a non-zero UDP checksum? If we do then we need + * to update it. + */ + udp_csum = udph->check; + if (likely(udp_csum)) { + u32 sum = udp_csum + cm->xlate_src_csum_adjustment; + sum = (sum & 0xffff) + (sum >> 16); + udph->check = (u16)sum; + } + } + + /* + * Do we have to perform translations of the destination address/port? + */ + if (unlikely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_DEST)) { + u16 udp_csum; + + iph->daddr = cm->xlate_dest_ip[0]; + udph->dest = cm->xlate_dest_port; + + /* + * Do we have a non-zero UDP checksum? If we do then we need + * to update it. + */ + udp_csum = udph->check; + if (likely(udp_csum)) { + u32 sum = udp_csum + cm->xlate_dest_csum_adjustment; + sum = (sum & 0xffff) + (sum >> 16); + udph->check = (u16)sum; + } + } + + /* + * Update traffic stats. + */ + cm->rx_packet_count++; + cm->rx_byte_count += len; + + /* + * If we're not already on the active list then insert ourselves at the tail + * of the current list. + */ + if (unlikely(!cm->active)) { + cm->active = true; + cm->active_prev = si->active_tail; + if (likely(si->active_tail)) { + si->active_tail->active_next = cm; + } else { + si->active_head = cm; + } + si->active_tail = cm; + } + + xmit_dev = cm->xmit_dev; + skb->dev = xmit_dev; + + /* + * Check to see if we need to write a header. + */ + if (likely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_L2_HDR)) { + if (unlikely(!(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR))) { + dev_hard_header(skb, xmit_dev, ETH_P_IPV6, + cm->xmit_dest_mac, cm->xmit_src_mac, len); + } else { + /* + * For the simple case we write this really fast. + */ + struct sfe_ipv6_eth_hdr *eth = (struct sfe_ipv6_eth_hdr *)__skb_push(skb, ETH_HLEN); + eth->h_proto = htons(ETH_P_IPV6); + eth->h_dest[0] = cm->xmit_dest_mac[0]; + eth->h_dest[1] = cm->xmit_dest_mac[1]; + eth->h_dest[2] = cm->xmit_dest_mac[2]; + eth->h_source[0] = cm->xmit_src_mac[0]; + eth->h_source[1] = cm->xmit_src_mac[1]; + eth->h_source[2] = cm->xmit_src_mac[2]; + } + } + + /* + * Update priority of skb. + */ + if (unlikely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_PRIORITY_REMARK)) { + skb->priority = cm->priority; + } + + /* + * Mark outgoing packet. + */ + skb->mark = cm->connection->mark; + if (skb->mark) { + DEBUG_TRACE("SKB MARK is NON ZERO %x\n", skb->mark); + } + + si->packets_forwarded++; + spin_unlock_bh(&si->lock); + + /* + * We're going to check for GSO flags when we transmit the packet so + * start fetching the necessary cache line now. + */ + prefetch(skb_shinfo(skb)); + + /* + * Mark that this packet has been fast forwarded. + */ + skb->fast_forwarded = 1; + + /* + * Send the packet on its way. + */ + dev_queue_xmit(skb); + + return 1; +} + +/* + * sfe_ipv6_process_tcp_option_sack() + * Parse TCP SACK option and update ack according + */ +static bool sfe_ipv6_process_tcp_option_sack(const struct sfe_ipv6_tcp_hdr *th, const u32 data_offs, + u32 *ack) +{ + u32 length = sizeof(struct sfe_ipv6_tcp_hdr); + u8 *ptr = (u8 *)th + length; + + /* + * Ignore processing if TCP packet has only TIMESTAMP option. + */ + if (likely(data_offs == length + TCPOLEN_TIMESTAMP + 1 + 1) + && likely(ptr[0] == TCPOPT_NOP) + && likely(ptr[1] == TCPOPT_NOP) + && likely(ptr[2] == TCPOPT_TIMESTAMP) + && likely(ptr[3] == TCPOLEN_TIMESTAMP)) { + return true; + } + + /* + * TCP options. Parse SACK option. + */ + while (length < data_offs) { + u8 size; + u8 kind; + + ptr = (u8 *)th + length; + kind = *ptr; + + /* + * NOP, for padding + * Not in the switch because to fast escape and to not calculate size + */ + if (kind == TCPOPT_NOP) { + length++; + continue; + } + + if (kind == TCPOPT_SACK) { + u32 sack = 0; + u8 re = 1 + 1; + + size = *(ptr + 1); + if ((size < (1 + 1 + TCPOLEN_SACK_PERBLOCK)) + || ((size - (1 + 1)) % (TCPOLEN_SACK_PERBLOCK)) + || (size > (data_offs - length))) { + return false; + } + + re += 4; + while (re < size) { + u32 sack_re; + u8 *sptr = ptr + re; + sack_re = (sptr[0] << 24) | (sptr[1] << 16) | (sptr[2] << 8) | sptr[3]; + if (sack_re > sack) { + sack = sack_re; + } + re += TCPOLEN_SACK_PERBLOCK; + } + if (sack > *ack) { + *ack = sack; + } + length += size; + continue; + } + if (kind == TCPOPT_EOL) { + return true; + } + size = *(ptr + 1); + if (size < 2) { + return false; + } + length += size; + } + + return true; +} + +/* + * sfe_ipv6_recv_tcp() + * Handle TCP packet receives and forwarding. + */ +static int sfe_ipv6_recv_tcp(struct sfe_ipv6 *si, struct sk_buff *skb, struct net_device *dev, + unsigned int len, struct sfe_ipv6_ip_hdr *iph, unsigned int ihl, bool flush_on_find) +{ + struct sfe_ipv6_tcp_hdr *tcph; + struct sfe_ipv6_addr *src_ip; + struct sfe_ipv6_addr *dest_ip; + __be16 src_port; + __be16 dest_port; + struct sfe_ipv6_connection_match *cm; + struct sfe_ipv6_connection_match *counter_cm; + u32 flags; + struct net_device *xmit_dev; + + /* + * Is our packet too short to contain a valid UDP header? + */ + if (!pskb_may_pull(skb, (sizeof(struct sfe_ipv6_tcp_hdr) + ihl))) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_HEADER_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("packet too short for TCP header\n"); + return 0; + } + + /* + * Read the IP address and port information. Read the IP header data first + * because we've almost certainly got that in the cache. We may not yet have + * the TCP header cached though so allow more time for any prefetching. + */ + src_ip = &iph->saddr; + dest_ip = &iph->daddr; + + tcph = (struct sfe_ipv6_tcp_hdr *)(skb->data + ihl); + src_port = tcph->source; + dest_port = tcph->dest; + flags = tcp_flag_word(tcph); + + spin_lock_bh(&si->lock); + + /* + * Look for a connection match. + */ +#ifdef CONFIG_NF_FLOW_COOKIE + cm = si->sfe_flow_cookie_table[skb->flow_cookie & SFE_FLOW_COOKIE_MASK].match; + if (unlikely(!cm)) { + cm = sfe_ipv6_find_connection_match(si, dev, IPPROTO_TCP, src_ip, src_port, dest_ip, dest_port); + } +#else + cm = sfe_ipv6_find_connection_match(si, dev, IPPROTO_TCP, src_ip, src_port, dest_ip, dest_port); +#endif + if (unlikely(!cm)) { + /* + * We didn't get a connection but as TCP is connection-oriented that + * may be because this is a non-fast connection (not running established). + * For diagnostic purposes we differentiate this here. + */ + if (likely((flags & (TCP_FLAG_SYN | TCP_FLAG_RST | TCP_FLAG_FIN | TCP_FLAG_ACK)) == TCP_FLAG_ACK)) { + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_NO_CONNECTION_FAST_FLAGS]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("no connection found - fast flags\n"); + return 0; + } + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_NO_CONNECTION_SLOW_FLAGS]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("no connection found - slow flags: 0x%x\n", + flags & (TCP_FLAG_SYN | TCP_FLAG_RST | TCP_FLAG_FIN | TCP_FLAG_ACK)); + return 0; + } + + /* + * If our packet has beern marked as "flush on find" we can't actually + * forward it in the fast path, but now that we've found an associated + * connection we can flush that out before we process the packet. + */ + if (unlikely(flush_on_find)) { + struct sfe_ipv6_connection *c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_IP_OPTIONS_OR_INITIAL_FRAGMENT]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("flush on find\n"); + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + +#ifdef CONFIG_XFRM + /* + * We can't accelerate the flow on this direction, just let it go + * through the slow path. + */ + if (unlikely(!cm->flow_accel)) { + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + return 0; + } +#endif + + /* + * Does our hop_limit allow forwarding? + */ + if (unlikely(iph->hop_limit < 2)) { + struct sfe_ipv6_connection *c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_SMALL_TTL]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("hop_limit too low\n"); + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * If our packet is larger than the MTU of the transmit interface then + * we can't forward it easily. + */ + if (unlikely((len > cm->xmit_dev_mtu) && !skb_is_gso(skb))) { + struct sfe_ipv6_connection *c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_NEEDS_FRAGMENTATION]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("larger than mtu\n"); + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * Look at our TCP flags. Anything missing an ACK or that has RST, SYN or FIN + * set is not a fast path packet. + */ + if (unlikely((flags & (TCP_FLAG_SYN | TCP_FLAG_RST | TCP_FLAG_FIN | TCP_FLAG_ACK)) != TCP_FLAG_ACK)) { + struct sfe_ipv6_connection *c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_FLAGS]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("TCP flags: 0x%x are not fast\n", + flags & (TCP_FLAG_SYN | TCP_FLAG_RST | TCP_FLAG_FIN | TCP_FLAG_ACK)); + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + counter_cm = cm->counter_match; + + /* + * Are we doing sequence number checking? + */ + if (likely(!(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK))) { + u32 seq; + u32 ack; + u32 sack; + u32 data_offs; + u32 end; + u32 left_edge; + u32 scaled_win; + u32 max_end; + + /* + * Is our sequence fully past the right hand edge of the window? + */ + seq = ntohl(tcph->seq); + if (unlikely((s32)(seq - (cm->protocol_state.tcp.max_end + 1)) > 0)) { + struct sfe_ipv6_connection *c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_SEQ_EXCEEDS_RIGHT_EDGE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("seq: %u exceeds right edge: %u\n", + seq, cm->protocol_state.tcp.max_end + 1); + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * Check that our TCP data offset isn't too short. + */ + data_offs = tcph->doff << 2; + if (unlikely(data_offs < sizeof(struct sfe_ipv6_tcp_hdr))) { + struct sfe_ipv6_connection *c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_SMALL_DATA_OFFS]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("TCP data offset: %u, too small\n", data_offs); + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * Update ACK according to any SACK option. + */ + ack = ntohl(tcph->ack_seq); + sack = ack; + if (unlikely(!sfe_ipv6_process_tcp_option_sack(tcph, data_offs, &sack))) { + struct sfe_ipv6_connection *c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_BAD_SACK]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("TCP option SACK size is wrong\n"); + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * Check that our TCP data offset isn't past the end of the packet. + */ + data_offs += sizeof(struct sfe_ipv6_ip_hdr); + if (unlikely(len < data_offs)) { + struct sfe_ipv6_connection *c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_BIG_DATA_OFFS]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("TCP data offset: %u, past end of packet: %u\n", + data_offs, len); + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + end = seq + len - data_offs; + + /* + * Is our sequence fully before the left hand edge of the window? + */ + if (unlikely((s32)(end - (cm->protocol_state.tcp.end + - counter_cm->protocol_state.tcp.max_win - 1)) < 0)) { + struct sfe_ipv6_connection *c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_SEQ_BEFORE_LEFT_EDGE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("seq: %u before left edge: %u\n", + end, cm->protocol_state.tcp.end - counter_cm->protocol_state.tcp.max_win - 1); + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * Are we acking data that is to the right of what has been sent? + */ + if (unlikely((s32)(sack - (counter_cm->protocol_state.tcp.end + 1)) > 0)) { + struct sfe_ipv6_connection *c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_ACK_EXCEEDS_RIGHT_EDGE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("ack: %u exceeds right edge: %u\n", + sack, counter_cm->protocol_state.tcp.end + 1); + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * Is our ack too far before the left hand edge of the window? + */ + left_edge = counter_cm->protocol_state.tcp.end + - cm->protocol_state.tcp.max_win + - SFE_IPV6_TCP_MAX_ACK_WINDOW + - 1; + if (unlikely((s32)(sack - left_edge) < 0)) { + struct sfe_ipv6_connection *c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_ACK_BEFORE_LEFT_EDGE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("ack: %u before left edge: %u\n", sack, left_edge); + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * Have we just seen the largest window size yet for this connection? If yes + * then we need to record the new value. + */ + scaled_win = ntohs(tcph->window) << cm->protocol_state.tcp.win_scale; + scaled_win += (sack - ack); + if (unlikely(cm->protocol_state.tcp.max_win < scaled_win)) { + cm->protocol_state.tcp.max_win = scaled_win; + } + + /* + * If our sequence and/or ack numbers have advanced then record the new state. + */ + if (likely((s32)(end - cm->protocol_state.tcp.end) >= 0)) { + cm->protocol_state.tcp.end = end; + } + + max_end = sack + scaled_win; + if (likely((s32)(max_end - counter_cm->protocol_state.tcp.max_end) >= 0)) { + counter_cm->protocol_state.tcp.max_end = max_end; + } + } + + /* + * From this point on we're good to modify the packet. + */ + + /* + * Check if skb was cloned. If it was, unshare it. Because + * the data area is going to be written in this path and we don't want to + * change the cloned skb's data section. + */ + if (unlikely(skb_cloned(skb))) { + DEBUG_TRACE("%px: skb is a cloned skb\n", skb); + skb = skb_unshare(skb, GFP_ATOMIC); + if (!skb) { + DEBUG_WARN("Failed to unshare the cloned skb\n"); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_CLONED_SKB_UNSHARE_ERROR]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + return 0; + } + + /* + * Update the iph and tcph pointers with the unshared skb's data area. + */ + iph = (struct sfe_ipv6_ip_hdr *)skb->data; + tcph = (struct sfe_ipv6_tcp_hdr *)(skb->data + ihl); + } + + /* + * Update DSCP + */ + if (unlikely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_DSCP_REMARK)) { + sfe_ipv6_change_dsfield(iph, cm->dscp); + } + + /* + * Decrement our hop_limit. + */ + iph->hop_limit -= 1; + + /* + * Do we have to perform translations of the source address/port? + */ + if (unlikely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_SRC)) { + u16 tcp_csum; + u32 sum; + + iph->saddr = cm->xlate_src_ip[0]; + tcph->source = cm->xlate_src_port; + + /* + * Do we have a non-zero UDP checksum? If we do then we need + * to update it. + */ + tcp_csum = tcph->check; + sum = tcp_csum + cm->xlate_src_csum_adjustment; + sum = (sum & 0xffff) + (sum >> 16); + tcph->check = (u16)sum; + } + + /* + * Do we have to perform translations of the destination address/port? + */ + if (unlikely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_DEST)) { + u16 tcp_csum; + u32 sum; + + iph->daddr = cm->xlate_dest_ip[0]; + tcph->dest = cm->xlate_dest_port; + + /* + * Do we have a non-zero UDP checksum? If we do then we need + * to update it. + */ + tcp_csum = tcph->check; + sum = tcp_csum + cm->xlate_dest_csum_adjustment; + sum = (sum & 0xffff) + (sum >> 16); + tcph->check = (u16)sum; + } + + /* + * Update traffic stats. + */ + cm->rx_packet_count++; + cm->rx_byte_count += len; + + /* + * If we're not already on the active list then insert ourselves at the tail + * of the current list. + */ + if (unlikely(!cm->active)) { + cm->active = true; + cm->active_prev = si->active_tail; + if (likely(si->active_tail)) { + si->active_tail->active_next = cm; + } else { + si->active_head = cm; + } + si->active_tail = cm; + } + + xmit_dev = cm->xmit_dev; + skb->dev = xmit_dev; + + /* + * Check to see if we need to write a header. + */ + if (likely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_L2_HDR)) { + if (unlikely(!(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR))) { + dev_hard_header(skb, xmit_dev, ETH_P_IPV6, + cm->xmit_dest_mac, cm->xmit_src_mac, len); + } else { + /* + * For the simple case we write this really fast. + */ + struct sfe_ipv6_eth_hdr *eth = (struct sfe_ipv6_eth_hdr *)__skb_push(skb, ETH_HLEN); + eth->h_proto = htons(ETH_P_IPV6); + eth->h_dest[0] = cm->xmit_dest_mac[0]; + eth->h_dest[1] = cm->xmit_dest_mac[1]; + eth->h_dest[2] = cm->xmit_dest_mac[2]; + eth->h_source[0] = cm->xmit_src_mac[0]; + eth->h_source[1] = cm->xmit_src_mac[1]; + eth->h_source[2] = cm->xmit_src_mac[2]; + } + } + + /* + * Update priority of skb. + */ + if (unlikely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_PRIORITY_REMARK)) { + skb->priority = cm->priority; + } + + /* + * Mark outgoing packet + */ + skb->mark = cm->connection->mark; + if (skb->mark) { + DEBUG_TRACE("SKB MARK is NON ZERO %x\n", skb->mark); + } + + si->packets_forwarded++; + spin_unlock_bh(&si->lock); + + /* + * We're going to check for GSO flags when we transmit the packet so + * start fetching the necessary cache line now. + */ + prefetch(skb_shinfo(skb)); + + /* + * Mark that this packet has been fast forwarded. + */ + skb->fast_forwarded = 1; + + /* + * Send the packet on its way. + */ + dev_queue_xmit(skb); + + return 1; +} + +/* + * sfe_ipv6_recv_icmp() + * Handle ICMP packet receives. + * + * ICMP packets aren't handled as a "fast path" and always have us process them + * through the default Linux stack. What we do need to do is look for any errors + * about connections we are handling in the fast path. If we find any such + * connections then we want to flush their state so that the ICMP error path + * within Linux has all of the correct state should it need it. + */ +static int sfe_ipv6_recv_icmp(struct sfe_ipv6 *si, struct sk_buff *skb, struct net_device *dev, + unsigned int len, struct sfe_ipv6_ip_hdr *iph, unsigned int ihl) +{ + struct icmp6hdr *icmph; + struct sfe_ipv6_ip_hdr *icmp_iph; + struct sfe_ipv6_udp_hdr *icmp_udph; + struct sfe_ipv6_tcp_hdr *icmp_tcph; + struct sfe_ipv6_addr *src_ip; + struct sfe_ipv6_addr *dest_ip; + __be16 src_port; + __be16 dest_port; + struct sfe_ipv6_connection_match *cm; + struct sfe_ipv6_connection *c; + u8 next_hdr; + + /* + * Is our packet too short to contain a valid ICMP header? + */ + len -= ihl; + if (!pskb_may_pull(skb, ihl + sizeof(struct icmp6hdr))) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_ICMP_HEADER_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("packet too short for ICMP header\n"); + return 0; + } + + /* + * We only handle "destination unreachable" and "time exceeded" messages. + */ + icmph = (struct icmp6hdr *)(skb->data + ihl); + if ((icmph->icmp6_type != ICMPV6_DEST_UNREACH) + && (icmph->icmp6_type != ICMPV6_TIME_EXCEED)) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_ICMP_UNHANDLED_TYPE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("unhandled ICMP type: 0x%x\n", icmph->icmp6_type); + return 0; + } + + /* + * Do we have the full embedded IP header? + * We should have 8 bytes of next L4 header - that's enough to identify + * the connection. + */ + len -= sizeof(struct icmp6hdr); + ihl += sizeof(struct icmp6hdr); + if (!pskb_may_pull(skb, ihl + sizeof(struct sfe_ipv6_ip_hdr) + sizeof(struct sfe_ipv6_ext_hdr))) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_ICMP_IPV6_HEADER_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("Embedded IP header not complete\n"); + return 0; + } + + /* + * Is our embedded IP version wrong? + */ + icmp_iph = (struct sfe_ipv6_ip_hdr *)(icmph + 1); + if (unlikely(icmp_iph->version != 6)) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_ICMP_IPV6_NON_V6]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("IP version: %u\n", icmp_iph->version); + return 0; + } + + len -= sizeof(struct sfe_ipv6_ip_hdr); + ihl += sizeof(struct sfe_ipv6_ip_hdr); + next_hdr = icmp_iph->nexthdr; + while (unlikely(sfe_ipv6_is_ext_hdr(next_hdr))) { + struct sfe_ipv6_ext_hdr *ext_hdr; + unsigned int ext_hdr_len; + + ext_hdr = (struct sfe_ipv6_ext_hdr *)(skb->data + ihl); + if (next_hdr == SFE_IPV6_EXT_HDR_FRAG) { + struct sfe_ipv6_frag_hdr *frag_hdr = (struct sfe_ipv6_frag_hdr *)ext_hdr; + unsigned int frag_off = ntohs(frag_hdr->frag_off); + + if (frag_off & SFE_IPV6_FRAG_OFFSET) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_NON_INITIAL_FRAGMENT]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("non-initial fragment\n"); + return 0; + } + } + + ext_hdr_len = ext_hdr->hdr_len; + ext_hdr_len <<= 3; + ext_hdr_len += sizeof(struct sfe_ipv6_ext_hdr); + len -= ext_hdr_len; + ihl += ext_hdr_len; + /* + * We should have 8 bytes of next header - that's enough to identify + * the connection. + */ + if (!pskb_may_pull(skb, ihl + sizeof(struct sfe_ipv6_ext_hdr))) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_HEADER_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("extension header %d not completed\n", next_hdr); + return 0; + } + + next_hdr = ext_hdr->next_hdr; + } + + /* + * Handle the embedded transport layer header. + */ + switch (next_hdr) { + case IPPROTO_UDP: + icmp_udph = (struct sfe_ipv6_udp_hdr *)(skb->data + ihl); + src_port = icmp_udph->source; + dest_port = icmp_udph->dest; + break; + + case IPPROTO_TCP: + icmp_tcph = (struct sfe_ipv6_tcp_hdr *)(skb->data + ihl); + src_port = icmp_tcph->source; + dest_port = icmp_tcph->dest; + break; + + default: + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_ICMP_IPV6_UNHANDLED_PROTOCOL]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("Unhandled embedded IP protocol: %u\n", next_hdr); + return 0; + } + + src_ip = &icmp_iph->saddr; + dest_ip = &icmp_iph->daddr; + + spin_lock_bh(&si->lock); + + /* + * Look for a connection match. Note that we reverse the source and destination + * here because our embedded message contains a packet that was sent in the + * opposite direction to the one in which we just received it. It will have + * been sent on the interface from which we received it though so that's still + * ok to use. + */ + cm = sfe_ipv6_find_connection_match(si, dev, icmp_iph->nexthdr, dest_ip, dest_port, src_ip, src_port); + if (unlikely(!cm)) { + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_ICMP_NO_CONNECTION]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("no connection found\n"); + return 0; + } + + /* + * We found a connection so now remove it from the connection list and flush + * its state. + */ + c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_ICMP_FLUSHED_CONNECTION]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; +} + +/* + * sfe_ipv6_recv() + * Handle packet receives and forwaring. + * + * Returns 1 if the packet is forwarded or 0 if it isn't. + */ +int sfe_ipv6_recv(struct net_device *dev, struct sk_buff *skb) +{ + struct sfe_ipv6 *si = &__si6; + unsigned int len; + unsigned int payload_len; + unsigned int ihl = sizeof(struct sfe_ipv6_ip_hdr); + bool flush_on_find = false; + struct sfe_ipv6_ip_hdr *iph; + u8 next_hdr; + + /* + * Check that we have space for an IP header and an uplayer header here. + */ + len = skb->len; + if (!pskb_may_pull(skb, ihl + sizeof(struct sfe_ipv6_ext_hdr))) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_HEADER_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("len: %u is too short\n", len); + return 0; + } + + /* + * Is our IP version wrong? + */ + iph = (struct sfe_ipv6_ip_hdr *)skb->data; + if (unlikely(iph->version != 6)) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_NON_V6]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("IP version: %u\n", iph->version); + return 0; + } + + /* + * Does our datagram fit inside the skb? + */ + payload_len = ntohs(iph->payload_len); + if (unlikely(payload_len > (len - ihl))) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_DATAGRAM_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("payload_len: %u, exceeds len: %u\n", payload_len, (len - (unsigned int)sizeof(struct sfe_ipv6_ip_hdr))); + return 0; + } + + next_hdr = iph->nexthdr; + while (unlikely(sfe_ipv6_is_ext_hdr(next_hdr))) { + struct sfe_ipv6_ext_hdr *ext_hdr; + unsigned int ext_hdr_len; + + ext_hdr = (struct sfe_ipv6_ext_hdr *)(skb->data + ihl); + if (next_hdr == SFE_IPV6_EXT_HDR_FRAG) { + struct sfe_ipv6_frag_hdr *frag_hdr = (struct sfe_ipv6_frag_hdr *)ext_hdr; + unsigned int frag_off = ntohs(frag_hdr->frag_off); + + if (frag_off & SFE_IPV6_FRAG_OFFSET) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_NON_INITIAL_FRAGMENT]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("non-initial fragment\n"); + return 0; + } + } + + ext_hdr_len = ext_hdr->hdr_len; + ext_hdr_len <<= 3; + ext_hdr_len += sizeof(struct sfe_ipv6_ext_hdr); + ihl += ext_hdr_len; + if (!pskb_may_pull(skb, ihl + sizeof(struct sfe_ipv6_ext_hdr))) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_HEADER_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("extension header %d not completed\n", next_hdr); + return 0; + } + + flush_on_find = true; + next_hdr = ext_hdr->next_hdr; + } + + if (IPPROTO_UDP == next_hdr) { + return sfe_ipv6_recv_udp(si, skb, dev, len, iph, ihl, flush_on_find); + } + + if (IPPROTO_TCP == next_hdr) { + return sfe_ipv6_recv_tcp(si, skb, dev, len, iph, ihl, flush_on_find); + } + + if (IPPROTO_ICMPV6 == next_hdr) { + return sfe_ipv6_recv_icmp(si, skb, dev, len, iph, ihl); + } + + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_UNHANDLED_PROTOCOL]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("not UDP, TCP or ICMP: %u\n", next_hdr); + return 0; +} + +/* + * sfe_ipv6_update_tcp_state() + * update TCP window variables. + */ +static void +sfe_ipv6_update_tcp_state(struct sfe_ipv6_connection *c, + struct sfe_connection_create *sic) +{ + struct sfe_ipv6_connection_match *orig_cm; + struct sfe_ipv6_connection_match *repl_cm; + struct sfe_ipv6_tcp_connection_match *orig_tcp; + struct sfe_ipv6_tcp_connection_match *repl_tcp; + + orig_cm = c->original_match; + repl_cm = c->reply_match; + orig_tcp = &orig_cm->protocol_state.tcp; + repl_tcp = &repl_cm->protocol_state.tcp; + + /* update orig */ + if (orig_tcp->max_win < sic->src_td_max_window) { + orig_tcp->max_win = sic->src_td_max_window; + } + if ((s32)(orig_tcp->end - sic->src_td_end) < 0) { + orig_tcp->end = sic->src_td_end; + } + if ((s32)(orig_tcp->max_end - sic->src_td_max_end) < 0) { + orig_tcp->max_end = sic->src_td_max_end; + } + + /* update reply */ + if (repl_tcp->max_win < sic->dest_td_max_window) { + repl_tcp->max_win = sic->dest_td_max_window; + } + if ((s32)(repl_tcp->end - sic->dest_td_end) < 0) { + repl_tcp->end = sic->dest_td_end; + } + if ((s32)(repl_tcp->max_end - sic->dest_td_max_end) < 0) { + repl_tcp->max_end = sic->dest_td_max_end; + } + + /* update match flags */ + orig_cm->flags &= ~SFE_IPV6_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; + repl_cm->flags &= ~SFE_IPV6_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; + if (sic->flags & SFE_CREATE_FLAG_NO_SEQ_CHECK) { + orig_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; + repl_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; + } +} + +/* + * sfe_ipv6_update_protocol_state() + * update protocol specified state machine. + */ +static void +sfe_ipv6_update_protocol_state(struct sfe_ipv6_connection *c, + struct sfe_connection_create *sic) +{ + switch (sic->protocol) { + case IPPROTO_TCP: + sfe_ipv6_update_tcp_state(c, sic); + break; + } +} + +/* + * sfe_ipv6_update_rule() + * update forwarding rule after rule is created. + */ +void sfe_ipv6_update_rule(struct sfe_connection_create *sic) +{ + struct sfe_ipv6_connection *c; + struct sfe_ipv6 *si = &__si6; + + spin_lock_bh(&si->lock); + + c = sfe_ipv6_find_connection(si, + sic->protocol, + sic->src_ip.ip6, + sic->src_port, + sic->dest_ip.ip6, + sic->dest_port); + if (c != NULL) { + sfe_ipv6_update_protocol_state(c, sic); + } + + spin_unlock_bh(&si->lock); +} + +/* + * sfe_ipv6_create_rule() + * Create a forwarding rule. + */ +int sfe_ipv6_create_rule(struct sfe_connection_create *sic) +{ + struct sfe_ipv6 *si = &__si6; + struct sfe_ipv6_connection *c; + struct sfe_ipv6_connection_match *original_cm; + struct sfe_ipv6_connection_match *reply_cm; + struct net_device *dest_dev; + struct net_device *src_dev; + + dest_dev = sic->dest_dev; + src_dev = sic->src_dev; + + if (unlikely((dest_dev->reg_state != NETREG_REGISTERED) || + (src_dev->reg_state != NETREG_REGISTERED))) { + return -EINVAL; + } + + spin_lock_bh(&si->lock); + si->connection_create_requests++; + + /* + * Check to see if there is already a flow that matches the rule we're + * trying to create. If there is then we can't create a new one. + */ + c = sfe_ipv6_find_connection(si, + sic->protocol, + sic->src_ip.ip6, + sic->src_port, + sic->dest_ip.ip6, + sic->dest_port); + if (c != NULL) { + si->connection_create_collisions++; + + /* + * If we already have the flow then it's likely that this + * request to create the connection rule contains more + * up-to-date information. Check and update accordingly. + */ + sfe_ipv6_update_protocol_state(c, sic); + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("connection already exists - mark: %08x, p: %d\n" + " s: %s:%pxM:%pI6:%u, d: %s:%pxM:%pI6:%u\n", + sic->mark, sic->protocol, + sic->src_dev->name, sic->src_mac, sic->src_ip.ip6, ntohs(sic->src_port), + sic->dest_dev->name, sic->dest_mac, sic->dest_ip.ip6, ntohs(sic->dest_port)); + return -EADDRINUSE; + } + + /* + * Allocate the various connection tracking objects. + */ + c = (struct sfe_ipv6_connection *)kmalloc(sizeof(struct sfe_ipv6_connection), GFP_ATOMIC); + if (unlikely(!c)) { + spin_unlock_bh(&si->lock); + return -ENOMEM; + } + + original_cm = (struct sfe_ipv6_connection_match *)kmalloc(sizeof(struct sfe_ipv6_connection_match), GFP_ATOMIC); + if (unlikely(!original_cm)) { + spin_unlock_bh(&si->lock); + kfree(c); + return -ENOMEM; + } + + reply_cm = (struct sfe_ipv6_connection_match *)kmalloc(sizeof(struct sfe_ipv6_connection_match), GFP_ATOMIC); + if (unlikely(!reply_cm)) { + spin_unlock_bh(&si->lock); + kfree(original_cm); + kfree(c); + return -ENOMEM; + } + + /* + * Fill in the "original" direction connection matching object. + * Note that the transmit MAC address is "dest_mac_xlate" because + * we always know both ends of a connection by their translated + * addresses and not their public addresses. + */ + original_cm->match_dev = src_dev; + original_cm->match_protocol = sic->protocol; + original_cm->match_src_ip[0] = sic->src_ip.ip6[0]; + original_cm->match_src_port = sic->src_port; + original_cm->match_dest_ip[0] = sic->dest_ip.ip6[0]; + original_cm->match_dest_port = sic->dest_port; + original_cm->xlate_src_ip[0] = sic->src_ip_xlate.ip6[0]; + original_cm->xlate_src_port = sic->src_port_xlate; + original_cm->xlate_dest_ip[0] = sic->dest_ip_xlate.ip6[0]; + original_cm->xlate_dest_port = sic->dest_port_xlate; + original_cm->rx_packet_count = 0; + original_cm->rx_packet_count64 = 0; + original_cm->rx_byte_count = 0; + original_cm->rx_byte_count64 = 0; + original_cm->xmit_dev = dest_dev; + original_cm->xmit_dev_mtu = sic->dest_mtu; + memcpy(original_cm->xmit_src_mac, dest_dev->dev_addr, ETH_ALEN); + memcpy(original_cm->xmit_dest_mac, sic->dest_mac_xlate, ETH_ALEN); + original_cm->connection = c; + original_cm->counter_match = reply_cm; + original_cm->flags = 0; + if (sic->flags & SFE_CREATE_FLAG_REMARK_PRIORITY) { + original_cm->priority = sic->src_priority; + original_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_PRIORITY_REMARK; + } + if (sic->flags & SFE_CREATE_FLAG_REMARK_DSCP) { + original_cm->dscp = sic->src_dscp << SFE_IPV6_DSCP_SHIFT; + original_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_DSCP_REMARK; + } +#ifdef CONFIG_NF_FLOW_COOKIE + original_cm->flow_cookie = 0; +#endif +#ifdef CONFIG_XFRM + original_cm->flow_accel = sic->original_accel; +#endif + original_cm->active_next = NULL; + original_cm->active_prev = NULL; + original_cm->active = false; + + /* + * For PPP links we don't write an L2 header. For everything else we do. + */ + if (!(dest_dev->flags & IFF_POINTOPOINT)) { + original_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_L2_HDR; + + /* + * If our dev writes Ethernet headers then we can write a really fast + * version. + */ + if (dest_dev->header_ops) { + if (dest_dev->header_ops->create == eth_header) { + original_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR; + } + } + } + + /* + * Fill in the "reply" direction connection matching object. + */ + reply_cm->match_dev = dest_dev; + reply_cm->match_protocol = sic->protocol; + reply_cm->match_src_ip[0] = sic->dest_ip_xlate.ip6[0]; + reply_cm->match_src_port = sic->dest_port_xlate; + reply_cm->match_dest_ip[0] = sic->src_ip_xlate.ip6[0]; + reply_cm->match_dest_port = sic->src_port_xlate; + reply_cm->xlate_src_ip[0] = sic->dest_ip.ip6[0]; + reply_cm->xlate_src_port = sic->dest_port; + reply_cm->xlate_dest_ip[0] = sic->src_ip.ip6[0]; + reply_cm->xlate_dest_port = sic->src_port; + reply_cm->rx_packet_count = 0; + reply_cm->rx_packet_count64 = 0; + reply_cm->rx_byte_count = 0; + reply_cm->rx_byte_count64 = 0; + reply_cm->xmit_dev = src_dev; + reply_cm->xmit_dev_mtu = sic->src_mtu; + memcpy(reply_cm->xmit_src_mac, src_dev->dev_addr, ETH_ALEN); + memcpy(reply_cm->xmit_dest_mac, sic->src_mac, ETH_ALEN); + reply_cm->connection = c; + reply_cm->counter_match = original_cm; + reply_cm->flags = 0; + if (sic->flags & SFE_CREATE_FLAG_REMARK_PRIORITY) { + reply_cm->priority = sic->dest_priority; + reply_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_PRIORITY_REMARK; + } + if (sic->flags & SFE_CREATE_FLAG_REMARK_DSCP) { + reply_cm->dscp = sic->dest_dscp << SFE_IPV6_DSCP_SHIFT; + reply_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_DSCP_REMARK; + } +#ifdef CONFIG_NF_FLOW_COOKIE + reply_cm->flow_cookie = 0; +#endif +#ifdef CONFIG_XFRM + reply_cm->flow_accel = sic->reply_accel; +#endif + reply_cm->active_next = NULL; + reply_cm->active_prev = NULL; + reply_cm->active = false; + + /* + * For PPP links we don't write an L2 header. For everything else we do. + */ + if (!(src_dev->flags & IFF_POINTOPOINT)) { + reply_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_L2_HDR; + + /* + * If our dev writes Ethernet headers then we can write a really fast + * version. + */ + if (src_dev->header_ops) { + if (src_dev->header_ops->create == eth_header) { + reply_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR; + } + } + } + + + if (!sfe_ipv6_addr_equal(sic->dest_ip.ip6, sic->dest_ip_xlate.ip6) || sic->dest_port != sic->dest_port_xlate) { + original_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_DEST; + reply_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_SRC; + } + + if (!sfe_ipv6_addr_equal(sic->src_ip.ip6, sic->src_ip_xlate.ip6) || sic->src_port != sic->src_port_xlate) { + original_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_SRC; + reply_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_DEST; + } + + c->protocol = sic->protocol; + c->src_ip[0] = sic->src_ip.ip6[0]; + c->src_ip_xlate[0] = sic->src_ip_xlate.ip6[0]; + c->src_port = sic->src_port; + c->src_port_xlate = sic->src_port_xlate; + c->original_dev = src_dev; + c->original_match = original_cm; + c->dest_ip[0] = sic->dest_ip.ip6[0]; + c->dest_ip_xlate[0] = sic->dest_ip_xlate.ip6[0]; + c->dest_port = sic->dest_port; + c->dest_port_xlate = sic->dest_port_xlate; + c->reply_dev = dest_dev; + c->reply_match = reply_cm; + c->mark = sic->mark; + c->debug_read_seq = 0; + c->last_sync_jiffies = get_jiffies_64(); + + /* + * Take hold of our source and dest devices for the duration of the connection. + */ + dev_hold(c->original_dev); + dev_hold(c->reply_dev); + + /* + * Initialize the protocol-specific information that we track. + */ + switch (sic->protocol) { + case IPPROTO_TCP: + original_cm->protocol_state.tcp.win_scale = sic->src_td_window_scale; + original_cm->protocol_state.tcp.max_win = sic->src_td_max_window ? sic->src_td_max_window : 1; + original_cm->protocol_state.tcp.end = sic->src_td_end; + original_cm->protocol_state.tcp.max_end = sic->src_td_max_end; + reply_cm->protocol_state.tcp.win_scale = sic->dest_td_window_scale; + reply_cm->protocol_state.tcp.max_win = sic->dest_td_max_window ? sic->dest_td_max_window : 1; + reply_cm->protocol_state.tcp.end = sic->dest_td_end; + reply_cm->protocol_state.tcp.max_end = sic->dest_td_max_end; + if (sic->flags & SFE_CREATE_FLAG_NO_SEQ_CHECK) { + original_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; + reply_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; + } + break; + } + + sfe_ipv6_connection_match_compute_translations(original_cm); + sfe_ipv6_connection_match_compute_translations(reply_cm); + sfe_ipv6_insert_connection(si, c); + + spin_unlock_bh(&si->lock); + + /* + * We have everything we need! + */ + DEBUG_INFO("new connection - mark: %08x, p: %d\n" + " s: %s:%pxM(%pxM):%pI6(%pI6):%u(%u)\n" + " d: %s:%pxM(%pxM):%pI6(%pI6):%u(%u)\n", + sic->mark, sic->protocol, + sic->src_dev->name, sic->src_mac, sic->src_mac_xlate, + sic->src_ip.ip6, sic->src_ip_xlate.ip6, ntohs(sic->src_port), ntohs(sic->src_port_xlate), + dest_dev->name, sic->dest_mac, sic->dest_mac_xlate, + sic->dest_ip.ip6, sic->dest_ip_xlate.ip6, ntohs(sic->dest_port), ntohs(sic->dest_port_xlate)); + + return 0; +} + +/* + * sfe_ipv6_destroy_rule() + * Destroy a forwarding rule. + */ +void sfe_ipv6_destroy_rule(struct sfe_connection_destroy *sid) +{ + struct sfe_ipv6 *si = &__si6; + struct sfe_ipv6_connection *c; + + spin_lock_bh(&si->lock); + si->connection_destroy_requests++; + + /* + * Check to see if we have a flow that matches the rule we're trying + * to destroy. If there isn't then we can't destroy it. + */ + c = sfe_ipv6_find_connection(si, sid->protocol, sid->src_ip.ip6, sid->src_port, + sid->dest_ip.ip6, sid->dest_port); + if (!c) { + si->connection_destroy_misses++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("connection does not exist - p: %d, s: %pI6:%u, d: %pI6:%u\n", + sid->protocol, sid->src_ip.ip6, ntohs(sid->src_port), + sid->dest_ip.ip6, ntohs(sid->dest_port)); + return; + } + + /* + * Remove our connection details from the hash tables. + */ + sfe_ipv6_remove_connection(si, c); + spin_unlock_bh(&si->lock); + + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_DESTROY); + + DEBUG_INFO("connection destroyed - p: %d, s: %pI6:%u, d: %pI6:%u\n", + sid->protocol, sid->src_ip.ip6, ntohs(sid->src_port), + sid->dest_ip.ip6, ntohs(sid->dest_port)); +} + +/* + * sfe_ipv6_register_sync_rule_callback() + * Register a callback for rule synchronization. + */ +void sfe_ipv6_register_sync_rule_callback(sfe_sync_rule_callback_t sync_rule_callback) +{ + struct sfe_ipv6 *si = &__si6; + + spin_lock_bh(&si->lock); + rcu_assign_pointer(si->sync_rule_callback, sync_rule_callback); + spin_unlock_bh(&si->lock); +} + +/* + * sfe_ipv6_get_debug_dev() + */ +static ssize_t sfe_ipv6_get_debug_dev(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct sfe_ipv6 *si = &__si6; + ssize_t count; + int num; + + spin_lock_bh(&si->lock); + num = si->debug_dev; + spin_unlock_bh(&si->lock); + + count = snprintf(buf, (ssize_t)PAGE_SIZE, "%d\n", num); + return count; +} + +/* + * sfe_ipv6_destroy_all_rules_for_dev() + * Destroy all connections that match a particular device. + * + * If we pass dev as NULL then this destroys all connections. + */ +void sfe_ipv6_destroy_all_rules_for_dev(struct net_device *dev) +{ + struct sfe_ipv6 *si = &__si6; + struct sfe_ipv6_connection *c; + +another_round: + spin_lock_bh(&si->lock); + + for (c = si->all_connections_head; c; c = c->all_connections_next) { + /* + * Does this connection relate to the device we are destroying? + */ + if (!dev + || (dev == c->original_dev) + || (dev == c->reply_dev)) { + break; + } + } + + if (c) { + sfe_ipv6_remove_connection(si, c); + } + + spin_unlock_bh(&si->lock); + + if (c) { + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_DESTROY); + goto another_round; + } +} + +/* + * sfe_ipv6_periodic_sync() + */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) +static void sfe_ipv6_periodic_sync(unsigned long arg) +#else +static void sfe_ipv6_periodic_sync(struct timer_list *tl) +#endif +{ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) + struct sfe_ipv6 *si = (struct sfe_ipv6 *)arg; +#else + struct sfe_ipv6 *si = from_timer(si, tl, timer); +#endif + u64 now_jiffies; + int quota; + sfe_sync_rule_callback_t sync_rule_callback; + + now_jiffies = get_jiffies_64(); + + rcu_read_lock(); + sync_rule_callback = rcu_dereference(si->sync_rule_callback); + if (!sync_rule_callback) { + rcu_read_unlock(); + goto done; + } + + spin_lock_bh(&si->lock); + sfe_ipv6_update_summary_stats(si); + + /* + * Get an estimate of the number of connections to parse in this sync. + */ + quota = (si->num_connections + 63) / 64; + + /* + * Walk the "active" list and sync the connection state. + */ + while (quota--) { + struct sfe_ipv6_connection_match *cm; + struct sfe_ipv6_connection_match *counter_cm; + struct sfe_ipv6_connection *c; + struct sfe_connection_sync sis; + + cm = si->active_head; + if (!cm) { + break; + } + + /* + * There's a possibility that our counter match is in the active list too. + * If it is then remove it. + */ + counter_cm = cm->counter_match; + if (counter_cm->active) { + counter_cm->active = false; + + /* + * We must have a connection preceding this counter match + * because that's the one that got us to this point, so we don't have + * to worry about removing the head of the list. + */ + counter_cm->active_prev->active_next = counter_cm->active_next; + + if (likely(counter_cm->active_next)) { + counter_cm->active_next->active_prev = counter_cm->active_prev; + } else { + si->active_tail = counter_cm->active_prev; + } + + counter_cm->active_next = NULL; + counter_cm->active_prev = NULL; + } + + /* + * Now remove the head of the active scan list. + */ + cm->active = false; + si->active_head = cm->active_next; + if (likely(cm->active_next)) { + cm->active_next->active_prev = NULL; + } else { + si->active_tail = NULL; + } + cm->active_next = NULL; + + /* + * Sync the connection state. + */ + c = cm->connection; + sfe_ipv6_gen_sync_connection(si, c, &sis, SFE_SYNC_REASON_STATS, now_jiffies); + + /* + * We don't want to be holding the lock when we sync! + */ + spin_unlock_bh(&si->lock); + sync_rule_callback(&sis); + spin_lock_bh(&si->lock); + } + + spin_unlock_bh(&si->lock); + rcu_read_unlock(); + +done: + mod_timer(&si->timer, jiffies + ((HZ + 99) / 100)); +} + +/* + * sfe_ipv6_debug_dev_read_start() + * Generate part of the XML output. + */ +static bool sfe_ipv6_debug_dev_read_start(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv6_debug_xml_write_state *ws) +{ + int bytes_read; + + si->debug_read_seq++; + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\n"); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + ws->state++; + return true; +} + +/* + * sfe_ipv6_debug_dev_read_connections_start() + * Generate part of the XML output. + */ +static bool sfe_ipv6_debug_dev_read_connections_start(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv6_debug_xml_write_state *ws) +{ + int bytes_read; + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n"); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + ws->state++; + return true; +} + +/* + * sfe_ipv6_debug_dev_read_connections_connection() + * Generate part of the XML output. + */ +static bool sfe_ipv6_debug_dev_read_connections_connection(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv6_debug_xml_write_state *ws) +{ + struct sfe_ipv6_connection *c; + struct sfe_ipv6_connection_match *original_cm; + struct sfe_ipv6_connection_match *reply_cm; + int bytes_read; + int protocol; + struct net_device *src_dev; + struct sfe_ipv6_addr src_ip; + struct sfe_ipv6_addr src_ip_xlate; + __be16 src_port; + __be16 src_port_xlate; + u64 src_rx_packets; + u64 src_rx_bytes; + struct net_device *dest_dev; + struct sfe_ipv6_addr dest_ip; + struct sfe_ipv6_addr dest_ip_xlate; + __be16 dest_port; + __be16 dest_port_xlate; + u64 dest_rx_packets; + u64 dest_rx_bytes; + u64 last_sync_jiffies; + u32 mark, src_priority, dest_priority, src_dscp, dest_dscp; +#ifdef CONFIG_NF_FLOW_COOKIE + int src_flow_cookie, dst_flow_cookie; +#endif + + spin_lock_bh(&si->lock); + + for (c = si->all_connections_head; c; c = c->all_connections_next) { + if (c->debug_read_seq < si->debug_read_seq) { + c->debug_read_seq = si->debug_read_seq; + break; + } + } + + /* + * If there were no connections then move to the next state. + */ + if (!c) { + spin_unlock_bh(&si->lock); + ws->state++; + return true; + } + + original_cm = c->original_match; + reply_cm = c->reply_match; + + protocol = c->protocol; + src_dev = c->original_dev; + src_ip = c->src_ip[0]; + src_ip_xlate = c->src_ip_xlate[0]; + src_port = c->src_port; + src_port_xlate = c->src_port_xlate; + src_priority = original_cm->priority; + src_dscp = original_cm->dscp >> SFE_IPV6_DSCP_SHIFT; + + sfe_ipv6_connection_match_update_summary_stats(original_cm); + sfe_ipv6_connection_match_update_summary_stats(reply_cm); + + src_rx_packets = original_cm->rx_packet_count64; + src_rx_bytes = original_cm->rx_byte_count64; + dest_dev = c->reply_dev; + dest_ip = c->dest_ip[0]; + dest_ip_xlate = c->dest_ip_xlate[0]; + dest_port = c->dest_port; + dest_port_xlate = c->dest_port_xlate; + dest_priority = reply_cm->priority; + dest_dscp = reply_cm->dscp >> SFE_IPV6_DSCP_SHIFT; + dest_rx_packets = reply_cm->rx_packet_count64; + dest_rx_bytes = reply_cm->rx_byte_count64; + last_sync_jiffies = get_jiffies_64() - c->last_sync_jiffies; + mark = c->mark; +#ifdef CONFIG_NF_FLOW_COOKIE + src_flow_cookie = original_cm->flow_cookie; + dst_flow_cookie = reply_cm->flow_cookie; +#endif + spin_unlock_bh(&si->lock); + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\t\n", + protocol, + src_dev->name, + &src_ip, &src_ip_xlate, + ntohs(src_port), ntohs(src_port_xlate), + src_priority, src_dscp, + src_rx_packets, src_rx_bytes, + dest_dev->name, + &dest_ip, &dest_ip_xlate, + ntohs(dest_port), ntohs(dest_port_xlate), + dest_priority, dest_dscp, + dest_rx_packets, dest_rx_bytes, +#ifdef CONFIG_NF_FLOW_COOKIE + src_flow_cookie, dst_flow_cookie, +#endif + last_sync_jiffies, mark); + + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + return true; +} + +/* + * sfe_ipv6_debug_dev_read_connections_end() + * Generate part of the XML output. + */ +static bool sfe_ipv6_debug_dev_read_connections_end(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv6_debug_xml_write_state *ws) +{ + int bytes_read; + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n"); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + ws->state++; + return true; +} + +/* + * sfe_ipv6_debug_dev_read_exceptions_start() + * Generate part of the XML output. + */ +static bool sfe_ipv6_debug_dev_read_exceptions_start(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv6_debug_xml_write_state *ws) +{ + int bytes_read; + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n"); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + ws->state++; + return true; +} + +/* + * sfe_ipv6_debug_dev_read_exceptions_exception() + * Generate part of the XML output. + */ +static bool sfe_ipv6_debug_dev_read_exceptions_exception(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv6_debug_xml_write_state *ws) +{ + u64 ct; + + spin_lock_bh(&si->lock); + ct = si->exception_events64[ws->iter_exception]; + spin_unlock_bh(&si->lock); + + if (ct) { + int bytes_read; + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, + "\t\t\n", + sfe_ipv6_exception_events_string[ws->iter_exception], + ct); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + } + + ws->iter_exception++; + if (ws->iter_exception >= SFE_IPV6_EXCEPTION_EVENT_LAST) { + ws->iter_exception = 0; + ws->state++; + } + + return true; +} + +/* + * sfe_ipv6_debug_dev_read_exceptions_end() + * Generate part of the XML output. + */ +static bool sfe_ipv6_debug_dev_read_exceptions_end(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv6_debug_xml_write_state *ws) +{ + int bytes_read; + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n"); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + ws->state++; + return true; +} + +/* + * sfe_ipv6_debug_dev_read_stats() + * Generate part of the XML output. + */ +static bool sfe_ipv6_debug_dev_read_stats(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv6_debug_xml_write_state *ws) +{ + int bytes_read; + unsigned int num_connections; + u64 packets_forwarded; + u64 packets_not_forwarded; + u64 connection_create_requests; + u64 connection_create_collisions; + u64 connection_destroy_requests; + u64 connection_destroy_misses; + u64 connection_flushes; + u64 connection_match_hash_hits; + u64 connection_match_hash_reorders; + + spin_lock_bh(&si->lock); + sfe_ipv6_update_summary_stats(si); + + num_connections = si->num_connections; + packets_forwarded = si->packets_forwarded64; + packets_not_forwarded = si->packets_not_forwarded64; + connection_create_requests = si->connection_create_requests64; + connection_create_collisions = si->connection_create_collisions64; + connection_destroy_requests = si->connection_destroy_requests64; + connection_destroy_misses = si->connection_destroy_misses64; + connection_flushes = si->connection_flushes64; + connection_match_hash_hits = si->connection_match_hash_hits64; + connection_match_hash_reorders = si->connection_match_hash_reorders64; + spin_unlock_bh(&si->lock); + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n", + num_connections, + packets_forwarded, + packets_not_forwarded, + connection_create_requests, + connection_create_collisions, + connection_destroy_requests, + connection_destroy_misses, + connection_flushes, + connection_match_hash_hits, + connection_match_hash_reorders); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + ws->state++; + return true; +} + +/* + * sfe_ipv6_debug_dev_read_end() + * Generate part of the XML output. + */ +static bool sfe_ipv6_debug_dev_read_end(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv6_debug_xml_write_state *ws) +{ + int bytes_read; + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\n"); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + ws->state++; + return true; +} + +/* + * Array of write functions that write various XML elements that correspond to + * our XML output state machine. + */ +static sfe_ipv6_debug_xml_write_method_t sfe_ipv6_debug_xml_write_methods[SFE_IPV6_DEBUG_XML_STATE_DONE] = { + sfe_ipv6_debug_dev_read_start, + sfe_ipv6_debug_dev_read_connections_start, + sfe_ipv6_debug_dev_read_connections_connection, + sfe_ipv6_debug_dev_read_connections_end, + sfe_ipv6_debug_dev_read_exceptions_start, + sfe_ipv6_debug_dev_read_exceptions_exception, + sfe_ipv6_debug_dev_read_exceptions_end, + sfe_ipv6_debug_dev_read_stats, + sfe_ipv6_debug_dev_read_end, +}; + +/* + * sfe_ipv6_debug_dev_read() + * Send info to userspace upon read request from user + */ +static ssize_t sfe_ipv6_debug_dev_read(struct file *filp, char *buffer, size_t length, loff_t *offset) +{ + char msg[CHAR_DEV_MSG_SIZE]; + int total_read = 0; + struct sfe_ipv6_debug_xml_write_state *ws; + struct sfe_ipv6 *si = &__si6; + + ws = (struct sfe_ipv6_debug_xml_write_state *)filp->private_data; + while ((ws->state != SFE_IPV6_DEBUG_XML_STATE_DONE) && (length > CHAR_DEV_MSG_SIZE)) { + if ((sfe_ipv6_debug_xml_write_methods[ws->state])(si, buffer, msg, &length, &total_read, ws)) { + continue; + } + } + + return total_read; +} + +/* + * sfe_ipv6_debug_dev_write() + * Write to char device resets some stats + */ +static ssize_t sfe_ipv6_debug_dev_write(struct file *filp, const char *buffer, size_t length, loff_t *offset) +{ + struct sfe_ipv6 *si = &__si6; + + spin_lock_bh(&si->lock); + sfe_ipv6_update_summary_stats(si); + + si->packets_forwarded64 = 0; + si->packets_not_forwarded64 = 0; + si->connection_create_requests64 = 0; + si->connection_create_collisions64 = 0; + si->connection_destroy_requests64 = 0; + si->connection_destroy_misses64 = 0; + si->connection_flushes64 = 0; + si->connection_match_hash_hits64 = 0; + si->connection_match_hash_reorders64 = 0; + spin_unlock_bh(&si->lock); + + return length; +} + +/* + * sfe_ipv6_debug_dev_open() + */ +static int sfe_ipv6_debug_dev_open(struct inode *inode, struct file *file) +{ + struct sfe_ipv6_debug_xml_write_state *ws; + + ws = (struct sfe_ipv6_debug_xml_write_state *)file->private_data; + if (ws) { + return 0; + } + + ws = kzalloc(sizeof(struct sfe_ipv6_debug_xml_write_state), GFP_KERNEL); + if (!ws) { + return -ENOMEM; + } + + ws->state = SFE_IPV6_DEBUG_XML_STATE_START; + file->private_data = ws; + + return 0; +} + +/* + * sfe_ipv6_debug_dev_release() + */ +static int sfe_ipv6_debug_dev_release(struct inode *inode, struct file *file) +{ + struct sfe_ipv6_debug_xml_write_state *ws; + + ws = (struct sfe_ipv6_debug_xml_write_state *)file->private_data; + if (ws) { + /* + * We've finished with our output so free the write state. + */ + kfree(ws); + } + + return 0; +} + +/* + * File operations used in the debug char device + */ +static struct file_operations sfe_ipv6_debug_dev_fops = { + .read = sfe_ipv6_debug_dev_read, + .write = sfe_ipv6_debug_dev_write, + .open = sfe_ipv6_debug_dev_open, + .release = sfe_ipv6_debug_dev_release +}; + +#ifdef CONFIG_NF_FLOW_COOKIE +/* + * sfe_ipv6_register_flow_cookie_cb + * register a function in SFE to let SFE use this function to configure flow cookie for a flow + * + * Hardware driver which support flow cookie should register a callback function in SFE. Then SFE + * can use this function to configure flow cookie for a flow. + * return: 0, success; !=0, fail + */ +int sfe_ipv6_register_flow_cookie_cb(sfe_ipv6_flow_cookie_set_func_t cb) +{ + struct sfe_ipv6 *si = &__si6; + + BUG_ON(!cb); + + if (si->flow_cookie_set_func) { + return -1; + } + + rcu_assign_pointer(si->flow_cookie_set_func, cb); + return 0; +} + +/* + * sfe_ipv6_unregister_flow_cookie_cb + * unregister function which is used to configure flow cookie for a flow + * + * return: 0, success; !=0, fail + */ +int sfe_ipv6_unregister_flow_cookie_cb(sfe_ipv6_flow_cookie_set_func_t cb) +{ + struct sfe_ipv6 *si = &__si6; + + RCU_INIT_POINTER(si->flow_cookie_set_func, NULL); + return 0; +} + +/* + * sfe_ipv6_get_flow_cookie() + */ +static ssize_t sfe_ipv6_get_flow_cookie(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct sfe_ipv6 *si = &__si6; + return snprintf(buf, (ssize_t)PAGE_SIZE, "%d\n", si->flow_cookie_enable); +} + +/* + * sfe_ipv6_set_flow_cookie() + */ +static ssize_t sfe_ipv6_set_flow_cookie(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct sfe_ipv6 *si = &__si6; + strict_strtol(buf, 0, (long int *)&si->flow_cookie_enable); + + return size; +} + +/* + * sysfs attributes. + */ +static const struct device_attribute sfe_ipv6_flow_cookie_attr = + __ATTR(flow_cookie_enable, S_IWUSR | S_IRUGO, sfe_ipv6_get_flow_cookie, sfe_ipv6_set_flow_cookie); +#endif /*CONFIG_NF_FLOW_COOKIE*/ + +/* + * sfe_ipv6_init() + */ +static int __init sfe_ipv6_init(void) +{ + struct sfe_ipv6 *si = &__si6; + int result = -1; + + DEBUG_INFO("SFE IPv6 init\n"); + + /* + * Create sys/sfe_ipv6 + */ + si->sys_sfe_ipv6 = kobject_create_and_add("sfe_ipv6", NULL); + if (!si->sys_sfe_ipv6) { + DEBUG_ERROR("failed to register sfe_ipv6\n"); + goto exit1; + } + + /* + * Create files, one for each parameter supported by this module. + */ + result = sysfs_create_file(si->sys_sfe_ipv6, &sfe_ipv6_debug_dev_attr.attr); + if (result) { + DEBUG_ERROR("failed to register debug dev file: %d\n", result); + goto exit2; + } + +#ifdef CONFIG_NF_FLOW_COOKIE + result = sysfs_create_file(si->sys_sfe_ipv6, &sfe_ipv6_flow_cookie_attr.attr); + if (result) { + DEBUG_ERROR("failed to register flow cookie enable file: %d\n", result); + goto exit3; + } +#endif /* CONFIG_NF_FLOW_COOKIE */ + + /* + * Register our debug char device. + */ + result = register_chrdev(0, "sfe_ipv6", &sfe_ipv6_debug_dev_fops); + if (result < 0) { + DEBUG_ERROR("Failed to register chrdev: %d\n", result); + goto exit4; + } + + si->debug_dev = result; + + /* + * Create a timer to handle periodic statistics. + */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) + setup_timer(&si->timer, sfe_ipv6_periodic_sync, (unsigned long)si); +#else + timer_setup(&si->timer, sfe_ipv6_periodic_sync, 0); +#endif + mod_timer(&si->timer, jiffies + ((HZ + 99) / 100)); + + spin_lock_init(&si->lock); + + return 0; + +exit4: +#ifdef CONFIG_NF_FLOW_COOKIE + sysfs_remove_file(si->sys_sfe_ipv6, &sfe_ipv6_flow_cookie_attr.attr); + +exit3: +#endif /* CONFIG_NF_FLOW_COOKIE */ + sysfs_remove_file(si->sys_sfe_ipv6, &sfe_ipv6_debug_dev_attr.attr); + +exit2: + kobject_put(si->sys_sfe_ipv6); + +exit1: + return result; +} + +/* + * sfe_ipv6_exit() + */ +static void __exit sfe_ipv6_exit(void) +{ + struct sfe_ipv6 *si = &__si6; + + DEBUG_INFO("SFE IPv6 exit\n"); + + /* + * Destroy all connections. + */ + sfe_ipv6_destroy_all_rules_for_dev(NULL); + + del_timer_sync(&si->timer); + + unregister_chrdev(si->debug_dev, "sfe_ipv6"); + +#ifdef CONFIG_NF_FLOW_COOKIE + sysfs_remove_file(si->sys_sfe_ipv6, &sfe_ipv6_flow_cookie_attr.attr); +#endif /* CONFIG_NF_FLOW_COOKIE */ + sysfs_remove_file(si->sys_sfe_ipv6, &sfe_ipv6_debug_dev_attr.attr); + + kobject_put(si->sys_sfe_ipv6); +} + +module_init(sfe_ipv6_init) +module_exit(sfe_ipv6_exit) + +EXPORT_SYMBOL(sfe_ipv6_recv); +EXPORT_SYMBOL(sfe_ipv6_create_rule); +EXPORT_SYMBOL(sfe_ipv6_destroy_rule); +EXPORT_SYMBOL(sfe_ipv6_destroy_all_rules_for_dev); +EXPORT_SYMBOL(sfe_ipv6_register_sync_rule_callback); +EXPORT_SYMBOL(sfe_ipv6_mark_rule); +EXPORT_SYMBOL(sfe_ipv6_update_rule); +#ifdef CONFIG_NF_FLOW_COOKIE +EXPORT_SYMBOL(sfe_ipv6_register_flow_cookie_cb); +EXPORT_SYMBOL(sfe_ipv6_unregister_flow_cookie_cb); +#endif + +MODULE_DESCRIPTION("Shortcut Forwarding Engine - IPv6 support"); +MODULE_LICENSE("Dual BSD/GPL"); + diff --git a/root/package/lean/shortcut-fe/simulated-driver/Makefile b/root/package/lean/shortcut-fe/simulated-driver/Makefile new file mode 100644 index 00000000..ecf9c41b --- /dev/null +++ b/root/package/lean/shortcut-fe/simulated-driver/Makefile @@ -0,0 +1,60 @@ +# +# Copyright (c) 2015,2016 The Linux Foundation. All rights reserved. +# Permission to use, copy, modify, and/or distribute this software for +# any purpose with or without fee is hereby granted, provided that the +# above copyright notice and this permission notice appear in all copies. +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=shortcut-fe-simulated-driver +PKG_RELEASE:=1 + +PKG_SOURCE_URL:=https://source.codeaurora.org/quic/qsdk/oss/lklm/shortcut-fe +PKG_SOURCE_PROTO:=git +PKG_SOURCE_DATE:=2021-03-17 +PKG_SOURCE_VERSION:=697977d8d0ccf0ab596e5692d08608a75dd7f33d +PKG_MIRROR_HASH:=659fa82a431e15af797a6c7069faeee02810453ad8b576c51c29f95a1761a045 + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/shortcut-fe-drv + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Support + DEPENDS:=@TARGET_ipq806x||TARGET_ipq807x +kmod-shortcut-fe + KCONFIG:= \ + CONFIG_NET_CLS_ACT=y \ + CONFIG_XFRM=y + TITLE:=Simulated sfe driver for ECM + FILES:=$(PKG_BUILD_DIR)/simulated-driver/shortcut-fe-drv.ko +endef + +define KernelPackage/shortcut-fe-drv/Description +Simulated sfe driver which act as an adapter to convert message +between a connection manager and the SFE core engine. +endef + +define Build/Compile + $(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \ + $(KERNEL_MAKE_FLAGS) \ + $(PKG_MAKE_FLAGS) \ + M="$(PKG_BUILD_DIR)/simulated-driver" \ + EXTRA_CFLAGS="-DSFE_SUPPORT_IPV6" \ + modules +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include/shortcut-fe + $(CP) -rf $(PKG_BUILD_DIR)/simulated-driver/sfe_drv.h $(1)/usr/include/shortcut-fe +endef + +$(eval $(call KernelPackage,shortcut-fe-drv)) diff --git a/root/package/lean/shortcut-fe/simulated-driver/patches/200-nss-qdisc-support.patch b/root/package/lean/shortcut-fe/simulated-driver/patches/200-nss-qdisc-support.patch new file mode 100644 index 00000000..638ad8a8 --- /dev/null +++ b/root/package/lean/shortcut-fe/simulated-driver/patches/200-nss-qdisc-support.patch @@ -0,0 +1,11 @@ +--- ./simulated-driver/sfe_drv.c.orig 2020-06-16 12:49:47.680153371 +0800 ++++ ./simulated-driver/sfe_drv.c 2020-06-16 12:50:18.540153371 +0800 +@@ -1167,7 +1167,7 @@ int sfe_drv_recv(struct sk_buff *skb) + * If ingress Qdisc configured, and packet not processed by ingress Qdisc yet + * We can not accelerate this packet. + */ +- if (dev->ingress_queue && !(skb->tc_verd & TC_NCLS)) { ++ if (dev->ingress_queue && !(skb->tc_verd_qca_nss & TC_NCLS)) { + return 0; + } + #endif From ebc515cbe6d1e4616e726fa35b5271e801836b4d Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Fri, 25 Nov 2022 14:41:16 +0800 Subject: [PATCH 068/102] Revert "fixshor" This reverts commit 3d0be0b22e23e9cf05563749328a8f4cda59c3a1. --- .../lean/shortcut-fe/fast-classifier/Makefile | 109 - .../shortcut-fe/fast-classifier/src/Makefile | 10 - .../fast-classifier/src/fast-classifier.c | 2002 --------- .../fast-classifier/src/fast-classifier.h | 57 - .../fast-classifier/src/nl_classifier_test.c | 281 -- .../fast-classifier/src/userspace_example.c | 232 -- .../lean/shortcut-fe/shortcut-fe/Makefile | 88 - .../shortcut-fe/files/etc/init.d/shortcut-fe | 51 - .../shortcut-fe/files/usr/bin/sfe_dump | 35 - .../lean/shortcut-fe/shortcut-fe/src/Kconfig | 14 - .../lean/shortcut-fe/shortcut-fe/src/Makefile | 24 - .../lean/shortcut-fe/shortcut-fe/src/sfe.h | 114 - .../shortcut-fe/src/sfe_backport.h | 195 - .../lean/shortcut-fe/shortcut-fe/src/sfe_cm.c | 1210 ------ .../lean/shortcut-fe/shortcut-fe/src/sfe_cm.h | 260 -- .../shortcut-fe/shortcut-fe/src/sfe_ipv4.c | 3618 ---------------- .../shortcut-fe/shortcut-fe/src/sfe_ipv6.c | 3625 ----------------- .../shortcut-fe/simulated-driver/Makefile | 60 - .../patches/200-nss-qdisc-support.patch | 11 - 19 files changed, 11996 deletions(-) delete mode 100644 root/package/lean/shortcut-fe/fast-classifier/Makefile delete mode 100644 root/package/lean/shortcut-fe/fast-classifier/src/Makefile delete mode 100644 root/package/lean/shortcut-fe/fast-classifier/src/fast-classifier.c delete mode 100644 root/package/lean/shortcut-fe/fast-classifier/src/fast-classifier.h delete mode 100644 root/package/lean/shortcut-fe/fast-classifier/src/nl_classifier_test.c delete mode 100644 root/package/lean/shortcut-fe/fast-classifier/src/userspace_example.c delete mode 100644 root/package/lean/shortcut-fe/shortcut-fe/Makefile delete mode 100644 root/package/lean/shortcut-fe/shortcut-fe/files/etc/init.d/shortcut-fe delete mode 100644 root/package/lean/shortcut-fe/shortcut-fe/files/usr/bin/sfe_dump delete mode 100644 root/package/lean/shortcut-fe/shortcut-fe/src/Kconfig delete mode 100644 root/package/lean/shortcut-fe/shortcut-fe/src/Makefile delete mode 100644 root/package/lean/shortcut-fe/shortcut-fe/src/sfe.h delete mode 100644 root/package/lean/shortcut-fe/shortcut-fe/src/sfe_backport.h delete mode 100644 root/package/lean/shortcut-fe/shortcut-fe/src/sfe_cm.c delete mode 100644 root/package/lean/shortcut-fe/shortcut-fe/src/sfe_cm.h delete mode 100644 root/package/lean/shortcut-fe/shortcut-fe/src/sfe_ipv4.c delete mode 100644 root/package/lean/shortcut-fe/shortcut-fe/src/sfe_ipv6.c delete mode 100644 root/package/lean/shortcut-fe/simulated-driver/Makefile delete mode 100644 root/package/lean/shortcut-fe/simulated-driver/patches/200-nss-qdisc-support.patch diff --git a/root/package/lean/shortcut-fe/fast-classifier/Makefile b/root/package/lean/shortcut-fe/fast-classifier/Makefile deleted file mode 100644 index 09c1174d..00000000 --- a/root/package/lean/shortcut-fe/fast-classifier/Makefile +++ /dev/null @@ -1,109 +0,0 @@ -# -# Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. -# Permission to use, copy, modify, and/or distribute this software for -# any purpose with or without fee is hereby granted, provided that the -# above copyright notice and this permission notice appear in all copies. -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -include $(TOPDIR)/rules.mk -include $(INCLUDE_DIR)/kernel.mk - -PKG_NAME:=fast-classifier -PKG_RELEASE:=6 - -include $(INCLUDE_DIR)/package.mk - -define KernelPackage/fast-classifier/Default - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Support - DEPENDS:=+kmod-ipt-conntrack +kmod-shortcut-fe - TITLE:=Kernel driver for FAST Classifier - FILES:=$(PKG_BUILD_DIR)/fast-classifier.ko - KCONFIG:= \ - CONFIG_NF_CONNTRACK_EVENTS=y \ - CONFIG_NF_CONNTRACK_CHAIN_EVENTS=y \ - CONFIG_NF_CONNTRACK_MARK=y \ - CONFIG_XFRM=y - CONFLICTS:=kmod-shortcut-fe-drv kmod-shortcut-fe-cm -endef - -define KernelPackage/fast-classifier - $(call KernelPackage/fast-classifier/Default) -endef - -define KernelPackage/fast-classifier-noload - $(call KernelPackage/fast-classifier/Default) -endef - -define KernelPackage/fast-classifier/Default/description -FAST Classifier talks to SFE to make decisions about offloading connections -endef - -define KernelPackage/fast-classifier/description -$(call KernelPackage/fast-classifier/Default/description) -endef - -define KernelPackage/fast-classifier-noload/description -$(call KernelPackage/fast-classifier/Default/description) - -This package does not load fast-classifier at boot by default -endef - -define Package/fast-classifier-example - TITLE:=Example user space program for fast-classifier - DEPENDS:=+libnl +kmod-fast-classifier -endef - -define Package/fast-classifier-example/description -Example user space program that communicates with fast -classifier kernel module -endef - -HAVE_ECM:=$(CONFIG_PACKAGE_kmod-qca-nss-ecm-premium)$(CONFIG_PACKAGE_kmod-qca-nss-ecm-noload)$(CONFIG_PACKAGE_kmod-qca-nss-ecm-premium-noload)$(CONFIG_PACKAGE_kmod-qca-nss-ecm-standard) - -define Build/Compile/kmod - +$(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \ - $(KERNEL_MAKE_FLAGS) \ - $(PKG_MAKE_FLAGS) \ - M="$(PKG_BUILD_DIR)" \ - CONFIG_FAST_CLASSIFIER=m \ - EXTRA_CFLAGS+="-DSFE_SUPPORT_IPV6" \ - $(if $(HAVE_ECM),EXTRA_CFLAGS+="-DCONFIG_SFE_ECM" CONFIG_SFE_ECM=y,) \ - modules -endef - -define Build/Compile/example - $(TARGET_CC) -o $(PKG_BUILD_DIR)/userspace_fast_classifier \ - -I $(PKG_BUILD_DIR) \ - -I$(STAGING_DIR)/usr/include/libnl \ - -I$(STAGING_DIR)/usr/include/libnl3 \ - -lnl-genl-3 -lnl-3 \ - $(PKG_BUILD_DIR)/nl_classifier_test.c -endef - -define Build/Compile - $(Build/Compile/kmod) - $(if $(CONFIG_PACKAGE_fast-classifier-example),$(Build/Compile/example)) -endef - -define Build/InstallDev - $(INSTALL_DIR) $(1)/usr/include - $(CP) $(PKG_BUILD_DIR)/fast-classifier.h $(1)/usr/include/ -endef - -define Package/fast-classifier-example/install - $(INSTALL_DIR) $(1)/sbin - $(CP) $(PKG_BUILD_DIR)/userspace_fast_classifier $(1)/sbin/ -endef - -$(eval $(call KernelPackage,fast-classifier)) -#$(eval $(call KernelPackage,fast-classifier-noload)) -#$(eval $(call BuildPackage,fast-classifier-example)) diff --git a/root/package/lean/shortcut-fe/fast-classifier/src/Makefile b/root/package/lean/shortcut-fe/fast-classifier/src/Makefile deleted file mode 100644 index 58dd06e0..00000000 --- a/root/package/lean/shortcut-fe/fast-classifier/src/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -obj-$(CONFIG_FAST_CLASSIFIER) += fast-classifier.o - -ifeq ($(SFE_SUPPORT_IPV6),) -SFE_SUPPORT_IPV6=y -endif -ccflags-$(SFE_SUPPORT_IPV6) += -DSFE_SUPPORT_IPV6 - -ccflags-y += -I$(obj)/../shortcut-fe - -obj ?= . diff --git a/root/package/lean/shortcut-fe/fast-classifier/src/fast-classifier.c b/root/package/lean/shortcut-fe/fast-classifier/src/fast-classifier.c deleted file mode 100644 index 944dfae3..00000000 --- a/root/package/lean/shortcut-fe/fast-classifier/src/fast-classifier.c +++ /dev/null @@ -1,2002 +0,0 @@ -/* - * fast-classifier.c - * Shortcut forwarding engine connection manager. - * fast-classifier - * - * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all copies. - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include "fast-classifier.h" - -typedef enum fast_classifier_exception { - FAST_CL_EXCEPTION_PACKET_BROADCAST, - FAST_CL_EXCEPTION_PACKET_MULTICAST, - FAST_CL_EXCEPTION_NO_IIF, - FAST_CL_EXCEPTION_NO_CT, - FAST_CL_EXCEPTION_CT_NO_TRACK, - FAST_CL_EXCEPTION_CT_NO_CONFIRM, - FAST_CL_EXCEPTION_CT_IS_ALG, - FAST_CL_EXCEPTION_IS_IPV4_MCAST, - FAST_CL_EXCEPTION_IS_IPV6_MCAST, - FAST_CL_EXCEPTION_TCP_NOT_ASSURED, - FAST_CL_EXCEPTION_TCP_NOT_ESTABLISHED, - FAST_CL_EXCEPTION_UNKNOW_PROTOCOL, - FAST_CL_EXCEPTION_NO_SRC_DEV, - FAST_CL_EXCEPTION_NO_SRC_XLATE_DEV, - FAST_CL_EXCEPTION_NO_DEST_DEV, - FAST_CL_EXCEPTION_NO_DEST_XLATE_DEV, - FAST_CL_EXCEPTION_NO_BRIDGE, - FAST_CL_EXCEPTION_LOCAL_OUT, - FAST_CL_EXCEPTION_WAIT_FOR_ACCELERATION, - FAST_CL_EXCEPTION_UPDATE_PROTOCOL_FAIL, - FAST_CL_EXCEPTION_CT_DESTROY_MISS, - FAST_CL_EXCEPTION_MAX -} fast_classifier_exception_t; - -static char *fast_classifier_exception_events_string[FAST_CL_EXCEPTION_MAX] = { - "PACKET_BROADCAST", - "PACKET_MULTICAST", - "NO_IIF", - "NO_CT", - "CT_NO_TRACK", - "CT_NO_CONFIRM", - "CT_IS_ALG", - "IS_IPV4_MCAST", - "IS_IPV6_MCAST", - "TCP_NOT_ASSURED", - "TCP_NOT_ESTABLISHED", - "UNKNOW_PROTOCOL", - "NO_SRC_DEV", - "NO_SRC_XLATE_DEV", - "NO_DEST_DEV", - "NO_DEST_XLATE_DEV", - "NO_BRIDGE", - "LOCAL_OUT", - "WAIT_FOR_ACCELERATION", - "UPDATE_PROTOCOL_FAIL", - "CT_DESTROY_MISS", -}; - -/* - * Per-module structure. - */ -struct fast_classifier { - spinlock_t lock; /* Lock for SMP correctness */ - - /* - * Control state. - */ - struct kobject *sys_fast_classifier; /* sysfs linkage */ - - /* - * Callback notifiers. - */ - struct notifier_block dev_notifier; /* Device notifier */ - struct notifier_block inet_notifier; /* IPv4 notifier */ - struct notifier_block inet6_notifier; /* IPv6 notifier */ - u32 exceptions[FAST_CL_EXCEPTION_MAX]; -}; - -static struct fast_classifier __sc; - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0)) -static struct nla_policy fast_classifier_genl_policy[FAST_CLASSIFIER_A_MAX + 1] = { - [FAST_CLASSIFIER_A_TUPLE] = { - .type = NLA_UNSPEC, - .len = sizeof(struct fast_classifier_tuple) - }, -}; -#endif /*KERNEL_VERSION(5, 2, 0)*/ - -static struct genl_multicast_group fast_classifier_genl_mcgrp[] = { - { - .name = FAST_CLASSIFIER_GENL_MCGRP, - }, -}; - -static int fast_classifier_offload_genl_msg(struct sk_buff *skb, struct genl_info *info); -static int fast_classifier_nl_genl_msg_DUMP(struct sk_buff *skb, struct netlink_callback *cb); - -static struct genl_ops fast_classifier_gnl_ops[] = { - { - .cmd = FAST_CLASSIFIER_C_OFFLOAD, - .flags = 0, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0)) - .policy = fast_classifier_genl_policy, -#endif /*KERNEL_VERSION(5, 2, 0)*/ - .doit = fast_classifier_offload_genl_msg, - .dumpit = NULL, - }, - { - .cmd = FAST_CLASSIFIER_C_OFFLOADED, - .flags = 0, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0)) - .policy = fast_classifier_genl_policy, -#endif /*KERNEL_VERSION(5, 2, 0)*/ - .doit = NULL, - .dumpit = fast_classifier_nl_genl_msg_DUMP, - }, - { - .cmd = FAST_CLASSIFIER_C_DONE, - .flags = 0, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0)) - .policy = fast_classifier_genl_policy, -#endif /*KERNEL_VERSION(5, 2, 0)*/ - .doit = NULL, - .dumpit = fast_classifier_nl_genl_msg_DUMP, - }, -}; - -static struct genl_family fast_classifier_gnl_family = { -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) - .id = GENL_ID_GENERATE, -#endif /*KERNEL_VERSION(4, 10, 0)*/ - .hdrsize = FAST_CLASSIFIER_GENL_HDRSIZE, - .name = FAST_CLASSIFIER_GENL_NAME, - .version = FAST_CLASSIFIER_GENL_VERSION, - .maxattr = FAST_CLASSIFIER_A_MAX, -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) - .ops = fast_classifier_gnl_ops, - .n_ops = ARRAY_SIZE(fast_classifier_gnl_ops), - .mcgrps = fast_classifier_genl_mcgrp, - .n_mcgrps = ARRAY_SIZE(fast_classifier_genl_mcgrp), -#endif /*KERNEL_VERSION(4, 10, 0)*/ -}; - -static atomic_t offload_msgs = ATOMIC_INIT(0); -static atomic_t offload_no_match_msgs = ATOMIC_INIT(0); -static atomic_t offloaded_msgs = ATOMIC_INIT(0); -static atomic_t done_msgs = ATOMIC_INIT(0); - -static atomic_t offloaded_fail_msgs = ATOMIC_INIT(0); -static atomic_t done_fail_msgs = ATOMIC_INIT(0); - -/* - * Accelerate incoming packets destined for bridge device - * If a incoming packet is ultimatly destined for - * a bridge device we will first see the packet coming - * from the phyiscal device, we can skip straight to - * processing the packet like it came from the bridge - * for some more performance gains - * - * This only works when the hook is above the bridge. We - * only implement ingress for now, because for egress we - * want to have the bridge devices qdiscs be used. - */ -static bool skip_to_bridge_ingress; - -/* - * fast_classifier_incr_exceptions() - * increase an exception counter. - */ -static inline void fast_classifier_incr_exceptions(fast_classifier_exception_t except) -{ - struct fast_classifier *sc = &__sc; - - spin_lock_bh(&sc->lock); - sc->exceptions[except]++; - spin_unlock_bh(&sc->lock); -} - -/* - * fast_classifier_recv() - * Handle packet receives. - * - * Returns 1 if the packet is forwarded or 0 if it isn't. - */ -int fast_classifier_recv(struct sk_buff *skb) -{ - struct net_device *dev; - struct net_device *master_dev = NULL; - int ret = 0; - - /* - * We know that for the vast majority of packets we need the transport - * layer header so we may as well start to fetch it now! - */ - prefetch(skb->data + 32); - barrier(); - - dev = skb->dev; - - /* - * Process packet like it arrived on the bridge device - */ - if (skip_to_bridge_ingress && - (dev->priv_flags & IFF_BRIDGE_PORT)) { - master_dev = sfe_dev_get_master(dev); - if (!master_dev) { - DEBUG_WARN("master dev is NULL %s\n", dev->name); - goto rx_exit; - } - dev = master_dev; - } - - /* - * We're only interested in IPv4 and IPv6 packets. - */ - if (likely(htons(ETH_P_IP) == skb->protocol)) { - struct in_device *in_dev; - - /* - * Does our input device support IP processing? - */ - in_dev = (struct in_device *)dev->ip_ptr; - if (unlikely(!in_dev)) { - DEBUG_TRACE("no IP processing for device: %s\n", dev->name); - goto rx_exit; - } - - /* - * Does it have an IP address? If it doesn't then we can't do anything - * interesting here! - */ - if (unlikely(!in_dev->ifa_list)) { - DEBUG_TRACE("no IP address for device: %s\n", dev->name); - goto rx_exit; - } - - ret = sfe_ipv4_recv(dev, skb); - - } else if (likely(htons(ETH_P_IPV6) == skb->protocol)) { - struct inet6_dev *in_dev; - - /* - * Does our input device support IPv6 processing? - */ - in_dev = (struct inet6_dev *)dev->ip6_ptr; - if (unlikely(!in_dev)) { - DEBUG_TRACE("no IPv6 processing for device: %s\n", dev->name); - goto rx_exit; - } - - /* - * Does it have an IPv6 address? If it doesn't then we can't do anything - * interesting here! - */ - if (unlikely(list_empty(&in_dev->addr_list))) { - DEBUG_TRACE("no IPv6 address for device: %s\n", dev->name); - goto rx_exit; - } - - ret = sfe_ipv6_recv(dev, skb); - - } else { - DEBUG_TRACE("not IP packet\n"); - } - -rx_exit: - if (master_dev) { - dev_put(master_dev); - } - - return ret; -} - -/* - * fast_classifier_find_dev_and_mac_addr() - * Find the device and MAC address for a given IPv4 address. - * - * Returns true if we find the device and MAC address, otherwise false. - * - * We look up the rtable entry for the address and, from its neighbour - * structure, obtain the hardware address. This means this function also - * works if the neighbours are routers too. - */ -static bool fast_classifier_find_dev_and_mac_addr(struct sk_buff *skb, sfe_ip_addr_t *addr, struct net_device **dev, u8 *mac_addr, bool is_v4) -{ - struct neighbour *neigh; - struct rtable *rt; - struct rt6_info *rt6; - struct dst_entry *dst; - struct net_device *mac_dev; - - /* - * If we have skb provided, use it as the original code is unable - * to lookup routes that are policy routed. - */ - if (unlikely(skb)) { - dst = skb_dst(skb); - goto skip_dst_lookup; - } - - /* - * Look up the rtable entry for the IP address then get the hardware - * address from its neighbour structure. This means this works when the - * neighbours are routers too. - */ - if (likely(is_v4)) { - rt = ip_route_output(&init_net, addr->ip, 0, 0, 0); - if (unlikely(IS_ERR(rt))) { - goto ret_fail; - } - - dst = (struct dst_entry *)rt; - } -#ifdef SFE_SUPPORT_IPV6 - else { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) - rt6 = rt6_lookup(&init_net, (struct in6_addr *)addr->ip6, 0, 0, NULL, 0); -#else - rt6 = rt6_lookup(&init_net, (struct in6_addr *)addr->ip6, 0, 0, 0); -#endif /*KERNEL_VERSION(4, 17, 0)*/ - if (!rt6) { - goto ret_fail; - } - - dst = (struct dst_entry *)rt6; - } -#endif - -skip_dst_lookup: - rcu_read_lock(); - neigh = sfe_dst_get_neighbour(dst, addr); - if (unlikely(!neigh)) { - rcu_read_unlock(); - if (likely(!skb)) - dst_release(dst); - - goto ret_fail; - } - - if (unlikely(!(neigh->nud_state & NUD_VALID))) { - rcu_read_unlock(); - neigh_release(neigh); - if (likely(!skb)) - dst_release(dst); - - goto ret_fail; - } - - mac_dev = neigh->dev; - if (!mac_dev) { - rcu_read_unlock(); - neigh_release(neigh); - if (likely(!skb)) - dst_release(dst); - - goto ret_fail; - } - - memcpy(mac_addr, neigh->ha, (size_t)mac_dev->addr_len); - - dev_hold(mac_dev); - *dev = mac_dev; - rcu_read_unlock(); - neigh_release(neigh); - if (likely(!skb)) - dst_release(dst); - - return true; - -ret_fail: - if (is_v4) { - DEBUG_TRACE("failed to find MAC address for IP: %pI4\n", addr); - - } else { - DEBUG_TRACE("failed to find MAC address for IP: %pI6\n", addr); - } - - return false; -} - -static DEFINE_SPINLOCK(sfe_connections_lock); - -struct sfe_connection { - struct hlist_node hl; - struct sfe_connection_create *sic; - struct nf_conn *ct; - int hits; - int offload_permit; - int offloaded; - bool is_v4; - unsigned char smac[ETH_ALEN]; - unsigned char dmac[ETH_ALEN]; -}; - -static int sfe_connections_size; - -#define FC_CONN_HASH_ORDER 13 -static DEFINE_HASHTABLE(fc_conn_ht, FC_CONN_HASH_ORDER); - -static u32 fc_conn_hash(sfe_ip_addr_t *saddr, sfe_ip_addr_t *daddr, - unsigned short sport, unsigned short dport, bool is_v4) -{ - u32 idx, cnt = ((is_v4 ? sizeof(saddr->ip) : sizeof(saddr->ip6))/sizeof(u32)); - u32 hash = 0; - - for (idx = 0; idx < cnt; idx++) { - hash ^= ((u32 *)saddr)[idx] ^ ((u32 *)daddr)[idx]; - } - - return hash ^ (sport | (dport << 16)); -} - -/* - * fast_classifier_update_protocol() - * Update sfe_ipv4_create struct with new protocol information before we offload - */ -static int fast_classifier_update_protocol(struct sfe_connection_create *p_sic, struct nf_conn *ct) -{ - #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) - struct net *net=NULL ; - struct nf_tcp_net *tn=NULL; - #endif - switch (p_sic->protocol) { - case IPPROTO_TCP: - p_sic->src_td_window_scale = ct->proto.tcp.seen[0].td_scale; - p_sic->src_td_max_window = ct->proto.tcp.seen[0].td_maxwin; - p_sic->src_td_end = ct->proto.tcp.seen[0].td_end; - p_sic->src_td_max_end = ct->proto.tcp.seen[0].td_maxend; - p_sic->dest_td_window_scale = ct->proto.tcp.seen[1].td_scale; - p_sic->dest_td_max_window = ct->proto.tcp.seen[1].td_maxwin; - p_sic->dest_td_end = ct->proto.tcp.seen[1].td_end; - p_sic->dest_td_max_end = ct->proto.tcp.seen[1].td_maxend; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) - net = nf_ct_net(ct); - tn = nf_tcp_pernet(net); - if ((tn&&tn->tcp_no_window_check) -#else - if (nf_ct_tcp_no_window_check -#endif - - || (ct->proto.tcp.seen[0].flags & IP_CT_TCP_FLAG_BE_LIBERAL) - || (ct->proto.tcp.seen[1].flags & IP_CT_TCP_FLAG_BE_LIBERAL)) { - p_sic->flags |= SFE_CREATE_FLAG_NO_SEQ_CHECK; - } - - /* - * If the connection is shutting down do not manage it. - * state can not be SYN_SENT, SYN_RECV because connection is assured - * Not managed states: FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE. - */ - spin_lock(&ct->lock); - if (ct->proto.tcp.state != TCP_CONNTRACK_ESTABLISHED) { - spin_unlock(&ct->lock); - fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_TCP_NOT_ESTABLISHED); - DEBUG_TRACE("connection in termination state: %#x, s: %pI4:%u, d: %pI4:%u\n", - ct->proto.tcp.state, &p_sic->src_ip, ntohs(p_sic->src_port), - &p_sic->dest_ip, ntohs(p_sic->dest_port)); - return 0; - } - spin_unlock(&ct->lock); - break; - - case IPPROTO_UDP: - break; - - default: - fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_UNKNOW_PROTOCOL); - DEBUG_TRACE("unhandled protocol %d\n", p_sic->protocol); - return 0; - } - - return 1; -} - -/* fast_classifier_send_genl_msg() - * Function to send a generic netlink message - */ -static void fast_classifier_send_genl_msg(int msg, struct fast_classifier_tuple *fc_msg) -{ - struct sk_buff *skb; - int rc; - int buf_len; - int total_len; - void *msg_head; - - /* - * Calculate our packet payload size. - * Start with our family header. - */ - buf_len = fast_classifier_gnl_family.hdrsize; - - /* - * Add the nla_total_size of each attribute we're going to nla_put(). - */ - buf_len += nla_total_size(sizeof(*fc_msg)); - - /* - * Lastly we need to add space for the NL message header since - * genlmsg_new only accounts for the GENL header and not the - * outer NL header. To do this, we use a NL helper function which - * calculates the total size of a netlink message given a payload size. - * Note this value does not include the GENL header, but that's - * added automatically by genlmsg_new. - */ - total_len = nlmsg_total_size(buf_len); - skb = genlmsg_new(total_len, GFP_ATOMIC); - if (!skb) - return; - - msg_head = genlmsg_put(skb, 0, 0, &fast_classifier_gnl_family, 0, msg); - if (!msg_head) { - nlmsg_free(skb); - return; - } - - rc = nla_put(skb, FAST_CLASSIFIER_A_TUPLE, sizeof(struct fast_classifier_tuple), fc_msg); - if (rc != 0) { - genlmsg_cancel(skb, msg_head); - nlmsg_free(skb); - return; - } - -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 19 , 0)) - rc = genlmsg_end(skb, msg_head); - if (rc < 0) { - genlmsg_cancel(skb, msg_head); - nlmsg_free(skb); - return; - } -#else - genlmsg_end(skb, msg_head); - -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) - rc = genlmsg_multicast(&fast_classifier_gnl_family, skb, 0, 0, GFP_ATOMIC); -#else - rc = genlmsg_multicast(skb, 0, fast_classifier_genl_mcgrp[0].id, GFP_ATOMIC); -#endif - switch (msg) { - case FAST_CLASSIFIER_C_OFFLOADED: - if (rc == 0) { - atomic_inc(&offloaded_msgs); - } else { - atomic_inc(&offloaded_fail_msgs); - } - break; - case FAST_CLASSIFIER_C_DONE: - if (rc == 0) { - atomic_inc(&done_msgs); - } else { - atomic_inc(&done_fail_msgs); - } - break; - default: - DEBUG_ERROR("fast-classifer: Unknown message type sent!\n"); - break; - } - - DEBUG_TRACE("Notify NL message %d ", msg); - if (fc_msg->ethertype == AF_INET) { - DEBUG_TRACE("sip=%pI4 dip=%pI4 ", &fc_msg->src_saddr, &fc_msg->dst_saddr); - } else { - DEBUG_TRACE("sip=%pI6 dip=%pI6 ", &fc_msg->src_saddr, &fc_msg->dst_saddr); - } - DEBUG_TRACE("protocol=%d sport=%d dport=%d smac=%pM dmac=%pM\n", - fc_msg->proto, fc_msg->sport, fc_msg->dport, fc_msg->smac, fc_msg->dmac); -} - -/* - * fast_classifier_find_conn() - * find a connection object in the hash table - * @pre the sfe_connection_lock must be held before calling this function - */ -static struct sfe_connection * -fast_classifier_find_conn(sfe_ip_addr_t *saddr, sfe_ip_addr_t *daddr, - unsigned short sport, unsigned short dport, - unsigned char proto, bool is_v4) -{ - struct sfe_connection_create *p_sic; - struct sfe_connection *conn; - u32 key; -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)) - struct hlist_node *node; -#endif - - key = fc_conn_hash(saddr, daddr, sport, dport, is_v4); - - sfe_hash_for_each_possible(fc_conn_ht, conn, node, hl, key) { - if (conn->is_v4 != is_v4) { - continue; - } - - p_sic = conn->sic; - - if (p_sic->protocol == proto && - p_sic->src_port == sport && - p_sic->dest_port == dport && - sfe_addr_equal(&p_sic->src_ip, saddr, is_v4) && - sfe_addr_equal(&p_sic->dest_ip, daddr, is_v4)) { - return conn; - } - } - - DEBUG_TRACE("connection not found\n"); - return NULL; -} - -/* - * fast_classifier_sb_find_conn() - * find a connection object in the hash table according to information of packet - * if not found, reverse the tuple and try again. - * @pre the sfe_connection_lock must be held before calling this function - */ -static struct sfe_connection * -fast_classifier_sb_find_conn(sfe_ip_addr_t *saddr, sfe_ip_addr_t *daddr, - unsigned short sport, unsigned short dport, - unsigned char proto, bool is_v4) -{ - struct sfe_connection_create *p_sic; - struct sfe_connection *conn; - u32 key; -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)) - struct hlist_node *node; -#endif - - key = fc_conn_hash(saddr, daddr, sport, dport, is_v4); - - sfe_hash_for_each_possible(fc_conn_ht, conn, node, hl, key) { - if (conn->is_v4 != is_v4) { - continue; - } - - p_sic = conn->sic; - - if (p_sic->protocol == proto && - p_sic->src_port == sport && - p_sic->dest_port_xlate == dport && - sfe_addr_equal(&p_sic->src_ip, saddr, is_v4) && - sfe_addr_equal(&p_sic->dest_ip_xlate, daddr, is_v4)) { - return conn; - } - } - - /* - * Reverse the tuple and try again - */ - key = fc_conn_hash(daddr, saddr, dport, sport, is_v4); - - sfe_hash_for_each_possible(fc_conn_ht, conn, node, hl, key) { - if (conn->is_v4 != is_v4) { - continue; - } - - p_sic = conn->sic; - - if (p_sic->protocol == proto && - p_sic->src_port == dport && - p_sic->dest_port_xlate == sport && - sfe_addr_equal(&p_sic->src_ip, daddr, is_v4) && - sfe_addr_equal(&p_sic->dest_ip_xlate, saddr, is_v4)) { - return conn; - } - } - - DEBUG_TRACE("connection not found\n"); - return NULL; -} - -/* - * fast_classifier_add_conn() - * add a connection object in the hash table if no duplicate - * @conn connection to add - * @return conn if successful, NULL if duplicate - */ -static struct sfe_connection * -fast_classifier_add_conn(struct sfe_connection *conn) -{ - struct sfe_connection_create *sic = conn->sic; - u32 key; - - spin_lock_bh(&sfe_connections_lock); - if (fast_classifier_find_conn(&sic->src_ip, &sic->dest_ip, sic->src_port, - sic->dest_port, sic->protocol, conn->is_v4)) { - spin_unlock_bh(&sfe_connections_lock); - return NULL; - } - - key = fc_conn_hash(&sic->src_ip, &sic->dest_ip, - sic->src_port, sic->dest_port, conn->is_v4); - - hash_add(fc_conn_ht, &conn->hl, key); - sfe_connections_size++; - spin_unlock_bh(&sfe_connections_lock); - - DEBUG_TRACE(" -> adding item to sfe_connections, new size: %d\n", sfe_connections_size); - - if (conn->is_v4) { - DEBUG_TRACE("new offloadable: key: %u proto: %d src_ip: %pI4 dst_ip: %pI4, src_port: %d, dst_port: %d\n", - key, sic->protocol, &(sic->src_ip), &(sic->dest_ip), sic->src_port, sic->dest_port); - } else { - DEBUG_TRACE("new offloadable: key: %u proto: %d src_ip: %pI6 dst_ip: %pI6, src_port: %d, dst_port: %d\n", - key, sic->protocol, &(sic->src_ip), &(sic->dest_ip), sic->src_port, sic->dest_port); - } - - return conn; -} - -/* - * fast_classifier_offload_genl_msg() - * Called from user space to offload a connection - */ -static int -fast_classifier_offload_genl_msg(struct sk_buff *skb, struct genl_info *info) -{ - struct nlattr *na; - struct fast_classifier_tuple *fc_msg; - struct sfe_connection *conn; - - na = info->attrs[FAST_CLASSIFIER_A_TUPLE]; - fc_msg = nla_data(na); - - if (fc_msg->ethertype == AF_INET) { - DEBUG_TRACE("want to offload: %d-%d, %pI4, %pI4, %d, %d SMAC=%pM DMAC=%pM\n", - fc_msg->ethertype, - fc_msg->proto, - &fc_msg->src_saddr, - &fc_msg->dst_saddr, - fc_msg->sport, - fc_msg->dport, - fc_msg->smac, - fc_msg->dmac); - } else { - DEBUG_TRACE("want to offload: %d-%d, %pI6, %pI6, %d, %d SMAC=%pM DMAC=%pM\n", - fc_msg->ethertype, - fc_msg->proto, - &fc_msg->src_saddr, - &fc_msg->dst_saddr, - fc_msg->sport, - fc_msg->dport, - fc_msg->smac, - fc_msg->dmac); - } - - spin_lock_bh(&sfe_connections_lock); - conn = fast_classifier_sb_find_conn((sfe_ip_addr_t *)&fc_msg->src_saddr, - (sfe_ip_addr_t *)&fc_msg->dst_saddr, - fc_msg->sport, - fc_msg->dport, - fc_msg->proto, - (fc_msg->ethertype == AF_INET)); - if (!conn) { - spin_unlock_bh(&sfe_connections_lock); - DEBUG_TRACE("REQUEST OFFLOAD NO MATCH\n"); - atomic_inc(&offload_no_match_msgs); - return 0; - } - - conn->offload_permit = 1; - spin_unlock_bh(&sfe_connections_lock); - atomic_inc(&offload_msgs); - - DEBUG_TRACE("INFO: calling sfe rule creation!\n"); - return 0; -} - -/* - * fast_classifier_nl_genl_msg_DUMP() - * ignore fast_classifier_messages OFFLOADED and DONE - */ -static int fast_classifier_nl_genl_msg_DUMP(struct sk_buff *skb, - struct netlink_callback *cb) -{ - return 0; -} - -/* auto offload connection once we have this many packets*/ -static int offload_at_pkts = 128; - -/* - * fast_classifier_post_routing() - * Called for packets about to leave the box - either locally generated or forwarded from another interface - */ -static unsigned int fast_classifier_post_routing(struct sk_buff *skb, bool is_v4) -{ - int ret; - struct sfe_connection_create sic; - struct sfe_connection_create *p_sic; - struct net_device *in; - struct nf_conn *ct; - enum ip_conntrack_info ctinfo; - struct net_device *dev; - struct net_device *src_dev; - struct net_device *dest_dev; - struct net_device *src_dev_tmp; - struct net_device *dest_dev_tmp; - struct net_device *src_br_dev = NULL; - struct net_device *dest_br_dev = NULL; - struct nf_conntrack_tuple orig_tuple; - struct nf_conntrack_tuple reply_tuple; - struct sfe_connection *conn; - struct sk_buff *tmp_skb = NULL; - - /* - * Don't process broadcast or multicast packets. - */ - if (unlikely(skb->pkt_type == PACKET_BROADCAST)) { - fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_PACKET_BROADCAST); - DEBUG_TRACE("broadcast, ignoring\n"); - return NF_ACCEPT; - } - if (unlikely(skb->pkt_type == PACKET_MULTICAST)) { - fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_PACKET_MULTICAST); - DEBUG_TRACE("multicast, ignoring\n"); - return NF_ACCEPT; - } - - /* - * Don't process packets that are not being forwarded. - */ - in = dev_get_by_index(&init_net, skb->skb_iif); - if (!in) { - fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_NO_IIF); - DEBUG_TRACE("packet not forwarding\n"); - return NF_ACCEPT; - } - - dev_put(in); - - /* - * Don't process packets that aren't being tracked by conntrack. - */ - ct = nf_ct_get(skb, &ctinfo); - if (unlikely(!ct)) { - fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_NO_CT); - DEBUG_TRACE("no conntrack connection, ignoring\n"); - return NF_ACCEPT; - } - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) - /* - * Don't process untracked connections. - */ - if (unlikely(nf_ct_is_untracked(ct))) { - fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_CT_NO_TRACK); - DEBUG_TRACE("untracked connection\n"); - return NF_ACCEPT; - } -#endif /*KERNEL_VERSION(4, 12, 0)*/ - - /* - * Unconfirmed connection may be dropped by Linux at the final step, - * So we don't process unconfirmed connections. - */ - if (!nf_ct_is_confirmed(ct)) { - fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_CT_NO_CONFIRM); - DEBUG_TRACE("unconfirmed connection\n"); - return NF_ACCEPT; - } - - /* - * Don't process connections that require support from a 'helper' (typically a NAT ALG). - */ - if (unlikely(nfct_help(ct))) { - fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_CT_IS_ALG); - DEBUG_TRACE("connection has helper\n"); - return NF_ACCEPT; - } - - memset(&sic, 0, sizeof(sic)); - - /* - * Look up the details of our connection in conntrack. - * - * Note that the data we get from conntrack is for the "ORIGINAL" direction - * but our packet may actually be in the "REPLY" direction. - */ - orig_tuple = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; - reply_tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple; - sic.protocol = (s32)orig_tuple.dst.protonum; - - sic.flags = 0; - - /* - * Get addressing information, non-NAT first - */ - if (likely(is_v4)) { - u32 dscp; - - sic.src_ip.ip = (__be32)orig_tuple.src.u3.ip; - sic.dest_ip.ip = (__be32)orig_tuple.dst.u3.ip; - - if (ipv4_is_multicast(sic.src_ip.ip) || ipv4_is_multicast(sic.dest_ip.ip)) { - fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_IS_IPV4_MCAST); - DEBUG_TRACE("multicast address\n"); - return NF_ACCEPT; - } - - /* - * NAT'ed addresses - note these are as seen from the 'reply' direction - * When NAT does not apply to this connection these will be identical to the above. - */ - sic.src_ip_xlate.ip = (__be32)reply_tuple.dst.u3.ip; - sic.dest_ip_xlate.ip = (__be32)reply_tuple.src.u3.ip; - - dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT; - if (dscp) { - sic.dest_dscp = dscp; - sic.src_dscp = sic.dest_dscp; - sic.flags |= SFE_CREATE_FLAG_REMARK_DSCP; - } - } else { - u32 dscp; - - sic.src_ip.ip6[0] = *((struct sfe_ipv6_addr *)&orig_tuple.src.u3.in6); - sic.dest_ip.ip6[0] = *((struct sfe_ipv6_addr *)&orig_tuple.dst.u3.in6); - - if (ipv6_addr_is_multicast((struct in6_addr *)sic.src_ip.ip6) || - ipv6_addr_is_multicast((struct in6_addr *)sic.dest_ip.ip6)) { - fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_IS_IPV6_MCAST); - DEBUG_TRACE("multicast address\n"); - return NF_ACCEPT; - } - - /* - * NAT'ed addresses - note these are as seen from the 'reply' direction - * When NAT does not apply to this connection these will be identical to the above. - */ - sic.src_ip_xlate.ip6[0] = *((struct sfe_ipv6_addr *)&reply_tuple.dst.u3.in6); - sic.dest_ip_xlate.ip6[0] = *((struct sfe_ipv6_addr *)&reply_tuple.src.u3.in6); - - dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT; - if (dscp) { - sic.dest_dscp = dscp; - sic.src_dscp = sic.dest_dscp; - sic.flags |= SFE_CREATE_FLAG_REMARK_DSCP; - } - } - - switch (sic.protocol) { - case IPPROTO_TCP: - sic.src_port = orig_tuple.src.u.tcp.port; - sic.dest_port = orig_tuple.dst.u.tcp.port; - sic.src_port_xlate = reply_tuple.dst.u.tcp.port; - sic.dest_port_xlate = reply_tuple.src.u.tcp.port; - - /* - * Don't try to manage a non-established connection. - */ - if (!test_bit(IPS_ASSURED_BIT, &ct->status)) { - fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_TCP_NOT_ASSURED); - DEBUG_TRACE("non-established connection\n"); - return NF_ACCEPT; - } - - break; - - case IPPROTO_UDP: - sic.src_port = orig_tuple.src.u.udp.port; - sic.dest_port = orig_tuple.dst.u.udp.port; - sic.src_port_xlate = reply_tuple.dst.u.udp.port; - sic.dest_port_xlate = reply_tuple.src.u.udp.port; - - /* - * Somehow, SFE is not playing nice with IPSec traffic. - * Do not accelerate for now. - */ - if (ntohs(sic.dest_port) == 4500 || ntohs(sic.dest_port) == 500) { - if (likely(is_v4)) - DEBUG_TRACE("quarkysg:: IPsec bypass: %pI4:%d(%pI4:%d) to %pI4:%d(%pI4:%d)\n", - &sic.src_ip.ip, ntohs(sic.src_port), &sic.src_ip_xlate.ip, ntohs(sic.src_port_xlate), - &sic.dest_ip.ip, ntohs(sic.dest_port), &sic.dest_ip_xlate.ip, ntohs(sic.dest_port_xlate)); - else - DEBUG_TRACE("quarkysg:: IPsec bypass: %pI6:%d to %pI6:%d\n", - &sic.src_ip.ip6, ntohs(sic.src_port), &sic.dest_ip.ip6, ntohs(sic.dest_port)); - return NF_ACCEPT; - } - break; - - default: - fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_UNKNOW_PROTOCOL); - DEBUG_TRACE("unhandled protocol %d\n", sic.protocol); - return NF_ACCEPT; - } - -#ifdef CONFIG_XFRM - sic.original_accel = 1; - sic.reply_accel = 1; -#endif - - /* - * Get QoS information - */ - if (skb->priority) { - sic.dest_priority = skb->priority; - sic.src_priority = sic.dest_priority; - sic.flags |= SFE_CREATE_FLAG_REMARK_PRIORITY; - } - - if (is_v4) { - DEBUG_TRACE("POST_ROUTE: checking new connection: %d src_ip: %pI4 dst_ip: %pI4, src_port: %d, dst_port: %d\n", - sic.protocol, &sic.src_ip, &sic.dest_ip, sic.src_port, sic.dest_port); - } else { - DEBUG_TRACE("POST_ROUTE: checking new connection: %d src_ip: %pI6 dst_ip: %pI6, src_port: %d, dst_port: %d\n", - sic.protocol, &sic.src_ip, &sic.dest_ip, sic.src_port, sic.dest_port); - } - - /* - * If we already have this connection in our list, skip it - * XXX: this may need to be optimized - */ - spin_lock_bh(&sfe_connections_lock); - - conn = fast_classifier_find_conn(&sic.src_ip, &sic.dest_ip, sic.src_port, sic.dest_port, sic.protocol, is_v4); - if (conn) { - conn->hits++; - - if (!conn->offloaded) { - if (conn->offload_permit || conn->hits >= offload_at_pkts) { - DEBUG_TRACE("OFFLOADING CONNECTION, TOO MANY HITS\n"); - - if (fast_classifier_update_protocol(conn->sic, conn->ct) == 0) { - spin_unlock_bh(&sfe_connections_lock); - fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_UPDATE_PROTOCOL_FAIL); - DEBUG_TRACE("UNKNOWN PROTOCOL OR CONNECTION CLOSING, SKIPPING\n"); - return NF_ACCEPT; - } - - DEBUG_TRACE("INFO: calling sfe rule creation!\n"); - spin_unlock_bh(&sfe_connections_lock); - - ret = is_v4 ? sfe_ipv4_create_rule(conn->sic) : sfe_ipv6_create_rule(conn->sic); - if ((ret == 0) || (ret == -EADDRINUSE)) { - struct fast_classifier_tuple fc_msg; - - if (is_v4) { - fc_msg.ethertype = AF_INET; - fc_msg.src_saddr.in = *((struct in_addr *)&sic.src_ip); - fc_msg.dst_saddr.in = *((struct in_addr *)&sic.dest_ip_xlate); - } else { - fc_msg.ethertype = AF_INET6; - fc_msg.src_saddr.in6 = *((struct in6_addr *)&sic.src_ip); - fc_msg.dst_saddr.in6 = *((struct in6_addr *)&sic.dest_ip_xlate); - } - - fc_msg.proto = sic.protocol; - fc_msg.sport = sic.src_port; - fc_msg.dport = sic.dest_port_xlate; - memcpy(fc_msg.smac, conn->smac, ETH_ALEN); - memcpy(fc_msg.dmac, conn->dmac, ETH_ALEN); - fast_classifier_send_genl_msg(FAST_CLASSIFIER_C_OFFLOADED, &fc_msg); - conn->offloaded = 1; - } - - return NF_ACCEPT; - } - } - - spin_unlock_bh(&sfe_connections_lock); - if (conn->offloaded) { - is_v4 ? sfe_ipv4_update_rule(conn->sic) : sfe_ipv6_update_rule(conn->sic); - } - - DEBUG_TRACE("FOUND, SKIPPING\n"); - fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_WAIT_FOR_ACCELERATION); - return NF_ACCEPT; - } - - spin_unlock_bh(&sfe_connections_lock); - - /* - * Get the net device and MAC addresses that correspond to the various source and - * destination host addresses. - */ - if (!fast_classifier_find_dev_and_mac_addr(NULL, &sic.src_ip, &src_dev_tmp, sic.src_mac, is_v4)) { - fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_NO_SRC_DEV); - return NF_ACCEPT; - } - src_dev = src_dev_tmp; - - if (!fast_classifier_find_dev_and_mac_addr(NULL, &sic.src_ip_xlate, &dev, sic.src_mac_xlate, is_v4)) { - fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_NO_SRC_XLATE_DEV); - goto done1; - } - dev_put(dev); - - if (unlikely(!is_v4)) - tmp_skb = skb; - - if (!fast_classifier_find_dev_and_mac_addr(tmp_skb, &sic.dest_ip, &dev, sic.dest_mac, is_v4)) { - fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_NO_DEST_DEV); - goto done1; - } - dev_put(dev); - - if (!fast_classifier_find_dev_and_mac_addr(skb, &sic.dest_ip_xlate, &dest_dev_tmp, sic.dest_mac_xlate, is_v4)) { - fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_NO_DEST_XLATE_DEV); - goto done1; - } - dest_dev = dest_dev_tmp; - - /* - * Our devices may actually be part of a bridge interface. If that's - * the case then find the bridge interface instead. - */ - if (src_dev->priv_flags & IFF_BRIDGE_PORT) { - src_br_dev = sfe_dev_get_master(src_dev); - if (!src_br_dev) { - fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_NO_BRIDGE); - DEBUG_TRACE("no bridge found for: %s\n", src_dev->name); - goto done2; - } - src_dev = src_br_dev; - } - - if (dest_dev->priv_flags & IFF_BRIDGE_PORT) { - dest_br_dev = sfe_dev_get_master(dest_dev); - if (!dest_br_dev) { - fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_NO_BRIDGE); - DEBUG_TRACE("no bridge found for: %s\n", dest_dev->name); - goto done3; - } - dest_dev = dest_br_dev; - } - - sic.src_dev = src_dev; - sic.dest_dev = dest_dev; - - sic.src_mtu = src_dev->mtu; - sic.dest_mtu = dest_dev->mtu; - - if (skb->mark) { - DEBUG_TRACE("SKB MARK NON ZERO %x\n", skb->mark); - } - sic.mark = skb->mark; - - conn = kmalloc(sizeof(*conn), GFP_ATOMIC); - if (!conn) { - printk(KERN_CRIT "ERROR: no memory for sfe\n"); - goto done4; - } - conn->hits = 0; - conn->offload_permit = 0; - conn->offloaded = 0; - conn->is_v4 = is_v4; - DEBUG_TRACE("Source MAC=%pM\n", sic.src_mac); - memcpy(conn->smac, sic.src_mac, ETH_ALEN); - memcpy(conn->dmac, sic.dest_mac_xlate, ETH_ALEN); - - p_sic = kmalloc(sizeof(*p_sic), GFP_ATOMIC); - if (!p_sic) { - printk(KERN_CRIT "ERROR: no memory for sfe\n"); - kfree(conn); - goto done4; - } - - memcpy(p_sic, &sic, sizeof(sic)); - conn->sic = p_sic; - conn->ct = ct; - - if (!fast_classifier_add_conn(conn)) { - kfree(conn->sic); - kfree(conn); - } - - /* - * If we had bridge ports then release them too. - */ -done4: - if (dest_br_dev) { - dev_put(dest_br_dev); - } -done3: - if (src_br_dev) { - dev_put(src_br_dev); - } -done2: - dev_put(dest_dev_tmp); -done1: - dev_put(src_dev_tmp); - - return NF_ACCEPT; -} - -/* - * fast_classifier_ipv4_post_routing_hook() - * Called for packets about to leave the box - either locally generated or forwarded from another interface - */ -fast_classifier_ipv4_post_routing_hook(hooknum, ops, skb, in_unused, out, okfn) -{ - return fast_classifier_post_routing(skb, true); -} - -/* - * fast_classifier_ipv6_post_routing_hook() - * Called for packets about to leave the box - either locally generated or forwarded from another interface - */ -fast_classifier_ipv6_post_routing_hook(hooknum, ops, skb, in_unused, out, okfn) -{ - return fast_classifier_post_routing(skb, false); -} - -/* - * fast_classifier_update_mark() - * updates the mark for a fast-classifier connection - */ -static void fast_classifier_update_mark(struct sfe_connection_mark *mark, bool is_v4) -{ - struct sfe_connection *conn; - - spin_lock_bh(&sfe_connections_lock); - - conn = fast_classifier_find_conn(&mark->src_ip, &mark->dest_ip, - mark->src_port, mark->dest_port, - mark->protocol, is_v4); - if (conn) { - conn->sic->mark = mark->mark; - } - - spin_unlock_bh(&sfe_connections_lock); -} - -#ifdef CONFIG_NF_CONNTRACK_EVENTS -/* - * fast_classifier_conntrack_event() - * Callback event invoked when a conntrack connection's state changes. - */ -#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS -static int fast_classifier_conntrack_event(struct notifier_block *this, - unsigned long events, void *ptr) -#else -static int fast_classifier_conntrack_event(unsigned int events, struct nf_ct_event *item) -#endif -{ -#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS - struct nf_ct_event *item = ptr; -#endif - struct sfe_connection_destroy sid; - struct nf_conn *ct = item->ct; - struct nf_conntrack_tuple orig_tuple; - struct sfe_connection *conn; - struct fast_classifier_tuple fc_msg; - int offloaded = 0; - bool is_v4; - - /* - * If we don't have a conntrack entry then we're done. - */ - if (unlikely(!ct)) { - DEBUG_WARN("no ct in conntrack event callback\n"); - return NOTIFY_DONE; - } - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) - /* - * If this is an untracked connection then we can't have any state either. - */ - if (unlikely(nf_ct_is_untracked(ct))) { - DEBUG_TRACE("ignoring untracked conn\n"); - return NOTIFY_DONE; - } -#endif /*KERNEL_VERSION(4, 12, 0)*/ - - orig_tuple = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; - sid.protocol = (s32)orig_tuple.dst.protonum; - - /* - * Extract information from the conntrack connection. We're only interested - * in nominal connection information (i.e. we're ignoring any NAT information). - */ - if (likely(nf_ct_l3num(ct) == AF_INET)) { - sid.src_ip.ip = (__be32)orig_tuple.src.u3.ip; - sid.dest_ip.ip = (__be32)orig_tuple.dst.u3.ip; - is_v4 = true; - } else if (likely(nf_ct_l3num(ct) == AF_INET6)) { - sid.src_ip.ip6[0] = *((struct sfe_ipv6_addr *)&orig_tuple.src.u3.in6); - sid.dest_ip.ip6[0] = *((struct sfe_ipv6_addr *)&orig_tuple.dst.u3.in6); - is_v4 = false; - } else { - DEBUG_TRACE("ignoring non-IPv4 and non-IPv6 connection\n"); - return NOTIFY_DONE; - } - - switch (sid.protocol) { - case IPPROTO_TCP: - sid.src_port = orig_tuple.src.u.tcp.port; - sid.dest_port = orig_tuple.dst.u.tcp.port; - break; - - case IPPROTO_UDP: - sid.src_port = orig_tuple.src.u.udp.port; - sid.dest_port = orig_tuple.dst.u.udp.port; - break; - - default: - DEBUG_TRACE("unhandled protocol: %d\n", sid.protocol); - return NOTIFY_DONE; - } - - /* - * Check for an updated mark - */ - if ((events & (1 << IPCT_MARK)) && (ct->mark != 0)) { - struct sfe_connection_mark mark; - - mark.protocol = sid.protocol; - mark.src_ip = sid.src_ip; - mark.dest_ip = sid.dest_ip; - mark.src_port = sid.src_port; - mark.dest_port = sid.dest_port; - mark.mark = ct->mark; - - is_v4 ? sfe_ipv4_mark_rule(&mark) : sfe_ipv6_mark_rule(&mark); - fast_classifier_update_mark(&mark, is_v4); - } - - /* - * We're only interested in destroy events at this point - */ - if (unlikely(!(events & (1 << IPCT_DESTROY)))) { - DEBUG_TRACE("ignoring non-destroy event\n"); - return NOTIFY_DONE; - } - - if (is_v4) { - DEBUG_TRACE("Try to clean up: proto: %d src_ip: %pI4 dst_ip: %pI4, src_port: %d, dst_port: %d\n", - sid.protocol, &sid.src_ip, &sid.dest_ip, ntohs(sid.src_port), ntohs(sid.dest_port)); - } else { - DEBUG_TRACE("Try to clean up: proto: %d src_ip: %pI6 dst_ip: %pI6, src_port: %d, dst_port: %d\n", - sid.protocol, &sid.src_ip, &sid.dest_ip, ntohs(sid.src_port), ntohs(sid.dest_port)); - } - - spin_lock_bh(&sfe_connections_lock); - - conn = fast_classifier_find_conn(&sid.src_ip, &sid.dest_ip, sid.src_port, sid.dest_port, sid.protocol, is_v4); - if (conn && conn->offloaded) { - if (is_v4) { - fc_msg.ethertype = AF_INET; - fc_msg.src_saddr.in = *((struct in_addr *)&conn->sic->src_ip); - fc_msg.dst_saddr.in = *((struct in_addr *)&conn->sic->dest_ip_xlate); - } else { - fc_msg.ethertype = AF_INET6; - fc_msg.src_saddr.in6 = *((struct in6_addr *)&conn->sic->src_ip); - fc_msg.dst_saddr.in6 = *((struct in6_addr *)&conn->sic->dest_ip_xlate); - } - - fc_msg.proto = conn->sic->protocol; - fc_msg.sport = conn->sic->src_port; - fc_msg.dport = conn->sic->dest_port_xlate; - memcpy(fc_msg.smac, conn->smac, ETH_ALEN); - memcpy(fc_msg.dmac, conn->dmac, ETH_ALEN); - offloaded = 1; - } - - if (conn) { - DEBUG_TRACE("Free connection\n"); - - hash_del(&conn->hl); - sfe_connections_size--; - kfree(conn->sic); - kfree(conn); - } else { - fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_CT_DESTROY_MISS); - } - - spin_unlock_bh(&sfe_connections_lock); - - is_v4 ? sfe_ipv4_destroy_rule(&sid) : sfe_ipv6_destroy_rule(&sid); - - if (offloaded) { - fast_classifier_send_genl_msg(FAST_CLASSIFIER_C_DONE, &fc_msg); - } - - return NOTIFY_DONE; -} - -/* - * Netfilter conntrack event system to monitor connection tracking changes - */ -#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS -static struct notifier_block fast_classifier_conntrack_notifier = { - .notifier_call = fast_classifier_conntrack_event, -}; -#else -static struct nf_ct_event_notifier fast_classifier_conntrack_notifier = { - .fcn = fast_classifier_conntrack_event, -}; -#endif -#endif - -/* - * Structure to establish a hook into the post routing netfilter point - this - * will pick up local outbound and packets going from one interface to another. - * - * Note: see include/linux/netfilter_ipv4.h for info related to priority levels. - * We want to examine packets after NAT translation and any ALG processing. - */ -static struct nf_hook_ops fast_classifier_ops_post_routing[] __read_mostly = { - SFE_IPV4_NF_POST_ROUTING_HOOK(__fast_classifier_ipv4_post_routing_hook), - SFE_IPV6_NF_POST_ROUTING_HOOK(__fast_classifier_ipv6_post_routing_hook), -}; - -/* - * fast_classifier_sync_rule() - * Synchronize a connection's state. - */ -static void fast_classifier_sync_rule(struct sfe_connection_sync *sis) -{ - struct nf_conntrack_tuple_hash *h; - struct nf_conntrack_tuple tuple; - struct nf_conn *ct; - SFE_NF_CONN_ACCT(acct); - - /* - * Create a tuple so as to be able to look up a connection - */ - memset(&tuple, 0, sizeof(tuple)); - tuple.src.u.all = (__be16)sis->src_port; - tuple.dst.dir = IP_CT_DIR_ORIGINAL; - tuple.dst.protonum = (u8)sis->protocol; - tuple.dst.u.all = (__be16)sis->dest_port; - - if (sis->is_v6) { - tuple.src.u3.in6 = *((struct in6_addr *)sis->src_ip.ip6); - tuple.dst.u3.in6 = *((struct in6_addr *)sis->dest_ip.ip6); - tuple.src.l3num = AF_INET6; - - DEBUG_TRACE("update connection - p: %d, s: %pI6:%u, d: %pI6:%u\n", - (int)tuple.dst.protonum, - &tuple.src.u3.in6, (unsigned int)ntohs(tuple.src.u.all), - &tuple.dst.u3.in6, (unsigned int)ntohs(tuple.dst.u.all)); - } else { - tuple.src.u3.ip = sis->src_ip.ip; - tuple.dst.u3.ip = sis->dest_ip.ip; - tuple.src.l3num = AF_INET; - - DEBUG_TRACE("update connection - p: %d, s: %pI4:%u, d: %pI4:%u\n", - (int)tuple.dst.protonum, - &tuple.src.u3.ip, (unsigned int)ntohs(tuple.src.u.all), - &tuple.dst.u3.ip, (unsigned int)ntohs(tuple.dst.u.all)); - } - - /* - * Update packet count for ingress on bridge device - */ - if (skip_to_bridge_ingress) { - struct rtnl_link_stats64 nlstats; - nlstats.tx_packets = 0; - nlstats.tx_bytes = 0; - - if (sis->src_dev && IFF_EBRIDGE && - (sis->src_new_packet_count || sis->src_new_byte_count)) { - nlstats.rx_packets = sis->src_new_packet_count; - nlstats.rx_bytes = sis->src_new_byte_count; - spin_lock_bh(&sfe_connections_lock); - br_dev_update_stats(sis->src_dev, &nlstats); - spin_unlock_bh(&sfe_connections_lock); - } - if (sis->dest_dev && IFF_EBRIDGE && - (sis->dest_new_packet_count || sis->dest_new_byte_count)) { - nlstats.rx_packets = sis->dest_new_packet_count; - nlstats.rx_bytes = sis->dest_new_byte_count; - spin_lock_bh(&sfe_connections_lock); - br_dev_update_stats(sis->dest_dev, &nlstats); - spin_unlock_bh(&sfe_connections_lock); - } - } - - /* - * Look up conntrack connection - */ - h = nf_conntrack_find_get(&init_net, SFE_NF_CT_DEFAULT_ZONE, &tuple); - if (unlikely(!h)) { - DEBUG_TRACE("no connection found\n"); - return; - } - - ct = nf_ct_tuplehash_to_ctrack(h); -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)) - NF_CT_ASSERT(ct->timeout.data == (unsigned long)ct); -#endif /*KERNEL_VERSION(4, 9, 0)*/ - - /* - * Only update if this is not a fixed timeout - */ - if (!test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) { - spin_lock_bh(&ct->lock); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) - ct->timeout += sis->delta_jiffies; -#else - ct->timeout.expires += sis->delta_jiffies; -#endif /*KERNEL_VERSION(4, 9, 0)*/ - spin_unlock_bh(&ct->lock); - } - - acct = nf_conn_acct_find(ct); - if (acct) { - spin_lock_bh(&ct->lock); - atomic64_add(sis->src_new_packet_count, &SFE_ACCT_COUNTER(acct)[IP_CT_DIR_ORIGINAL].packets); - atomic64_add(sis->src_new_byte_count, &SFE_ACCT_COUNTER(acct)[IP_CT_DIR_ORIGINAL].bytes); - atomic64_add(sis->dest_new_packet_count, &SFE_ACCT_COUNTER(acct)[IP_CT_DIR_REPLY].packets); - atomic64_add(sis->dest_new_byte_count, &SFE_ACCT_COUNTER(acct)[IP_CT_DIR_REPLY].bytes); - spin_unlock_bh(&ct->lock); - } - - switch (sis->protocol) { - case IPPROTO_TCP: - spin_lock_bh(&ct->lock); - if (ct->proto.tcp.seen[0].td_maxwin < sis->src_td_max_window) { - ct->proto.tcp.seen[0].td_maxwin = sis->src_td_max_window; - } - if ((s32)(ct->proto.tcp.seen[0].td_end - sis->src_td_end) < 0) { - ct->proto.tcp.seen[0].td_end = sis->src_td_end; - } - if ((s32)(ct->proto.tcp.seen[0].td_maxend - sis->src_td_max_end) < 0) { - ct->proto.tcp.seen[0].td_maxend = sis->src_td_max_end; - } - if (ct->proto.tcp.seen[1].td_maxwin < sis->dest_td_max_window) { - ct->proto.tcp.seen[1].td_maxwin = sis->dest_td_max_window; - } - if ((s32)(ct->proto.tcp.seen[1].td_end - sis->dest_td_end) < 0) { - ct->proto.tcp.seen[1].td_end = sis->dest_td_end; - } - if ((s32)(ct->proto.tcp.seen[1].td_maxend - sis->dest_td_max_end) < 0) { - ct->proto.tcp.seen[1].td_maxend = sis->dest_td_max_end; - } - spin_unlock_bh(&ct->lock); - break; - } - - /* - * Release connection - */ - nf_ct_put(ct); -} - -/* - * fast_classifier_device_event() - */ -static int fast_classifier_device_event(struct notifier_block *this, unsigned long event, void *ptr) -{ - struct net_device *dev = SFE_DEV_EVENT_PTR(ptr); - - if (dev && (event == NETDEV_DOWN)) { - sfe_ipv4_destroy_all_rules_for_dev(dev); - sfe_ipv6_destroy_all_rules_for_dev(dev); - } - - return NOTIFY_DONE; -} - -/* - * fast_classifier_inet_event() - */ -static int fast_classifier_inet_event(struct notifier_block *this, unsigned long event, void *ptr) -{ - struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev; - - if (dev && (event == NETDEV_DOWN)) { - sfe_ipv4_destroy_all_rules_for_dev(dev); - } - - return NOTIFY_DONE; -} - -/* - * fast_classifier_inet6_event() - */ -static int fast_classifier_inet6_event(struct notifier_block *this, unsigned long event, void *ptr) -{ - struct net_device *dev = ((struct inet6_ifaddr *)ptr)->idev->dev; - - if (dev && (event == NETDEV_DOWN)) { - sfe_ipv6_destroy_all_rules_for_dev(dev); - } - - return NOTIFY_DONE; -} - -/* - * fast_classifier_get_offload_at_pkts() - */ -static ssize_t fast_classifier_get_offload_at_pkts(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return snprintf(buf, (ssize_t)PAGE_SIZE, "%d\n", offload_at_pkts); -} - -/* - * fast_classifier_set_offload_at_pkts() - */ -static ssize_t fast_classifier_set_offload_at_pkts(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - long new; - int ret; - - ret = kstrtol(buf, 0, &new); - if (ret == -EINVAL || ((int)new != new)) - return -EINVAL; - - offload_at_pkts = new; - - return size; -} - -/* - * fast_classifier_get_debug_info() - */ -static ssize_t fast_classifier_get_debug_info(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - size_t len = 0; - struct sfe_connection *conn; - u32 i; -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)) - struct hlist_node *node; -#endif - - spin_lock_bh(&sfe_connections_lock); - len += scnprintf(buf, PAGE_SIZE - len, "size=%d offload=%d offload_no_match=%d" - " offloaded=%d done=%d offloaded_fail=%d done_fail=%d\n", - sfe_connections_size, - atomic_read(&offload_msgs), - atomic_read(&offload_no_match_msgs), - atomic_read(&offloaded_msgs), - atomic_read(&done_msgs), - atomic_read(&offloaded_fail_msgs), - atomic_read(&done_fail_msgs)); - sfe_hash_for_each(fc_conn_ht, i, node, conn, hl) { - len += scnprintf(buf + len, PAGE_SIZE - len, - (conn->is_v4 ? "o=%d, p=%d [%pM]:%pI4:%u %pI4:%u:[%pM] m=%08x h=%d\n" : "o=%d, p=%d [%pM]:%pI6:%u %pI6:%u:[%pM] m=%08x h=%d\n"), - conn->offloaded, - conn->sic->protocol, - conn->sic->src_mac, - &conn->sic->src_ip, - ntohs(conn->sic->src_port), - &conn->sic->dest_ip, - ntohs(conn->sic->dest_port), - conn->sic->dest_mac_xlate, - conn->sic->mark, - conn->hits); - } - spin_unlock_bh(&sfe_connections_lock); - - return len; -} - -/* - * fast_classifier_get_skip_bridge_ingress() - */ -static ssize_t fast_classifier_get_skip_bridge_ingress(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return snprintf(buf, (ssize_t)PAGE_SIZE, "%d\n", skip_to_bridge_ingress); -} - -/* - * fast_classifier_set_skip_bridge_ingress() - */ -static ssize_t fast_classifier_set_skip_bridge_ingress(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - long new; - int ret; - - ret = kstrtol(buf, 0, &new); - if (ret == -EINVAL || ((int)new != new)) - return -EINVAL; - - skip_to_bridge_ingress = new ? 1 : 0; - - return size; -} - -/* - * fast_classifier_get_exceptions - * dump exception counters - */ -static ssize_t fast_classifier_get_exceptions(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int idx, len; - struct fast_classifier *sc = &__sc; - - spin_lock_bh(&sc->lock); - for (len = 0, idx = 0; idx < FAST_CL_EXCEPTION_MAX; idx++) { - if (sc->exceptions[idx]) { - len += snprintf(buf + len, (ssize_t)(PAGE_SIZE - len), "%s = %d\n", fast_classifier_exception_events_string[idx], sc->exceptions[idx]); - } - } - spin_unlock_bh(&sc->lock); - - return len; -} - -/* - * sysfs attributes. - */ -static const struct device_attribute fast_classifier_offload_at_pkts_attr = - __ATTR(offload_at_pkts, S_IWUSR | S_IRUGO, fast_classifier_get_offload_at_pkts, fast_classifier_set_offload_at_pkts); -static const struct device_attribute fast_classifier_debug_info_attr = - __ATTR(debug_info, S_IRUGO, fast_classifier_get_debug_info, NULL); -static const struct device_attribute fast_classifier_skip_bridge_ingress = - __ATTR(skip_to_bridge_ingress, S_IWUSR | S_IRUGO, fast_classifier_get_skip_bridge_ingress, fast_classifier_set_skip_bridge_ingress); -static const struct device_attribute fast_classifier_exceptions_attr = - __ATTR(exceptions, S_IRUGO, fast_classifier_get_exceptions, NULL); - -/* - * fast_classifier_init() - */ -static int __init fast_classifier_init(void) -{ - struct fast_classifier *sc = &__sc; - int result = -1; -#ifdef CONFIG_SFE_ECM - int (*fast_recv)(struct sk_buff *skb); -#endif - - printk(KERN_ALERT "fast-classifier: starting up\n"); - DEBUG_INFO("SFE CM init\n"); - - hash_init(fc_conn_ht); - - /* - * Create sys/fast_classifier - */ - sc->sys_fast_classifier = kobject_create_and_add("fast_classifier", NULL); - if (!sc->sys_fast_classifier) { - DEBUG_ERROR("failed to register fast_classifier\n"); - goto exit1; - } - - result = sysfs_create_file(sc->sys_fast_classifier, &fast_classifier_offload_at_pkts_attr.attr); - if (result) { - DEBUG_ERROR("failed to register offload at pkgs: %d\n", result); - goto exit2; - } - - result = sysfs_create_file(sc->sys_fast_classifier, &fast_classifier_debug_info_attr.attr); - if (result) { - DEBUG_ERROR("failed to register debug dev: %d\n", result); - sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_offload_at_pkts_attr.attr); - goto exit2; - } - - result = sysfs_create_file(sc->sys_fast_classifier, &fast_classifier_skip_bridge_ingress.attr); - if (result) { - DEBUG_ERROR("failed to register skip bridge on ingress: %d\n", result); - sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_offload_at_pkts_attr.attr); - sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_debug_info_attr.attr); - goto exit2; - } - - result = sysfs_create_file(sc->sys_fast_classifier, &fast_classifier_exceptions_attr.attr); - if (result) { - DEBUG_ERROR("failed to register exceptions file: %d\n", result); - sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_offload_at_pkts_attr.attr); - sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_debug_info_attr.attr); - sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_skip_bridge_ingress.attr); - goto exit2; - } - - sc->dev_notifier.notifier_call = fast_classifier_device_event; - sc->dev_notifier.priority = 1; - register_netdevice_notifier(&sc->dev_notifier); - - sc->inet_notifier.notifier_call = fast_classifier_inet_event; - sc->inet_notifier.priority = 1; - register_inetaddr_notifier(&sc->inet_notifier); - - sc->inet6_notifier.notifier_call = fast_classifier_inet6_event; - sc->inet6_notifier.priority = 1; - register_inet6addr_notifier(&sc->inet6_notifier); - - /* - * Register our netfilter hooks. - */ - result = nf_register_net_hooks(&init_net, fast_classifier_ops_post_routing, ARRAY_SIZE(fast_classifier_ops_post_routing)); - if (result < 0) { - DEBUG_ERROR("can't register nf post routing hook: %d\n", result); - goto exit3; - } - -#ifdef CONFIG_NF_CONNTRACK_EVENTS - /* - * Register a notifier hook to get fast notifications of expired connections. - */ -#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS - result = nf_conntrack_register_chain_notifier(&init_net, &fast_classifier_conntrack_notifier); -#else - result = nf_conntrack_register_notifier(&init_net, &fast_classifier_conntrack_notifier); -#endif - if (result < 0) { - DEBUG_ERROR("can't register nf notifier hook: %d\n", result); - goto exit4; - } -#endif - - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) - result = genl_register_family(&fast_classifier_gnl_family); - if (result) { - DEBUG_ERROR("failed to register genl family: %d\n", result); - goto exit5; - } -#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) - result = genl_register_family_with_ops_groups(&fast_classifier_gnl_family, - fast_classifier_gnl_ops, - fast_classifier_genl_mcgrp); - if (result) { - DEBUG_ERROR("failed to register genl ops: %d\n", result); - goto exit5; - } -#else - result = genl_register_family(&fast_classifier_gnl_family); - if (result) { - printk(KERN_CRIT "unable to register genl family\n"); - goto exit5; - } - - result = genl_register_ops(&fast_classifier_gnl_family, fast_classifier_gnl_ops); - if (result) { - printk(KERN_CRIT "unable to register ops\n"); - goto exit6; - } - - result = genl_register_mc_group(&fast_classifier_gnl_family, - fast_classifier_genl_mcgrp); - if (result) { - printk(KERN_CRIT "unable to register multicast group\n"); - goto exit6; - } -#endif - - printk(KERN_ALERT "fast-classifier: registered\n"); - - spin_lock_init(&sc->lock); - - /* - * Hook the receive path in the network stack. - */ -#ifdef CONFIG_SFE_ECM - rcu_read_lock(); - fast_recv = rcu_dereference(athrs_fast_nat_recv); - rcu_read_unlock(); - if (!fast_recv) { - BUG_ON(athrs_fast_nat_recv); - } -#else - BUG_ON(athrs_fast_nat_recv); -#endif - RCU_INIT_POINTER(athrs_fast_nat_recv, fast_classifier_recv); - - /* - * Hook the shortcut sync callback. - */ - sfe_ipv4_register_sync_rule_callback(fast_classifier_sync_rule); - sfe_ipv6_register_sync_rule_callback(fast_classifier_sync_rule); - return 0; - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)) -exit6: - genl_unregister_family(&fast_classifier_gnl_family); -#endif - -exit5: -#ifdef CONFIG_NF_CONNTRACK_EVENTS -#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS - nf_conntrack_unregister_chain_notifier(&init_net, &fast_classifier_conntrack_notifier); -#else - nf_conntrack_unregister_notifier(&init_net, &fast_classifier_conntrack_notifier); -#endif - -exit4: -#endif - nf_unregister_net_hooks(&init_net, fast_classifier_ops_post_routing, ARRAY_SIZE(fast_classifier_ops_post_routing)); - -exit3: - unregister_inetaddr_notifier(&sc->inet_notifier); - unregister_inet6addr_notifier(&sc->inet6_notifier); - unregister_netdevice_notifier(&sc->dev_notifier); - sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_offload_at_pkts_attr.attr); - sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_debug_info_attr.attr); - sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_skip_bridge_ingress.attr); - sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_exceptions_attr.attr); - -exit2: - kobject_put(sc->sys_fast_classifier); - -exit1: - return result; -} - -/* - * fast_classifier_exit() - */ -static void __exit fast_classifier_exit(void) -{ - struct fast_classifier *sc = &__sc; - int result = -1; - - DEBUG_INFO("SFE CM exit\n"); - printk(KERN_ALERT "fast-classifier: shutting down\n"); - - /* - * Unregister our sync callback. - */ - sfe_ipv4_register_sync_rule_callback(NULL); - sfe_ipv6_register_sync_rule_callback(NULL); - - /* - * Unregister our receive callback. - */ - RCU_INIT_POINTER(athrs_fast_nat_recv, NULL); - - /* - * Wait for all callbacks to complete. - */ - rcu_barrier(); - - /* - * Destroy all connections. - */ - sfe_ipv4_destroy_all_rules_for_dev(NULL); - sfe_ipv6_destroy_all_rules_for_dev(NULL); - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)) - result = genl_unregister_ops(&fast_classifier_gnl_family, fast_classifier_gnl_ops); - if (result != 0) { - printk(KERN_CRIT "Unable to unreigster genl_ops\n"); - } -#endif - - result = genl_unregister_family(&fast_classifier_gnl_family); - if (result != 0) { - printk(KERN_CRIT "Unable to unregister genl_family\n"); - } - -#ifdef CONFIG_NF_CONNTRACK_EVENTS -#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS - nf_conntrack_unregister_chain_notifier(&init_net, &fast_classifier_conntrack_notifier); -#else - nf_conntrack_unregister_notifier(&init_net, &fast_classifier_conntrack_notifier); -#endif -#endif - nf_unregister_net_hooks(&init_net, fast_classifier_ops_post_routing, ARRAY_SIZE(fast_classifier_ops_post_routing)); - - unregister_inet6addr_notifier(&sc->inet6_notifier); - unregister_inetaddr_notifier(&sc->inet_notifier); - unregister_netdevice_notifier(&sc->dev_notifier); - - kobject_put(sc->sys_fast_classifier); -} - -module_init(fast_classifier_init) -module_exit(fast_classifier_exit) - -MODULE_DESCRIPTION("Shortcut Forwarding Engine - Connection Manager"); -MODULE_LICENSE("Dual BSD/GPL"); - diff --git a/root/package/lean/shortcut-fe/fast-classifier/src/fast-classifier.h b/root/package/lean/shortcut-fe/fast-classifier/src/fast-classifier.h deleted file mode 100644 index 6b7a18cf..00000000 --- a/root/package/lean/shortcut-fe/fast-classifier/src/fast-classifier.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * User space header to send message to the fast classifier - * - * Copyright (c) 2013,2016 The Linux Foundation. All rights reserved. - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all copies. - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include - -#define FAST_CLASSIFIER_GENL_VERSION (1) -#define FAST_CLASSIFIER_GENL_NAME "FC" -#define FAST_CLASSIFIER_GENL_MCGRP "FC_MCGRP" -#define FAST_CLASSIFIER_GENL_HDRSIZE (0) - -enum { - FAST_CLASSIFIER_A_UNSPEC, - FAST_CLASSIFIER_A_TUPLE, - __FAST_CLASSIFIER_A_MAX, -}; - -#define FAST_CLASSIFIER_A_MAX (__FAST_CLASSIFIER_A_MAX - 1) - -enum { - FAST_CLASSIFIER_C_UNSPEC, - FAST_CLASSIFIER_C_OFFLOAD, - FAST_CLASSIFIER_C_OFFLOADED, - FAST_CLASSIFIER_C_DONE, - __FAST_CLASSIFIER_C_MAX, -}; - -#define FAST_CLASSIFIER_C_MAX (__FAST_CLASSIFIER_C_MAX - 1) - -struct fast_classifier_tuple { - unsigned short ethertype; - unsigned char proto; - union { - struct in_addr in; - struct in6_addr in6; - } src_saddr; - union { - struct in_addr in; - struct in6_addr in6; - } dst_saddr; - unsigned short sport; - unsigned short dport; - unsigned char smac[ETH_ALEN]; - unsigned char dmac[ETH_ALEN]; -}; diff --git a/root/package/lean/shortcut-fe/fast-classifier/src/nl_classifier_test.c b/root/package/lean/shortcut-fe/fast-classifier/src/nl_classifier_test.c deleted file mode 100644 index 63941796..00000000 --- a/root/package/lean/shortcut-fe/fast-classifier/src/nl_classifier_test.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright (c) 2016 The Linux Foundation. All rights reserved. - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all copies. - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include - -#define NL_CLASSIFIER_GENL_VERSION 1 -#define NL_CLASSIFIER_GENL_FAMILY "FC" -#define NL_CLASSIFIER_GENL_GROUP "FC_MCGRP" -#define NL_CLASSIFIER_GENL_HDRSIZE 0 - -enum NL_CLASSIFIER_CMD { - NL_CLASSIFIER_CMD_UNSPEC, - NL_CLASSIFIER_CMD_ACCEL, - NL_CLASSIFIER_CMD_ACCEL_OK, - NL_CLASSIFIER_CMD_CONNECTION_CLOSED, - NL_CLASSIFIER_CMD_MAX, -}; - -enum NL_CLASSIFIER_ATTR { - NL_CLASSIFIER_ATTR_UNSPEC, - NL_CLASSIFIER_ATTR_TUPLE, - NL_CLASSIFIER_ATTR_MAX, -}; - -union nl_classifier_tuple_ip { - struct in_addr in; - struct in6_addr in6; -}; - -struct nl_classifier_tuple { - unsigned short af; - unsigned char proto; - union nl_classifier_tuple_ip src_ip; - union nl_classifier_tuple_ip dst_ip; - unsigned short sport; - unsigned short dport; - unsigned char smac[6]; - unsigned char dmac[6]; -}; - -struct nl_classifier_instance { - struct nl_sock *sock; - int family_id; - int group_id; - int stop; -}; - -struct nl_classifier_instance nl_cls_inst; - -static struct nla_policy nl_classifier_genl_policy[(NL_CLASSIFIER_ATTR_MAX+1)] = { - [NL_CLASSIFIER_ATTR_TUPLE] = { .type = NLA_UNSPEC }, -}; - -void nl_classifier_dump_nl_tuple(struct nl_classifier_tuple *tuple) -{ - char ip_str[64]; - - printf("protocol = %s\n", (tuple->proto == IPPROTO_UDP) ? "udp" : ((tuple->proto == IPPROTO_TCP) ? "tcp" : "unknown")); - printf("source ip = %s\n", inet_ntop(tuple->af, &tuple->src_ip, ip_str, sizeof(ip_str))); - printf("destination ip = %s\n", inet_ntop(tuple->af, &tuple->dst_ip, ip_str, sizeof(ip_str))); - printf("source port = %d\n", ntohs(tuple->sport)); - printf("destination port = %d\n", ntohs(tuple->dport)); -} - -int nl_classifier_msg_recv(struct nl_msg *msg, void *arg) -{ - struct nlmsghdr *nlh = nlmsg_hdr(msg); - struct genlmsghdr *gnlh = nlmsg_data(nlh); - struct nlattr *attrs[(NL_CLASSIFIER_ATTR_MAX+1)]; - - genlmsg_parse(nlh, NL_CLASSIFIER_GENL_HDRSIZE, attrs, NL_CLASSIFIER_ATTR_MAX, nl_classifier_genl_policy); - - switch (gnlh->cmd) { - case NL_CLASSIFIER_CMD_ACCEL_OK: - printf("Acceleration successful:\n"); - nl_classifier_dump_nl_tuple(nla_data(attrs[NL_CLASSIFIER_ATTR_TUPLE])); - return NL_OK; - case NL_CLASSIFIER_CMD_CONNECTION_CLOSED: - printf("Connection is closed:\n"); - nl_classifier_dump_nl_tuple(nla_data(attrs[NL_CLASSIFIER_ATTR_TUPLE])); - return NL_OK; - default: - printf("nl classifier received unknow message %d\n", gnlh->cmd); - } - - return NL_SKIP; -} - -void nl_classifier_offload(struct nl_classifier_instance *inst, - unsigned char proto, unsigned long *src_saddr, - unsigned long *dst_saddr, unsigned short sport, - unsigned short dport, int af) -{ - struct nl_msg *msg; - int ret; - struct nl_classifier_tuple classifier_msg; - - memset(&classifier_msg, 0, sizeof(classifier_msg)); - classifier_msg.af = af; - classifier_msg.proto = proto; - memcpy(&classifier_msg.src_ip, src_saddr, (af == AF_INET ? 4 : 16)); - memcpy(&classifier_msg.dst_ip, dst_saddr, (af == AF_INET ? 4 : 16)); - classifier_msg.sport = sport; - classifier_msg.dport = dport; - - msg = nlmsg_alloc(); - if (!msg) { - printf("Unable to allocate message\n"); - return; - } - - genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, inst->family_id, - NL_CLASSIFIER_GENL_HDRSIZE, NLM_F_REQUEST, - NL_CLASSIFIER_CMD_ACCEL, NL_CLASSIFIER_GENL_VERSION); - nla_put(msg, NL_CLASSIFIER_ATTR_TUPLE, sizeof(classifier_msg), &classifier_msg); - - ret = nl_send_auto(inst->sock, msg); - if (ret < 0) { - printf("send netlink message failed.\n"); - nlmsg_free(msg); - return; - } - - nlmsg_free(msg); - printf("nl classifier offload connection successful\n"); -} - -int nl_classifier_init(struct nl_classifier_instance *inst) -{ - int ret; - - inst->sock = nl_socket_alloc(); - if (!inst->sock) { - printf("Unable to allocation socket.\n"); - return -1; - } - genl_connect(inst->sock); - - inst->family_id = genl_ctrl_resolve(inst->sock, NL_CLASSIFIER_GENL_FAMILY); - if (inst->family_id < 0) { - printf("Unable to resolve family %s\n", NL_CLASSIFIER_GENL_FAMILY); - goto init_failed; - } - - inst->group_id = genl_ctrl_resolve_grp(inst->sock, NL_CLASSIFIER_GENL_FAMILY, NL_CLASSIFIER_GENL_GROUP); - if (inst->group_id < 0) { - printf("Unable to resolve mcast group %s\n", NL_CLASSIFIER_GENL_GROUP); - goto init_failed; - } - - ret = nl_socket_add_membership(inst->sock, inst->group_id); - if (ret < 0) { - printf("Unable to add membership\n"); - goto init_failed; - } - - nl_socket_disable_seq_check(inst->sock); - nl_socket_modify_cb(inst->sock, NL_CB_VALID, NL_CB_CUSTOM, nl_classifier_msg_recv, NULL); - - printf("nl classifier init successful\n"); - return 0; - -init_failed: - if (inst->sock) { - nl_close(inst->sock); - nl_socket_free(inst->sock); - inst->sock = NULL; - } - return -1; -} - -void nl_classifier_exit(struct nl_classifier_instance *inst) -{ - if (inst->sock) { - nl_close(inst->sock); - nl_socket_free(inst->sock); - inst->sock = NULL; - } - printf("nl classifier exit successful\n"); -} - -int nl_classifier_parse_arg(int argc, char *argv[], unsigned char *proto, unsigned long *src_saddr, - unsigned long *dst_saddr, unsigned short *sport, unsigned short *dport, int *af) -{ - int ret; - unsigned short port; - - if (argc < 7) { - printf("help: nl_classifier \n"); - return -1; - } - - if (0 == strncmp(argv[1], "v4", 2)) { - *af = AF_INET; - } else if (0 == strncmp(argv[1], "v6", 2)) { - *af = AF_INET6; - } else { - printf("Address family is not supported"); - return -1; - } - - if (0 == strncmp(argv[2], "udp", 3)) { - *proto = IPPROTO_UDP; - } else if (0 == strncmp(argv[2], "tcp", 3)) { - *proto = IPPROTO_TCP; - } else { - printf("Protocol is not supported"); - return -1; - } - - ret = inet_pton(*af, argv[3], src_saddr); - if (ret <= 0) { - printf("source ip has wrong format\n"); - return -1; - } - - ret = inet_pton(*af, argv[4], dst_saddr); - if (ret <= 0) { - printf("destination ip has wrong format\n"); - return -1; - } - - port = strtol(argv[5], NULL, 0); - *sport = htons(port); - port = strtol(argv[6], NULL, 0); - *dport = htons(port); - - printf("nl classifier parse arguments successful\n"); - return 0; -} - -int main(int argc, char *argv[]) -{ - struct nl_classifier_instance *inst = &nl_cls_inst; - unsigned char proto; - unsigned long src_addr[4]; - unsigned long dst_addr[4]; - unsigned short sport; - unsigned short dport; - int af; - int ret; - - ret = nl_classifier_parse_arg(argc, argv, &proto, src_addr, dst_addr, &sport, &dport, &af); - if (ret < 0) { - printf("Failed to parse arguments\n"); - return ret; - } - - ret = nl_classifier_init(inst); - if (ret < 0) { - printf("Unable to init generic netlink\n"); - return ret; - } - - nl_classifier_offload(inst, proto, src_addr, dst_addr, sport, dport, af); - - /* main loop to listen on message */ - while (!inst->stop) { - nl_recvmsgs_default(inst->sock); - } - - nl_classifier_exit(inst); - - return 0; -} diff --git a/root/package/lean/shortcut-fe/fast-classifier/src/userspace_example.c b/root/package/lean/shortcut-fe/fast-classifier/src/userspace_example.c deleted file mode 100644 index 4f4113d9..00000000 --- a/root/package/lean/shortcut-fe/fast-classifier/src/userspace_example.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (c) 2013,2016 The Linux Foundation. All rights reserved. - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all copies. - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include - -#include - -static struct nl_sock *sock; -static struct nl_sock *sock_event; -static int family; -static int grp_id; - -static struct nla_policy fast_classifier_genl_policy[FAST_CLASSIFIER_A_MAX + 1] = { - [FAST_CLASSIFIER_A_TUPLE] = { .type = NLA_UNSPEC }, -}; - -void dump_fc_tuple(struct fast_classifier_tuple *fc_msg) -{ - char src_str[INET_ADDRSTRLEN]; - char dst_str[INET_ADDRSTRLEN]; - - printf("TUPLE: %d, %s, %s, %d, %d" - " SMAC=%02x:%02x:%02x:%02x:%02x:%02x", - " DMAC=%02x:%02x:%02x:%02x:%02x:%02x\n", - fc_msg->proto, - inet_ntop(AF_INET, - &fc_msg->src_saddr.in.s_addr, - src_str, - INET_ADDRSTRLEN), - inet_ntop(AF_INET, - &fc_msg->dst_saddr.in.s_addr, - dst_str, - INET_ADDRSTRLEN), - fc_msg->sport, fc_msg->dport, - fc_msg->smac[0], fc_msg->smac[1], fc_msg->smac[2], - fc_msg->smac[3], fc_msg->smac[4], fc_msg->smac[5], - fc_msg->dmac[0], fc_msg->dmac[1], fc_msg->dmac[2], - fc_msg->dmac[3], fc_msg->dmac[4], fc_msg->dmac[5]); -} - -static int parse_cb(struct nl_msg *msg, void *arg) -{ - struct nlmsghdr *nlh = nlmsg_hdr(msg); - struct genlmsghdr *gnlh = nlmsg_data(nlh); - struct nlattr *attrs[FAST_CLASSIFIER_A_MAX]; - - genlmsg_parse(nlh, 0, attrs, FAST_CLASSIFIER_A_MAX, fast_classifier_genl_policy); - - switch (gnlh->cmd) { - case FAST_CLASSIFIER_C_OFFLOADED: - printf("Got a offloaded message\n"); - dump_fc_tuple(nla_data(attrs[FAST_CLASSIFIER_A_TUPLE])); - return NL_OK; - case FAST_CLASSIFIER_C_DONE: - printf("Got a done message\n"); - dump_fc_tuple(nla_data(attrs[FAST_CLASSIFIER_A_TUPLE])); - return NL_OK; - } - - return NL_SKIP; -} - -int fast_classifier_init(void) -{ - int err; - - sock = nl_socket_alloc(); - if (!sock) { - printf("Unable to allocation socket.\n"); - return -1; - } - genl_connect(sock); - - sock_event = nl_socket_alloc(); - if (!sock_event) { - nl_close(sock); - nl_socket_free(sock); - printf("Unable to allocation socket.\n"); - return -1; - } - genl_connect(sock_event); - - family = genl_ctrl_resolve(sock, FAST_CLASSIFIER_GENL_NAME); - if (family < 0) { - nl_close(sock_event); - nl_close(sock); - nl_socket_free(sock); - nl_socket_free(sock_event); - printf("Unable to resolve family\n"); - return -1; - } - - grp_id = genl_ctrl_resolve_grp(sock, FAST_CLASSIFIER_GENL_NAME, - FAST_CLASSIFIER_GENL_MCGRP); - if (grp_id < 0) { - printf("Unable to resolve mcast group\n"); - return -1; - } - - err = nl_socket_add_membership(sock_event, grp_id); - if (err < 0) { - printf("Unable to add membership\n"); - return -1; - } - - nl_socket_disable_seq_check(sock_event); - nl_socket_modify_cb(sock_event, NL_CB_VALID, NL_CB_CUSTOM, parse_cb, NULL); - - return 0; -} - -void fast_classifier_close(void) -{ - nl_close(sock_event); - nl_close(sock); - nl_socket_free(sock_event); - nl_socket_free(sock); -} - -void fast_classifier_ipv4_offload(unsigned char proto, unsigned long src_saddr, - unsigned long dst_saddr, unsigned short sport, - unsigned short dport) -{ - struct nl_msg *msg; - int ret; -#ifdef DEBUG - char src_str[INET_ADDRSTRLEN]; - char dst_str[INET_ADDRSTRLEN]; -#endif - struct fast_classifier_tuple fc_msg; - -#ifdef DEBUG - printf("DEBUG: would offload: %d, %s, %s, %d, %d\n", proto, - inet_ntop(AF_INET, &src_saddr, src_str, INET_ADDRSTRLEN), - inet_ntop(AF_INET, &dst_saddr, dst_str, INET_ADDRSTRLEN), - sport, dport); -#endif - - fc_msg.proto = proto; - fc_msg.src_saddr.in.s_addr = src_saddr; - fc_msg.dst_saddr.in.s_addr = dst_saddr; - fc_msg.sport = sport; - fc_msg.dport = dport; - fc_msg.smac[0] = 'a'; - fc_msg.smac[1] = 'b'; - fc_msg.smac[2] = 'c'; - fc_msg.smac[3] = 'd'; - fc_msg.smac[4] = 'e'; - fc_msg.smac[5] = 'f'; - fc_msg.dmac[0] = 'f'; - fc_msg.dmac[1] = 'e'; - fc_msg.dmac[2] = 'd'; - fc_msg.dmac[3] = 'c'; - fc_msg.dmac[4] = 'b'; - fc_msg.dmac[5] = 'a'; - - if (fast_classifier_init() < 0) { - printf("Unable to init generic netlink\n"); - exit(1); - } - - msg = nlmsg_alloc(); - if (!msg) { - nl_socket_free(sock); - printf("Unable to allocate message\n"); - return; - } - - genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, - FAST_CLASSIFIER_GENL_HDRSIZE, NLM_F_REQUEST, - FAST_CLASSIFIER_C_OFFLOAD, FAST_CLASSIFIER_GENL_VERSION); - nla_put(msg, 1, sizeof(fc_msg), &fc_msg); - - ret = nl_send_auto_complete(sock, msg); - - nlmsg_free(msg); - if (ret < 0) { - printf("nlmsg_free failed"); - nl_close(sock); - nl_socket_free(sock); - return; - } - - ret = nl_wait_for_ack(sock); - if (ret < 0) { - printf("wait for ack failed"); - nl_close(sock); - nl_socket_free(sock); - return; - } -} - -void fast_classifier_listen_for_messages(void) -{ - printf("waiting for netlink events\n"); - - while (1) { - nl_recvmsgs_default(sock_event); - } -} - -int main(int argc, char *argv[]) -{ - if (fast_classifier_init() < 0) { - printf("Unable to init generic netlink\n"); - exit(1); - } - - fast_classifier_ipv4_offload('a', 0, 0, 0, 0); - - /* this never returns */ - fast_classifier_listen_for_messages(); - - fast_classifier_close(); - - return 0; -} diff --git a/root/package/lean/shortcut-fe/shortcut-fe/Makefile b/root/package/lean/shortcut-fe/shortcut-fe/Makefile deleted file mode 100644 index dd53042e..00000000 --- a/root/package/lean/shortcut-fe/shortcut-fe/Makefile +++ /dev/null @@ -1,88 +0,0 @@ -# -# Copyright (c) 2013-2018, 2020 The Linux Foundation. All rights reserved. -# Permission to use, copy, modify, and/or distribute this software for -# any purpose with or without fee is hereby granted, provided that the -# above copyright notice and this permission notice appear in all copies. -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -include $(TOPDIR)/rules.mk -include $(INCLUDE_DIR)/kernel.mk - -PKG_NAME:=shortcut-fe -PKG_RELEASE:=8 - -include $(INCLUDE_DIR)/package.mk - -define KernelPackage/shortcut-fe - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Support - DEPENDS:=@IPV6 +kmod-nf-conntrack - TITLE:=Kernel driver for SFE - FILES:= \ - $(PKG_BUILD_DIR)/shortcut-fe.ko \ - $(PKG_BUILD_DIR)/shortcut-fe-ipv6.ko - KCONFIG:= \ - CONFIG_NF_CONNTRACK_EVENTS=y \ - CONFIG_NF_CONNTRACK_TIMEOUT=y \ - CONFIG_SHORTCUT_FE=y \ - CONFIG_XFRM=y - PROVIDES:=$(PKG_NAME) - AUTOLOAD:=$(call AutoLoad,09,shortcut-fe shortcut-fe-ipv6) -endef - -define KernelPackage/shortcut-fe/Description -Shortcut is an in-Linux-kernel IP packet forwarding engine. -endef - -define KernelPackage/shortcut-fe/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) ./files/usr/bin/sfe_dump $(1)/usr/bin -endef - -HAVE_ECM:=$(CONFIG_PACKAGE_kmod-qca-nss-ecm-premium)$(CONFIG_PACKAGE_kmod-qca-nss-ecm-noload)$(CONFIG_PACKAGE_kmod-qca-nss-ecm-premium-noload)$(CONFIG_PACKAGE_kmod-qca-nss-ecm-standard) - -define KernelPackage/shortcut-fe-cm - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Support - DEPENDS:=+kmod-ipt-conntrack +kmod-shortcut-fe - TITLE:=Kernel driver for SFE - FILES:=$(PKG_BUILD_DIR)/shortcut-fe-cm.ko - KCONFIG:= \ - CONFIG_NF_CONNTRACK_CHAIN_EVENTS=y \ - CONFIG_NF_CONNTRACK_EVENTS=y \ - CONFIG_XFRM=y - CONFLICTS:=kmod-shortcut-fe-drv -endef - -define KernelPackage/shortcut-fe-cm/Description -Simple connection manager for the Shortcut forwarding engine. -endef - -define Build/Compile - $(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \ - $(KERNEL_MAKE_FLAGS) \ - $(PKG_MAKE_FLAGS) \ - M="$(PKG_BUILD_DIR)" \ - EXTRA_CFLAGS+="-DSFE_SUPPORT_IPV6" SFE_SUPPORT_IPV6=y \ - $(if $(HAVE_ECM),EXTRA_CFLAGS+="-DCONFIG_SFE_ECM" CONFIG_SFE_ECM=y,) \ - modules -endef - -ifneq ($(CONFIG_PACKAGE_kmod-shortcut-fe)$(CONFIG_PACKAGE_kmod-shortcut-fe-cm),) -define Build/InstallDev - $(INSTALL_DIR) $(1)/usr/include/shortcut-fe - $(CP) -rf $(PKG_BUILD_DIR)/sfe.h $(1)/usr/include/shortcut-fe -endef -endif - -$(eval $(call KernelPackage,shortcut-fe)) -$(eval $(call KernelPackage,shortcut-fe-cm)) diff --git a/root/package/lean/shortcut-fe/shortcut-fe/files/etc/init.d/shortcut-fe b/root/package/lean/shortcut-fe/shortcut-fe/files/etc/init.d/shortcut-fe deleted file mode 100644 index 838512a3..00000000 --- a/root/package/lean/shortcut-fe/shortcut-fe/files/etc/init.d/shortcut-fe +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/sh /etc/rc.common -# -# Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. -# Permission to use, copy, modify, and/or distribute this software for -# any purpose with or without fee is hereby granted, provided that the -# above copyright notice and this permission notice appear in all copies. -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -#SFE connection manager has a lower priority, it should be started after other connection manager -#to detect the existence of connection manager with higher priority -START=70 - -have_cm() { - [ -d "/sys/kernel/debug/ecm" ] && echo 1 && return - - echo 0 -} - -#load shortcut-fe and connection manager -load_sfe() { - local kernel_version=$(uname -r) - - [ -d "/sys/module/shortcut_fe" ] || insmod /lib/modules/$kernel_version/shortcut-fe.ko - [ -d "/sys/module/shortcut_fe_ipv6" ] || insmod /lib/modules/$kernel_version/shortcut-fe-ipv6.ko - - [ -e "/lib/modules/$kernel_version/shortcut-fe-cm.ko" ] && { - [ -d /sys/module/shortcut_fe_cm ] || insmod /lib/modules/$kernel_version/shortcut-fe-cm.ko - } - [ -e "/lib/modules/$kernel_version/fast-classifier.ko" ] && { - [ -d /sys/module/fast_classifier ] || insmod /lib/modules/$kernel_version/fast-classifier.ko - } -} - -start() { - [ "$(have_cm)" = "0" ] && load_sfe -} - -stop() { - [ -d "/sys/module/shortcut_fe_cm" ] && rmmod shortcut_fe_cm - [ -d "/sys/module/shortcut_fe_ipv6" ] && rmmod shortcut_fe_ipv6 - [ -d "/sys/module/shortcut_fe" ] && rmmod shortcut_fe - [ -d "/sys/module/shortcut_fe_drv" ] && rmmod shortcut_fe_drv - [ -d "/sys/module/fast_classifier" ] && rmmod fast_classifier -} diff --git a/root/package/lean/shortcut-fe/shortcut-fe/files/usr/bin/sfe_dump b/root/package/lean/shortcut-fe/shortcut-fe/files/usr/bin/sfe_dump deleted file mode 100644 index 2a224e0c..00000000 --- a/root/package/lean/shortcut-fe/shortcut-fe/files/usr/bin/sfe_dump +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2015 The Linux Foundation. All rights reserved. -# Permission to use, copy, modify, and/or distribute this software for -# any purpose with or without fee is hereby granted, provided that the -# above copyright notice and this permission notice appear in all copies. -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -#@sfe_dump -#@example : sfe_dump (ipv4|ipv6) -sfe_dump(){ - [ -e "/dev/sfe_ipv4" ] || { - dev_num=$(cat /sys/sfe_ipv4/debug_dev) - mknod /dev/sfe_ipv4 c $dev_num 0 - } - [ -e "/dev/sfe_ipv6" ] || { - dev_num=$(cat /sys/sfe_ipv6/debug_dev) - mknod /dev/sfe_ipv6 c $dev_num 0 - } - cat /dev/sfe_$1 -} - -if [ -z "$1" ]; then - sfe_dump ipv4 - sfe_dump ipv6 -else - sfe_dump $1 -fi diff --git a/root/package/lean/shortcut-fe/shortcut-fe/src/Kconfig b/root/package/lean/shortcut-fe/shortcut-fe/src/Kconfig deleted file mode 100644 index 487f1e06..00000000 --- a/root/package/lean/shortcut-fe/shortcut-fe/src/Kconfig +++ /dev/null @@ -1,14 +0,0 @@ -# -# Shortcut forwarding engine -# - -config SHORTCUT_FE - tristate "Shortcut Forwarding Engine" - depends on NF_CONNTRACK - ---help--- - Shortcut is a fast in-kernel packet forwarding engine. - - To compile this code as a module, choose M here: the module will be - called shortcut-fe. - - If unsure, say N. diff --git a/root/package/lean/shortcut-fe/shortcut-fe/src/Makefile b/root/package/lean/shortcut-fe/shortcut-fe/src/Makefile deleted file mode 100644 index 991a20ec..00000000 --- a/root/package/lean/shortcut-fe/shortcut-fe/src/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -# -# Makefile for Shortcut FE. -# - -obj-m += shortcut-fe.o - -ifdef SFE_SUPPORT_IPV6 -obj-m += shortcut-fe-ipv6.o -endif - -obj-m += shortcut-fe-cm.o - -shortcut-fe-objs := \ - sfe_ipv4.o - -ifdef SFE_SUPPORT_IPV6 -shortcut-fe-ipv6-objs := \ - sfe_ipv6.o -endif - -shortcut-fe-cm-objs := \ - sfe_cm.o - -ccflags-y += -Werror -Wall diff --git a/root/package/lean/shortcut-fe/shortcut-fe/src/sfe.h b/root/package/lean/shortcut-fe/shortcut-fe/src/sfe.h deleted file mode 100644 index 279e7b3d..00000000 --- a/root/package/lean/shortcut-fe/shortcut-fe/src/sfe.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * sfe.h - * Shortcut forwarding engine. - * - * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved. - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all copies. - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - - -/* - * The following are debug macros used throughout the SFE. - * - * The DEBUG_LEVEL enables the followings based on its value, - * when dynamic debug option is disabled. - * - * 0 = OFF - * 1 = ASSERTS / ERRORS - * 2 = 1 + WARN - * 3 = 2 + INFO - * 4 = 3 + TRACE - */ -#define DEBUG_LEVEL 2 - -#if (DEBUG_LEVEL < 1) -#define DEBUG_ASSERT(s, ...) -#define DEBUG_ERROR(s, ...) -#else -#define DEBUG_ASSERT(c, s, ...) if (!(c)) { pr_emerg("ASSERT: %s:%d:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__); BUG(); } -#define DEBUG_ERROR(s, ...) pr_err("%s:%d:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) -#endif - -#if defined(CONFIG_DYNAMIC_DEBUG) -/* - * Compile messages for dynamic enable/disable - */ -#define DEBUG_WARN(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) -#define DEBUG_INFO(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) -#define DEBUG_TRACE(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) -#else - -/* - * Statically compile messages at different levels - */ -#if (DEBUG_LEVEL < 2) -#define DEBUG_WARN(s, ...) -#else -#define DEBUG_WARN(s, ...) pr_warn("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) -#endif - -#if (DEBUG_LEVEL < 3) -#define DEBUG_INFO(s, ...) -#else -#define DEBUG_INFO(s, ...) pr_notice("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) -#endif - -#if (DEBUG_LEVEL < 4) -#define DEBUG_TRACE(s, ...) -#else -#define DEBUG_TRACE(s, ...) pr_info("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) -#endif -#endif - -#ifdef CONFIG_NF_FLOW_COOKIE -typedef int (*flow_cookie_set_func_t)(u32 protocol, __be32 src_ip, __be16 src_port, - __be32 dst_ip, __be16 dst_port, u16 flow_cookie); -/* - * sfe_register_flow_cookie_cb - * register a function in SFE to let SFE use this function to configure flow cookie for a flow - * - * Hardware driver which support flow cookie should register a callback function in SFE. Then SFE - * can use this function to configure flow cookie for a flow. - * return: 0, success; !=0, fail - */ -int sfe_register_flow_cookie_cb(flow_cookie_set_func_t cb); - -/* - * sfe_unregister_flow_cookie_cb - * unregister function which is used to configure flow cookie for a flow - * - * return: 0, success; !=0, fail - */ -int sfe_unregister_flow_cookie_cb(flow_cookie_set_func_t cb); - -typedef int (*sfe_ipv6_flow_cookie_set_func_t)(u32 protocol, __be32 src_ip[4], __be16 src_port, - __be32 dst_ip[4], __be16 dst_port, u16 flow_cookie); - -/* - * sfe_ipv6_register_flow_cookie_cb - * register a function in SFE to let SFE use this function to configure flow cookie for a flow - * - * Hardware driver which support flow cookie should register a callback function in SFE. Then SFE - * can use this function to configure flow cookie for a flow. - * return: 0, success; !=0, fail - */ -int sfe_ipv6_register_flow_cookie_cb(sfe_ipv6_flow_cookie_set_func_t cb); - -/* - * sfe_ipv6_unregister_flow_cookie_cb - * unregister function which is used to configure flow cookie for a flow - * - * return: 0, success; !=0, fail - */ -int sfe_ipv6_unregister_flow_cookie_cb(sfe_ipv6_flow_cookie_set_func_t cb); - -#endif /*CONFIG_NF_FLOW_COOKIE*/ diff --git a/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_backport.h b/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_backport.h deleted file mode 100644 index d2d60c73..00000000 --- a/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_backport.h +++ /dev/null @@ -1,195 +0,0 @@ -/* - * sfe_backport.h - * Shortcut forwarding engine compatible header file. - * - * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all copies. - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) -#include -#else -enum udp_conntrack { - UDP_CT_UNREPLIED, - UDP_CT_REPLIED, - UDP_CT_MAX -}; - -static inline unsigned int * -nf_ct_timeout_lookup(struct net *net, struct nf_conn *ct, - struct nf_conntrack_l4proto *l4proto) -{ -#ifdef CONFIG_NF_CONNTRACK_TIMEOUT - struct nf_conn_timeout *timeout_ext; - unsigned int *timeouts; - - timeout_ext = nf_ct_timeout_find(ct); - if (timeout_ext) - timeouts = NF_CT_TIMEOUT_EXT_DATA(timeout_ext); - else - timeouts = l4proto->get_timeouts(net); - - return timeouts; -#else - return l4proto->get_timeouts(net); -#endif /*CONFIG_NF_CONNTRACK_TIMEOUT*/ -} -#endif /*KERNEL_VERSION(3, 7, 0)*/ -#endif /*KERNEL_VERSION(3, 4, 0)*/ - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) -#define sfe_define_post_routing_hook(FN_NAME, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ -static unsigned int FN_NAME(void *priv, \ - struct sk_buff *SKB, \ - const struct nf_hook_state *state) -#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) -#define sfe_define_post_routing_hook(FN_NAME, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ -static unsigned int FN_NAME(const struct nf_hook_ops *OPS, \ - struct sk_buff *SKB, \ - const struct net_device *UNUSED, \ - const struct net_device *OUT, \ - int (*OKFN)(struct sk_buff *)) -#else -#define sfe_define_post_routing_hook(FN_NAME, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ -static unsigned int FN_NAME(unsigned int HOOKNUM, \ - struct sk_buff *SKB, \ - const struct net_device *UNUSED, \ - const struct net_device *OUT, \ - int (*OKFN)(struct sk_buff *)) -#endif - -#define sfe_cm_ipv4_post_routing_hook(HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ - sfe_define_post_routing_hook(__sfe_cm_ipv4_post_routing_hook, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) -#define sfe_cm_ipv6_post_routing_hook(HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ - sfe_define_post_routing_hook(__sfe_cm_ipv6_post_routing_hook, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) -#define fast_classifier_ipv4_post_routing_hook(HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ - sfe_define_post_routing_hook(__fast_classifier_ipv4_post_routing_hook, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) -#define fast_classifier_ipv6_post_routing_hook(HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ - sfe_define_post_routing_hook(__fast_classifier_ipv6_post_routing_hook, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) -#define SFE_IPV4_NF_POST_ROUTING_HOOK(fn) \ - { \ - .hook = fn, \ - .pf = NFPROTO_IPV4, \ - .hooknum = NF_INET_POST_ROUTING, \ - .priority = NF_IP_PRI_NAT_SRC + 1, \ - } -#else -#define SFE_IPV4_NF_POST_ROUTING_HOOK(fn) \ - { \ - .hook = fn, \ - .owner = THIS_MODULE, \ - .pf = NFPROTO_IPV4, \ - .hooknum = NF_INET_POST_ROUTING, \ - .priority = NF_IP_PRI_NAT_SRC + 1, \ - } -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) -#define SFE_IPV6_NF_POST_ROUTING_HOOK(fn) \ - { \ - .hook = fn, \ - .pf = NFPROTO_IPV6, \ - .hooknum = NF_INET_POST_ROUTING, \ - .priority = NF_IP_PRI_NAT_SRC + 1, \ - } -#else -#define SFE_IPV6_NF_POST_ROUTING_HOOK(fn) \ - { \ - .hook = fn, \ - .owner = THIS_MODULE, \ - .pf = NFPROTO_IPV6, \ - .hooknum = NF_INET_POST_ROUTING, \ - .priority = NF_IP6_PRI_NAT_SRC + 1, \ - } -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0)) -#define SFE_NF_CT_DEFAULT_ZONE (&nf_ct_zone_dflt) -#else -#define SFE_NF_CT_DEFAULT_ZONE NF_CT_DEFAULT_ZONE -#endif - -/* - * sfe_dev_get_master - * get master of bridge port, and hold it - */ -static inline struct net_device *sfe_dev_get_master(struct net_device *dev) -{ - struct net_device *master; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) - rcu_read_lock(); - master = netdev_master_upper_dev_get_rcu(dev); - if (master) - dev_hold(master); - - rcu_read_unlock(); -#else - master = dev->master; - if (master) - dev_hold(master); -#endif - return master; -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) -#define SFE_DEV_EVENT_PTR(PTR) netdev_notifier_info_to_dev(PTR) -#else -#define SFE_DEV_EVENT_PTR(PTR) (struct net_device *)(PTR) -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) -#define SFE_NF_CONN_ACCT(NM) struct nf_conn_acct *NM -#else -#define SFE_NF_CONN_ACCT(NM) struct nf_conn_counter *NM -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) -#define SFE_ACCT_COUNTER(NM) ((NM)->counter) -#else -#define SFE_ACCT_COUNTER(NM) (NM) -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) -#define sfe_hash_for_each_possible(name, obj, node, member, key) \ - hash_for_each_possible(name, obj, member, key) -#else -#define sfe_hash_for_each_possible(name, obj, node, member, key) \ - hash_for_each_possible(name, obj, node, member, key) -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) -#define sfe_hash_for_each(name, bkt, node, obj, member) \ - hash_for_each(name, bkt, obj, member) -#else -#define sfe_hash_for_each(name, bkt, node, obj, member) \ - hash_for_each(name, bkt, node, obj, member) -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) -#define sfe_dst_get_neighbour(dst, daddr) dst_neigh_lookup(dst, addr) -#else -static inline struct neighbour * -sfe_dst_get_neighbour(struct dst_entry *dst, void *daddr) -{ - struct neighbour *neigh = dst_get_neighbour_noref(dst); - - if (neigh) - neigh_hold(neigh); - - return neigh; -} -#endif diff --git a/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_cm.c b/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_cm.c deleted file mode 100644 index 2d3f79a0..00000000 --- a/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_cm.c +++ /dev/null @@ -1,1210 +0,0 @@ -/* - * sfe-cm.c - * Shortcut forwarding engine connection manager. - * - * Copyright (c) 2013-2018, 2020 The Linux Foundation. All rights reserved. - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all copies. - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sfe.h" -#include "sfe_cm.h" -#include "sfe_backport.h" - -typedef enum sfe_cm_exception { - SFE_CM_EXCEPTION_PACKET_BROADCAST, - SFE_CM_EXCEPTION_PACKET_MULTICAST, - SFE_CM_EXCEPTION_NO_IIF, - SFE_CM_EXCEPTION_NO_CT, - SFE_CM_EXCEPTION_CT_NO_TRACK, - SFE_CM_EXCEPTION_CT_NO_CONFIRM, - SFE_CM_EXCEPTION_CT_IS_ALG, - SFE_CM_EXCEPTION_IS_IPV4_MCAST, - SFE_CM_EXCEPTION_IS_IPV6_MCAST, - SFE_CM_EXCEPTION_TCP_NOT_ASSURED, - SFE_CM_EXCEPTION_TCP_NOT_ESTABLISHED, - SFE_CM_EXCEPTION_UNKNOW_PROTOCOL, - SFE_CM_EXCEPTION_NO_SRC_DEV, - SFE_CM_EXCEPTION_NO_SRC_XLATE_DEV, - SFE_CM_EXCEPTION_NO_DEST_DEV, - SFE_CM_EXCEPTION_NO_DEST_XLATE_DEV, - SFE_CM_EXCEPTION_NO_BRIDGE, - SFE_CM_EXCEPTION_LOCAL_OUT, - SFE_CM_EXCEPTION_MAX -} sfe_cm_exception_t; - -static char *sfe_cm_exception_events_string[SFE_CM_EXCEPTION_MAX] = { - "PACKET_BROADCAST", - "PACKET_MULTICAST", - "NO_IIF", - "NO_CT", - "CT_NO_TRACK", - "CT_NO_CONFIRM", - "CT_IS_ALG", - "IS_IPV4_MCAST", - "IS_IPV6_MCAST", - "TCP_NOT_ASSURED", - "TCP_NOT_ESTABLISHED", - "UNKNOW_PROTOCOL", - "NO_SRC_DEV", - "NO_SRC_XLATE_DEV", - "NO_DEST_DEV", - "NO_DEST_XLATE_DEV", - "NO_BRIDGE", - "LOCAL_OUT" -}; - -/* - * Per-module structure. - */ -struct sfe_cm { - spinlock_t lock; /* Lock for SMP correctness */ - - /* - * Control state. - */ - struct kobject *sys_sfe_cm; /* sysfs linkage */ - - /* - * Callback notifiers. - */ - struct notifier_block dev_notifier; /* Device notifier */ - struct notifier_block inet_notifier; /* IPv4 notifier */ - struct notifier_block inet6_notifier; /* IPv6 notifier */ - u32 exceptions[SFE_CM_EXCEPTION_MAX]; -}; - -static struct sfe_cm __sc; - -/* - * sfe_cm_incr_exceptions() - * increase an exception counter. - */ -static inline void sfe_cm_incr_exceptions(sfe_cm_exception_t except) -{ - struct sfe_cm *sc = &__sc; - - spin_lock_bh(&sc->lock); - sc->exceptions[except]++; - spin_unlock_bh(&sc->lock); -} - -/* - * sfe_cm_recv() - * Handle packet receives. - * - * Returns 1 if the packet is forwarded or 0 if it isn't. - */ -int sfe_cm_recv(struct sk_buff *skb) -{ - struct net_device *dev; - - /* - * We know that for the vast majority of packets we need the transport - * layer header so we may as well start to fetch it now! - */ - prefetch(skb->data + 32); - barrier(); - - dev = skb->dev; - - /* - * We're only interested in IPv4 and IPv6 packets. - */ - if (likely(htons(ETH_P_IP) == skb->protocol)) { - struct in_device *in_dev; - - /* - * Does our input device support IP processing? - */ - in_dev = (struct in_device *)dev->ip_ptr; - if (unlikely(!in_dev)) { - DEBUG_TRACE("no IP processing for device: %s\n", dev->name); - return 0; - } - - /* - * Does it have an IP address? If it doesn't then we can't do anything - * interesting here! - */ - if (unlikely(!in_dev->ifa_list)) { - DEBUG_TRACE("no IP address for device: %s\n", dev->name); - return 0; - } - - return sfe_ipv4_recv(dev, skb); - } - - if (likely(htons(ETH_P_IPV6) == skb->protocol)) { - struct inet6_dev *in_dev; - - /* - * Does our input device support IPv6 processing? - */ - in_dev = (struct inet6_dev *)dev->ip6_ptr; - if (unlikely(!in_dev)) { - DEBUG_TRACE("no IPv6 processing for device: %s\n", dev->name); - return 0; - } - - /* - * Does it have an IPv6 address? If it doesn't then we can't do anything - * interesting here! - */ - if (unlikely(list_empty(&in_dev->addr_list))) { - DEBUG_TRACE("no IPv6 address for device: %s\n", dev->name); - return 0; - } - - return sfe_ipv6_recv(dev, skb); - } - - DEBUG_TRACE("not IP packet\n"); - return 0; -} - -/* - * sfe_cm_find_dev_and_mac_addr() - * Find the device and MAC address for a given IPv4/IPv6 address. - * - * Returns true if we find the device and MAC address, otherwise false. - * - * We look up the rtable entry for the address and, from its neighbour - * structure, obtain the hardware address. This means this function also - * works if the neighbours are routers too. - */ -static bool sfe_cm_find_dev_and_mac_addr(struct sk_buff *skb, sfe_ip_addr_t *addr, struct net_device **dev, u8 *mac_addr, int is_v4) -{ - struct neighbour *neigh; - struct rtable *rt; - struct rt6_info *rt6; - struct dst_entry *dst; - struct net_device *mac_dev; - - /* - * If we have skb provided, use it as the original code is unable - * to lookup routes that are policy routed. - */ - if (unlikely(skb)) { - dst = skb_dst(skb); - goto skip_dst_lookup; - } - - /* - * Look up the rtable entry for the IP address then get the hardware - * address from its neighbour structure. This means this work when the - * neighbours are routers too. - */ - if (likely(is_v4)) { - rt = ip_route_output(&init_net, addr->ip, 0, 0, 0); - if (unlikely(IS_ERR(rt))) { - goto ret_fail; - } - - dst = (struct dst_entry *)rt; - } else { -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0)) - rt6 = rt6_lookup(&init_net, (struct in6_addr *)addr->ip6, 0, 0, 0); -#else - rt6 = rt6_lookup(&init_net, (struct in6_addr *)addr->ip6, 0, 0, NULL, 0); -#endif - if (!rt6) { - goto ret_fail; - } - - dst = (struct dst_entry *)rt6; - } - -skip_dst_lookup: - rcu_read_lock(); - neigh = sfe_dst_get_neighbour(dst, addr); - if (unlikely(!neigh)) { - rcu_read_unlock(); - if (likely(!skb)) - dst_release(dst); - goto ret_fail; - } - - if (unlikely(!(neigh->nud_state & NUD_VALID))) { - rcu_read_unlock(); - neigh_release(neigh); - if (likely(!skb)) - dst_release(dst); - goto ret_fail; - } - - mac_dev = neigh->dev; - if (!mac_dev) { - rcu_read_unlock(); - neigh_release(neigh); - if (likely(!skb)) - dst_release(dst); - goto ret_fail; - } - - memcpy(mac_addr, neigh->ha, (size_t)mac_dev->addr_len); - - dev_hold(mac_dev); - *dev = mac_dev; - rcu_read_unlock(); - neigh_release(neigh); - if (likely(!skb)) - dst_release(dst); - - return true; - -ret_fail: - if (is_v4) { - DEBUG_TRACE("failed to find MAC address for IP: %pI4\n", &addr->ip); - - } else { - DEBUG_TRACE("failed to find MAC address for IP: %pI6\n", addr->ip6); - } - - return false; -} - -/* - * sfe_cm_post_routing() - * Called for packets about to leave the box - either locally generated or forwarded from another interface - */ -static unsigned int sfe_cm_post_routing(struct sk_buff *skb, int is_v4) -{ - struct sfe_connection_create sic; - struct net_device *in; - struct nf_conn *ct; - enum ip_conntrack_info ctinfo; - struct net_device *dev; - struct net_device *src_dev; - struct net_device *dest_dev; - struct net_device *src_dev_tmp; - struct net_device *dest_dev_tmp; - struct net_device *src_br_dev = NULL; - struct net_device *dest_br_dev = NULL; - struct nf_conntrack_tuple orig_tuple; - struct nf_conntrack_tuple reply_tuple; - struct sk_buff *tmp_skb = NULL; - SFE_NF_CONN_ACCT(acct); - - #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) - struct net *net=NULL; - struct nf_tcp_net *tn=NULL; - #endif - - /* - * Don't process broadcast or multicast packets. - */ - if (unlikely(skb->pkt_type == PACKET_BROADCAST)) { - sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_PACKET_BROADCAST); - DEBUG_TRACE("broadcast, ignoring\n"); - return NF_ACCEPT; - } - if (unlikely(skb->pkt_type == PACKET_MULTICAST)) { - sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_PACKET_MULTICAST); - DEBUG_TRACE("multicast, ignoring\n"); - return NF_ACCEPT; - } - -#ifdef CONFIG_XFRM - /* - * Packet to xfrm for encapsulation, we can't process it - */ - if (unlikely(skb_dst(skb)->xfrm)) { - DEBUG_TRACE("packet to xfrm, ignoring\n"); - return NF_ACCEPT; - } -#endif - - /* - * Don't process locally generated packets. - */ - if (skb->sk) { - sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_LOCAL_OUT); - DEBUG_TRACE("skip local out packet\n"); - return NF_ACCEPT; - } - - /* - * Don't process packets that are not being forwarded. - */ - in = dev_get_by_index(&init_net, skb->skb_iif); - if (!in) { - sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_IIF); - DEBUG_TRACE("packet not forwarding\n"); - return NF_ACCEPT; - } - - dev_put(in); - - /* - * Don't process packets that aren't being tracked by conntrack. - */ - ct = nf_ct_get(skb, &ctinfo); - if (unlikely(!ct)) { - sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_CT); - DEBUG_TRACE("no conntrack connection, ignoring\n"); - return NF_ACCEPT; - } - - /* - * Don't process untracked connections. - */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) - if (unlikely(nf_ct_is_untracked(ct))) { -#else - if (unlikely(ctinfo == IP_CT_UNTRACKED)) { -#endif - sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_CT_NO_TRACK); - DEBUG_TRACE("untracked connection\n"); - return NF_ACCEPT; - } - - /* - * Unconfirmed connection may be dropped by Linux at the final step, - * So we don't process unconfirmed connections. - */ - if (!nf_ct_is_confirmed(ct)) { - sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_CT_NO_CONFIRM); - DEBUG_TRACE("unconfirmed connection\n"); - return NF_ACCEPT; - } - - /* - * Don't process connections that require support from a 'helper' (typically a NAT ALG). - */ - if (unlikely(nfct_help(ct))) { - sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_CT_IS_ALG); - DEBUG_TRACE("connection has helper\n"); - return NF_ACCEPT; - } - - /* - * Check if the acceleration of a flow could be rejected quickly. - */ - acct = nf_conn_acct_find(ct); - if (acct) { - long long packets = atomic64_read(&SFE_ACCT_COUNTER(acct)[CTINFO2DIR(ctinfo)].packets); - if ((packets > 0xff) && (packets & 0xff)) { - /* - * Connection hits slow path at least 256 times, so it must be not able to accelerate. - * But we also give it a chance to walk through ECM every 256 packets - */ - return NF_ACCEPT; - } - } - - /* - * Look up the details of our connection in conntrack. - * - * Note that the data we get from conntrack is for the "ORIGINAL" direction - * but our packet may actually be in the "REPLY" direction. - */ - orig_tuple = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; - reply_tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple; - sic.protocol = (s32)orig_tuple.dst.protonum; - - sic.flags = 0; - - /* - * Get addressing information, non-NAT first - */ - if (likely(is_v4)) { - u32 dscp; - - sic.src_ip.ip = (__be32)orig_tuple.src.u3.ip; - sic.dest_ip.ip = (__be32)orig_tuple.dst.u3.ip; - - if (ipv4_is_multicast(sic.src_ip.ip) || ipv4_is_multicast(sic.dest_ip.ip)) { - sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_IS_IPV4_MCAST); - DEBUG_TRACE("multicast address\n"); - return NF_ACCEPT; - } - - /* - * NAT'ed addresses - note these are as seen from the 'reply' direction - * When NAT does not apply to this connection these will be identical to the above. - */ - sic.src_ip_xlate.ip = (__be32)reply_tuple.dst.u3.ip; - sic.dest_ip_xlate.ip = (__be32)reply_tuple.src.u3.ip; - - dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT; - if (dscp) { - sic.dest_dscp = dscp; - sic.src_dscp = sic.dest_dscp; - sic.flags |= SFE_CREATE_FLAG_REMARK_DSCP; - } - } else { - u32 dscp; - - sic.src_ip.ip6[0] = *((struct sfe_ipv6_addr *)&orig_tuple.src.u3.in6); - sic.dest_ip.ip6[0] = *((struct sfe_ipv6_addr *)&orig_tuple.dst.u3.in6); - - if (ipv6_addr_is_multicast((struct in6_addr *)sic.src_ip.ip6) || - ipv6_addr_is_multicast((struct in6_addr *)sic.dest_ip.ip6)) { - sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_IS_IPV6_MCAST); - DEBUG_TRACE("multicast address\n"); - return NF_ACCEPT; - } - - /* - * NAT'ed addresses - note these are as seen from the 'reply' direction - * When NAT does not apply to this connection these will be identical to the above. - */ - sic.src_ip_xlate.ip6[0] = *((struct sfe_ipv6_addr *)&reply_tuple.dst.u3.in6); - sic.dest_ip_xlate.ip6[0] = *((struct sfe_ipv6_addr *)&reply_tuple.src.u3.in6); - - dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT; - if (dscp) { - sic.dest_dscp = dscp; - sic.src_dscp = sic.dest_dscp; - sic.flags |= SFE_CREATE_FLAG_REMARK_DSCP; - } - } - - switch (sic.protocol) { - case IPPROTO_TCP: - sic.src_port = orig_tuple.src.u.tcp.port; - sic.dest_port = orig_tuple.dst.u.tcp.port; - sic.src_port_xlate = reply_tuple.dst.u.tcp.port; - sic.dest_port_xlate = reply_tuple.src.u.tcp.port; - sic.src_td_window_scale = ct->proto.tcp.seen[0].td_scale; - sic.src_td_max_window = ct->proto.tcp.seen[0].td_maxwin; - sic.src_td_end = ct->proto.tcp.seen[0].td_end; - sic.src_td_max_end = ct->proto.tcp.seen[0].td_maxend; - sic.dest_td_window_scale = ct->proto.tcp.seen[1].td_scale; - sic.dest_td_max_window = ct->proto.tcp.seen[1].td_maxwin; - sic.dest_td_end = ct->proto.tcp.seen[1].td_end; - sic.dest_td_max_end = ct->proto.tcp.seen[1].td_maxend; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) - net = nf_ct_net(ct); - tn = nf_tcp_pernet(net); - if ((tn&&tn->tcp_no_window_check) -#else - if (nf_ct_tcp_no_window_check -#endif - || (ct->proto.tcp.seen[0].flags & IP_CT_TCP_FLAG_BE_LIBERAL) - || (ct->proto.tcp.seen[1].flags & IP_CT_TCP_FLAG_BE_LIBERAL)) { - sic.flags |= SFE_CREATE_FLAG_NO_SEQ_CHECK; - } - - /* - * Don't try to manage a non-established connection. - */ - if (!test_bit(IPS_ASSURED_BIT, &ct->status)) { - sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_TCP_NOT_ASSURED); - DEBUG_TRACE("non-established connection\n"); - return NF_ACCEPT; - } - - /* - * If the connection is shutting down do not manage it. - * state can not be SYN_SENT, SYN_RECV because connection is assured - * Not managed states: FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE. - */ - spin_lock_bh(&ct->lock); - if (ct->proto.tcp.state != TCP_CONNTRACK_ESTABLISHED) { - spin_unlock_bh(&ct->lock); - sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_TCP_NOT_ESTABLISHED); - DEBUG_TRACE("connection in termination state: %#x, s: %pI4:%u, d: %pI4:%u\n", - ct->proto.tcp.state, &sic.src_ip, ntohs(sic.src_port), - &sic.dest_ip, ntohs(sic.dest_port)); - return NF_ACCEPT; - } - spin_unlock_bh(&ct->lock); - - /* - * Somehow, SFE is not playing nice with IPSec traffic. - * Do not accelerate for now. - */ - if (ntohs(sic.dest_port) == 4500 || ntohs(sic.dest_port) == 500) { - if (likely(is_v4)) - DEBUG_TRACE("IPsec bypass: %pI4:%d(%pI4:%d) to %pI4:%d(%pI4:%d)\n", - &sic.src_ip.ip, ntohs(sic.src_port), &sic.src_ip_xlate.ip, ntohs(sic.src_port_xlate), - &sic.dest_ip.ip, ntohs(sic.dest_port), &sic.dest_ip_xlate.ip, ntohs(sic.dest_port_xlate)); - else - DEBUG_TRACE("IPsec bypass: %pI6:%d to %pI6:%d\n", - &sic.src_ip.ip6, ntohs(sic.src_port), &sic.dest_ip.ip6, ntohs(sic.dest_port)); - return NF_ACCEPT; - } - break; - - case IPPROTO_UDP: - sic.src_port = orig_tuple.src.u.udp.port; - sic.dest_port = orig_tuple.dst.u.udp.port; - sic.src_port_xlate = reply_tuple.dst.u.udp.port; - sic.dest_port_xlate = reply_tuple.src.u.udp.port; - break; - - default: - sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_UNKNOW_PROTOCOL); - DEBUG_TRACE("unhandled protocol %d\n", sic.protocol); - return NF_ACCEPT; - } - -#ifdef CONFIG_XFRM - sic.original_accel = 1; - sic.reply_accel = 1; - - /* - * For packets de-capsulated from xfrm, we still can accelerate it - * on the direction we just received the packet. - */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)) - if (unlikely(skb->sp)) { -#else - if (unlikely(secpath_exists(skb))) { -#endif - if (sic.protocol == IPPROTO_TCP && - !(sic.flags & SFE_CREATE_FLAG_NO_SEQ_CHECK)) { - return NF_ACCEPT; - } - - if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) { - sic.reply_accel = 0; - } else { - sic.original_accel = 0; - } - } -#endif - - /* - * Get QoS information - */ - if (skb->priority) { - sic.dest_priority = skb->priority; - sic.src_priority = sic.dest_priority; - sic.flags |= SFE_CREATE_FLAG_REMARK_PRIORITY; - } - - /* - * Get the net device and MAC addresses that correspond to the various source and - * destination host addresses. - */ - if (!sfe_cm_find_dev_and_mac_addr(NULL, &sic.src_ip, &src_dev_tmp, sic.src_mac, is_v4)) { - sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_SRC_DEV); - return NF_ACCEPT; - } - src_dev = src_dev_tmp; - - if (!sfe_cm_find_dev_and_mac_addr(NULL, &sic.src_ip_xlate, &dev, sic.src_mac_xlate, is_v4)) { - sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_SRC_XLATE_DEV); - goto done1; - } - dev_put(dev); - /* Somehow, for IPv6, we need this workaround as well */ - if (unlikely(!is_v4)) - tmp_skb = skb; - if (!sfe_cm_find_dev_and_mac_addr(tmp_skb, &sic.dest_ip, &dev, sic.dest_mac, is_v4)) { - sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_DEST_DEV); - goto done1; - } - dev_put(dev); - - if (!sfe_cm_find_dev_and_mac_addr(skb, &sic.dest_ip_xlate, &dest_dev_tmp, sic.dest_mac_xlate, is_v4)) { - sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_DEST_XLATE_DEV); - goto done1; - } - dest_dev = dest_dev_tmp; - - /* - * Our devices may actually be part of a bridge interface. If that's - * the case then find the bridge interface instead. - */ - if (src_dev->priv_flags & IFF_BRIDGE_PORT) { - src_br_dev = sfe_dev_get_master(src_dev); - if (!src_br_dev) { - sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_BRIDGE); - DEBUG_TRACE("no bridge found for: %s\n", src_dev->name); - goto done2; - } - src_dev = src_br_dev; - } - - if (dest_dev->priv_flags & IFF_BRIDGE_PORT) { - dest_br_dev = sfe_dev_get_master(dest_dev); - if (!dest_br_dev) { - sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_BRIDGE); - DEBUG_TRACE("no bridge found for: %s\n", dest_dev->name); - goto done3; - } - dest_dev = dest_br_dev; - } - - sic.src_dev = src_dev; - sic.dest_dev = dest_dev; - - sic.src_mtu = src_dev->mtu; - sic.dest_mtu = dest_dev->mtu; - - if (likely(is_v4)) { - sfe_ipv4_create_rule(&sic); - } else { - sfe_ipv6_create_rule(&sic); - } - - /* - * If we had bridge ports then release them too. - */ - if (dest_br_dev) { - dev_put(dest_br_dev); - } -done3: - if (src_br_dev) { - dev_put(src_br_dev); - } -done2: - dev_put(dest_dev_tmp); -done1: - dev_put(src_dev_tmp); - - return NF_ACCEPT; -} - -/* - * sfe_cm_ipv4_post_routing_hook() - * Called for packets about to leave the box - either locally generated or forwarded from another interface - */ -sfe_cm_ipv4_post_routing_hook(hooknum, ops, skb, in_unused, out, okfn) -{ - return sfe_cm_post_routing(skb, true); -} - -/* - * sfe_cm_ipv6_post_routing_hook() - * Called for packets about to leave the box - either locally generated or forwarded from another interface - */ -sfe_cm_ipv6_post_routing_hook(hooknum, ops, skb, in_unused, out, okfn) -{ - return sfe_cm_post_routing(skb, false); -} - -#ifdef CONFIG_NF_CONNTRACK_EVENTS -/* - * sfe_cm_conntrack_event() - * Callback event invoked when a conntrack connection's state changes. - */ -#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS -static int sfe_cm_conntrack_event(struct notifier_block *this, - unsigned long events, void *ptr) -#else -static int sfe_cm_conntrack_event(unsigned int events, struct nf_ct_event *item) -#endif -{ -#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS - struct nf_ct_event *item = ptr; -#endif - struct sfe_connection_destroy sid; - struct nf_conn *ct = item->ct; - struct nf_conntrack_tuple orig_tuple; - - /* - * If we don't have a conntrack entry then we're done. - */ - if (unlikely(!ct)) { - DEBUG_WARN("no ct in conntrack event callback\n"); - return NOTIFY_DONE; - } - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) - if (unlikely(nf_ct_is_untracked(ct))) { - DEBUG_TRACE("ignoring untracked conn\n"); - return NOTIFY_DONE; - } -#endif - - /* - * We're only interested in destroy events. - */ - if (unlikely(!(events & (1 << IPCT_DESTROY)))) { - DEBUG_TRACE("ignoring non-destroy event\n"); - return NOTIFY_DONE; - } - - orig_tuple = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; - sid.protocol = (s32)orig_tuple.dst.protonum; - - /* - * Extract information from the conntrack connection. We're only interested - * in nominal connection information (i.e. we're ignoring any NAT information). - */ - switch (sid.protocol) { - case IPPROTO_TCP: - sid.src_port = orig_tuple.src.u.tcp.port; - sid.dest_port = orig_tuple.dst.u.tcp.port; - break; - - case IPPROTO_UDP: - sid.src_port = orig_tuple.src.u.udp.port; - sid.dest_port = orig_tuple.dst.u.udp.port; - break; - - default: - DEBUG_TRACE("unhandled protocol: %d\n", sid.protocol); - return NOTIFY_DONE; - } - - if (likely(nf_ct_l3num(ct) == AF_INET)) { - sid.src_ip.ip = (__be32)orig_tuple.src.u3.ip; - sid.dest_ip.ip = (__be32)orig_tuple.dst.u3.ip; - - sfe_ipv4_destroy_rule(&sid); - } else if (likely(nf_ct_l3num(ct) == AF_INET6)) { - sid.src_ip.ip6[0] = *((struct sfe_ipv6_addr *)&orig_tuple.src.u3.in6); - sid.dest_ip.ip6[0] = *((struct sfe_ipv6_addr *)&orig_tuple.dst.u3.in6); - - sfe_ipv6_destroy_rule(&sid); - } else { - DEBUG_TRACE("ignoring non-IPv4 and non-IPv6 connection\n"); - } - - return NOTIFY_DONE; -} - -/* - * Netfilter conntrack event system to monitor connection tracking changes - */ -#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS -static struct notifier_block sfe_cm_conntrack_notifier = { - .notifier_call = sfe_cm_conntrack_event, -}; -#else -static struct nf_ct_event_notifier sfe_cm_conntrack_notifier = { - .fcn = sfe_cm_conntrack_event, -}; -#endif -#endif - -/* - * Structure to establish a hook into the post routing netfilter point - this - * will pick up local outbound and packets going from one interface to another. - * - * Note: see include/linux/netfilter_ipv4.h for info related to priority levels. - * We want to examine packets after NAT translation and any ALG processing. - */ -static struct nf_hook_ops sfe_cm_ops_post_routing[] __read_mostly = { - SFE_IPV4_NF_POST_ROUTING_HOOK(__sfe_cm_ipv4_post_routing_hook), -#ifdef SFE_SUPPORT_IPV6 - SFE_IPV6_NF_POST_ROUTING_HOOK(__sfe_cm_ipv6_post_routing_hook), -#endif -}; - -/* - * sfe_cm_sync_rule() - * Synchronize a connection's state. - */ -static void sfe_cm_sync_rule(struct sfe_connection_sync *sis) -{ - struct nf_conntrack_tuple_hash *h; - struct nf_conntrack_tuple tuple; - struct nf_conn *ct; - SFE_NF_CONN_ACCT(acct); - - /* - * Create a tuple so as to be able to look up a connection - */ - memset(&tuple, 0, sizeof(tuple)); - tuple.src.u.all = (__be16)sis->src_port; - tuple.dst.dir = IP_CT_DIR_ORIGINAL; - tuple.dst.protonum = (u8)sis->protocol; - tuple.dst.u.all = (__be16)sis->dest_port; - - if (sis->is_v6) { - tuple.src.u3.in6 = *((struct in6_addr *)sis->src_ip.ip6); - tuple.dst.u3.in6 = *((struct in6_addr *)sis->dest_ip.ip6); - tuple.src.l3num = AF_INET6; - - DEBUG_TRACE("update connection - p: %d, s: %pI6:%u, d: %pI6:%u\n", - (int)tuple.dst.protonum, - &tuple.src.u3.in6, (unsigned int)ntohs(tuple.src.u.all), - &tuple.dst.u3.in6, (unsigned int)ntohs(tuple.dst.u.all)); - } else { - tuple.src.u3.ip = sis->src_ip.ip; - tuple.dst.u3.ip = sis->dest_ip.ip; - tuple.src.l3num = AF_INET; - - DEBUG_TRACE("update connection - p: %d, s: %pI4:%u, d: %pI4:%u\n", - (int)tuple.dst.protonum, - &tuple.src.u3.ip, (unsigned int)ntohs(tuple.src.u.all), - &tuple.dst.u3.ip, (unsigned int)ntohs(tuple.dst.u.all)); - } - - /* - * Look up conntrack connection - */ - h = nf_conntrack_find_get(&init_net, SFE_NF_CT_DEFAULT_ZONE, &tuple); - if (unlikely(!h)) { - DEBUG_TRACE("no connection found\n"); - return; - } - - ct = nf_ct_tuplehash_to_ctrack(h); -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)) - NF_CT_ASSERT(ct->timeout.data == (unsigned long)ct); -#endif - /* - * Only update if this is not a fixed timeout - */ - if (!test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) { - spin_lock_bh(&ct->lock); -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)) - ct->timeout.expires += sis->delta_jiffies; -#else - ct->timeout += sis->delta_jiffies; -#endif - spin_unlock_bh(&ct->lock); - } - - acct = nf_conn_acct_find(ct); - if (acct) { - spin_lock_bh(&ct->lock); - atomic64_add(sis->src_new_packet_count, &SFE_ACCT_COUNTER(acct)[IP_CT_DIR_ORIGINAL].packets); - atomic64_add(sis->src_new_byte_count, &SFE_ACCT_COUNTER(acct)[IP_CT_DIR_ORIGINAL].bytes); - atomic64_add(sis->dest_new_packet_count, &SFE_ACCT_COUNTER(acct)[IP_CT_DIR_REPLY].packets); - atomic64_add(sis->dest_new_byte_count, &SFE_ACCT_COUNTER(acct)[IP_CT_DIR_REPLY].bytes); - spin_unlock_bh(&ct->lock); - } - - switch (sis->protocol) { - case IPPROTO_TCP: - spin_lock_bh(&ct->lock); - if (ct->proto.tcp.seen[0].td_maxwin < sis->src_td_max_window) { - ct->proto.tcp.seen[0].td_maxwin = sis->src_td_max_window; - } - if ((s32)(ct->proto.tcp.seen[0].td_end - sis->src_td_end) < 0) { - ct->proto.tcp.seen[0].td_end = sis->src_td_end; - } - if ((s32)(ct->proto.tcp.seen[0].td_maxend - sis->src_td_max_end) < 0) { - ct->proto.tcp.seen[0].td_maxend = sis->src_td_max_end; - } - if (ct->proto.tcp.seen[1].td_maxwin < sis->dest_td_max_window) { - ct->proto.tcp.seen[1].td_maxwin = sis->dest_td_max_window; - } - if ((s32)(ct->proto.tcp.seen[1].td_end - sis->dest_td_end) < 0) { - ct->proto.tcp.seen[1].td_end = sis->dest_td_end; - } - if ((s32)(ct->proto.tcp.seen[1].td_maxend - sis->dest_td_max_end) < 0) { - ct->proto.tcp.seen[1].td_maxend = sis->dest_td_max_end; - } - spin_unlock_bh(&ct->lock); - break; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) - case IPPROTO_UDP: - /* - * In Linux connection track, UDP flow has two timeout values: - * /proc/sys/net/netfilter/nf_conntrack_udp_timeout: - * this is for uni-direction UDP flow, normally its value is 60 seconds - * /proc/sys/net/netfilter/nf_conntrack_udp_timeout_stream: - * this is for bi-direction UDP flow, normally its value is 180 seconds - * - * Linux will update timer of UDP flow to stream timeout once it seen packets - * in reply direction. But if flow is accelerated by NSS or SFE, Linux won't - * see any packets. So we have to do the same thing in our stats sync message. - */ - if (!test_bit(IPS_ASSURED_BIT, &ct->status) && acct) { - u_int64_t reply_pkts = atomic64_read(&SFE_ACCT_COUNTER(acct)[IP_CT_DIR_REPLY].packets); - - if (reply_pkts != 0) { - unsigned int *timeouts; - struct nf_conntrack_l4proto *l4proto __maybe_unused; - set_bit(IPS_SEEN_REPLY_BIT, &ct->status); - set_bit(IPS_ASSURED_BIT, &ct->status); - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)) - l4proto = __nf_ct_l4proto_find((sis->is_v6 ? AF_INET6 : AF_INET), IPPROTO_UDP); - timeouts = nf_ct_timeout_lookup(&init_net, ct, l4proto); - spin_lock_bh(&ct->lock); - ct->timeout.expires = jiffies + timeouts[UDP_CT_REPLIED]; - spin_unlock_bh(&ct->lock); -#else - timeouts = nf_ct_timeout_lookup(ct); - if (!timeouts) { - timeouts = nf_udp_pernet(nf_ct_net(ct))->timeouts; - } - - spin_lock_bh(&ct->lock); - ct->timeout = jiffies + timeouts[UDP_CT_REPLIED]; - spin_unlock_bh(&ct->lock); -#endif - } - } - break; -#endif /*KERNEL_VERSION(3, 4, 0)*/ - } - - /* - * Release connection - */ - nf_ct_put(ct); -} - -/* - * sfe_cm_device_event() - */ -int sfe_cm_device_event(struct notifier_block *this, unsigned long event, void *ptr) -{ - struct net_device *dev = SFE_DEV_EVENT_PTR(ptr); - - if (dev && (event == NETDEV_DOWN)) { - sfe_ipv4_destroy_all_rules_for_dev(dev); - sfe_ipv6_destroy_all_rules_for_dev(dev); - } - - return NOTIFY_DONE; -} - -/* - * sfe_cm_inet_event() - */ -static int sfe_cm_inet_event(struct notifier_block *this, unsigned long event, void *ptr) -{ - struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev; - - if (dev && (event == NETDEV_DOWN)) { - sfe_ipv4_destroy_all_rules_for_dev(dev); - } - - return NOTIFY_DONE; -} - -/* - * sfe_cm_inet6_event() - */ -static int sfe_cm_inet6_event(struct notifier_block *this, unsigned long event, void *ptr) -{ - struct net_device *dev = ((struct inet6_ifaddr *)ptr)->idev->dev; - - if (dev && (event == NETDEV_DOWN)) { - sfe_ipv6_destroy_all_rules_for_dev(dev); - } - - return NOTIFY_DONE; -} - -/* - * sfe_cm_get_exceptions - * dump exception counters - */ -static ssize_t sfe_cm_get_exceptions(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int idx, len; - struct sfe_cm *sc = &__sc; - - spin_lock_bh(&sc->lock); - for (len = 0, idx = 0; idx < SFE_CM_EXCEPTION_MAX; idx++) { - if (sc->exceptions[idx]) { - len += snprintf(buf + len, (ssize_t)(PAGE_SIZE - len), "%s = %d\n", sfe_cm_exception_events_string[idx], sc->exceptions[idx]); - } - } - spin_unlock_bh(&sc->lock); - - return len; -} - -/* - * sysfs attributes. - */ -static const struct device_attribute sfe_cm_exceptions_attr = - __ATTR(exceptions, S_IRUGO, sfe_cm_get_exceptions, NULL); - -/* - * sfe_cm_init() - */ -static int __init sfe_cm_init(void) -{ - struct sfe_cm *sc = &__sc; - int result = -1; -#ifdef CONFIG_SFE_ECM - int (*fast_recv)(struct sk_buff *skb); -#endif - - DEBUG_INFO("SFE CM init\n"); - - /* - * Create sys/sfe_cm - */ - sc->sys_sfe_cm = kobject_create_and_add("sfe_cm", NULL); - if (!sc->sys_sfe_cm) { - DEBUG_ERROR("failed to register sfe_cm\n"); - goto exit1; - } - - /* - * Create sys/sfe_cm/exceptions - */ - result = sysfs_create_file(sc->sys_sfe_cm, &sfe_cm_exceptions_attr.attr); - if (result) { - DEBUG_ERROR("failed to register exceptions file: %d\n", result); - goto exit2; - } - - sc->dev_notifier.notifier_call = sfe_cm_device_event; - sc->dev_notifier.priority = 1; - register_netdevice_notifier(&sc->dev_notifier); - - sc->inet_notifier.notifier_call = sfe_cm_inet_event; - sc->inet_notifier.priority = 1; - register_inetaddr_notifier(&sc->inet_notifier); - - sc->inet6_notifier.notifier_call = sfe_cm_inet6_event; - sc->inet6_notifier.priority = 1; - register_inet6addr_notifier(&sc->inet6_notifier); - /* - * Register our netfilter hooks. - */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)) - result = nf_register_hooks(sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing)); -#else - result = nf_register_net_hooks(&init_net, sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing)); -#endif - if (result < 0) { - DEBUG_ERROR("can't register nf post routing hook: %d\n", result); - goto exit3; - } - - /* - * Register a notifier hook to get fast notifications of expired connections. - * Note: In CONFIG_NF_CONNTRACK_CHAIN_EVENTS enabled case, nf_conntrack_register_notifier() - * function always returns 0. - */ -#ifdef CONFIG_NF_CONNTRACK_EVENTS -#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS - result = nf_conntrack_register_chain_notifier(&init_net, &sfe_cm_conntrack_notifier); -#else - result = nf_conntrack_register_notifier(&init_net, &sfe_cm_conntrack_notifier); -#endif - if (result < 0) { - DEBUG_ERROR("can't register nf notifier hook: %d\n", result); - goto exit4; - } -#endif - spin_lock_init(&sc->lock); - - /* - * Hook the receive path in the network stack. - */ -#ifdef CONFIG_SFE_ECM - rcu_read_lock(); - fast_recv = rcu_dereference(athrs_fast_nat_recv); - rcu_read_unlock(); - if (!fast_recv) { - BUG_ON(athrs_fast_nat_recv); - } -#else - BUG_ON(athrs_fast_nat_recv); -#endif - RCU_INIT_POINTER(athrs_fast_nat_recv, sfe_cm_recv); - - /* - * Hook the shortcut sync callback. - */ - sfe_ipv4_register_sync_rule_callback(sfe_cm_sync_rule); - sfe_ipv6_register_sync_rule_callback(sfe_cm_sync_rule); - return 0; - -#ifdef CONFIG_NF_CONNTRACK_EVENTS -exit4: -#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)) - nf_unregister_hooks(sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing)); -#else - nf_unregister_net_hooks(&init_net, sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing)); -#endif - -#endif -#endif -exit3: - unregister_inet6addr_notifier(&sc->inet6_notifier); - unregister_inetaddr_notifier(&sc->inet_notifier); - unregister_netdevice_notifier(&sc->dev_notifier); -exit2: - kobject_put(sc->sys_sfe_cm); - -exit1: - return result; -} - -/* - * sfe_cm_exit() - */ -static void __exit sfe_cm_exit(void) -{ - struct sfe_cm *sc = &__sc; - - DEBUG_INFO("SFE CM exit\n"); - - /* - * Unregister our sync callback. - */ - sfe_ipv4_register_sync_rule_callback(NULL); - sfe_ipv6_register_sync_rule_callback(NULL); - - /* - * Unregister our receive callback. - */ - RCU_INIT_POINTER(athrs_fast_nat_recv, NULL); - - /* - * Wait for all callbacks to complete. - */ - rcu_barrier(); - - /* - * Destroy all connections. - */ - sfe_ipv4_destroy_all_rules_for_dev(NULL); - sfe_ipv6_destroy_all_rules_for_dev(NULL); - -#ifdef CONFIG_NF_CONNTRACK_EVENTS -#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS - nf_conntrack_unregister_chain_notifier(&init_net, &sfe_cm_conntrack_notifier); -#else - nf_conntrack_unregister_notifier(&init_net, &sfe_cm_conntrack_notifier); -#endif -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)) - nf_unregister_hooks(sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing)); -#else - nf_unregister_net_hooks(&init_net, sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing)); -#endif - unregister_inet6addr_notifier(&sc->inet6_notifier); - unregister_inetaddr_notifier(&sc->inet_notifier); - unregister_netdevice_notifier(&sc->dev_notifier); - - kobject_put(sc->sys_sfe_cm); -} - -module_init(sfe_cm_init) -module_exit(sfe_cm_exit) - -MODULE_DESCRIPTION("Shortcut Forwarding Engine - Connection Manager"); -MODULE_LICENSE("Dual BSD/GPL"); - diff --git a/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_cm.h b/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_cm.h deleted file mode 100644 index 124c86f4..00000000 --- a/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_cm.h +++ /dev/null @@ -1,260 +0,0 @@ -/* - * sfe_cm.h - * Shortcut forwarding engine. - * - * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all copies. - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * connection flags. - */ -#define SFE_CREATE_FLAG_NO_SEQ_CHECK BIT(0) - /* Indicates that we should not check sequence numbers */ -#define SFE_CREATE_FLAG_REMARK_PRIORITY BIT(1) - /* Indicates that we should remark priority of skb */ -#define SFE_CREATE_FLAG_REMARK_DSCP BIT(2) - /* Indicates that we should remark DSCP of packet */ - -/* - * IPv6 address structure - */ -struct sfe_ipv6_addr { - __be32 addr[4]; -}; - -typedef union { - __be32 ip; - struct sfe_ipv6_addr ip6[1]; -} sfe_ip_addr_t; - -/* - * connection creation structure. - */ -struct sfe_connection_create { - int protocol; - struct net_device *src_dev; - struct net_device *dest_dev; - u32 flags; - u32 src_mtu; - u32 dest_mtu; - sfe_ip_addr_t src_ip; - sfe_ip_addr_t src_ip_xlate; - sfe_ip_addr_t dest_ip; - sfe_ip_addr_t dest_ip_xlate; - __be16 src_port; - __be16 src_port_xlate; - __be16 dest_port; - __be16 dest_port_xlate; - u8 src_mac[ETH_ALEN]; - u8 src_mac_xlate[ETH_ALEN]; - u8 dest_mac[ETH_ALEN]; - u8 dest_mac_xlate[ETH_ALEN]; - u8 src_td_window_scale; - u32 src_td_max_window; - u32 src_td_end; - u32 src_td_max_end; - u8 dest_td_window_scale; - u32 dest_td_max_window; - u32 dest_td_end; - u32 dest_td_max_end; - u32 mark; -#ifdef CONFIG_XFRM - u32 original_accel; - u32 reply_accel; -#endif - u32 src_priority; - u32 dest_priority; - u32 src_dscp; - u32 dest_dscp; -}; - -/* - * connection destruction structure. - */ -struct sfe_connection_destroy { - int protocol; - sfe_ip_addr_t src_ip; - sfe_ip_addr_t dest_ip; - __be16 src_port; - __be16 dest_port; -}; - -typedef enum sfe_sync_reason { - SFE_SYNC_REASON_STATS, /* Sync is to synchronize stats */ - SFE_SYNC_REASON_FLUSH, /* Sync is to flush a entry */ - SFE_SYNC_REASON_DESTROY /* Sync is to destroy a entry(requested by connection manager) */ -} sfe_sync_reason_t; - -/* - * Structure used to sync connection stats/state back within the system. - * - * NOTE: The addresses here are NON-NAT addresses, i.e. the true endpoint addressing. - * 'src' is the creator of the connection. - */ -struct sfe_connection_sync { - struct net_device *src_dev; - struct net_device *dest_dev; - int is_v6; /* Is it for ipv6? */ - int protocol; /* IP protocol number (IPPROTO_...) */ - sfe_ip_addr_t src_ip; /* Non-NAT source address, i.e. the creator of the connection */ - sfe_ip_addr_t src_ip_xlate; /* NATed source address */ - __be16 src_port; /* Non-NAT source port */ - __be16 src_port_xlate; /* NATed source port */ - sfe_ip_addr_t dest_ip; /* Non-NAT destination address, i.e. to whom the connection was created */ - sfe_ip_addr_t dest_ip_xlate; /* NATed destination address */ - __be16 dest_port; /* Non-NAT destination port */ - __be16 dest_port_xlate; /* NATed destination port */ - u32 src_td_max_window; - u32 src_td_end; - u32 src_td_max_end; - u64 src_packet_count; - u64 src_byte_count; - u32 src_new_packet_count; - u32 src_new_byte_count; - u32 dest_td_max_window; - u32 dest_td_end; - u32 dest_td_max_end; - u64 dest_packet_count; - u64 dest_byte_count; - u32 dest_new_packet_count; - u32 dest_new_byte_count; - u32 reason; /* reason for stats sync message, i.e. destroy, flush, period sync */ - u64 delta_jiffies; /* Time to be added to the current timeout to keep the connection alive */ -}; - -/* - * connection mark structure - */ -struct sfe_connection_mark { - int protocol; - sfe_ip_addr_t src_ip; - sfe_ip_addr_t dest_ip; - __be16 src_port; - __be16 dest_port; - u32 mark; -}; - -/* - * Expose the hook for the receive processing. - */ -extern int (*athrs_fast_nat_recv)(struct sk_buff *skb); - -/* - * Expose what should be a static flag in the TCP connection tracker. - */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0) -extern int nf_ct_tcp_no_window_check; -#endif -/* - * This callback will be called in a timer - * at 100 times per second to sync stats back to - * Linux connection track. - * - * A RCU lock is taken to prevent this callback - * from unregistering. - */ -typedef void (*sfe_sync_rule_callback_t)(struct sfe_connection_sync *); - -/* - * IPv4 APIs used by connection manager - */ -int sfe_ipv4_recv(struct net_device *dev, struct sk_buff *skb); -int sfe_ipv4_create_rule(struct sfe_connection_create *sic); -void sfe_ipv4_destroy_rule(struct sfe_connection_destroy *sid); -void sfe_ipv4_destroy_all_rules_for_dev(struct net_device *dev); -void sfe_ipv4_register_sync_rule_callback(sfe_sync_rule_callback_t callback); -void sfe_ipv4_update_rule(struct sfe_connection_create *sic); -void sfe_ipv4_mark_rule(struct sfe_connection_mark *mark); - -#ifdef SFE_SUPPORT_IPV6 -/* - * IPv6 APIs used by connection manager - */ -int sfe_ipv6_recv(struct net_device *dev, struct sk_buff *skb); -int sfe_ipv6_create_rule(struct sfe_connection_create *sic); -void sfe_ipv6_destroy_rule(struct sfe_connection_destroy *sid); -void sfe_ipv6_destroy_all_rules_for_dev(struct net_device *dev); -void sfe_ipv6_register_sync_rule_callback(sfe_sync_rule_callback_t callback); -void sfe_ipv6_update_rule(struct sfe_connection_create *sic); -void sfe_ipv6_mark_rule(struct sfe_connection_mark *mark); -#else -static inline int sfe_ipv6_recv(struct net_device *dev, struct sk_buff *skb) -{ - return 0; -} - -static inline int sfe_ipv6_create_rule(struct sfe_connection_create *sic) -{ - return 0; -} - -static inline void sfe_ipv6_destroy_rule(struct sfe_connection_destroy *sid) -{ - return; -} - -static inline void sfe_ipv6_destroy_all_rules_for_dev(struct net_device *dev) -{ - return; -} - -static inline void sfe_ipv6_register_sync_rule_callback(sfe_sync_rule_callback_t callback) -{ - return; -} - -static inline void sfe_ipv6_update_rule(struct sfe_connection_create *sic) -{ - return; -} - -static inline void sfe_ipv6_mark_rule(struct sfe_connection_mark *mark) -{ - return; -} -#endif - -/* - * sfe_ipv6_addr_equal() - * compare ipv6 address - * - * return: 1, equal; 0, no equal - */ -static inline int sfe_ipv6_addr_equal(struct sfe_ipv6_addr *a, - struct sfe_ipv6_addr *b) -{ - return a->addr[0] == b->addr[0] && - a->addr[1] == b->addr[1] && - a->addr[2] == b->addr[2] && - a->addr[3] == b->addr[3]; -} - -/* - * sfe_ipv4_addr_equal() - * compare ipv4 address - * - * return: 1, equal; 0, no equal - */ -#define sfe_ipv4_addr_equal(a, b) ((u32)(a) == (u32)(b)) - -/* - * sfe_addr_equal() - * compare ipv4 or ipv6 address - * - * return: 1, equal; 0, no equal - */ -static inline int sfe_addr_equal(sfe_ip_addr_t *a, - sfe_ip_addr_t *b, int is_v4) -{ - return is_v4 ? sfe_ipv4_addr_equal(a->ip, b->ip) : sfe_ipv6_addr_equal(a->ip6, b->ip6); -} diff --git a/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_ipv4.c b/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_ipv4.c deleted file mode 100644 index cdcdd66d..00000000 --- a/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_ipv4.c +++ /dev/null @@ -1,3618 +0,0 @@ -/* - * sfe_ipv4.c - * Shortcut forwarding engine - IPv4 edition. - * - * Copyright (c) 2013-2016, 2019-2020 The Linux Foundation. All rights reserved. - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all copies. - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "sfe.h" -#include "sfe_cm.h" - -/* - * By default Linux IP header and transport layer header structures are - * unpacked, assuming that such headers should be 32-bit aligned. - * Unfortunately some wireless adaptors can't cope with this requirement and - * some CPUs can't handle misaligned accesses. For those platforms we - * define SFE_IPV4_UNALIGNED_IP_HEADER and mark the structures as packed. - * When we do this the compiler will generate slightly worse code than for the - * aligned case (on most platforms) but will be much quicker than fixing - * things up in an unaligned trap handler. - */ -#define SFE_IPV4_UNALIGNED_IP_HEADER 1 -#if SFE_IPV4_UNALIGNED_IP_HEADER -#define SFE_IPV4_UNALIGNED_STRUCT __attribute__((packed)) -#else -#define SFE_IPV4_UNALIGNED_STRUCT -#endif - -/* - * An Ethernet header, but with an optional "packed" attribute to - * help with performance on some platforms (see the definition of - * SFE_IPV4_UNALIGNED_STRUCT) - */ -struct sfe_ipv4_eth_hdr { - __be16 h_dest[ETH_ALEN / 2]; - __be16 h_source[ETH_ALEN / 2]; - __be16 h_proto; -} SFE_IPV4_UNALIGNED_STRUCT; - -#define SFE_IPV4_DSCP_MASK 0x3 -#define SFE_IPV4_DSCP_SHIFT 2 - -/* - * An IPv4 header, but with an optional "packed" attribute to - * help with performance on some platforms (see the definition of - * SFE_IPV4_UNALIGNED_STRUCT) - */ -struct sfe_ipv4_ip_hdr { -#if defined(__LITTLE_ENDIAN_BITFIELD) - __u8 ihl:4, - version:4; -#elif defined (__BIG_ENDIAN_BITFIELD) - __u8 version:4, - ihl:4; -#else -#error "Please fix " -#endif - __u8 tos; - __be16 tot_len; - __be16 id; - __be16 frag_off; - __u8 ttl; - __u8 protocol; - __sum16 check; - __be32 saddr; - __be32 daddr; - - /* - * The options start here. - */ -} SFE_IPV4_UNALIGNED_STRUCT; - -/* - * A UDP header, but with an optional "packed" attribute to - * help with performance on some platforms (see the definition of - * SFE_IPV4_UNALIGNED_STRUCT) - */ -struct sfe_ipv4_udp_hdr { - __be16 source; - __be16 dest; - __be16 len; - __sum16 check; -} SFE_IPV4_UNALIGNED_STRUCT; - -/* - * A TCP header, but with an optional "packed" attribute to - * help with performance on some platforms (see the definition of - * SFE_IPV4_UNALIGNED_STRUCT) - */ -struct sfe_ipv4_tcp_hdr { - __be16 source; - __be16 dest; - __be32 seq; - __be32 ack_seq; -#if defined(__LITTLE_ENDIAN_BITFIELD) - __u16 res1:4, - doff:4, - fin:1, - syn:1, - rst:1, - psh:1, - ack:1, - urg:1, - ece:1, - cwr:1; -#elif defined(__BIG_ENDIAN_BITFIELD) - __u16 doff:4, - res1:4, - cwr:1, - ece:1, - urg:1, - ack:1, - psh:1, - rst:1, - syn:1, - fin:1; -#else -#error "Adjust your defines" -#endif - __be16 window; - __sum16 check; - __be16 urg_ptr; -} SFE_IPV4_UNALIGNED_STRUCT; - -/* - * Specifies the lower bound on ACK numbers carried in the TCP header - */ -#define SFE_IPV4_TCP_MAX_ACK_WINDOW 65520 - -/* - * IPv4 TCP connection match additional data. - */ -struct sfe_ipv4_tcp_connection_match { - u8 win_scale; /* Window scale */ - u32 max_win; /* Maximum window size seen */ - u32 end; /* Sequence number of the next byte to send (seq + segment length) */ - u32 max_end; /* Sequence number of the last byte to ack */ -}; - -/* - * Bit flags for IPv4 connection matching entry. - */ -#define SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_SRC (1<<0) - /* Perform source translation */ -#define SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_DEST (1<<1) - /* Perform destination translation */ -#define SFE_IPV4_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK (1<<2) - /* Ignore TCP sequence numbers */ -#define SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR (1<<3) - /* Fast Ethernet header write */ -#define SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_L2_HDR (1<<4) - /* Fast Ethernet header write */ -#define SFE_IPV4_CONNECTION_MATCH_FLAG_PRIORITY_REMARK (1<<5) - /* remark priority of SKB */ -#define SFE_IPV4_CONNECTION_MATCH_FLAG_DSCP_REMARK (1<<6) - /* remark DSCP of packet */ - -/* - * IPv4 connection matching structure. - */ -struct sfe_ipv4_connection_match { - /* - * References to other objects. - */ - struct sfe_ipv4_connection_match *next; - struct sfe_ipv4_connection_match *prev; - struct sfe_ipv4_connection *connection; - struct sfe_ipv4_connection_match *counter_match; - /* Matches the flow in the opposite direction as the one in *connection */ - struct sfe_ipv4_connection_match *active_next; - struct sfe_ipv4_connection_match *active_prev; - bool active; /* Flag to indicate if we're on the active list */ - - /* - * Characteristics that identify flows that match this rule. - */ - struct net_device *match_dev; /* Network device */ - u8 match_protocol; /* Protocol */ - __be32 match_src_ip; /* Source IP address */ - __be32 match_dest_ip; /* Destination IP address */ - __be16 match_src_port; /* Source port/connection ident */ - __be16 match_dest_port; /* Destination port/connection ident */ - - /* - * Control the operations of the match. - */ - u32 flags; /* Bit flags */ -#ifdef CONFIG_NF_FLOW_COOKIE - u32 flow_cookie; /* used flow cookie, for debug */ -#endif -#ifdef CONFIG_XFRM - u32 flow_accel; /* The flow accelerated or not */ -#endif - - /* - * Connection state that we track once we match. - */ - union { /* Protocol-specific state */ - struct sfe_ipv4_tcp_connection_match tcp; - } protocol_state; - /* - * Stats recorded in a sync period. These stats will be added to - * rx_packet_count64/rx_byte_count64 after a sync period. - */ - u32 rx_packet_count; - u32 rx_byte_count; - - /* - * Packet translation information. - */ - __be32 xlate_src_ip; /* Address after source translation */ - __be16 xlate_src_port; /* Port/connection ident after source translation */ - u16 xlate_src_csum_adjustment; - /* Transport layer checksum adjustment after source translation */ - u16 xlate_src_partial_csum_adjustment; - /* Transport layer pseudo header checksum adjustment after source translation */ - - __be32 xlate_dest_ip; /* Address after destination translation */ - __be16 xlate_dest_port; /* Port/connection ident after destination translation */ - u16 xlate_dest_csum_adjustment; - /* Transport layer checksum adjustment after destination translation */ - u16 xlate_dest_partial_csum_adjustment; - /* Transport layer pseudo header checksum adjustment after destination translation */ - - /* - * QoS information - */ - u32 priority; - u32 dscp; - - /* - * Packet transmit information. - */ - struct net_device *xmit_dev; /* Network device on which to transmit */ - unsigned short int xmit_dev_mtu; - /* Interface MTU */ - u16 xmit_dest_mac[ETH_ALEN / 2]; - /* Destination MAC address to use when forwarding */ - u16 xmit_src_mac[ETH_ALEN / 2]; - /* Source MAC address to use when forwarding */ - - /* - * Summary stats. - */ - u64 rx_packet_count64; - u64 rx_byte_count64; -}; - -/* - * Per-connection data structure. - */ -struct sfe_ipv4_connection { - struct sfe_ipv4_connection *next; - /* Pointer to the next entry in a hash chain */ - struct sfe_ipv4_connection *prev; - /* Pointer to the previous entry in a hash chain */ - int protocol; /* IP protocol number */ - __be32 src_ip; /* Src IP addr pre-translation */ - __be32 src_ip_xlate; /* Src IP addr post-translation */ - __be32 dest_ip; /* Dest IP addr pre-translation */ - __be32 dest_ip_xlate; /* Dest IP addr post-translation */ - __be16 src_port; /* Src port pre-translation */ - __be16 src_port_xlate; /* Src port post-translation */ - __be16 dest_port; /* Dest port pre-translation */ - __be16 dest_port_xlate; /* Dest port post-translation */ - struct sfe_ipv4_connection_match *original_match; - /* Original direction matching structure */ - struct net_device *original_dev; - /* Original direction source device */ - struct sfe_ipv4_connection_match *reply_match; - /* Reply direction matching structure */ - struct net_device *reply_dev; /* Reply direction source device */ - u64 last_sync_jiffies; /* Jiffies count for the last sync */ - struct sfe_ipv4_connection *all_connections_next; - /* Pointer to the next entry in the list of all connections */ - struct sfe_ipv4_connection *all_connections_prev; - /* Pointer to the previous entry in the list of all connections */ - u32 mark; /* mark for outgoing packet */ - u32 debug_read_seq; /* sequence number for debug dump */ -}; - -/* - * IPv4 connections and hash table size information. - */ -#define SFE_IPV4_CONNECTION_HASH_SHIFT 12 -#define SFE_IPV4_CONNECTION_HASH_SIZE (1 << SFE_IPV4_CONNECTION_HASH_SHIFT) -#define SFE_IPV4_CONNECTION_HASH_MASK (SFE_IPV4_CONNECTION_HASH_SIZE - 1) - -#ifdef CONFIG_NF_FLOW_COOKIE -#define SFE_FLOW_COOKIE_SIZE 2048 -#define SFE_FLOW_COOKIE_MASK 0x7ff - -struct sfe_flow_cookie_entry { - struct sfe_ipv4_connection_match *match; - unsigned long last_clean_time; -}; -#endif - -enum sfe_ipv4_exception_events { - SFE_IPV4_EXCEPTION_EVENT_UDP_HEADER_INCOMPLETE, - SFE_IPV4_EXCEPTION_EVENT_UDP_NO_CONNECTION, - SFE_IPV4_EXCEPTION_EVENT_UDP_IP_OPTIONS_OR_INITIAL_FRAGMENT, - SFE_IPV4_EXCEPTION_EVENT_UDP_SMALL_TTL, - SFE_IPV4_EXCEPTION_EVENT_UDP_NEEDS_FRAGMENTATION, - SFE_IPV4_EXCEPTION_EVENT_TCP_HEADER_INCOMPLETE, - SFE_IPV4_EXCEPTION_EVENT_TCP_NO_CONNECTION_SLOW_FLAGS, - SFE_IPV4_EXCEPTION_EVENT_TCP_NO_CONNECTION_FAST_FLAGS, - SFE_IPV4_EXCEPTION_EVENT_TCP_IP_OPTIONS_OR_INITIAL_FRAGMENT, - SFE_IPV4_EXCEPTION_EVENT_TCP_SMALL_TTL, - SFE_IPV4_EXCEPTION_EVENT_TCP_NEEDS_FRAGMENTATION, - SFE_IPV4_EXCEPTION_EVENT_TCP_FLAGS, - SFE_IPV4_EXCEPTION_EVENT_TCP_SEQ_EXCEEDS_RIGHT_EDGE, - SFE_IPV4_EXCEPTION_EVENT_TCP_SMALL_DATA_OFFS, - SFE_IPV4_EXCEPTION_EVENT_TCP_BAD_SACK, - SFE_IPV4_EXCEPTION_EVENT_TCP_BIG_DATA_OFFS, - SFE_IPV4_EXCEPTION_EVENT_TCP_SEQ_BEFORE_LEFT_EDGE, - SFE_IPV4_EXCEPTION_EVENT_TCP_ACK_EXCEEDS_RIGHT_EDGE, - SFE_IPV4_EXCEPTION_EVENT_TCP_ACK_BEFORE_LEFT_EDGE, - SFE_IPV4_EXCEPTION_EVENT_ICMP_HEADER_INCOMPLETE, - SFE_IPV4_EXCEPTION_EVENT_ICMP_UNHANDLED_TYPE, - SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_HEADER_INCOMPLETE, - SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_NON_V4, - SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_IP_OPTIONS_INCOMPLETE, - SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_UDP_HEADER_INCOMPLETE, - SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_TCP_HEADER_INCOMPLETE, - SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_UNHANDLED_PROTOCOL, - SFE_IPV4_EXCEPTION_EVENT_ICMP_NO_CONNECTION, - SFE_IPV4_EXCEPTION_EVENT_ICMP_FLUSHED_CONNECTION, - SFE_IPV4_EXCEPTION_EVENT_HEADER_INCOMPLETE, - SFE_IPV4_EXCEPTION_EVENT_BAD_TOTAL_LENGTH, - SFE_IPV4_EXCEPTION_EVENT_NON_V4, - SFE_IPV4_EXCEPTION_EVENT_NON_INITIAL_FRAGMENT, - SFE_IPV4_EXCEPTION_EVENT_DATAGRAM_INCOMPLETE, - SFE_IPV4_EXCEPTION_EVENT_IP_OPTIONS_INCOMPLETE, - SFE_IPV4_EXCEPTION_EVENT_UNHANDLED_PROTOCOL, - SFE_IPV4_EXCEPTION_EVENT_CLONED_SKB_UNSHARE_ERROR, - SFE_IPV4_EXCEPTION_EVENT_LAST -}; - -static char *sfe_ipv4_exception_events_string[SFE_IPV4_EXCEPTION_EVENT_LAST] = { - "UDP_HEADER_INCOMPLETE", - "UDP_NO_CONNECTION", - "UDP_IP_OPTIONS_OR_INITIAL_FRAGMENT", - "UDP_SMALL_TTL", - "UDP_NEEDS_FRAGMENTATION", - "TCP_HEADER_INCOMPLETE", - "TCP_NO_CONNECTION_SLOW_FLAGS", - "TCP_NO_CONNECTION_FAST_FLAGS", - "TCP_IP_OPTIONS_OR_INITIAL_FRAGMENT", - "TCP_SMALL_TTL", - "TCP_NEEDS_FRAGMENTATION", - "TCP_FLAGS", - "TCP_SEQ_EXCEEDS_RIGHT_EDGE", - "TCP_SMALL_DATA_OFFS", - "TCP_BAD_SACK", - "TCP_BIG_DATA_OFFS", - "TCP_SEQ_BEFORE_LEFT_EDGE", - "TCP_ACK_EXCEEDS_RIGHT_EDGE", - "TCP_ACK_BEFORE_LEFT_EDGE", - "ICMP_HEADER_INCOMPLETE", - "ICMP_UNHANDLED_TYPE", - "ICMP_IPV4_HEADER_INCOMPLETE", - "ICMP_IPV4_NON_V4", - "ICMP_IPV4_IP_OPTIONS_INCOMPLETE", - "ICMP_IPV4_UDP_HEADER_INCOMPLETE", - "ICMP_IPV4_TCP_HEADER_INCOMPLETE", - "ICMP_IPV4_UNHANDLED_PROTOCOL", - "ICMP_NO_CONNECTION", - "ICMP_FLUSHED_CONNECTION", - "HEADER_INCOMPLETE", - "BAD_TOTAL_LENGTH", - "NON_V4", - "NON_INITIAL_FRAGMENT", - "DATAGRAM_INCOMPLETE", - "IP_OPTIONS_INCOMPLETE", - "UNHANDLED_PROTOCOL", - "CLONED_SKB_UNSHARE_ERROR" -}; - -/* - * Per-module structure. - */ -struct sfe_ipv4 { - spinlock_t lock; /* Lock for SMP correctness */ - struct sfe_ipv4_connection_match *active_head; - /* Head of the list of recently active connections */ - struct sfe_ipv4_connection_match *active_tail; - /* Tail of the list of recently active connections */ - struct sfe_ipv4_connection *all_connections_head; - /* Head of the list of all connections */ - struct sfe_ipv4_connection *all_connections_tail; - /* Tail of the list of all connections */ - unsigned int num_connections; /* Number of connections */ - struct timer_list timer; /* Timer used for periodic sync ops */ - sfe_sync_rule_callback_t __rcu sync_rule_callback; - /* Callback function registered by a connection manager for stats syncing */ - struct sfe_ipv4_connection *conn_hash[SFE_IPV4_CONNECTION_HASH_SIZE]; - /* Connection hash table */ - struct sfe_ipv4_connection_match *conn_match_hash[SFE_IPV4_CONNECTION_HASH_SIZE]; - /* Connection match hash table */ -#ifdef CONFIG_NF_FLOW_COOKIE - struct sfe_flow_cookie_entry sfe_flow_cookie_table[SFE_FLOW_COOKIE_SIZE]; - /* flow cookie table*/ - flow_cookie_set_func_t flow_cookie_set_func; - /* function used to configure flow cookie in hardware*/ - int flow_cookie_enable; - /* Enable/disable flow cookie at runtime */ -#endif - - /* - * Stats recorded in a sync period. These stats will be added to - * connection_xxx64 after a sync period. - */ - u32 connection_create_requests; - /* Number of IPv4 connection create requests */ - u32 connection_create_collisions; - /* Number of IPv4 connection create requests that collided with existing hash table entries */ - u32 connection_destroy_requests; - /* Number of IPv4 connection destroy requests */ - u32 connection_destroy_misses; - /* Number of IPv4 connection destroy requests that missed our hash table */ - u32 connection_match_hash_hits; - /* Number of IPv4 connection match hash hits */ - u32 connection_match_hash_reorders; - /* Number of IPv4 connection match hash reorders */ - u32 connection_flushes; /* Number of IPv4 connection flushes */ - u32 packets_forwarded; /* Number of IPv4 packets forwarded */ - u32 packets_not_forwarded; /* Number of IPv4 packets not forwarded */ - u32 exception_events[SFE_IPV4_EXCEPTION_EVENT_LAST]; - - /* - * Summary statistics. - */ - u64 connection_create_requests64; - /* Number of IPv4 connection create requests */ - u64 connection_create_collisions64; - /* Number of IPv4 connection create requests that collided with existing hash table entries */ - u64 connection_destroy_requests64; - /* Number of IPv4 connection destroy requests */ - u64 connection_destroy_misses64; - /* Number of IPv4 connection destroy requests that missed our hash table */ - u64 connection_match_hash_hits64; - /* Number of IPv4 connection match hash hits */ - u64 connection_match_hash_reorders64; - /* Number of IPv4 connection match hash reorders */ - u64 connection_flushes64; /* Number of IPv4 connection flushes */ - u64 packets_forwarded64; /* Number of IPv4 packets forwarded */ - u64 packets_not_forwarded64; - /* Number of IPv4 packets not forwarded */ - u64 exception_events64[SFE_IPV4_EXCEPTION_EVENT_LAST]; - - /* - * Control state. - */ - struct kobject *sys_sfe_ipv4; /* sysfs linkage */ - int debug_dev; /* Major number of the debug char device */ - u32 debug_read_seq; /* sequence number for debug dump */ -}; - -/* - * Enumeration of the XML output. - */ -enum sfe_ipv4_debug_xml_states { - SFE_IPV4_DEBUG_XML_STATE_START, - SFE_IPV4_DEBUG_XML_STATE_CONNECTIONS_START, - SFE_IPV4_DEBUG_XML_STATE_CONNECTIONS_CONNECTION, - SFE_IPV4_DEBUG_XML_STATE_CONNECTIONS_END, - SFE_IPV4_DEBUG_XML_STATE_EXCEPTIONS_START, - SFE_IPV4_DEBUG_XML_STATE_EXCEPTIONS_EXCEPTION, - SFE_IPV4_DEBUG_XML_STATE_EXCEPTIONS_END, - SFE_IPV4_DEBUG_XML_STATE_STATS, - SFE_IPV4_DEBUG_XML_STATE_END, - SFE_IPV4_DEBUG_XML_STATE_DONE -}; - -/* - * XML write state. - */ -struct sfe_ipv4_debug_xml_write_state { - enum sfe_ipv4_debug_xml_states state; - /* XML output file state machine state */ - int iter_exception; /* Next exception iterator */ -}; - -typedef bool (*sfe_ipv4_debug_xml_write_method_t)(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, - int *total_read, struct sfe_ipv4_debug_xml_write_state *ws); - -static struct sfe_ipv4 __si; - -/* - * sfe_ipv4_gen_ip_csum() - * Generate the IP checksum for an IPv4 header. - * - * Note that this function assumes that we have only 20 bytes of IP header. - */ -static inline u16 sfe_ipv4_gen_ip_csum(struct sfe_ipv4_ip_hdr *iph) -{ - u32 sum; - u16 *i = (u16 *)iph; - - iph->check = 0; - - /* - * Generate the sum. - */ - sum = i[0] + i[1] + i[2] + i[3] + i[4] + i[5] + i[6] + i[7] + i[8] + i[9]; - - /* - * Fold it to ones-complement form. - */ - sum = (sum & 0xffff) + (sum >> 16); - sum = (sum & 0xffff) + (sum >> 16); - - return (u16)sum ^ 0xffff; -} - -/* - * sfe_ipv4_get_connection_match_hash() - * Generate the hash used in connection match lookups. - */ -static inline unsigned int sfe_ipv4_get_connection_match_hash(struct net_device *dev, u8 protocol, - __be32 src_ip, __be16 src_port, - __be32 dest_ip, __be16 dest_port) -{ - size_t dev_addr = (size_t)dev; - u32 hash = ((u32)dev_addr) ^ ntohl(src_ip ^ dest_ip) ^ protocol ^ ntohs(src_port ^ dest_port); - return ((hash >> SFE_IPV4_CONNECTION_HASH_SHIFT) ^ hash) & SFE_IPV4_CONNECTION_HASH_MASK; -} - -/* - * sfe_ipv4_find_sfe_ipv4_connection_match() - * Get the IPv4 flow match info that corresponds to a particular 5-tuple. - * - * On entry we must be holding the lock that protects the hash table. - */ -static struct sfe_ipv4_connection_match * -sfe_ipv4_find_sfe_ipv4_connection_match(struct sfe_ipv4 *si, struct net_device *dev, u8 protocol, - __be32 src_ip, __be16 src_port, - __be32 dest_ip, __be16 dest_port) -{ - struct sfe_ipv4_connection_match *cm; - struct sfe_ipv4_connection_match *head; - unsigned int conn_match_idx; - - conn_match_idx = sfe_ipv4_get_connection_match_hash(dev, protocol, src_ip, src_port, dest_ip, dest_port); - cm = si->conn_match_hash[conn_match_idx]; - - /* - * If we don't have anything in this chain then bail. - */ - if (unlikely(!cm)) { - return NULL; - } - - /* - * Hopefully the first entry is the one we want. - */ - if ((cm->match_src_port == src_port) - && (cm->match_dest_port == dest_port) - && (cm->match_src_ip == src_ip) - && (cm->match_dest_ip == dest_ip) - && (cm->match_protocol == protocol) - && (cm->match_dev == dev)) { - si->connection_match_hash_hits++; - return cm; - } - - /* - * Unfortunately we didn't find it at head, so we search it in chain and - * move matching entry to the top of the hash chain. We presume that this - * will be reused again very quickly. - */ - head = cm; - do { - cm = cm->next; - } while (cm && (cm->match_src_port != src_port - || cm->match_dest_port != dest_port - || cm->match_src_ip != src_ip - || cm->match_dest_ip != dest_ip - || cm->match_protocol != protocol - || cm->match_dev != dev)); - - /* - * Not found then we're done. - */ - if (unlikely(!cm)) { - return NULL; - } - - /* - * We found a match so move it. - */ - if (cm->next) { - cm->next->prev = cm->prev; - } - cm->prev->next = cm->next; - cm->prev = NULL; - cm->next = head; - head->prev = cm; - si->conn_match_hash[conn_match_idx] = cm; - si->connection_match_hash_reorders++; - - return cm; -} - -/* - * sfe_ipv4_connection_match_update_summary_stats() - * Update the summary stats for a connection match entry. - */ -static inline void sfe_ipv4_connection_match_update_summary_stats(struct sfe_ipv4_connection_match *cm) -{ - cm->rx_packet_count64 += cm->rx_packet_count; - cm->rx_packet_count = 0; - cm->rx_byte_count64 += cm->rx_byte_count; - cm->rx_byte_count = 0; -} - -/* - * sfe_ipv4_connection_match_compute_translations() - * Compute port and address translations for a connection match entry. - */ -static void sfe_ipv4_connection_match_compute_translations(struct sfe_ipv4_connection_match *cm) -{ - /* - * Before we insert the entry look to see if this is tagged as doing address - * translations. If it is then work out the adjustment that we need to apply - * to the transport checksum. - */ - if (cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_SRC) { - /* - * Precompute an incremental checksum adjustment so we can - * edit packets in this stream very quickly. The algorithm is from RFC1624. - */ - u16 src_ip_hi = cm->match_src_ip >> 16; - u16 src_ip_lo = cm->match_src_ip & 0xffff; - u32 xlate_src_ip = ~cm->xlate_src_ip; - u16 xlate_src_ip_hi = xlate_src_ip >> 16; - u16 xlate_src_ip_lo = xlate_src_ip & 0xffff; - u16 xlate_src_port = ~cm->xlate_src_port; - u32 adj; - - /* - * When we compute this fold it down to a 16-bit offset - * as that way we can avoid having to do a double - * folding of the twos-complement result because the - * addition of 2 16-bit values cannot cause a double - * wrap-around! - */ - adj = src_ip_hi + src_ip_lo + cm->match_src_port - + xlate_src_ip_hi + xlate_src_ip_lo + xlate_src_port; - adj = (adj & 0xffff) + (adj >> 16); - adj = (adj & 0xffff) + (adj >> 16); - cm->xlate_src_csum_adjustment = (u16)adj; - - } - - if (cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_DEST) { - /* - * Precompute an incremental checksum adjustment so we can - * edit packets in this stream very quickly. The algorithm is from RFC1624. - */ - u16 dest_ip_hi = cm->match_dest_ip >> 16; - u16 dest_ip_lo = cm->match_dest_ip & 0xffff; - u32 xlate_dest_ip = ~cm->xlate_dest_ip; - u16 xlate_dest_ip_hi = xlate_dest_ip >> 16; - u16 xlate_dest_ip_lo = xlate_dest_ip & 0xffff; - u16 xlate_dest_port = ~cm->xlate_dest_port; - u32 adj; - - /* - * When we compute this fold it down to a 16-bit offset - * as that way we can avoid having to do a double - * folding of the twos-complement result because the - * addition of 2 16-bit values cannot cause a double - * wrap-around! - */ - adj = dest_ip_hi + dest_ip_lo + cm->match_dest_port - + xlate_dest_ip_hi + xlate_dest_ip_lo + xlate_dest_port; - adj = (adj & 0xffff) + (adj >> 16); - adj = (adj & 0xffff) + (adj >> 16); - cm->xlate_dest_csum_adjustment = (u16)adj; - } - - if (cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_SRC) { - u32 adj = ~cm->match_src_ip + cm->xlate_src_ip; - if (adj < cm->xlate_src_ip) { - adj++; - } - - adj = (adj & 0xffff) + (adj >> 16); - adj = (adj & 0xffff) + (adj >> 16); - cm->xlate_src_partial_csum_adjustment = (u16)adj; - } - - if (cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_DEST) { - u32 adj = ~cm->match_dest_ip + cm->xlate_dest_ip; - if (adj < cm->xlate_dest_ip) { - adj++; - } - - adj = (adj & 0xffff) + (adj >> 16); - adj = (adj & 0xffff) + (adj >> 16); - cm->xlate_dest_partial_csum_adjustment = (u16)adj; - } - -} - -/* - * sfe_ipv4_update_summary_stats() - * Update the summary stats. - */ -static void sfe_ipv4_update_summary_stats(struct sfe_ipv4 *si) -{ - int i; - - si->connection_create_requests64 += si->connection_create_requests; - si->connection_create_requests = 0; - si->connection_create_collisions64 += si->connection_create_collisions; - si->connection_create_collisions = 0; - si->connection_destroy_requests64 += si->connection_destroy_requests; - si->connection_destroy_requests = 0; - si->connection_destroy_misses64 += si->connection_destroy_misses; - si->connection_destroy_misses = 0; - si->connection_match_hash_hits64 += si->connection_match_hash_hits; - si->connection_match_hash_hits = 0; - si->connection_match_hash_reorders64 += si->connection_match_hash_reorders; - si->connection_match_hash_reorders = 0; - si->connection_flushes64 += si->connection_flushes; - si->connection_flushes = 0; - si->packets_forwarded64 += si->packets_forwarded; - si->packets_forwarded = 0; - si->packets_not_forwarded64 += si->packets_not_forwarded; - si->packets_not_forwarded = 0; - - for (i = 0; i < SFE_IPV4_EXCEPTION_EVENT_LAST; i++) { - si->exception_events64[i] += si->exception_events[i]; - si->exception_events[i] = 0; - } -} - -/* - * sfe_ipv4_insert_sfe_ipv4_connection_match() - * Insert a connection match into the hash. - * - * On entry we must be holding the lock that protects the hash table. - */ -static inline void sfe_ipv4_insert_sfe_ipv4_connection_match(struct sfe_ipv4 *si, - struct sfe_ipv4_connection_match *cm) -{ - struct sfe_ipv4_connection_match **hash_head; - struct sfe_ipv4_connection_match *prev_head; - unsigned int conn_match_idx - = sfe_ipv4_get_connection_match_hash(cm->match_dev, cm->match_protocol, - cm->match_src_ip, cm->match_src_port, - cm->match_dest_ip, cm->match_dest_port); - - hash_head = &si->conn_match_hash[conn_match_idx]; - prev_head = *hash_head; - cm->prev = NULL; - if (prev_head) { - prev_head->prev = cm; - } - - cm->next = prev_head; - *hash_head = cm; - -#ifdef CONFIG_NF_FLOW_COOKIE - if (!si->flow_cookie_enable) - return; - - /* - * Configure hardware to put a flow cookie in packet of this flow, - * then we can accelerate the lookup process when we received this packet. - */ - for (conn_match_idx = 1; conn_match_idx < SFE_FLOW_COOKIE_SIZE; conn_match_idx++) { - struct sfe_flow_cookie_entry *entry = &si->sfe_flow_cookie_table[conn_match_idx]; - - if ((NULL == entry->match) && time_is_before_jiffies(entry->last_clean_time + HZ)) { - flow_cookie_set_func_t func; - - rcu_read_lock(); - func = rcu_dereference(si->flow_cookie_set_func); - if (func) { - if (!func(cm->match_protocol, cm->match_src_ip, cm->match_src_port, - cm->match_dest_ip, cm->match_dest_port, conn_match_idx)) { - entry->match = cm; - cm->flow_cookie = conn_match_idx; - } - } - rcu_read_unlock(); - - break; - } - } -#endif -} - -/* - * sfe_ipv4_remove_sfe_ipv4_connection_match() - * Remove a connection match object from the hash. - * - * On entry we must be holding the lock that protects the hash table. - */ -static inline void sfe_ipv4_remove_sfe_ipv4_connection_match(struct sfe_ipv4 *si, struct sfe_ipv4_connection_match *cm) -{ -#ifdef CONFIG_NF_FLOW_COOKIE - if (si->flow_cookie_enable) { - /* - * Tell hardware that we no longer need a flow cookie in packet of this flow - */ - unsigned int conn_match_idx; - - for (conn_match_idx = 1; conn_match_idx < SFE_FLOW_COOKIE_SIZE; conn_match_idx++) { - struct sfe_flow_cookie_entry *entry = &si->sfe_flow_cookie_table[conn_match_idx]; - - if (cm == entry->match) { - flow_cookie_set_func_t func; - - rcu_read_lock(); - func = rcu_dereference(si->flow_cookie_set_func); - if (func) { - func(cm->match_protocol, cm->match_src_ip, cm->match_src_port, - cm->match_dest_ip, cm->match_dest_port, 0); - } - rcu_read_unlock(); - - cm->flow_cookie = 0; - entry->match = NULL; - entry->last_clean_time = jiffies; - break; - } - } - } -#endif - - /* - * Unlink the connection match entry from the hash. - */ - if (cm->prev) { - cm->prev->next = cm->next; - } else { - unsigned int conn_match_idx - = sfe_ipv4_get_connection_match_hash(cm->match_dev, cm->match_protocol, - cm->match_src_ip, cm->match_src_port, - cm->match_dest_ip, cm->match_dest_port); - si->conn_match_hash[conn_match_idx] = cm->next; - } - - if (cm->next) { - cm->next->prev = cm->prev; - } - - /* - * If the connection match entry is in the active list remove it. - */ - if (cm->active) { - if (likely(cm->active_prev)) { - cm->active_prev->active_next = cm->active_next; - } else { - si->active_head = cm->active_next; - } - - if (likely(cm->active_next)) { - cm->active_next->active_prev = cm->active_prev; - } else { - si->active_tail = cm->active_prev; - } - } -} - -/* - * sfe_ipv4_get_connection_hash() - * Generate the hash used in connection lookups. - */ -static inline unsigned int sfe_ipv4_get_connection_hash(u8 protocol, __be32 src_ip, __be16 src_port, - __be32 dest_ip, __be16 dest_port) -{ - u32 hash = ntohl(src_ip ^ dest_ip) ^ protocol ^ ntohs(src_port ^ dest_port); - return ((hash >> SFE_IPV4_CONNECTION_HASH_SHIFT) ^ hash) & SFE_IPV4_CONNECTION_HASH_MASK; -} - -/* - * sfe_ipv4_find_sfe_ipv4_connection() - * Get the IPv4 connection info that corresponds to a particular 5-tuple. - * - * On entry we must be holding the lock that protects the hash table. - */ -static inline struct sfe_ipv4_connection *sfe_ipv4_find_sfe_ipv4_connection(struct sfe_ipv4 *si, u32 protocol, - __be32 src_ip, __be16 src_port, - __be32 dest_ip, __be16 dest_port) -{ - struct sfe_ipv4_connection *c; - unsigned int conn_idx = sfe_ipv4_get_connection_hash(protocol, src_ip, src_port, dest_ip, dest_port); - c = si->conn_hash[conn_idx]; - - /* - * If we don't have anything in this chain then bale. - */ - if (unlikely(!c)) { - return NULL; - } - - /* - * Hopefully the first entry is the one we want. - */ - if ((c->src_port == src_port) - && (c->dest_port == dest_port) - && (c->src_ip == src_ip) - && (c->dest_ip == dest_ip) - && (c->protocol == protocol)) { - return c; - } - - /* - * Unfortunately we didn't find it at head, so we search it in chain. - */ - do { - c = c->next; - } while (c && (c->src_port != src_port - || c->dest_port != dest_port - || c->src_ip != src_ip - || c->dest_ip != dest_ip - || c->protocol != protocol)); - - /* - * Will need connection entry for next create/destroy metadata, - * So no need to re-order entry for these requests - */ - return c; -} - -/* - * sfe_ipv4_mark_rule() - * Updates the mark for a current offloaded connection - * - * Will take hash lock upon entry - */ -void sfe_ipv4_mark_rule(struct sfe_connection_mark *mark) -{ - struct sfe_ipv4 *si = &__si; - struct sfe_ipv4_connection *c; - - spin_lock_bh(&si->lock); - c = sfe_ipv4_find_sfe_ipv4_connection(si, mark->protocol, - mark->src_ip.ip, mark->src_port, - mark->dest_ip.ip, mark->dest_port); - if (c) { - WARN_ON((0 != c->mark) && (0 == mark->mark)); - c->mark = mark->mark; - } - spin_unlock_bh(&si->lock); - - if (c) { - DEBUG_TRACE("Matching connection found for mark, " - "setting from %08x to %08x\n", - c->mark, mark->mark); - } -} - -/* - * sfe_ipv4_insert_sfe_ipv4_connection() - * Insert a connection into the hash. - * - * On entry we must be holding the lock that protects the hash table. - */ -static void sfe_ipv4_insert_sfe_ipv4_connection(struct sfe_ipv4 *si, struct sfe_ipv4_connection *c) -{ - struct sfe_ipv4_connection **hash_head; - struct sfe_ipv4_connection *prev_head; - unsigned int conn_idx; - - /* - * Insert entry into the connection hash. - */ - conn_idx = sfe_ipv4_get_connection_hash(c->protocol, c->src_ip, c->src_port, - c->dest_ip, c->dest_port); - hash_head = &si->conn_hash[conn_idx]; - prev_head = *hash_head; - c->prev = NULL; - if (prev_head) { - prev_head->prev = c; - } - - c->next = prev_head; - *hash_head = c; - - /* - * Insert entry into the "all connections" list. - */ - if (si->all_connections_tail) { - c->all_connections_prev = si->all_connections_tail; - si->all_connections_tail->all_connections_next = c; - } else { - c->all_connections_prev = NULL; - si->all_connections_head = c; - } - - si->all_connections_tail = c; - c->all_connections_next = NULL; - si->num_connections++; - - /* - * Insert the connection match objects too. - */ - sfe_ipv4_insert_sfe_ipv4_connection_match(si, c->original_match); - sfe_ipv4_insert_sfe_ipv4_connection_match(si, c->reply_match); -} - -/* - * sfe_ipv4_remove_sfe_ipv4_connection() - * Remove a sfe_ipv4_connection object from the hash. - * - * On entry we must be holding the lock that protects the hash table. - */ -static void sfe_ipv4_remove_sfe_ipv4_connection(struct sfe_ipv4 *si, struct sfe_ipv4_connection *c) -{ - /* - * Remove the connection match objects. - */ - sfe_ipv4_remove_sfe_ipv4_connection_match(si, c->reply_match); - sfe_ipv4_remove_sfe_ipv4_connection_match(si, c->original_match); - - /* - * Unlink the connection. - */ - if (c->prev) { - c->prev->next = c->next; - } else { - unsigned int conn_idx = sfe_ipv4_get_connection_hash(c->protocol, c->src_ip, c->src_port, - c->dest_ip, c->dest_port); - si->conn_hash[conn_idx] = c->next; - } - - if (c->next) { - c->next->prev = c->prev; - } - - /* - * Unlink connection from all_connections list - */ - if (c->all_connections_prev) { - c->all_connections_prev->all_connections_next = c->all_connections_next; - } else { - si->all_connections_head = c->all_connections_next; - } - - if (c->all_connections_next) { - c->all_connections_next->all_connections_prev = c->all_connections_prev; - } else { - si->all_connections_tail = c->all_connections_prev; - } - - si->num_connections--; -} - -/* - * sfe_ipv4_sync_sfe_ipv4_connection() - * Sync a connection. - * - * On entry to this function we expect that the lock for the connection is either - * already held or isn't required. - */ -static void sfe_ipv4_gen_sync_sfe_ipv4_connection(struct sfe_ipv4 *si, struct sfe_ipv4_connection *c, - struct sfe_connection_sync *sis, sfe_sync_reason_t reason, - u64 now_jiffies) -{ - struct sfe_ipv4_connection_match *original_cm; - struct sfe_ipv4_connection_match *reply_cm; - - /* - * Fill in the update message. - */ - sis->is_v6 = 0; - sis->protocol = c->protocol; - sis->src_ip.ip = c->src_ip; - sis->src_ip_xlate.ip = c->src_ip_xlate; - sis->dest_ip.ip = c->dest_ip; - sis->dest_ip_xlate.ip = c->dest_ip_xlate; - sis->src_port = c->src_port; - sis->src_port_xlate = c->src_port_xlate; - sis->dest_port = c->dest_port; - sis->dest_port_xlate = c->dest_port_xlate; - - original_cm = c->original_match; - reply_cm = c->reply_match; - sis->src_td_max_window = original_cm->protocol_state.tcp.max_win; - sis->src_td_end = original_cm->protocol_state.tcp.end; - sis->src_td_max_end = original_cm->protocol_state.tcp.max_end; - sis->dest_td_max_window = reply_cm->protocol_state.tcp.max_win; - sis->dest_td_end = reply_cm->protocol_state.tcp.end; - sis->dest_td_max_end = reply_cm->protocol_state.tcp.max_end; - - sis->src_new_packet_count = original_cm->rx_packet_count; - sis->src_new_byte_count = original_cm->rx_byte_count; - sis->dest_new_packet_count = reply_cm->rx_packet_count; - sis->dest_new_byte_count = reply_cm->rx_byte_count; - - sfe_ipv4_connection_match_update_summary_stats(original_cm); - sfe_ipv4_connection_match_update_summary_stats(reply_cm); - - sis->src_dev = original_cm->match_dev; - sis->src_packet_count = original_cm->rx_packet_count64; - sis->src_byte_count = original_cm->rx_byte_count64; - - sis->dest_dev = reply_cm->match_dev; - sis->dest_packet_count = reply_cm->rx_packet_count64; - sis->dest_byte_count = reply_cm->rx_byte_count64; - - sis->reason = reason; - - /* - * Get the time increment since our last sync. - */ - sis->delta_jiffies = now_jiffies - c->last_sync_jiffies; - c->last_sync_jiffies = now_jiffies; -} - -/* - * sfe_ipv4_flush_sfe_ipv4_connection() - * Flush a connection and free all associated resources. - * - * We need to be called with bottom halves disabled locally as we need to acquire - * the connection hash lock and release it again. In general we're actually called - * from within a BH and so we're fine, but we're also called when connections are - * torn down. - */ -static void sfe_ipv4_flush_sfe_ipv4_connection(struct sfe_ipv4 *si, - struct sfe_ipv4_connection *c, - sfe_sync_reason_t reason) -{ - struct sfe_connection_sync sis; - u64 now_jiffies; - sfe_sync_rule_callback_t sync_rule_callback; - - rcu_read_lock(); - spin_lock_bh(&si->lock); - si->connection_flushes++; - sync_rule_callback = rcu_dereference(si->sync_rule_callback); - spin_unlock_bh(&si->lock); - - if (sync_rule_callback) { - /* - * Generate a sync message and then sync. - */ - now_jiffies = get_jiffies_64(); - sfe_ipv4_gen_sync_sfe_ipv4_connection(si, c, &sis, reason, now_jiffies); - sync_rule_callback(&sis); - } - - rcu_read_unlock(); - - /* - * Release our hold of the source and dest devices and free the memory - * for our connection objects. - */ - dev_put(c->original_dev); - dev_put(c->reply_dev); - kfree(c->original_match); - kfree(c->reply_match); - kfree(c); -} - -/* - * sfe_ipv4_recv_udp() - * Handle UDP packet receives and forwarding. - */ -static int sfe_ipv4_recv_udp(struct sfe_ipv4 *si, struct sk_buff *skb, struct net_device *dev, - unsigned int len, struct sfe_ipv4_ip_hdr *iph, unsigned int ihl, bool flush_on_find) -{ - struct sfe_ipv4_udp_hdr *udph; - __be32 src_ip; - __be32 dest_ip; - __be16 src_port; - __be16 dest_port; - struct sfe_ipv4_connection_match *cm; - u8 ttl; - struct net_device *xmit_dev; - - /* - * Is our packet too short to contain a valid UDP header? - */ - if (unlikely(!pskb_may_pull(skb, (sizeof(struct sfe_ipv4_udp_hdr) + ihl)))) { - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_UDP_HEADER_INCOMPLETE]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("packet too short for UDP header\n"); - return 0; - } - - /* - * Read the IP address and port information. Read the IP header data first - * because we've almost certainly got that in the cache. We may not yet have - * the UDP header cached though so allow more time for any prefetching. - */ - src_ip = iph->saddr; - dest_ip = iph->daddr; - - udph = (struct sfe_ipv4_udp_hdr *)(skb->data + ihl); - src_port = udph->source; - dest_port = udph->dest; - - spin_lock_bh(&si->lock); - - /* - * Look for a connection match. - */ -#ifdef CONFIG_NF_FLOW_COOKIE - cm = si->sfe_flow_cookie_table[skb->flow_cookie & SFE_FLOW_COOKIE_MASK].match; - if (unlikely(!cm)) { - cm = sfe_ipv4_find_sfe_ipv4_connection_match(si, dev, IPPROTO_UDP, src_ip, src_port, dest_ip, dest_port); - } -#else - cm = sfe_ipv4_find_sfe_ipv4_connection_match(si, dev, IPPROTO_UDP, src_ip, src_port, dest_ip, dest_port); -#endif - if (unlikely(!cm)) { - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_UDP_NO_CONNECTION]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("no connection found\n"); - return 0; - } - - /* - * If our packet has beern marked as "flush on find" we can't actually - * forward it in the fast path, but now that we've found an associated - * connection we can flush that out before we process the packet. - */ - if (unlikely(flush_on_find)) { - struct sfe_ipv4_connection *c = cm->connection; - sfe_ipv4_remove_sfe_ipv4_connection(si, c); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_UDP_IP_OPTIONS_OR_INITIAL_FRAGMENT]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("flush on find\n"); - sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; - } - -#ifdef CONFIG_XFRM - /* - * We can't accelerate the flow on this direction, just let it go - * through the slow path. - */ - if (unlikely(!cm->flow_accel)) { - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - return 0; - } -#endif - - /* - * Does our TTL allow forwarding? - */ - ttl = iph->ttl; - if (unlikely(ttl < 2)) { - struct sfe_ipv4_connection *c = cm->connection; - sfe_ipv4_remove_sfe_ipv4_connection(si, c); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_UDP_SMALL_TTL]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("ttl too low\n"); - sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; - } - - /* - * If our packet is larger than the MTU of the transmit interface then - * we can't forward it easily. - */ - if (unlikely(len > cm->xmit_dev_mtu)) { - struct sfe_ipv4_connection *c = cm->connection; - sfe_ipv4_remove_sfe_ipv4_connection(si, c); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_UDP_NEEDS_FRAGMENTATION]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("larger than mtu\n"); - sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; - } - - /* - * From this point on we're good to modify the packet. - */ - - /* - * Check if skb was cloned. If it was, unshare it. Because - * the data area is going to be written in this path and we don't want to - * change the cloned skb's data section. - */ - if (unlikely(skb_cloned(skb))) { - DEBUG_TRACE("%px: skb is a cloned skb\n", skb); - skb = skb_unshare(skb, GFP_ATOMIC); - if (!skb) { - DEBUG_WARN("Failed to unshare the cloned skb\n"); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_CLONED_SKB_UNSHARE_ERROR]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - return 0; - } - - /* - * Update the iph and udph pointers with the unshared skb's data area. - */ - iph = (struct sfe_ipv4_ip_hdr *)skb->data; - udph = (struct sfe_ipv4_udp_hdr *)(skb->data + ihl); - } - - /* - * Update DSCP - */ - if (unlikely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_DSCP_REMARK)) { - iph->tos = (iph->tos & SFE_IPV4_DSCP_MASK) | cm->dscp; - } - - /* - * Decrement our TTL. - */ - iph->ttl = ttl - 1; - - /* - * Do we have to perform translations of the source address/port? - */ - if (unlikely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_SRC)) { - u16 udp_csum; - - iph->saddr = cm->xlate_src_ip; - udph->source = cm->xlate_src_port; - - /* - * Do we have a non-zero UDP checksum? If we do then we need - * to update it. - */ - udp_csum = udph->check; - if (likely(udp_csum)) { - u32 sum; - - if (unlikely(skb->ip_summed == CHECKSUM_PARTIAL)) { - sum = udp_csum + cm->xlate_src_partial_csum_adjustment; - } else { - sum = udp_csum + cm->xlate_src_csum_adjustment; - } - - sum = (sum & 0xffff) + (sum >> 16); - udph->check = (u16)sum; - } - } - - /* - * Do we have to perform translations of the destination address/port? - */ - if (unlikely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_DEST)) { - u16 udp_csum; - - iph->daddr = cm->xlate_dest_ip; - udph->dest = cm->xlate_dest_port; - - /* - * Do we have a non-zero UDP checksum? If we do then we need - * to update it. - */ - udp_csum = udph->check; - if (likely(udp_csum)) { - u32 sum; - - if (unlikely(skb->ip_summed == CHECKSUM_PARTIAL)) { - sum = udp_csum + cm->xlate_dest_partial_csum_adjustment; - } else { - sum = udp_csum + cm->xlate_dest_csum_adjustment; - } - - sum = (sum & 0xffff) + (sum >> 16); - udph->check = (u16)sum; - } - } - - /* - * Replace the IP checksum. - */ - iph->check = sfe_ipv4_gen_ip_csum(iph); - - /* - * Update traffic stats. - */ - cm->rx_packet_count++; - cm->rx_byte_count += len; - - /* - * If we're not already on the active list then insert ourselves at the tail - * of the current list. - */ - if (unlikely(!cm->active)) { - cm->active = true; - cm->active_prev = si->active_tail; - if (likely(si->active_tail)) { - si->active_tail->active_next = cm; - } else { - si->active_head = cm; - } - si->active_tail = cm; - } - - xmit_dev = cm->xmit_dev; - skb->dev = xmit_dev; - - /* - * Check to see if we need to write a header. - */ - if (likely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_L2_HDR)) { - if (unlikely(!(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR))) { - dev_hard_header(skb, xmit_dev, ETH_P_IP, - cm->xmit_dest_mac, cm->xmit_src_mac, len); - } else { - /* - * For the simple case we write this really fast. - */ - struct sfe_ipv4_eth_hdr *eth = (struct sfe_ipv4_eth_hdr *)__skb_push(skb, ETH_HLEN); - eth->h_proto = htons(ETH_P_IP); - eth->h_dest[0] = cm->xmit_dest_mac[0]; - eth->h_dest[1] = cm->xmit_dest_mac[1]; - eth->h_dest[2] = cm->xmit_dest_mac[2]; - eth->h_source[0] = cm->xmit_src_mac[0]; - eth->h_source[1] = cm->xmit_src_mac[1]; - eth->h_source[2] = cm->xmit_src_mac[2]; - } - } - - /* - * Update priority of skb. - */ - if (unlikely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_PRIORITY_REMARK)) { - skb->priority = cm->priority; - } - - /* - * Mark outgoing packet. - */ - skb->mark = cm->connection->mark; - if (skb->mark) { - DEBUG_TRACE("SKB MARK is NON ZERO %x\n", skb->mark); - } - - si->packets_forwarded++; - spin_unlock_bh(&si->lock); - - /* - * We're going to check for GSO flags when we transmit the packet so - * start fetching the necessary cache line now. - */ - prefetch(skb_shinfo(skb)); - - /* - * Mark that this packet has been fast forwarded. - */ - skb->fast_forwarded = 1; - - /* - * Send the packet on its way. - */ - dev_queue_xmit(skb); - - return 1; -} - -/* - * sfe_ipv4_process_tcp_option_sack() - * Parse TCP SACK option and update ack according - */ -static bool sfe_ipv4_process_tcp_option_sack(const struct sfe_ipv4_tcp_hdr *th, const u32 data_offs, - u32 *ack) -{ - u32 length = sizeof(struct sfe_ipv4_tcp_hdr); - u8 *ptr = (u8 *)th + length; - - /* - * Ignore processing if TCP packet has only TIMESTAMP option. - */ - if (likely(data_offs == length + TCPOLEN_TIMESTAMP + 1 + 1) - && likely(ptr[0] == TCPOPT_NOP) - && likely(ptr[1] == TCPOPT_NOP) - && likely(ptr[2] == TCPOPT_TIMESTAMP) - && likely(ptr[3] == TCPOLEN_TIMESTAMP)) { - return true; - } - - /* - * TCP options. Parse SACK option. - */ - while (length < data_offs) { - u8 size; - u8 kind; - - ptr = (u8 *)th + length; - kind = *ptr; - - /* - * NOP, for padding - * Not in the switch because to fast escape and to not calculate size - */ - if (kind == TCPOPT_NOP) { - length++; - continue; - } - - if (kind == TCPOPT_SACK) { - u32 sack = 0; - u8 re = 1 + 1; - - size = *(ptr + 1); - if ((size < (1 + 1 + TCPOLEN_SACK_PERBLOCK)) - || ((size - (1 + 1)) % (TCPOLEN_SACK_PERBLOCK)) - || (size > (data_offs - length))) { - return false; - } - - re += 4; - while (re < size) { - u32 sack_re; - u8 *sptr = ptr + re; - sack_re = (sptr[0] << 24) | (sptr[1] << 16) | (sptr[2] << 8) | sptr[3]; - if (sack_re > sack) { - sack = sack_re; - } - re += TCPOLEN_SACK_PERBLOCK; - } - if (sack > *ack) { - *ack = sack; - } - length += size; - continue; - } - if (kind == TCPOPT_EOL) { - return true; - } - size = *(ptr + 1); - if (size < 2) { - return false; - } - length += size; - } - - return true; -} - -/* - * sfe_ipv4_recv_tcp() - * Handle TCP packet receives and forwarding. - */ -static int sfe_ipv4_recv_tcp(struct sfe_ipv4 *si, struct sk_buff *skb, struct net_device *dev, - unsigned int len, struct sfe_ipv4_ip_hdr *iph, unsigned int ihl, bool flush_on_find) -{ - struct sfe_ipv4_tcp_hdr *tcph; - __be32 src_ip; - __be32 dest_ip; - __be16 src_port; - __be16 dest_port; - struct sfe_ipv4_connection_match *cm; - struct sfe_ipv4_connection_match *counter_cm; - u8 ttl; - u32 flags; - struct net_device *xmit_dev; - - /* - * Is our packet too short to contain a valid UDP header? - */ - if (unlikely(!pskb_may_pull(skb, (sizeof(struct sfe_ipv4_tcp_hdr) + ihl)))) { - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_HEADER_INCOMPLETE]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("packet too short for TCP header\n"); - return 0; - } - - /* - * Read the IP address and port information. Read the IP header data first - * because we've almost certainly got that in the cache. We may not yet have - * the TCP header cached though so allow more time for any prefetching. - */ - src_ip = iph->saddr; - dest_ip = iph->daddr; - - tcph = (struct sfe_ipv4_tcp_hdr *)(skb->data + ihl); - src_port = tcph->source; - dest_port = tcph->dest; - flags = tcp_flag_word(tcph); - - spin_lock_bh(&si->lock); - - /* - * Look for a connection match. - */ -#ifdef CONFIG_NF_FLOW_COOKIE - cm = si->sfe_flow_cookie_table[skb->flow_cookie & SFE_FLOW_COOKIE_MASK].match; - if (unlikely(!cm)) { - cm = sfe_ipv4_find_sfe_ipv4_connection_match(si, dev, IPPROTO_TCP, src_ip, src_port, dest_ip, dest_port); - } -#else - cm = sfe_ipv4_find_sfe_ipv4_connection_match(si, dev, IPPROTO_TCP, src_ip, src_port, dest_ip, dest_port); -#endif - if (unlikely(!cm)) { - /* - * We didn't get a connection but as TCP is connection-oriented that - * may be because this is a non-fast connection (not running established). - * For diagnostic purposes we differentiate this here. - */ - if (likely((flags & (TCP_FLAG_SYN | TCP_FLAG_RST | TCP_FLAG_FIN | TCP_FLAG_ACK)) == TCP_FLAG_ACK)) { - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_NO_CONNECTION_FAST_FLAGS]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("no connection found - fast flags\n"); - return 0; - } - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_NO_CONNECTION_SLOW_FLAGS]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("no connection found - slow flags: 0x%x\n", - flags & (TCP_FLAG_SYN | TCP_FLAG_RST | TCP_FLAG_FIN | TCP_FLAG_ACK)); - return 0; - } - - /* - * If our packet has beern marked as "flush on find" we can't actually - * forward it in the fast path, but now that we've found an associated - * connection we can flush that out before we process the packet. - */ - if (unlikely(flush_on_find)) { - struct sfe_ipv4_connection *c = cm->connection; - sfe_ipv4_remove_sfe_ipv4_connection(si, c); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_IP_OPTIONS_OR_INITIAL_FRAGMENT]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("flush on find\n"); - sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; - } - -#ifdef CONFIG_XFRM - /* - * We can't accelerate the flow on this direction, just let it go - * through the slow path. - */ - if (unlikely(!cm->flow_accel)) { - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - return 0; - } -#endif - /* - * Does our TTL allow forwarding? - */ - ttl = iph->ttl; - if (unlikely(ttl < 2)) { - struct sfe_ipv4_connection *c = cm->connection; - sfe_ipv4_remove_sfe_ipv4_connection(si, c); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_SMALL_TTL]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("ttl too low\n"); - sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; - } - - /* - * If our packet is larger than the MTU of the transmit interface then - * we can't forward it easily. - */ - if (unlikely((len > cm->xmit_dev_mtu) && !skb_is_gso(skb))) { - struct sfe_ipv4_connection *c = cm->connection; - sfe_ipv4_remove_sfe_ipv4_connection(si, c); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_NEEDS_FRAGMENTATION]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("larger than mtu\n"); - sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; - } - - /* - * Look at our TCP flags. Anything missing an ACK or that has RST, SYN or FIN - * set is not a fast path packet. - */ - if (unlikely((flags & (TCP_FLAG_SYN | TCP_FLAG_RST | TCP_FLAG_FIN | TCP_FLAG_ACK)) != TCP_FLAG_ACK)) { - struct sfe_ipv4_connection *c = cm->connection; - sfe_ipv4_remove_sfe_ipv4_connection(si, c); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_FLAGS]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("TCP flags: 0x%x are not fast\n", - flags & (TCP_FLAG_SYN | TCP_FLAG_RST | TCP_FLAG_FIN | TCP_FLAG_ACK)); - sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; - } - - counter_cm = cm->counter_match; - - /* - * Are we doing sequence number checking? - */ - if (likely(!(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK))) { - u32 seq; - u32 ack; - u32 sack; - u32 data_offs; - u32 end; - u32 left_edge; - u32 scaled_win; - u32 max_end; - - /* - * Is our sequence fully past the right hand edge of the window? - */ - seq = ntohl(tcph->seq); - if (unlikely((s32)(seq - (cm->protocol_state.tcp.max_end + 1)) > 0)) { - struct sfe_ipv4_connection *c = cm->connection; - sfe_ipv4_remove_sfe_ipv4_connection(si, c); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_SEQ_EXCEEDS_RIGHT_EDGE]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("seq: %u exceeds right edge: %u\n", - seq, cm->protocol_state.tcp.max_end + 1); - sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; - } - - /* - * Check that our TCP data offset isn't too short. - */ - data_offs = tcph->doff << 2; - if (unlikely(data_offs < sizeof(struct sfe_ipv4_tcp_hdr))) { - struct sfe_ipv4_connection *c = cm->connection; - sfe_ipv4_remove_sfe_ipv4_connection(si, c); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_SMALL_DATA_OFFS]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("TCP data offset: %u, too small\n", data_offs); - sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; - } - - /* - * Update ACK according to any SACK option. - */ - ack = ntohl(tcph->ack_seq); - sack = ack; - if (unlikely(!sfe_ipv4_process_tcp_option_sack(tcph, data_offs, &sack))) { - struct sfe_ipv4_connection *c = cm->connection; - sfe_ipv4_remove_sfe_ipv4_connection(si, c); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_BAD_SACK]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("TCP option SACK size is wrong\n"); - sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; - } - - /* - * Check that our TCP data offset isn't past the end of the packet. - */ - data_offs += sizeof(struct sfe_ipv4_ip_hdr); - if (unlikely(len < data_offs)) { - struct sfe_ipv4_connection *c = cm->connection; - sfe_ipv4_remove_sfe_ipv4_connection(si, c); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_BIG_DATA_OFFS]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("TCP data offset: %u, past end of packet: %u\n", - data_offs, len); - sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; - } - - end = seq + len - data_offs; - - /* - * Is our sequence fully before the left hand edge of the window? - */ - if (unlikely((s32)(end - (cm->protocol_state.tcp.end - - counter_cm->protocol_state.tcp.max_win - 1)) < 0)) { - struct sfe_ipv4_connection *c = cm->connection; - sfe_ipv4_remove_sfe_ipv4_connection(si, c); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_SEQ_BEFORE_LEFT_EDGE]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("seq: %u before left edge: %u\n", - end, cm->protocol_state.tcp.end - counter_cm->protocol_state.tcp.max_win - 1); - sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; - } - - /* - * Are we acking data that is to the right of what has been sent? - */ - if (unlikely((s32)(sack - (counter_cm->protocol_state.tcp.end + 1)) > 0)) { - struct sfe_ipv4_connection *c = cm->connection; - sfe_ipv4_remove_sfe_ipv4_connection(si, c); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_ACK_EXCEEDS_RIGHT_EDGE]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("ack: %u exceeds right edge: %u\n", - sack, counter_cm->protocol_state.tcp.end + 1); - sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; - } - - /* - * Is our ack too far before the left hand edge of the window? - */ - left_edge = counter_cm->protocol_state.tcp.end - - cm->protocol_state.tcp.max_win - - SFE_IPV4_TCP_MAX_ACK_WINDOW - - 1; - if (unlikely((s32)(sack - left_edge) < 0)) { - struct sfe_ipv4_connection *c = cm->connection; - sfe_ipv4_remove_sfe_ipv4_connection(si, c); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_ACK_BEFORE_LEFT_EDGE]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("ack: %u before left edge: %u\n", sack, left_edge); - sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; - } - - /* - * Have we just seen the largest window size yet for this connection? If yes - * then we need to record the new value. - */ - scaled_win = ntohs(tcph->window) << cm->protocol_state.tcp.win_scale; - scaled_win += (sack - ack); - if (unlikely(cm->protocol_state.tcp.max_win < scaled_win)) { - cm->protocol_state.tcp.max_win = scaled_win; - } - - /* - * If our sequence and/or ack numbers have advanced then record the new state. - */ - if (likely((s32)(end - cm->protocol_state.tcp.end) >= 0)) { - cm->protocol_state.tcp.end = end; - } - - max_end = sack + scaled_win; - if (likely((s32)(max_end - counter_cm->protocol_state.tcp.max_end) >= 0)) { - counter_cm->protocol_state.tcp.max_end = max_end; - } - } - - /* - * From this point on we're good to modify the packet. - */ - - /* - * Check if skb was cloned. If it was, unshare it. Because - * the data area is going to be written in this path and we don't want to - * change the cloned skb's data section. - */ - if (unlikely(skb_cloned(skb))) { - DEBUG_TRACE("%px: skb is a cloned skb\n", skb); - skb = skb_unshare(skb, GFP_ATOMIC); - if (!skb) { - DEBUG_WARN("Failed to unshare the cloned skb\n"); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_CLONED_SKB_UNSHARE_ERROR]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - return 0; - } - - /* - * Update the iph and tcph pointers with the unshared skb's data area. - */ - iph = (struct sfe_ipv4_ip_hdr *)skb->data; - tcph = (struct sfe_ipv4_tcp_hdr *)(skb->data + ihl); - } - - /* - * Update DSCP - */ - if (unlikely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_DSCP_REMARK)) { - iph->tos = (iph->tos & SFE_IPV4_DSCP_MASK) | cm->dscp; - } - - /* - * Decrement our TTL. - */ - iph->ttl = ttl - 1; - - /* - * Do we have to perform translations of the source address/port? - */ - if (unlikely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_SRC)) { - u16 tcp_csum; - u32 sum; - - iph->saddr = cm->xlate_src_ip; - tcph->source = cm->xlate_src_port; - - /* - * Do we have a non-zero UDP checksum? If we do then we need - * to update it. - */ - tcp_csum = tcph->check; - if (unlikely(skb->ip_summed == CHECKSUM_PARTIAL)) { - sum = tcp_csum + cm->xlate_src_partial_csum_adjustment; - } else { - sum = tcp_csum + cm->xlate_src_csum_adjustment; - } - - sum = (sum & 0xffff) + (sum >> 16); - tcph->check = (u16)sum; - } - - /* - * Do we have to perform translations of the destination address/port? - */ - if (unlikely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_DEST)) { - u16 tcp_csum; - u32 sum; - - iph->daddr = cm->xlate_dest_ip; - tcph->dest = cm->xlate_dest_port; - - /* - * Do we have a non-zero UDP checksum? If we do then we need - * to update it. - */ - tcp_csum = tcph->check; - if (unlikely(skb->ip_summed == CHECKSUM_PARTIAL)) { - sum = tcp_csum + cm->xlate_dest_partial_csum_adjustment; - } else { - sum = tcp_csum + cm->xlate_dest_csum_adjustment; - } - - sum = (sum & 0xffff) + (sum >> 16); - tcph->check = (u16)sum; - } - - /* - * Replace the IP checksum. - */ - iph->check = sfe_ipv4_gen_ip_csum(iph); - - /* - * Update traffic stats. - */ - cm->rx_packet_count++; - cm->rx_byte_count += len; - - /* - * If we're not already on the active list then insert ourselves at the tail - * of the current list. - */ - if (unlikely(!cm->active)) { - cm->active = true; - cm->active_prev = si->active_tail; - if (likely(si->active_tail)) { - si->active_tail->active_next = cm; - } else { - si->active_head = cm; - } - si->active_tail = cm; - } - - xmit_dev = cm->xmit_dev; - skb->dev = xmit_dev; - - /* - * Check to see if we need to write a header. - */ - if (likely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_L2_HDR)) { - if (unlikely(!(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR))) { - dev_hard_header(skb, xmit_dev, ETH_P_IP, - cm->xmit_dest_mac, cm->xmit_src_mac, len); - } else { - /* - * For the simple case we write this really fast. - */ - struct sfe_ipv4_eth_hdr *eth = (struct sfe_ipv4_eth_hdr *)__skb_push(skb, ETH_HLEN); - eth->h_proto = htons(ETH_P_IP); - eth->h_dest[0] = cm->xmit_dest_mac[0]; - eth->h_dest[1] = cm->xmit_dest_mac[1]; - eth->h_dest[2] = cm->xmit_dest_mac[2]; - eth->h_source[0] = cm->xmit_src_mac[0]; - eth->h_source[1] = cm->xmit_src_mac[1]; - eth->h_source[2] = cm->xmit_src_mac[2]; - } - } - - /* - * Update priority of skb. - */ - if (unlikely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_PRIORITY_REMARK)) { - skb->priority = cm->priority; - } - - /* - * Mark outgoing packet - */ - skb->mark = cm->connection->mark; - if (skb->mark) { - DEBUG_TRACE("SKB MARK is NON ZERO %x\n", skb->mark); - } - - si->packets_forwarded++; - spin_unlock_bh(&si->lock); - - /* - * We're going to check for GSO flags when we transmit the packet so - * start fetching the necessary cache line now. - */ - prefetch(skb_shinfo(skb)); - - /* - * Mark that this packet has been fast forwarded. - */ - skb->fast_forwarded = 1; - - /* - * Send the packet on its way. - */ - dev_queue_xmit(skb); - - return 1; -} - -/* - * sfe_ipv4_recv_icmp() - * Handle ICMP packet receives. - * - * ICMP packets aren't handled as a "fast path" and always have us process them - * through the default Linux stack. What we do need to do is look for any errors - * about connections we are handling in the fast path. If we find any such - * connections then we want to flush their state so that the ICMP error path - * within Linux has all of the correct state should it need it. - */ -static int sfe_ipv4_recv_icmp(struct sfe_ipv4 *si, struct sk_buff *skb, struct net_device *dev, - unsigned int len, struct sfe_ipv4_ip_hdr *iph, unsigned int ihl) -{ - struct icmphdr *icmph; - struct sfe_ipv4_ip_hdr *icmp_iph; - unsigned int icmp_ihl_words; - unsigned int icmp_ihl; - u32 *icmp_trans_h; - struct sfe_ipv4_udp_hdr *icmp_udph; - struct sfe_ipv4_tcp_hdr *icmp_tcph; - __be32 src_ip; - __be32 dest_ip; - __be16 src_port; - __be16 dest_port; - struct sfe_ipv4_connection_match *cm; - struct sfe_ipv4_connection *c; - u32 pull_len = sizeof(struct icmphdr) + ihl; - - /* - * Is our packet too short to contain a valid ICMP header? - */ - len -= ihl; - if (!pskb_may_pull(skb, pull_len)) { - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_HEADER_INCOMPLETE]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("packet too short for ICMP header\n"); - return 0; - } - - /* - * We only handle "destination unreachable" and "time exceeded" messages. - */ - icmph = (struct icmphdr *)(skb->data + ihl); - if ((icmph->type != ICMP_DEST_UNREACH) - && (icmph->type != ICMP_TIME_EXCEEDED)) { - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_UNHANDLED_TYPE]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("unhandled ICMP type: 0x%x\n", icmph->type); - return 0; - } - - /* - * Do we have the full embedded IP header? - */ - len -= sizeof(struct icmphdr); - pull_len += sizeof(struct sfe_ipv4_ip_hdr); - if (!pskb_may_pull(skb, pull_len)) { - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_HEADER_INCOMPLETE]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("Embedded IP header not complete\n"); - return 0; - } - - /* - * Is our embedded IP version wrong? - */ - icmp_iph = (struct sfe_ipv4_ip_hdr *)(icmph + 1); - if (unlikely(icmp_iph->version != 4)) { - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_NON_V4]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("IP version: %u\n", icmp_iph->version); - return 0; - } - - /* - * Do we have the full embedded IP header, including any options? - */ - icmp_ihl_words = icmp_iph->ihl; - icmp_ihl = icmp_ihl_words << 2; - pull_len += icmp_ihl - sizeof(struct sfe_ipv4_ip_hdr); - if (!pskb_may_pull(skb, pull_len)) { - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_IP_OPTIONS_INCOMPLETE]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("Embedded header not large enough for IP options\n"); - return 0; - } - - len -= icmp_ihl; - icmp_trans_h = ((u32 *)icmp_iph) + icmp_ihl_words; - - /* - * Handle the embedded transport layer header. - */ - switch (icmp_iph->protocol) { - case IPPROTO_UDP: - /* - * We should have 8 bytes of UDP header - that's enough to identify - * the connection. - */ - pull_len += 8; - if (!pskb_may_pull(skb, pull_len)) { - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_UDP_HEADER_INCOMPLETE]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("Incomplete embedded UDP header\n"); - return 0; - } - - icmp_udph = (struct sfe_ipv4_udp_hdr *)icmp_trans_h; - src_port = icmp_udph->source; - dest_port = icmp_udph->dest; - break; - - case IPPROTO_TCP: - /* - * We should have 8 bytes of TCP header - that's enough to identify - * the connection. - */ - pull_len += 8; - if (!pskb_may_pull(skb, pull_len)) { - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_TCP_HEADER_INCOMPLETE]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("Incomplete embedded TCP header\n"); - return 0; - } - - icmp_tcph = (struct sfe_ipv4_tcp_hdr *)icmp_trans_h; - src_port = icmp_tcph->source; - dest_port = icmp_tcph->dest; - break; - - default: - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_UNHANDLED_PROTOCOL]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("Unhandled embedded IP protocol: %u\n", icmp_iph->protocol); - return 0; - } - - src_ip = icmp_iph->saddr; - dest_ip = icmp_iph->daddr; - - spin_lock_bh(&si->lock); - - /* - * Look for a connection match. Note that we reverse the source and destination - * here because our embedded message contains a packet that was sent in the - * opposite direction to the one in which we just received it. It will have - * been sent on the interface from which we received it though so that's still - * ok to use. - */ - cm = sfe_ipv4_find_sfe_ipv4_connection_match(si, dev, icmp_iph->protocol, dest_ip, dest_port, src_ip, src_port); - if (unlikely(!cm)) { - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_NO_CONNECTION]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("no connection found\n"); - return 0; - } - - /* - * We found a connection so now remove it from the connection list and flush - * its state. - */ - c = cm->connection; - sfe_ipv4_remove_sfe_ipv4_connection(si, c); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_FLUSHED_CONNECTION]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; -} - -/* - * sfe_ipv4_recv() - * Handle packet receives and forwaring. - * - * Returns 1 if the packet is forwarded or 0 if it isn't. - */ -int sfe_ipv4_recv(struct net_device *dev, struct sk_buff *skb) -{ - struct sfe_ipv4 *si = &__si; - unsigned int len; - unsigned int tot_len; - unsigned int frag_off; - unsigned int ihl; - bool flush_on_find; - bool ip_options; - struct sfe_ipv4_ip_hdr *iph; - u32 protocol; - - /* - * Check that we have space for an IP header here. - */ - len = skb->len; - if (unlikely(!pskb_may_pull(skb, sizeof(struct sfe_ipv4_ip_hdr)))) { - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_HEADER_INCOMPLETE]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("len: %u is too short\n", len); - return 0; - } - - /* - * Check that our "total length" is large enough for an IP header. - */ - iph = (struct sfe_ipv4_ip_hdr *)skb->data; - tot_len = ntohs(iph->tot_len); - if (unlikely(tot_len < sizeof(struct sfe_ipv4_ip_hdr))) { - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_BAD_TOTAL_LENGTH]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("tot_len: %u is too short\n", tot_len); - return 0; - } - - /* - * Is our IP version wrong? - */ - if (unlikely(iph->version != 4)) { - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_NON_V4]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("IP version: %u\n", iph->version); - return 0; - } - - /* - * Does our datagram fit inside the skb? - */ - if (unlikely(tot_len > len)) { - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_DATAGRAM_INCOMPLETE]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("tot_len: %u, exceeds len: %u\n", tot_len, len); - return 0; - } - - /* - * Do we have a non-initial fragment? - */ - frag_off = ntohs(iph->frag_off); - if (unlikely(frag_off & IP_OFFSET)) { - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_NON_INITIAL_FRAGMENT]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("non-initial fragment\n"); - return 0; - } - - /* - * If we have a (first) fragment then mark it to cause any connection to flush. - */ - flush_on_find = unlikely(frag_off & IP_MF) ? true : false; - - /* - * Do we have any IP options? That's definite a slow path! If we do have IP - * options we need to recheck our header size. - */ - ihl = iph->ihl << 2; - ip_options = unlikely(ihl != sizeof(struct sfe_ipv4_ip_hdr)) ? true : false; - if (unlikely(ip_options)) { - if (unlikely(len < ihl)) { - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_IP_OPTIONS_INCOMPLETE]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("len: %u is too short for header of size: %u\n", len, ihl); - return 0; - } - - flush_on_find = true; - } - - protocol = iph->protocol; - if (IPPROTO_UDP == protocol) { - return sfe_ipv4_recv_udp(si, skb, dev, len, iph, ihl, flush_on_find); - } - - if (IPPROTO_TCP == protocol) { - return sfe_ipv4_recv_tcp(si, skb, dev, len, iph, ihl, flush_on_find); - } - - if (IPPROTO_ICMP == protocol) { - return sfe_ipv4_recv_icmp(si, skb, dev, len, iph, ihl); - } - - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV4_EXCEPTION_EVENT_UNHANDLED_PROTOCOL]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("not UDP, TCP or ICMP: %u\n", protocol); - return 0; -} - -static void -sfe_ipv4_update_tcp_state(struct sfe_ipv4_connection *c, - struct sfe_connection_create *sic) -{ - struct sfe_ipv4_connection_match *orig_cm; - struct sfe_ipv4_connection_match *repl_cm; - struct sfe_ipv4_tcp_connection_match *orig_tcp; - struct sfe_ipv4_tcp_connection_match *repl_tcp; - - orig_cm = c->original_match; - repl_cm = c->reply_match; - orig_tcp = &orig_cm->protocol_state.tcp; - repl_tcp = &repl_cm->protocol_state.tcp; - - /* update orig */ - if (orig_tcp->max_win < sic->src_td_max_window) { - orig_tcp->max_win = sic->src_td_max_window; - } - if ((s32)(orig_tcp->end - sic->src_td_end) < 0) { - orig_tcp->end = sic->src_td_end; - } - if ((s32)(orig_tcp->max_end - sic->src_td_max_end) < 0) { - orig_tcp->max_end = sic->src_td_max_end; - } - - /* update reply */ - if (repl_tcp->max_win < sic->dest_td_max_window) { - repl_tcp->max_win = sic->dest_td_max_window; - } - if ((s32)(repl_tcp->end - sic->dest_td_end) < 0) { - repl_tcp->end = sic->dest_td_end; - } - if ((s32)(repl_tcp->max_end - sic->dest_td_max_end) < 0) { - repl_tcp->max_end = sic->dest_td_max_end; - } - - /* update match flags */ - orig_cm->flags &= ~SFE_IPV4_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; - repl_cm->flags &= ~SFE_IPV4_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; - if (sic->flags & SFE_CREATE_FLAG_NO_SEQ_CHECK) { - orig_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; - repl_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; - } -} - -static void -sfe_ipv4_update_protocol_state(struct sfe_ipv4_connection *c, - struct sfe_connection_create *sic) -{ - switch (sic->protocol) { - case IPPROTO_TCP: - sfe_ipv4_update_tcp_state(c, sic); - break; - } -} - -void sfe_ipv4_update_rule(struct sfe_connection_create *sic) -{ - struct sfe_ipv4_connection *c; - struct sfe_ipv4 *si = &__si; - - spin_lock_bh(&si->lock); - - c = sfe_ipv4_find_sfe_ipv4_connection(si, - sic->protocol, - sic->src_ip.ip, - sic->src_port, - sic->dest_ip.ip, - sic->dest_port); - if (c != NULL) { - sfe_ipv4_update_protocol_state(c, sic); - } - - spin_unlock_bh(&si->lock); -} - -/* - * sfe_ipv4_create_rule() - * Create a forwarding rule. - */ -int sfe_ipv4_create_rule(struct sfe_connection_create *sic) -{ - struct sfe_ipv4 *si = &__si; - struct sfe_ipv4_connection *c; - struct sfe_ipv4_connection_match *original_cm; - struct sfe_ipv4_connection_match *reply_cm; - struct net_device *dest_dev; - struct net_device *src_dev; - - dest_dev = sic->dest_dev; - src_dev = sic->src_dev; - - if (unlikely((dest_dev->reg_state != NETREG_REGISTERED) || - (src_dev->reg_state != NETREG_REGISTERED))) { - return -EINVAL; - } - - spin_lock_bh(&si->lock); - si->connection_create_requests++; - - /* - * Check to see if there is already a flow that matches the rule we're - * trying to create. If there is then we can't create a new one. - */ - c = sfe_ipv4_find_sfe_ipv4_connection(si, - sic->protocol, - sic->src_ip.ip, - sic->src_port, - sic->dest_ip.ip, - sic->dest_port); - if (c != NULL) { - si->connection_create_collisions++; - - /* - * If we already have the flow then it's likely that this - * request to create the connection rule contains more - * up-to-date information. Check and update accordingly. - */ - sfe_ipv4_update_protocol_state(c, sic); - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("connection already exists - mark: %08x, p: %d\n" - " s: %s:%pxM:%pI4:%u, d: %s:%pxM:%pI4:%u\n", - sic->mark, sic->protocol, - sic->src_dev->name, sic->src_mac, &sic->src_ip.ip, ntohs(sic->src_port), - sic->dest_dev->name, sic->dest_mac, &sic->dest_ip.ip, ntohs(sic->dest_port)); - return -EADDRINUSE; - } - - /* - * Allocate the various connection tracking objects. - */ - c = (struct sfe_ipv4_connection *)kmalloc(sizeof(struct sfe_ipv4_connection), GFP_ATOMIC); - if (unlikely(!c)) { - spin_unlock_bh(&si->lock); - return -ENOMEM; - } - - original_cm = (struct sfe_ipv4_connection_match *)kmalloc(sizeof(struct sfe_ipv4_connection_match), GFP_ATOMIC); - if (unlikely(!original_cm)) { - spin_unlock_bh(&si->lock); - kfree(c); - return -ENOMEM; - } - - reply_cm = (struct sfe_ipv4_connection_match *)kmalloc(sizeof(struct sfe_ipv4_connection_match), GFP_ATOMIC); - if (unlikely(!reply_cm)) { - spin_unlock_bh(&si->lock); - kfree(original_cm); - kfree(c); - return -ENOMEM; - } - - /* - * Fill in the "original" direction connection matching object. - * Note that the transmit MAC address is "dest_mac_xlate" because - * we always know both ends of a connection by their translated - * addresses and not their public addresses. - */ - original_cm->match_dev = src_dev; - original_cm->match_protocol = sic->protocol; - original_cm->match_src_ip = sic->src_ip.ip; - original_cm->match_src_port = sic->src_port; - original_cm->match_dest_ip = sic->dest_ip.ip; - original_cm->match_dest_port = sic->dest_port; - original_cm->xlate_src_ip = sic->src_ip_xlate.ip; - original_cm->xlate_src_port = sic->src_port_xlate; - original_cm->xlate_dest_ip = sic->dest_ip_xlate.ip; - original_cm->xlate_dest_port = sic->dest_port_xlate; - original_cm->rx_packet_count = 0; - original_cm->rx_packet_count64 = 0; - original_cm->rx_byte_count = 0; - original_cm->rx_byte_count64 = 0; - original_cm->xmit_dev = dest_dev; - original_cm->xmit_dev_mtu = sic->dest_mtu; - memcpy(original_cm->xmit_src_mac, dest_dev->dev_addr, ETH_ALEN); - memcpy(original_cm->xmit_dest_mac, sic->dest_mac_xlate, ETH_ALEN); - original_cm->connection = c; - original_cm->counter_match = reply_cm; - original_cm->flags = 0; - if (sic->flags & SFE_CREATE_FLAG_REMARK_PRIORITY) { - original_cm->priority = sic->src_priority; - original_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_PRIORITY_REMARK; - } - if (sic->flags & SFE_CREATE_FLAG_REMARK_DSCP) { - original_cm->dscp = sic->src_dscp << SFE_IPV4_DSCP_SHIFT; - original_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_DSCP_REMARK; - } -#ifdef CONFIG_NF_FLOW_COOKIE - original_cm->flow_cookie = 0; -#endif -#ifdef CONFIG_XFRM - original_cm->flow_accel = sic->original_accel; -#endif - original_cm->active_next = NULL; - original_cm->active_prev = NULL; - original_cm->active = false; - - /* - * For PPP links we don't write an L2 header. For everything else we do. - */ - if (!(dest_dev->flags & IFF_POINTOPOINT)) { - original_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_L2_HDR; - - /* - * If our dev writes Ethernet headers then we can write a really fast - * version. - */ - if (dest_dev->header_ops) { - if (dest_dev->header_ops->create == eth_header) { - original_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR; - } - } - } - - /* - * Fill in the "reply" direction connection matching object. - */ - reply_cm->match_dev = dest_dev; - reply_cm->match_protocol = sic->protocol; - reply_cm->match_src_ip = sic->dest_ip_xlate.ip; - reply_cm->match_src_port = sic->dest_port_xlate; - reply_cm->match_dest_ip = sic->src_ip_xlate.ip; - reply_cm->match_dest_port = sic->src_port_xlate; - reply_cm->xlate_src_ip = sic->dest_ip.ip; - reply_cm->xlate_src_port = sic->dest_port; - reply_cm->xlate_dest_ip = sic->src_ip.ip; - reply_cm->xlate_dest_port = sic->src_port; - reply_cm->rx_packet_count = 0; - reply_cm->rx_packet_count64 = 0; - reply_cm->rx_byte_count = 0; - reply_cm->rx_byte_count64 = 0; - reply_cm->xmit_dev = src_dev; - reply_cm->xmit_dev_mtu = sic->src_mtu; - memcpy(reply_cm->xmit_src_mac, src_dev->dev_addr, ETH_ALEN); - memcpy(reply_cm->xmit_dest_mac, sic->src_mac, ETH_ALEN); - reply_cm->connection = c; - reply_cm->counter_match = original_cm; - reply_cm->flags = 0; - if (sic->flags & SFE_CREATE_FLAG_REMARK_PRIORITY) { - reply_cm->priority = sic->dest_priority; - reply_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_PRIORITY_REMARK; - } - if (sic->flags & SFE_CREATE_FLAG_REMARK_DSCP) { - reply_cm->dscp = sic->dest_dscp << SFE_IPV4_DSCP_SHIFT; - reply_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_DSCP_REMARK; - } -#ifdef CONFIG_NF_FLOW_COOKIE - reply_cm->flow_cookie = 0; -#endif -#ifdef CONFIG_XFRM - reply_cm->flow_accel = sic->reply_accel; -#endif - reply_cm->active_next = NULL; - reply_cm->active_prev = NULL; - reply_cm->active = false; - - /* - * For PPP links we don't write an L2 header. For everything else we do. - */ - if (!(src_dev->flags & IFF_POINTOPOINT)) { - reply_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_L2_HDR; - - /* - * If our dev writes Ethernet headers then we can write a really fast - * version. - */ - if (src_dev->header_ops) { - if (src_dev->header_ops->create == eth_header) { - reply_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR; - } - } - } - - - if (sic->dest_ip.ip != sic->dest_ip_xlate.ip || sic->dest_port != sic->dest_port_xlate) { - original_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_DEST; - reply_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_SRC; - } - - if (sic->src_ip.ip != sic->src_ip_xlate.ip || sic->src_port != sic->src_port_xlate) { - original_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_SRC; - reply_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_DEST; - } - - c->protocol = sic->protocol; - c->src_ip = sic->src_ip.ip; - c->src_ip_xlate = sic->src_ip_xlate.ip; - c->src_port = sic->src_port; - c->src_port_xlate = sic->src_port_xlate; - c->original_dev = src_dev; - c->original_match = original_cm; - c->dest_ip = sic->dest_ip.ip; - c->dest_ip_xlate = sic->dest_ip_xlate.ip; - c->dest_port = sic->dest_port; - c->dest_port_xlate = sic->dest_port_xlate; - c->reply_dev = dest_dev; - c->reply_match = reply_cm; - c->mark = sic->mark; - c->debug_read_seq = 0; - c->last_sync_jiffies = get_jiffies_64(); - - /* - * Take hold of our source and dest devices for the duration of the connection. - */ - dev_hold(c->original_dev); - dev_hold(c->reply_dev); - - /* - * Initialize the protocol-specific information that we track. - */ - switch (sic->protocol) { - case IPPROTO_TCP: - original_cm->protocol_state.tcp.win_scale = sic->src_td_window_scale; - original_cm->protocol_state.tcp.max_win = sic->src_td_max_window ? sic->src_td_max_window : 1; - original_cm->protocol_state.tcp.end = sic->src_td_end; - original_cm->protocol_state.tcp.max_end = sic->src_td_max_end; - reply_cm->protocol_state.tcp.win_scale = sic->dest_td_window_scale; - reply_cm->protocol_state.tcp.max_win = sic->dest_td_max_window ? sic->dest_td_max_window : 1; - reply_cm->protocol_state.tcp.end = sic->dest_td_end; - reply_cm->protocol_state.tcp.max_end = sic->dest_td_max_end; - if (sic->flags & SFE_CREATE_FLAG_NO_SEQ_CHECK) { - original_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; - reply_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; - } - break; - } - - sfe_ipv4_connection_match_compute_translations(original_cm); - sfe_ipv4_connection_match_compute_translations(reply_cm); - sfe_ipv4_insert_sfe_ipv4_connection(si, c); - - spin_unlock_bh(&si->lock); - - /* - * We have everything we need! - */ - DEBUG_INFO("new connection - mark: %08x, p: %d\n" - " s: %s:%pxM(%pxM):%pI4(%pI4):%u(%u)\n" - " d: %s:%pxM(%pxM):%pI4(%pI4):%u(%u)\n", - sic->mark, sic->protocol, - sic->src_dev->name, sic->src_mac, sic->src_mac_xlate, - &sic->src_ip.ip, &sic->src_ip_xlate.ip, ntohs(sic->src_port), ntohs(sic->src_port_xlate), - dest_dev->name, sic->dest_mac, sic->dest_mac_xlate, - &sic->dest_ip.ip, &sic->dest_ip_xlate.ip, ntohs(sic->dest_port), ntohs(sic->dest_port_xlate)); - - return 0; -} - -/* - * sfe_ipv4_destroy_rule() - * Destroy a forwarding rule. - */ -void sfe_ipv4_destroy_rule(struct sfe_connection_destroy *sid) -{ - struct sfe_ipv4 *si = &__si; - struct sfe_ipv4_connection *c; - - spin_lock_bh(&si->lock); - si->connection_destroy_requests++; - - /* - * Check to see if we have a flow that matches the rule we're trying - * to destroy. If there isn't then we can't destroy it. - */ - c = sfe_ipv4_find_sfe_ipv4_connection(si, sid->protocol, sid->src_ip.ip, sid->src_port, - sid->dest_ip.ip, sid->dest_port); - if (!c) { - si->connection_destroy_misses++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("connection does not exist - p: %d, s: %pI4:%u, d: %pI4:%u\n", - sid->protocol, &sid->src_ip, ntohs(sid->src_port), - &sid->dest_ip, ntohs(sid->dest_port)); - return; - } - - /* - * Remove our connection details from the hash tables. - */ - sfe_ipv4_remove_sfe_ipv4_connection(si, c); - spin_unlock_bh(&si->lock); - - sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_DESTROY); - - DEBUG_INFO("connection destroyed - p: %d, s: %pI4:%u, d: %pI4:%u\n", - sid->protocol, &sid->src_ip.ip, ntohs(sid->src_port), - &sid->dest_ip.ip, ntohs(sid->dest_port)); -} - -/* - * sfe_ipv4_register_sync_rule_callback() - * Register a callback for rule synchronization. - */ -void sfe_ipv4_register_sync_rule_callback(sfe_sync_rule_callback_t sync_rule_callback) -{ - struct sfe_ipv4 *si = &__si; - - spin_lock_bh(&si->lock); - rcu_assign_pointer(si->sync_rule_callback, sync_rule_callback); - spin_unlock_bh(&si->lock); -} - -/* - * sfe_ipv4_get_debug_dev() - */ -static ssize_t sfe_ipv4_get_debug_dev(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct sfe_ipv4 *si = &__si; - ssize_t count; - int num; - - spin_lock_bh(&si->lock); - num = si->debug_dev; - spin_unlock_bh(&si->lock); - - count = snprintf(buf, (ssize_t)PAGE_SIZE, "%d\n", num); - return count; -} - -/* - * sysfs attributes. - */ -static const struct device_attribute sfe_ipv4_debug_dev_attr = - __ATTR(debug_dev, S_IWUSR | S_IRUGO, sfe_ipv4_get_debug_dev, NULL); - -/* - * sfe_ipv4_destroy_all_rules_for_dev() - * Destroy all connections that match a particular device. - * - * If we pass dev as NULL then this destroys all connections. - */ -void sfe_ipv4_destroy_all_rules_for_dev(struct net_device *dev) -{ - struct sfe_ipv4 *si = &__si; - struct sfe_ipv4_connection *c; - -another_round: - spin_lock_bh(&si->lock); - - for (c = si->all_connections_head; c; c = c->all_connections_next) { - /* - * Does this connection relate to the device we are destroying? - */ - if (!dev - || (dev == c->original_dev) - || (dev == c->reply_dev)) { - break; - } - } - - if (c) { - sfe_ipv4_remove_sfe_ipv4_connection(si, c); - } - - spin_unlock_bh(&si->lock); - - if (c) { - sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_DESTROY); - goto another_round; - } -} - -/* - * sfe_ipv4_periodic_sync() - */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) -static void sfe_ipv4_periodic_sync(unsigned long arg) -#else -static void sfe_ipv4_periodic_sync(struct timer_list *tl) -#endif -{ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) - struct sfe_ipv4 *si = (struct sfe_ipv4 *)arg; -#else - struct sfe_ipv4 *si = from_timer(si, tl, timer); -#endif - u64 now_jiffies; - int quota; - sfe_sync_rule_callback_t sync_rule_callback; - - now_jiffies = get_jiffies_64(); - - rcu_read_lock(); - sync_rule_callback = rcu_dereference(si->sync_rule_callback); - if (!sync_rule_callback) { - rcu_read_unlock(); - goto done; - } - - spin_lock_bh(&si->lock); - sfe_ipv4_update_summary_stats(si); - - /* - * Get an estimate of the number of connections to parse in this sync. - */ - quota = (si->num_connections + 63) / 64; - - /* - * Walk the "active" list and sync the connection state. - */ - while (quota--) { - struct sfe_ipv4_connection_match *cm; - struct sfe_ipv4_connection_match *counter_cm; - struct sfe_ipv4_connection *c; - struct sfe_connection_sync sis; - - cm = si->active_head; - if (!cm) { - break; - } - - /* - * There's a possibility that our counter match is in the active list too. - * If it is then remove it. - */ - counter_cm = cm->counter_match; - if (counter_cm->active) { - counter_cm->active = false; - - /* - * We must have a connection preceding this counter match - * because that's the one that got us to this point, so we don't have - * to worry about removing the head of the list. - */ - counter_cm->active_prev->active_next = counter_cm->active_next; - - if (likely(counter_cm->active_next)) { - counter_cm->active_next->active_prev = counter_cm->active_prev; - } else { - si->active_tail = counter_cm->active_prev; - } - - counter_cm->active_next = NULL; - counter_cm->active_prev = NULL; - } - - /* - * Now remove the head of the active scan list. - */ - cm->active = false; - si->active_head = cm->active_next; - if (likely(cm->active_next)) { - cm->active_next->active_prev = NULL; - } else { - si->active_tail = NULL; - } - cm->active_next = NULL; - - /* - * Sync the connection state. - */ - c = cm->connection; - sfe_ipv4_gen_sync_sfe_ipv4_connection(si, c, &sis, SFE_SYNC_REASON_STATS, now_jiffies); - - /* - * We don't want to be holding the lock when we sync! - */ - spin_unlock_bh(&si->lock); - sync_rule_callback(&sis); - spin_lock_bh(&si->lock); - } - - spin_unlock_bh(&si->lock); - rcu_read_unlock(); - -done: - mod_timer(&si->timer, jiffies + ((HZ + 99) / 100)); -} - -#define CHAR_DEV_MSG_SIZE 768 - -/* - * sfe_ipv4_debug_dev_read_start() - * Generate part of the XML output. - */ -static bool sfe_ipv4_debug_dev_read_start(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, - int *total_read, struct sfe_ipv4_debug_xml_write_state *ws) -{ - int bytes_read; - - si->debug_read_seq++; - - bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\n"); - if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { - return false; - } - - *length -= bytes_read; - *total_read += bytes_read; - - ws->state++; - return true; -} - -/* - * sfe_ipv4_debug_dev_read_connections_start() - * Generate part of the XML output. - */ -static bool sfe_ipv4_debug_dev_read_connections_start(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, - int *total_read, struct sfe_ipv4_debug_xml_write_state *ws) -{ - int bytes_read; - - bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n"); - if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { - return false; - } - - *length -= bytes_read; - *total_read += bytes_read; - - ws->state++; - return true; -} - -/* - * sfe_ipv4_debug_dev_read_connections_connection() - * Generate part of the XML output. - */ -static bool sfe_ipv4_debug_dev_read_connections_connection(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, - int *total_read, struct sfe_ipv4_debug_xml_write_state *ws) -{ - struct sfe_ipv4_connection *c; - struct sfe_ipv4_connection_match *original_cm; - struct sfe_ipv4_connection_match *reply_cm; - int bytes_read; - int protocol; - struct net_device *src_dev; - __be32 src_ip; - __be32 src_ip_xlate; - __be16 src_port; - __be16 src_port_xlate; - u64 src_rx_packets; - u64 src_rx_bytes; - struct net_device *dest_dev; - __be32 dest_ip; - __be32 dest_ip_xlate; - __be16 dest_port; - __be16 dest_port_xlate; - u64 dest_rx_packets; - u64 dest_rx_bytes; - u64 last_sync_jiffies; - u32 mark, src_priority, dest_priority, src_dscp, dest_dscp; -#ifdef CONFIG_NF_FLOW_COOKIE - int src_flow_cookie, dst_flow_cookie; -#endif - - spin_lock_bh(&si->lock); - - for (c = si->all_connections_head; c; c = c->all_connections_next) { - if (c->debug_read_seq < si->debug_read_seq) { - c->debug_read_seq = si->debug_read_seq; - break; - } - } - - /* - * If there were no connections then move to the next state. - */ - if (!c) { - spin_unlock_bh(&si->lock); - ws->state++; - return true; - } - - original_cm = c->original_match; - reply_cm = c->reply_match; - - protocol = c->protocol; - src_dev = c->original_dev; - src_ip = c->src_ip; - src_ip_xlate = c->src_ip_xlate; - src_port = c->src_port; - src_port_xlate = c->src_port_xlate; - src_priority = original_cm->priority; - src_dscp = original_cm->dscp >> SFE_IPV4_DSCP_SHIFT; - - sfe_ipv4_connection_match_update_summary_stats(original_cm); - sfe_ipv4_connection_match_update_summary_stats(reply_cm); - - src_rx_packets = original_cm->rx_packet_count64; - src_rx_bytes = original_cm->rx_byte_count64; - dest_dev = c->reply_dev; - dest_ip = c->dest_ip; - dest_ip_xlate = c->dest_ip_xlate; - dest_port = c->dest_port; - dest_port_xlate = c->dest_port_xlate; - dest_priority = reply_cm->priority; - dest_dscp = reply_cm->dscp >> SFE_IPV4_DSCP_SHIFT; - dest_rx_packets = reply_cm->rx_packet_count64; - dest_rx_bytes = reply_cm->rx_byte_count64; - last_sync_jiffies = get_jiffies_64() - c->last_sync_jiffies; - mark = c->mark; -#ifdef CONFIG_NF_FLOW_COOKIE - src_flow_cookie = original_cm->flow_cookie; - dst_flow_cookie = reply_cm->flow_cookie; -#endif - spin_unlock_bh(&si->lock); - - bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\t\n", - protocol, - src_dev->name, - &src_ip, &src_ip_xlate, - ntohs(src_port), ntohs(src_port_xlate), - src_priority, src_dscp, - src_rx_packets, src_rx_bytes, - dest_dev->name, - &dest_ip, &dest_ip_xlate, - ntohs(dest_port), ntohs(dest_port_xlate), - dest_priority, dest_dscp, - dest_rx_packets, dest_rx_bytes, -#ifdef CONFIG_NF_FLOW_COOKIE - src_flow_cookie, dst_flow_cookie, -#endif - last_sync_jiffies, mark); - - if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { - return false; - } - - *length -= bytes_read; - *total_read += bytes_read; - - return true; -} - -/* - * sfe_ipv4_debug_dev_read_connections_end() - * Generate part of the XML output. - */ -static bool sfe_ipv4_debug_dev_read_connections_end(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, - int *total_read, struct sfe_ipv4_debug_xml_write_state *ws) -{ - int bytes_read; - - bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n"); - if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { - return false; - } - - *length -= bytes_read; - *total_read += bytes_read; - - ws->state++; - return true; -} - -/* - * sfe_ipv4_debug_dev_read_exceptions_start() - * Generate part of the XML output. - */ -static bool sfe_ipv4_debug_dev_read_exceptions_start(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, - int *total_read, struct sfe_ipv4_debug_xml_write_state *ws) -{ - int bytes_read; - - bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n"); - if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { - return false; - } - - *length -= bytes_read; - *total_read += bytes_read; - - ws->state++; - return true; -} - -/* - * sfe_ipv4_debug_dev_read_exceptions_exception() - * Generate part of the XML output. - */ -static bool sfe_ipv4_debug_dev_read_exceptions_exception(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, - int *total_read, struct sfe_ipv4_debug_xml_write_state *ws) -{ - u64 ct; - - spin_lock_bh(&si->lock); - ct = si->exception_events64[ws->iter_exception]; - spin_unlock_bh(&si->lock); - - if (ct) { - int bytes_read; - - bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, - "\t\t\n", - sfe_ipv4_exception_events_string[ws->iter_exception], - ct); - if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { - return false; - } - - *length -= bytes_read; - *total_read += bytes_read; - } - - ws->iter_exception++; - if (ws->iter_exception >= SFE_IPV4_EXCEPTION_EVENT_LAST) { - ws->iter_exception = 0; - ws->state++; - } - - return true; -} - -/* - * sfe_ipv4_debug_dev_read_exceptions_end() - * Generate part of the XML output. - */ -static bool sfe_ipv4_debug_dev_read_exceptions_end(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, - int *total_read, struct sfe_ipv4_debug_xml_write_state *ws) -{ - int bytes_read; - - bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n"); - if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { - return false; - } - - *length -= bytes_read; - *total_read += bytes_read; - - ws->state++; - return true; -} - -/* - * sfe_ipv4_debug_dev_read_stats() - * Generate part of the XML output. - */ -static bool sfe_ipv4_debug_dev_read_stats(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, - int *total_read, struct sfe_ipv4_debug_xml_write_state *ws) -{ - int bytes_read; - unsigned int num_connections; - u64 packets_forwarded; - u64 packets_not_forwarded; - u64 connection_create_requests; - u64 connection_create_collisions; - u64 connection_destroy_requests; - u64 connection_destroy_misses; - u64 connection_flushes; - u64 connection_match_hash_hits; - u64 connection_match_hash_reorders; - - spin_lock_bh(&si->lock); - sfe_ipv4_update_summary_stats(si); - - num_connections = si->num_connections; - packets_forwarded = si->packets_forwarded64; - packets_not_forwarded = si->packets_not_forwarded64; - connection_create_requests = si->connection_create_requests64; - connection_create_collisions = si->connection_create_collisions64; - connection_destroy_requests = si->connection_destroy_requests64; - connection_destroy_misses = si->connection_destroy_misses64; - connection_flushes = si->connection_flushes64; - connection_match_hash_hits = si->connection_match_hash_hits64; - connection_match_hash_reorders = si->connection_match_hash_reorders64; - spin_unlock_bh(&si->lock); - - bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n", - num_connections, - packets_forwarded, - packets_not_forwarded, - connection_create_requests, - connection_create_collisions, - connection_destroy_requests, - connection_destroy_misses, - connection_flushes, - connection_match_hash_hits, - connection_match_hash_reorders); - if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { - return false; - } - - *length -= bytes_read; - *total_read += bytes_read; - - ws->state++; - return true; -} - -/* - * sfe_ipv4_debug_dev_read_end() - * Generate part of the XML output. - */ -static bool sfe_ipv4_debug_dev_read_end(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, - int *total_read, struct sfe_ipv4_debug_xml_write_state *ws) -{ - int bytes_read; - - bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\n"); - if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { - return false; - } - - *length -= bytes_read; - *total_read += bytes_read; - - ws->state++; - return true; -} - -/* - * Array of write functions that write various XML elements that correspond to - * our XML output state machine. - */ -static sfe_ipv4_debug_xml_write_method_t sfe_ipv4_debug_xml_write_methods[SFE_IPV4_DEBUG_XML_STATE_DONE] = { - sfe_ipv4_debug_dev_read_start, - sfe_ipv4_debug_dev_read_connections_start, - sfe_ipv4_debug_dev_read_connections_connection, - sfe_ipv4_debug_dev_read_connections_end, - sfe_ipv4_debug_dev_read_exceptions_start, - sfe_ipv4_debug_dev_read_exceptions_exception, - sfe_ipv4_debug_dev_read_exceptions_end, - sfe_ipv4_debug_dev_read_stats, - sfe_ipv4_debug_dev_read_end, -}; - -/* - * sfe_ipv4_debug_dev_read() - * Send info to userspace upon read request from user - */ -static ssize_t sfe_ipv4_debug_dev_read(struct file *filp, char *buffer, size_t length, loff_t *offset) -{ - char msg[CHAR_DEV_MSG_SIZE]; - int total_read = 0; - struct sfe_ipv4_debug_xml_write_state *ws; - struct sfe_ipv4 *si = &__si; - - ws = (struct sfe_ipv4_debug_xml_write_state *)filp->private_data; - while ((ws->state != SFE_IPV4_DEBUG_XML_STATE_DONE) && (length > CHAR_DEV_MSG_SIZE)) { - if ((sfe_ipv4_debug_xml_write_methods[ws->state])(si, buffer, msg, &length, &total_read, ws)) { - continue; - } - } - - return total_read; -} - -/* - * sfe_ipv4_debug_dev_write() - * Write to char device resets some stats - */ -static ssize_t sfe_ipv4_debug_dev_write(struct file *filp, const char *buffer, size_t length, loff_t *offset) -{ - struct sfe_ipv4 *si = &__si; - - spin_lock_bh(&si->lock); - sfe_ipv4_update_summary_stats(si); - - si->packets_forwarded64 = 0; - si->packets_not_forwarded64 = 0; - si->connection_create_requests64 = 0; - si->connection_create_collisions64 = 0; - si->connection_destroy_requests64 = 0; - si->connection_destroy_misses64 = 0; - si->connection_flushes64 = 0; - si->connection_match_hash_hits64 = 0; - si->connection_match_hash_reorders64 = 0; - spin_unlock_bh(&si->lock); - - return length; -} - -/* - * sfe_ipv4_debug_dev_open() - */ -static int sfe_ipv4_debug_dev_open(struct inode *inode, struct file *file) -{ - struct sfe_ipv4_debug_xml_write_state *ws; - - ws = (struct sfe_ipv4_debug_xml_write_state *)file->private_data; - if (!ws) { - ws = kzalloc(sizeof(struct sfe_ipv4_debug_xml_write_state), GFP_KERNEL); - if (!ws) { - return -ENOMEM; - } - - ws->state = SFE_IPV4_DEBUG_XML_STATE_START; - file->private_data = ws; - } - - return 0; -} - -/* - * sfe_ipv4_debug_dev_release() - */ -static int sfe_ipv4_debug_dev_release(struct inode *inode, struct file *file) -{ - struct sfe_ipv4_debug_xml_write_state *ws; - - ws = (struct sfe_ipv4_debug_xml_write_state *)file->private_data; - if (ws) { - /* - * We've finished with our output so free the write state. - */ - kfree(ws); - } - - return 0; -} - -/* - * File operations used in the debug char device - */ -static struct file_operations sfe_ipv4_debug_dev_fops = { - .read = sfe_ipv4_debug_dev_read, - .write = sfe_ipv4_debug_dev_write, - .open = sfe_ipv4_debug_dev_open, - .release = sfe_ipv4_debug_dev_release -}; - -#ifdef CONFIG_NF_FLOW_COOKIE -/* - * sfe_register_flow_cookie_cb - * register a function in SFE to let SFE use this function to configure flow cookie for a flow - * - * Hardware driver which support flow cookie should register a callback function in SFE. Then SFE - * can use this function to configure flow cookie for a flow. - * return: 0, success; !=0, fail - */ -int sfe_register_flow_cookie_cb(flow_cookie_set_func_t cb) -{ - struct sfe_ipv4 *si = &__si; - - BUG_ON(!cb); - - if (si->flow_cookie_set_func) { - return -1; - } - - rcu_assign_pointer(si->flow_cookie_set_func, cb); - return 0; -} - -/* - * sfe_unregister_flow_cookie_cb - * unregister function which is used to configure flow cookie for a flow - * - * return: 0, success; !=0, fail - */ -int sfe_unregister_flow_cookie_cb(flow_cookie_set_func_t cb) -{ - struct sfe_ipv4 *si = &__si; - - RCU_INIT_POINTER(si->flow_cookie_set_func, NULL); - return 0; -} - -/* - * sfe_ipv4_get_flow_cookie() - */ -static ssize_t sfe_ipv4_get_flow_cookie(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct sfe_ipv4 *si = &__si; - return snprintf(buf, (ssize_t)PAGE_SIZE, "%d\n", si->flow_cookie_enable); -} - -/* - * sfe_ipv4_set_flow_cookie() - */ -static ssize_t sfe_ipv4_set_flow_cookie(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - struct sfe_ipv4 *si = &__si; - strict_strtol(buf, 0, (long int *)&si->flow_cookie_enable); - - return size; -} - -/* - * sysfs attributes. - */ -static const struct device_attribute sfe_ipv4_flow_cookie_attr = - __ATTR(flow_cookie_enable, S_IWUSR | S_IRUGO, sfe_ipv4_get_flow_cookie, sfe_ipv4_set_flow_cookie); -#endif /*CONFIG_NF_FLOW_COOKIE*/ - -/* - * sfe_ipv4_init() - */ -static int __init sfe_ipv4_init(void) -{ - struct sfe_ipv4 *si = &__si; - int result = -1; - - DEBUG_INFO("SFE IPv4 init\n"); - - /* - * Create sys/sfe_ipv4 - */ - si->sys_sfe_ipv4 = kobject_create_and_add("sfe_ipv4", NULL); - if (!si->sys_sfe_ipv4) { - DEBUG_ERROR("failed to register sfe_ipv4\n"); - goto exit1; - } - - /* - * Create files, one for each parameter supported by this module. - */ - result = sysfs_create_file(si->sys_sfe_ipv4, &sfe_ipv4_debug_dev_attr.attr); - if (result) { - DEBUG_ERROR("failed to register debug dev file: %d\n", result); - goto exit2; - } - -#ifdef CONFIG_NF_FLOW_COOKIE - result = sysfs_create_file(si->sys_sfe_ipv4, &sfe_ipv4_flow_cookie_attr.attr); - if (result) { - DEBUG_ERROR("failed to register flow cookie enable file: %d\n", result); - goto exit3; - } -#endif /* CONFIG_NF_FLOW_COOKIE */ - - /* - * Register our debug char device. - */ - result = register_chrdev(0, "sfe_ipv4", &sfe_ipv4_debug_dev_fops); - if (result < 0) { - DEBUG_ERROR("Failed to register chrdev: %d\n", result); - goto exit4; - } - - si->debug_dev = result; - - /* - * Create a timer to handle periodic statistics. - */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) - setup_timer(&si->timer, sfe_ipv4_periodic_sync, (unsigned long)si); -#else - timer_setup(&si->timer, sfe_ipv4_periodic_sync, 0); -#endif - mod_timer(&si->timer, jiffies + ((HZ + 99) / 100)); - - spin_lock_init(&si->lock); - - return 0; - -exit4: -#ifdef CONFIG_NF_FLOW_COOKIE - sysfs_remove_file(si->sys_sfe_ipv4, &sfe_ipv4_flow_cookie_attr.attr); - -exit3: -#endif /* CONFIG_NF_FLOW_COOKIE */ - sysfs_remove_file(si->sys_sfe_ipv4, &sfe_ipv4_debug_dev_attr.attr); - -exit2: - kobject_put(si->sys_sfe_ipv4); - -exit1: - return result; -} - -/* - * sfe_ipv4_exit() - */ -static void __exit sfe_ipv4_exit(void) -{ - struct sfe_ipv4 *si = &__si; - - DEBUG_INFO("SFE IPv4 exit\n"); - - /* - * Destroy all connections. - */ - sfe_ipv4_destroy_all_rules_for_dev(NULL); - - del_timer_sync(&si->timer); - - unregister_chrdev(si->debug_dev, "sfe_ipv4"); - -#ifdef CONFIG_NF_FLOW_COOKIE - sysfs_remove_file(si->sys_sfe_ipv4, &sfe_ipv4_flow_cookie_attr.attr); -#endif /* CONFIG_NF_FLOW_COOKIE */ - sysfs_remove_file(si->sys_sfe_ipv4, &sfe_ipv4_debug_dev_attr.attr); - - kobject_put(si->sys_sfe_ipv4); - -} - -module_init(sfe_ipv4_init) -module_exit(sfe_ipv4_exit) - -EXPORT_SYMBOL(sfe_ipv4_recv); -EXPORT_SYMBOL(sfe_ipv4_create_rule); -EXPORT_SYMBOL(sfe_ipv4_destroy_rule); -EXPORT_SYMBOL(sfe_ipv4_destroy_all_rules_for_dev); -EXPORT_SYMBOL(sfe_ipv4_register_sync_rule_callback); -EXPORT_SYMBOL(sfe_ipv4_mark_rule); -EXPORT_SYMBOL(sfe_ipv4_update_rule); -#ifdef CONFIG_NF_FLOW_COOKIE -EXPORT_SYMBOL(sfe_register_flow_cookie_cb); -EXPORT_SYMBOL(sfe_unregister_flow_cookie_cb); -#endif - -MODULE_DESCRIPTION("Shortcut Forwarding Engine - IPv4 edition"); -MODULE_LICENSE("Dual BSD/GPL"); - diff --git a/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_ipv6.c b/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_ipv6.c deleted file mode 100644 index ae330669..00000000 --- a/root/package/lean/shortcut-fe/shortcut-fe/src/sfe_ipv6.c +++ /dev/null @@ -1,3625 +0,0 @@ -/* - * sfe_ipv6.c - * Shortcut forwarding engine - IPv6 support. - * - * Copyright (c) 2015-2016, 2019-2020 The Linux Foundation. All rights reserved. - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all copies. - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "sfe.h" -#include "sfe_cm.h" - -/* - * By default Linux IP header and transport layer header structures are - * unpacked, assuming that such headers should be 32-bit aligned. - * Unfortunately some wireless adaptors can't cope with this requirement and - * some CPUs can't handle misaligned accesses. For those platforms we - * define SFE_IPV6_UNALIGNED_IP_HEADER and mark the structures as packed. - * When we do this the compiler will generate slightly worse code than for the - * aligned case (on most platforms) but will be much quicker than fixing - * things up in an unaligned trap handler. - */ -#define SFE_IPV6_UNALIGNED_IP_HEADER 1 -#if SFE_IPV6_UNALIGNED_IP_HEADER -#define SFE_IPV6_UNALIGNED_STRUCT __attribute__((packed)) -#else -#define SFE_IPV6_UNALIGNED_STRUCT -#endif - -#define CHAR_DEV_MSG_SIZE 768 - -/* - * An Ethernet header, but with an optional "packed" attribute to - * help with performance on some platforms (see the definition of - * SFE_IPV6_UNALIGNED_STRUCT) - */ -struct sfe_ipv6_eth_hdr { - __be16 h_dest[ETH_ALEN / 2]; - __be16 h_source[ETH_ALEN / 2]; - __be16 h_proto; -} SFE_IPV6_UNALIGNED_STRUCT; - -#define SFE_IPV6_DSCP_MASK 0xf03f -#define SFE_IPV6_DSCP_SHIFT 2 - -/* - * An IPv6 header, but with an optional "packed" attribute to - * help with performance on some platforms (see the definition of - * SFE_IPV6_UNALIGNED_STRUCT) - */ -struct sfe_ipv6_ip_hdr { -#if defined(__LITTLE_ENDIAN_BITFIELD) - __u8 priority:4, - version:4; -#elif defined(__BIG_ENDIAN_BITFIELD) - __u8 version:4, - priority:4; -#else -#error "Please fix " -#endif - __u8 flow_lbl[3]; - __be16 payload_len; - __u8 nexthdr; - __u8 hop_limit; - struct sfe_ipv6_addr saddr; - struct sfe_ipv6_addr daddr; - - /* - * The extension header start here. - */ -} SFE_IPV6_UNALIGNED_STRUCT; - -#define SFE_IPV6_EXT_HDR_HOP 0 -#define SFE_IPV6_EXT_HDR_ROUTING 43 -#define SFE_IPV6_EXT_HDR_FRAG 44 -#define SFE_IPV6_EXT_HDR_ESP 50 -#define SFE_IPV6_EXT_HDR_AH 51 -#define SFE_IPV6_EXT_HDR_NONE 59 -#define SFE_IPV6_EXT_HDR_DST 60 -#define SFE_IPV6_EXT_HDR_MH 135 - -/* - * fragmentation header - */ - -struct sfe_ipv6_frag_hdr { - __u8 nexthdr; - __u8 reserved; - __be16 frag_off; - __be32 identification; -}; - -#define SFE_IPV6_FRAG_OFFSET 0xfff8 - -/* - * generic IPv6 extension header - */ -struct sfe_ipv6_ext_hdr { - __u8 next_hdr; - __u8 hdr_len; - __u8 padding[6]; -} SFE_IPV6_UNALIGNED_STRUCT; - -/* - * A UDP header, but with an optional "packed" attribute to - * help with performance on some platforms (see the definition of - * SFE_IPV6_UNALIGNED_STRUCT) - */ -struct sfe_ipv6_udp_hdr { - __be16 source; - __be16 dest; - __be16 len; - __sum16 check; -} SFE_IPV6_UNALIGNED_STRUCT; - -/* - * A TCP header, but with an optional "packed" attribute to - * help with performance on some platforms (see the definition of - * SFE_IPV6_UNALIGNED_STRUCT) - */ -struct sfe_ipv6_tcp_hdr { - __be16 source; - __be16 dest; - __be32 seq; - __be32 ack_seq; -#if defined(__LITTLE_ENDIAN_BITFIELD) - __u16 res1:4, - doff:4, - fin:1, - syn:1, - rst:1, - psh:1, - ack:1, - urg:1, - ece:1, - cwr:1; -#elif defined(__BIG_ENDIAN_BITFIELD) - __u16 doff:4, - res1:4, - cwr:1, - ece:1, - urg:1, - ack:1, - psh:1, - rst:1, - syn:1, - fin:1; -#else -#error "Adjust your defines" -#endif - __be16 window; - __sum16 check; - __be16 urg_ptr; -} SFE_IPV6_UNALIGNED_STRUCT; - -/* - * Specifies the lower bound on ACK numbers carried in the TCP header - */ -#define SFE_IPV6_TCP_MAX_ACK_WINDOW 65520 - -/* - * IPv6 TCP connection match additional data. - */ -struct sfe_ipv6_tcp_connection_match { - u8 win_scale; /* Window scale */ - u32 max_win; /* Maximum window size seen */ - u32 end; /* Sequence number of the next byte to send (seq + segment length) */ - u32 max_end; /* Sequence number of the last byte to ack */ -}; - -/* - * Bit flags for IPv6 connection matching entry. - */ -#define SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_SRC (1<<0) - /* Perform source translation */ -#define SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_DEST (1<<1) - /* Perform destination translation */ -#define SFE_IPV6_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK (1<<2) - /* Ignore TCP sequence numbers */ -#define SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR (1<<3) - /* Fast Ethernet header write */ -#define SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_L2_HDR (1<<4) - /* Fast Ethernet header write */ -#define SFE_IPV6_CONNECTION_MATCH_FLAG_PRIORITY_REMARK (1<<5) - /* remark priority of SKB */ -#define SFE_IPV6_CONNECTION_MATCH_FLAG_DSCP_REMARK (1<<6) - /* remark DSCP of packet */ - -/* - * IPv6 connection matching structure. - */ -struct sfe_ipv6_connection_match { - /* - * References to other objects. - */ - struct sfe_ipv6_connection_match *next; - struct sfe_ipv6_connection_match *prev; - struct sfe_ipv6_connection *connection; - struct sfe_ipv6_connection_match *counter_match; - /* Matches the flow in the opposite direction as the one in connection */ - struct sfe_ipv6_connection_match *active_next; - struct sfe_ipv6_connection_match *active_prev; - bool active; /* Flag to indicate if we're on the active list */ - - /* - * Characteristics that identify flows that match this rule. - */ - struct net_device *match_dev; /* Network device */ - u8 match_protocol; /* Protocol */ - struct sfe_ipv6_addr match_src_ip[1]; /* Source IP address */ - struct sfe_ipv6_addr match_dest_ip[1]; /* Destination IP address */ - __be16 match_src_port; /* Source port/connection ident */ - __be16 match_dest_port; /* Destination port/connection ident */ - - /* - * Control the operations of the match. - */ - u32 flags; /* Bit flags */ -#ifdef CONFIG_NF_FLOW_COOKIE - u32 flow_cookie; /* used flow cookie, for debug */ -#endif -#ifdef CONFIG_XFRM - u32 flow_accel; /* The flow accelerated or not */ -#endif - - /* - * Connection state that we track once we match. - */ - union { /* Protocol-specific state */ - struct sfe_ipv6_tcp_connection_match tcp; - } protocol_state; - /* - * Stats recorded in a sync period. These stats will be added to - * rx_packet_count64/rx_byte_count64 after a sync period. - */ - u32 rx_packet_count; - u32 rx_byte_count; - - /* - * Packet translation information. - */ - struct sfe_ipv6_addr xlate_src_ip[1]; /* Address after source translation */ - __be16 xlate_src_port; /* Port/connection ident after source translation */ - u16 xlate_src_csum_adjustment; - /* Transport layer checksum adjustment after source translation */ - struct sfe_ipv6_addr xlate_dest_ip[1]; /* Address after destination translation */ - __be16 xlate_dest_port; /* Port/connection ident after destination translation */ - u16 xlate_dest_csum_adjustment; - /* Transport layer checksum adjustment after destination translation */ - - /* - * QoS information - */ - u32 priority; - u32 dscp; - - /* - * Packet transmit information. - */ - struct net_device *xmit_dev; /* Network device on which to transmit */ - unsigned short int xmit_dev_mtu; - /* Interface MTU */ - u16 xmit_dest_mac[ETH_ALEN / 2]; - /* Destination MAC address to use when forwarding */ - u16 xmit_src_mac[ETH_ALEN / 2]; - /* Source MAC address to use when forwarding */ - - /* - * Summary stats. - */ - u64 rx_packet_count64; - u64 rx_byte_count64; -}; - -/* - * Per-connection data structure. - */ -struct sfe_ipv6_connection { - struct sfe_ipv6_connection *next; - /* Pointer to the next entry in a hash chain */ - struct sfe_ipv6_connection *prev; - /* Pointer to the previous entry in a hash chain */ - int protocol; /* IP protocol number */ - struct sfe_ipv6_addr src_ip[1]; /* Src IP addr pre-translation */ - struct sfe_ipv6_addr src_ip_xlate[1]; /* Src IP addr post-translation */ - struct sfe_ipv6_addr dest_ip[1]; /* Dest IP addr pre-translation */ - struct sfe_ipv6_addr dest_ip_xlate[1]; /* Dest IP addr post-translation */ - __be16 src_port; /* Src port pre-translation */ - __be16 src_port_xlate; /* Src port post-translation */ - __be16 dest_port; /* Dest port pre-translation */ - __be16 dest_port_xlate; /* Dest port post-translation */ - struct sfe_ipv6_connection_match *original_match; - /* Original direction matching structure */ - struct net_device *original_dev; - /* Original direction source device */ - struct sfe_ipv6_connection_match *reply_match; - /* Reply direction matching structure */ - struct net_device *reply_dev; /* Reply direction source device */ - u64 last_sync_jiffies; /* Jiffies count for the last sync */ - struct sfe_ipv6_connection *all_connections_next; - /* Pointer to the next entry in the list of all connections */ - struct sfe_ipv6_connection *all_connections_prev; - /* Pointer to the previous entry in the list of all connections */ - u32 mark; /* mark for outgoing packet */ - u32 debug_read_seq; /* sequence number for debug dump */ -}; - -/* - * IPv6 connections and hash table size information. - */ -#define SFE_IPV6_CONNECTION_HASH_SHIFT 12 -#define SFE_IPV6_CONNECTION_HASH_SIZE (1 << SFE_IPV6_CONNECTION_HASH_SHIFT) -#define SFE_IPV6_CONNECTION_HASH_MASK (SFE_IPV6_CONNECTION_HASH_SIZE - 1) - -#ifdef CONFIG_NF_FLOW_COOKIE -#define SFE_FLOW_COOKIE_SIZE 2048 -#define SFE_FLOW_COOKIE_MASK 0x7ff - -struct sfe_ipv6_flow_cookie_entry { - struct sfe_ipv6_connection_match *match; - unsigned long last_clean_time; -}; -#endif - -enum sfe_ipv6_exception_events { - SFE_IPV6_EXCEPTION_EVENT_UDP_HEADER_INCOMPLETE, - SFE_IPV6_EXCEPTION_EVENT_UDP_NO_CONNECTION, - SFE_IPV6_EXCEPTION_EVENT_UDP_IP_OPTIONS_OR_INITIAL_FRAGMENT, - SFE_IPV6_EXCEPTION_EVENT_UDP_SMALL_TTL, - SFE_IPV6_EXCEPTION_EVENT_UDP_NEEDS_FRAGMENTATION, - SFE_IPV6_EXCEPTION_EVENT_TCP_HEADER_INCOMPLETE, - SFE_IPV6_EXCEPTION_EVENT_TCP_NO_CONNECTION_SLOW_FLAGS, - SFE_IPV6_EXCEPTION_EVENT_TCP_NO_CONNECTION_FAST_FLAGS, - SFE_IPV6_EXCEPTION_EVENT_TCP_IP_OPTIONS_OR_INITIAL_FRAGMENT, - SFE_IPV6_EXCEPTION_EVENT_TCP_SMALL_TTL, - SFE_IPV6_EXCEPTION_EVENT_TCP_NEEDS_FRAGMENTATION, - SFE_IPV6_EXCEPTION_EVENT_TCP_FLAGS, - SFE_IPV6_EXCEPTION_EVENT_TCP_SEQ_EXCEEDS_RIGHT_EDGE, - SFE_IPV6_EXCEPTION_EVENT_TCP_SMALL_DATA_OFFS, - SFE_IPV6_EXCEPTION_EVENT_TCP_BAD_SACK, - SFE_IPV6_EXCEPTION_EVENT_TCP_BIG_DATA_OFFS, - SFE_IPV6_EXCEPTION_EVENT_TCP_SEQ_BEFORE_LEFT_EDGE, - SFE_IPV6_EXCEPTION_EVENT_TCP_ACK_EXCEEDS_RIGHT_EDGE, - SFE_IPV6_EXCEPTION_EVENT_TCP_ACK_BEFORE_LEFT_EDGE, - SFE_IPV6_EXCEPTION_EVENT_ICMP_HEADER_INCOMPLETE, - SFE_IPV6_EXCEPTION_EVENT_ICMP_UNHANDLED_TYPE, - SFE_IPV6_EXCEPTION_EVENT_ICMP_IPV6_HEADER_INCOMPLETE, - SFE_IPV6_EXCEPTION_EVENT_ICMP_IPV6_NON_V6, - SFE_IPV6_EXCEPTION_EVENT_ICMP_IPV6_IP_OPTIONS_INCOMPLETE, - SFE_IPV6_EXCEPTION_EVENT_ICMP_IPV6_UDP_HEADER_INCOMPLETE, - SFE_IPV6_EXCEPTION_EVENT_ICMP_IPV6_TCP_HEADER_INCOMPLETE, - SFE_IPV6_EXCEPTION_EVENT_ICMP_IPV6_UNHANDLED_PROTOCOL, - SFE_IPV6_EXCEPTION_EVENT_ICMP_NO_CONNECTION, - SFE_IPV6_EXCEPTION_EVENT_ICMP_FLUSHED_CONNECTION, - SFE_IPV6_EXCEPTION_EVENT_HEADER_INCOMPLETE, - SFE_IPV6_EXCEPTION_EVENT_BAD_TOTAL_LENGTH, - SFE_IPV6_EXCEPTION_EVENT_NON_V6, - SFE_IPV6_EXCEPTION_EVENT_NON_INITIAL_FRAGMENT, - SFE_IPV6_EXCEPTION_EVENT_DATAGRAM_INCOMPLETE, - SFE_IPV6_EXCEPTION_EVENT_IP_OPTIONS_INCOMPLETE, - SFE_IPV6_EXCEPTION_EVENT_UNHANDLED_PROTOCOL, - SFE_IPV6_EXCEPTION_EVENT_FLOW_COOKIE_ADD_FAIL, - SFE_IPV6_EXCEPTION_EVENT_CLONED_SKB_UNSHARE_ERROR, - SFE_IPV6_EXCEPTION_EVENT_LAST -}; - -static char *sfe_ipv6_exception_events_string[SFE_IPV6_EXCEPTION_EVENT_LAST] = { - "UDP_HEADER_INCOMPLETE", - "UDP_NO_CONNECTION", - "UDP_IP_OPTIONS_OR_INITIAL_FRAGMENT", - "UDP_SMALL_TTL", - "UDP_NEEDS_FRAGMENTATION", - "TCP_HEADER_INCOMPLETE", - "TCP_NO_CONNECTION_SLOW_FLAGS", - "TCP_NO_CONNECTION_FAST_FLAGS", - "TCP_IP_OPTIONS_OR_INITIAL_FRAGMENT", - "TCP_SMALL_TTL", - "TCP_NEEDS_FRAGMENTATION", - "TCP_FLAGS", - "TCP_SEQ_EXCEEDS_RIGHT_EDGE", - "TCP_SMALL_DATA_OFFS", - "TCP_BAD_SACK", - "TCP_BIG_DATA_OFFS", - "TCP_SEQ_BEFORE_LEFT_EDGE", - "TCP_ACK_EXCEEDS_RIGHT_EDGE", - "TCP_ACK_BEFORE_LEFT_EDGE", - "ICMP_HEADER_INCOMPLETE", - "ICMP_UNHANDLED_TYPE", - "ICMP_IPV6_HEADER_INCOMPLETE", - "ICMP_IPV6_NON_V6", - "ICMP_IPV6_IP_OPTIONS_INCOMPLETE", - "ICMP_IPV6_UDP_HEADER_INCOMPLETE", - "ICMP_IPV6_TCP_HEADER_INCOMPLETE", - "ICMP_IPV6_UNHANDLED_PROTOCOL", - "ICMP_NO_CONNECTION", - "ICMP_FLUSHED_CONNECTION", - "HEADER_INCOMPLETE", - "BAD_TOTAL_LENGTH", - "NON_V6", - "NON_INITIAL_FRAGMENT", - "DATAGRAM_INCOMPLETE", - "IP_OPTIONS_INCOMPLETE", - "UNHANDLED_PROTOCOL", - "FLOW_COOKIE_ADD_FAIL", - "CLONED_SKB_UNSHARE_ERROR" -}; - -/* - * Per-module structure. - */ -struct sfe_ipv6 { - spinlock_t lock; /* Lock for SMP correctness */ - struct sfe_ipv6_connection_match *active_head; - /* Head of the list of recently active connections */ - struct sfe_ipv6_connection_match *active_tail; - /* Tail of the list of recently active connections */ - struct sfe_ipv6_connection *all_connections_head; - /* Head of the list of all connections */ - struct sfe_ipv6_connection *all_connections_tail; - /* Tail of the list of all connections */ - unsigned int num_connections; /* Number of connections */ - struct timer_list timer; /* Timer used for periodic sync ops */ - sfe_sync_rule_callback_t __rcu sync_rule_callback; - /* Callback function registered by a connection manager for stats syncing */ - struct sfe_ipv6_connection *conn_hash[SFE_IPV6_CONNECTION_HASH_SIZE]; - /* Connection hash table */ - struct sfe_ipv6_connection_match *conn_match_hash[SFE_IPV6_CONNECTION_HASH_SIZE]; - /* Connection match hash table */ -#ifdef CONFIG_NF_FLOW_COOKIE - struct sfe_ipv6_flow_cookie_entry sfe_flow_cookie_table[SFE_FLOW_COOKIE_SIZE]; - /* flow cookie table*/ - sfe_ipv6_flow_cookie_set_func_t flow_cookie_set_func; - /* function used to configure flow cookie in hardware*/ - int flow_cookie_enable; - /* Enable/disable flow cookie at runtime */ -#endif - - /* - * Stats recorded in a sync period. These stats will be added to - * connection_xxx64 after a sync period. - */ - u32 connection_create_requests; - /* Number of IPv6 connection create requests */ - u32 connection_create_collisions; - /* Number of IPv6 connection create requests that collided with existing hash table entries */ - u32 connection_destroy_requests; - /* Number of IPv6 connection destroy requests */ - u32 connection_destroy_misses; - /* Number of IPv6 connection destroy requests that missed our hash table */ - u32 connection_match_hash_hits; - /* Number of IPv6 connection match hash hits */ - u32 connection_match_hash_reorders; - /* Number of IPv6 connection match hash reorders */ - u32 connection_flushes; /* Number of IPv6 connection flushes */ - u32 packets_forwarded; /* Number of IPv6 packets forwarded */ - u32 packets_not_forwarded; /* Number of IPv6 packets not forwarded */ - u32 exception_events[SFE_IPV6_EXCEPTION_EVENT_LAST]; - - /* - * Summary statistics. - */ - u64 connection_create_requests64; - /* Number of IPv6 connection create requests */ - u64 connection_create_collisions64; - /* Number of IPv6 connection create requests that collided with existing hash table entries */ - u64 connection_destroy_requests64; - /* Number of IPv6 connection destroy requests */ - u64 connection_destroy_misses64; - /* Number of IPv6 connection destroy requests that missed our hash table */ - u64 connection_match_hash_hits64; - /* Number of IPv6 connection match hash hits */ - u64 connection_match_hash_reorders64; - /* Number of IPv6 connection match hash reorders */ - u64 connection_flushes64; /* Number of IPv6 connection flushes */ - u64 packets_forwarded64; /* Number of IPv6 packets forwarded */ - u64 packets_not_forwarded64; - /* Number of IPv6 packets not forwarded */ - u64 exception_events64[SFE_IPV6_EXCEPTION_EVENT_LAST]; - - /* - * Control state. - */ - struct kobject *sys_sfe_ipv6; /* sysfs linkage */ - int debug_dev; /* Major number of the debug char device */ - u32 debug_read_seq; /* sequence number for debug dump */ -}; - -/* - * Enumeration of the XML output. - */ -enum sfe_ipv6_debug_xml_states { - SFE_IPV6_DEBUG_XML_STATE_START, - SFE_IPV6_DEBUG_XML_STATE_CONNECTIONS_START, - SFE_IPV6_DEBUG_XML_STATE_CONNECTIONS_CONNECTION, - SFE_IPV6_DEBUG_XML_STATE_CONNECTIONS_END, - SFE_IPV6_DEBUG_XML_STATE_EXCEPTIONS_START, - SFE_IPV6_DEBUG_XML_STATE_EXCEPTIONS_EXCEPTION, - SFE_IPV6_DEBUG_XML_STATE_EXCEPTIONS_END, - SFE_IPV6_DEBUG_XML_STATE_STATS, - SFE_IPV6_DEBUG_XML_STATE_END, - SFE_IPV6_DEBUG_XML_STATE_DONE -}; - -/* - * XML write state. - */ -struct sfe_ipv6_debug_xml_write_state { - enum sfe_ipv6_debug_xml_states state; - /* XML output file state machine state */ - int iter_exception; /* Next exception iterator */ -}; - -typedef bool (*sfe_ipv6_debug_xml_write_method_t)(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, - int *total_read, struct sfe_ipv6_debug_xml_write_state *ws); - -static struct sfe_ipv6 __si6; - -/* - * sfe_ipv6_get_debug_dev() - */ -static ssize_t sfe_ipv6_get_debug_dev(struct device *dev, struct device_attribute *attr, char *buf); - -/* - * sysfs attributes. - */ -static const struct device_attribute sfe_ipv6_debug_dev_attr = - __ATTR(debug_dev, S_IWUSR | S_IRUGO, sfe_ipv6_get_debug_dev, NULL); - -/* - * sfe_ipv6_is_ext_hdr() - * check if we recognize ipv6 extension header - */ -static inline bool sfe_ipv6_is_ext_hdr(u8 hdr) -{ - return (hdr == SFE_IPV6_EXT_HDR_HOP) || - (hdr == SFE_IPV6_EXT_HDR_ROUTING) || - (hdr == SFE_IPV6_EXT_HDR_FRAG) || - (hdr == SFE_IPV6_EXT_HDR_AH) || - (hdr == SFE_IPV6_EXT_HDR_DST) || - (hdr == SFE_IPV6_EXT_HDR_MH); -} - -/* - * sfe_ipv6_change_dsfield() - * change dscp field in IPv6 packet - */ -static inline void sfe_ipv6_change_dsfield(struct sfe_ipv6_ip_hdr *iph, u8 dscp) -{ - __be16 *p = (__be16 *)iph; - - *p = ((*p & htons(SFE_IPV6_DSCP_MASK)) | htons((u16)dscp << 4)); -} - -/* - * sfe_ipv6_get_connection_match_hash() - * Generate the hash used in connection match lookups. - */ -static inline unsigned int sfe_ipv6_get_connection_match_hash(struct net_device *dev, u8 protocol, - struct sfe_ipv6_addr *src_ip, __be16 src_port, - struct sfe_ipv6_addr *dest_ip, __be16 dest_port) -{ - u32 idx, hash = 0; - size_t dev_addr = (size_t)dev; - - for (idx = 0; idx < 4; idx++) { - hash ^= src_ip->addr[idx] ^ dest_ip->addr[idx]; - } - hash = ((u32)dev_addr) ^ hash ^ protocol ^ ntohs(src_port ^ dest_port); - return ((hash >> SFE_IPV6_CONNECTION_HASH_SHIFT) ^ hash) & SFE_IPV6_CONNECTION_HASH_MASK; -} - -/* - * sfe_ipv6_find_connection_match() - * Get the IPv6 flow match info that corresponds to a particular 5-tuple. - * - * On entry we must be holding the lock that protects the hash table. - */ -static struct sfe_ipv6_connection_match * -sfe_ipv6_find_connection_match(struct sfe_ipv6 *si, struct net_device *dev, u8 protocol, - struct sfe_ipv6_addr *src_ip, __be16 src_port, - struct sfe_ipv6_addr *dest_ip, __be16 dest_port) -{ - struct sfe_ipv6_connection_match *cm; - struct sfe_ipv6_connection_match *head; - unsigned int conn_match_idx; - - conn_match_idx = sfe_ipv6_get_connection_match_hash(dev, protocol, src_ip, src_port, dest_ip, dest_port); - cm = si->conn_match_hash[conn_match_idx]; - - /* - * If we don't have anything in this chain then bail. - */ - if (unlikely(!cm)) { - return NULL; - } - - /* - * Hopefully the first entry is the one we want. - */ - if ((cm->match_src_port == src_port) - && (cm->match_dest_port == dest_port) - && (sfe_ipv6_addr_equal(cm->match_src_ip, src_ip)) - && (sfe_ipv6_addr_equal(cm->match_dest_ip, dest_ip)) - && (cm->match_protocol == protocol) - && (cm->match_dev == dev)) { - si->connection_match_hash_hits++; - return cm; - } - - /* - * Unfortunately we didn't find it at head, so we search it in chain and - * move matching entry to the top of the hash chain. We presume that this - * will be reused again very quickly. - */ - head = cm; - do { - cm = cm->next; - } while (cm && (cm->match_src_port != src_port - || cm->match_dest_port != dest_port - || !sfe_ipv6_addr_equal(cm->match_src_ip, src_ip) - || !sfe_ipv6_addr_equal(cm->match_dest_ip, dest_ip) - || cm->match_protocol != protocol - || cm->match_dev != dev)); - - /* - * Not found then we're done. - */ - if (unlikely(!cm)) { - return NULL; - } - - /* - * We found a match so move it. - */ - if (cm->next) { - cm->next->prev = cm->prev; - } - cm->prev->next = cm->next; - cm->prev = NULL; - cm->next = head; - head->prev = cm; - si->conn_match_hash[conn_match_idx] = cm; - si->connection_match_hash_reorders++; - - return cm; -} - -/* - * sfe_ipv6_connection_match_update_summary_stats() - * Update the summary stats for a connection match entry. - */ -static inline void sfe_ipv6_connection_match_update_summary_stats(struct sfe_ipv6_connection_match *cm) -{ - cm->rx_packet_count64 += cm->rx_packet_count; - cm->rx_packet_count = 0; - cm->rx_byte_count64 += cm->rx_byte_count; - cm->rx_byte_count = 0; -} - -/* - * sfe_ipv6_connection_match_compute_translations() - * Compute port and address translations for a connection match entry. - */ -static void sfe_ipv6_connection_match_compute_translations(struct sfe_ipv6_connection_match *cm) -{ - u32 diff[9]; - u32 *idx_32; - u16 *idx_16; - - /* - * Before we insert the entry look to see if this is tagged as doing address - * translations. If it is then work out the adjustment that we need to apply - * to the transport checksum. - */ - if (cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_SRC) { - u32 adj = 0; - u32 carry = 0; - - /* - * Precompute an incremental checksum adjustment so we can - * edit packets in this stream very quickly. The algorithm is from RFC1624. - */ - idx_32 = diff; - *(idx_32++) = cm->match_src_ip->addr[0]; - *(idx_32++) = cm->match_src_ip->addr[1]; - *(idx_32++) = cm->match_src_ip->addr[2]; - *(idx_32++) = cm->match_src_ip->addr[3]; - - idx_16 = (u16 *)idx_32; - *(idx_16++) = cm->match_src_port; - *(idx_16++) = ~cm->xlate_src_port; - idx_32 = (u32 *)idx_16; - - *(idx_32++) = ~cm->xlate_src_ip->addr[0]; - *(idx_32++) = ~cm->xlate_src_ip->addr[1]; - *(idx_32++) = ~cm->xlate_src_ip->addr[2]; - *(idx_32++) = ~cm->xlate_src_ip->addr[3]; - - /* - * When we compute this fold it down to a 16-bit offset - * as that way we can avoid having to do a double - * folding of the twos-complement result because the - * addition of 2 16-bit values cannot cause a double - * wrap-around! - */ - for (idx_32 = diff; idx_32 < diff + 9; idx_32++) { - u32 w = *idx_32; - adj += carry; - adj += w; - carry = (w > adj); - } - adj += carry; - adj = (adj & 0xffff) + (adj >> 16); - adj = (adj & 0xffff) + (adj >> 16); - cm->xlate_src_csum_adjustment = (u16)adj; - } - - if (cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_DEST) { - u32 adj = 0; - u32 carry = 0; - - /* - * Precompute an incremental checksum adjustment so we can - * edit packets in this stream very quickly. The algorithm is from RFC1624. - */ - idx_32 = diff; - *(idx_32++) = cm->match_dest_ip->addr[0]; - *(idx_32++) = cm->match_dest_ip->addr[1]; - *(idx_32++) = cm->match_dest_ip->addr[2]; - *(idx_32++) = cm->match_dest_ip->addr[3]; - - idx_16 = (u16 *)idx_32; - *(idx_16++) = cm->match_dest_port; - *(idx_16++) = ~cm->xlate_dest_port; - idx_32 = (u32 *)idx_16; - - *(idx_32++) = ~cm->xlate_dest_ip->addr[0]; - *(idx_32++) = ~cm->xlate_dest_ip->addr[1]; - *(idx_32++) = ~cm->xlate_dest_ip->addr[2]; - *(idx_32++) = ~cm->xlate_dest_ip->addr[3]; - - /* - * When we compute this fold it down to a 16-bit offset - * as that way we can avoid having to do a double - * folding of the twos-complement result because the - * addition of 2 16-bit values cannot cause a double - * wrap-around! - */ - for (idx_32 = diff; idx_32 < diff + 9; idx_32++) { - u32 w = *idx_32; - adj += carry; - adj += w; - carry = (w > adj); - } - adj += carry; - adj = (adj & 0xffff) + (adj >> 16); - adj = (adj & 0xffff) + (adj >> 16); - cm->xlate_dest_csum_adjustment = (u16)adj; - } -} - -/* - * sfe_ipv6_update_summary_stats() - * Update the summary stats. - */ -static void sfe_ipv6_update_summary_stats(struct sfe_ipv6 *si) -{ - int i; - - si->connection_create_requests64 += si->connection_create_requests; - si->connection_create_requests = 0; - si->connection_create_collisions64 += si->connection_create_collisions; - si->connection_create_collisions = 0; - si->connection_destroy_requests64 += si->connection_destroy_requests; - si->connection_destroy_requests = 0; - si->connection_destroy_misses64 += si->connection_destroy_misses; - si->connection_destroy_misses = 0; - si->connection_match_hash_hits64 += si->connection_match_hash_hits; - si->connection_match_hash_hits = 0; - si->connection_match_hash_reorders64 += si->connection_match_hash_reorders; - si->connection_match_hash_reorders = 0; - si->connection_flushes64 += si->connection_flushes; - si->connection_flushes = 0; - si->packets_forwarded64 += si->packets_forwarded; - si->packets_forwarded = 0; - si->packets_not_forwarded64 += si->packets_not_forwarded; - si->packets_not_forwarded = 0; - - for (i = 0; i < SFE_IPV6_EXCEPTION_EVENT_LAST; i++) { - si->exception_events64[i] += si->exception_events[i]; - si->exception_events[i] = 0; - } -} - -/* - * sfe_ipv6_insert_connection_match() - * Insert a connection match into the hash. - * - * On entry we must be holding the lock that protects the hash table. - */ -static inline void sfe_ipv6_insert_connection_match(struct sfe_ipv6 *si, - struct sfe_ipv6_connection_match *cm) -{ - struct sfe_ipv6_connection_match **hash_head; - struct sfe_ipv6_connection_match *prev_head; - unsigned int conn_match_idx - = sfe_ipv6_get_connection_match_hash(cm->match_dev, cm->match_protocol, - cm->match_src_ip, cm->match_src_port, - cm->match_dest_ip, cm->match_dest_port); - - hash_head = &si->conn_match_hash[conn_match_idx]; - prev_head = *hash_head; - cm->prev = NULL; - if (prev_head) { - prev_head->prev = cm; - } - - cm->next = prev_head; - *hash_head = cm; - -#ifdef CONFIG_NF_FLOW_COOKIE - if (!si->flow_cookie_enable || !(cm->flags & (SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_SRC | SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_DEST))) - return; - - /* - * Configure hardware to put a flow cookie in packet of this flow, - * then we can accelerate the lookup process when we received this packet. - */ - for (conn_match_idx = 1; conn_match_idx < SFE_FLOW_COOKIE_SIZE; conn_match_idx++) { - struct sfe_ipv6_flow_cookie_entry *entry = &si->sfe_flow_cookie_table[conn_match_idx]; - - if ((NULL == entry->match) && time_is_before_jiffies(entry->last_clean_time + HZ)) { - sfe_ipv6_flow_cookie_set_func_t func; - - rcu_read_lock(); - func = rcu_dereference(si->flow_cookie_set_func); - if (func) { - if (!func(cm->match_protocol, cm->match_src_ip->addr, cm->match_src_port, - cm->match_dest_ip->addr, cm->match_dest_port, conn_match_idx)) { - entry->match = cm; - cm->flow_cookie = conn_match_idx; - } else { - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_FLOW_COOKIE_ADD_FAIL]++; - } - } - rcu_read_unlock(); - - break; - } - } -#endif -} - -/* - * sfe_ipv6_remove_connection_match() - * Remove a connection match object from the hash. - * - * On entry we must be holding the lock that protects the hash table. - */ -static inline void sfe_ipv6_remove_connection_match(struct sfe_ipv6 *si, struct sfe_ipv6_connection_match *cm) -{ -#ifdef CONFIG_NF_FLOW_COOKIE - if (si->flow_cookie_enable) { - /* - * Tell hardware that we no longer need a flow cookie in packet of this flow - */ - unsigned int conn_match_idx; - - for (conn_match_idx = 1; conn_match_idx < SFE_FLOW_COOKIE_SIZE; conn_match_idx++) { - struct sfe_ipv6_flow_cookie_entry *entry = &si->sfe_flow_cookie_table[conn_match_idx]; - - if (cm == entry->match) { - sfe_ipv6_flow_cookie_set_func_t func; - - rcu_read_lock(); - func = rcu_dereference(si->flow_cookie_set_func); - if (func) { - func(cm->match_protocol, cm->match_src_ip->addr, cm->match_src_port, - cm->match_dest_ip->addr, cm->match_dest_port, 0); - } - rcu_read_unlock(); - - cm->flow_cookie = 0; - entry->match = NULL; - entry->last_clean_time = jiffies; - break; - } - } - } -#endif - - /* - * Unlink the connection match entry from the hash. - */ - if (cm->prev) { - cm->prev->next = cm->next; - } else { - unsigned int conn_match_idx - = sfe_ipv6_get_connection_match_hash(cm->match_dev, cm->match_protocol, - cm->match_src_ip, cm->match_src_port, - cm->match_dest_ip, cm->match_dest_port); - si->conn_match_hash[conn_match_idx] = cm->next; - } - - if (cm->next) { - cm->next->prev = cm->prev; - } - - /* - * If the connection match entry is in the active list remove it. - */ - if (cm->active) { - if (likely(cm->active_prev)) { - cm->active_prev->active_next = cm->active_next; - } else { - si->active_head = cm->active_next; - } - - if (likely(cm->active_next)) { - cm->active_next->active_prev = cm->active_prev; - } else { - si->active_tail = cm->active_prev; - } - } -} - -/* - * sfe_ipv6_get_connection_hash() - * Generate the hash used in connection lookups. - */ -static inline unsigned int sfe_ipv6_get_connection_hash(u8 protocol, struct sfe_ipv6_addr *src_ip, __be16 src_port, - struct sfe_ipv6_addr *dest_ip, __be16 dest_port) -{ - u32 idx, hash = 0; - - for (idx = 0; idx < 4; idx++) { - hash ^= src_ip->addr[idx] ^ dest_ip->addr[idx]; - } - hash = hash ^ protocol ^ ntohs(src_port ^ dest_port); - return ((hash >> SFE_IPV6_CONNECTION_HASH_SHIFT) ^ hash) & SFE_IPV6_CONNECTION_HASH_MASK; -} - -/* - * sfe_ipv6_find_connection() - * Get the IPv6 connection info that corresponds to a particular 5-tuple. - * - * On entry we must be holding the lock that protects the hash table. - */ -static inline struct sfe_ipv6_connection *sfe_ipv6_find_connection(struct sfe_ipv6 *si, u32 protocol, - struct sfe_ipv6_addr *src_ip, __be16 src_port, - struct sfe_ipv6_addr *dest_ip, __be16 dest_port) -{ - struct sfe_ipv6_connection *c; - unsigned int conn_idx = sfe_ipv6_get_connection_hash(protocol, src_ip, src_port, dest_ip, dest_port); - c = si->conn_hash[conn_idx]; - - /* - * If we don't have anything in this chain then bale. - */ - if (unlikely(!c)) { - return NULL; - } - - /* - * Hopefully the first entry is the one we want. - */ - if ((c->src_port == src_port) - && (c->dest_port == dest_port) - && (sfe_ipv6_addr_equal(c->src_ip, src_ip)) - && (sfe_ipv6_addr_equal(c->dest_ip, dest_ip)) - && (c->protocol == protocol)) { - return c; - } - - /* - * Unfortunately we didn't find it at head, so we search it in chain. - */ - do { - c = c->next; - } while (c && (c->src_port != src_port - || c->dest_port != dest_port - || !sfe_ipv6_addr_equal(c->src_ip, src_ip) - || !sfe_ipv6_addr_equal(c->dest_ip, dest_ip) - || c->protocol != protocol)); - - /* - * Will need connection entry for next create/destroy metadata, - * So no need to re-order entry for these requests - */ - return c; -} - -/* - * sfe_ipv6_mark_rule() - * Updates the mark for a current offloaded connection - * - * Will take hash lock upon entry - */ -void sfe_ipv6_mark_rule(struct sfe_connection_mark *mark) -{ - struct sfe_ipv6 *si = &__si6; - struct sfe_ipv6_connection *c; - - spin_lock_bh(&si->lock); - c = sfe_ipv6_find_connection(si, mark->protocol, - mark->src_ip.ip6, mark->src_port, - mark->dest_ip.ip6, mark->dest_port); - if (c) { - WARN_ON((0 != c->mark) && (0 == mark->mark)); - c->mark = mark->mark; - } - spin_unlock_bh(&si->lock); - - if (c) { - DEBUG_TRACE("Matching connection found for mark, " - "setting from %08x to %08x\n", - c->mark, mark->mark); - } -} - -/* - * sfe_ipv6_insert_connection() - * Insert a connection into the hash. - * - * On entry we must be holding the lock that protects the hash table. - */ -static void sfe_ipv6_insert_connection(struct sfe_ipv6 *si, struct sfe_ipv6_connection *c) -{ - struct sfe_ipv6_connection **hash_head; - struct sfe_ipv6_connection *prev_head; - unsigned int conn_idx; - - /* - * Insert entry into the connection hash. - */ - conn_idx = sfe_ipv6_get_connection_hash(c->protocol, c->src_ip, c->src_port, - c->dest_ip, c->dest_port); - hash_head = &si->conn_hash[conn_idx]; - prev_head = *hash_head; - c->prev = NULL; - if (prev_head) { - prev_head->prev = c; - } - - c->next = prev_head; - *hash_head = c; - - /* - * Insert entry into the "all connections" list. - */ - if (si->all_connections_tail) { - c->all_connections_prev = si->all_connections_tail; - si->all_connections_tail->all_connections_next = c; - } else { - c->all_connections_prev = NULL; - si->all_connections_head = c; - } - - si->all_connections_tail = c; - c->all_connections_next = NULL; - si->num_connections++; - - /* - * Insert the connection match objects too. - */ - sfe_ipv6_insert_connection_match(si, c->original_match); - sfe_ipv6_insert_connection_match(si, c->reply_match); -} - -/* - * sfe_ipv6_remove_connection() - * Remove a sfe_ipv6_connection object from the hash. - * - * On entry we must be holding the lock that protects the hash table. - */ -static void sfe_ipv6_remove_connection(struct sfe_ipv6 *si, struct sfe_ipv6_connection *c) -{ - /* - * Remove the connection match objects. - */ - sfe_ipv6_remove_connection_match(si, c->reply_match); - sfe_ipv6_remove_connection_match(si, c->original_match); - - /* - * Unlink the connection. - */ - if (c->prev) { - c->prev->next = c->next; - } else { - unsigned int conn_idx = sfe_ipv6_get_connection_hash(c->protocol, c->src_ip, c->src_port, - c->dest_ip, c->dest_port); - si->conn_hash[conn_idx] = c->next; - } - - if (c->next) { - c->next->prev = c->prev; - } - - /* - * Unlink connection from all_connections list - */ - if (c->all_connections_prev) { - c->all_connections_prev->all_connections_next = c->all_connections_next; - } else { - si->all_connections_head = c->all_connections_next; - } - - if (c->all_connections_next) { - c->all_connections_next->all_connections_prev = c->all_connections_prev; - } else { - si->all_connections_tail = c->all_connections_prev; - } - - si->num_connections--; -} - -/* - * sfe_ipv6_gen_sync_connection() - * Sync a connection. - * - * On entry to this function we expect that the lock for the connection is either - * already held or isn't required. - */ -static void sfe_ipv6_gen_sync_connection(struct sfe_ipv6 *si, struct sfe_ipv6_connection *c, - struct sfe_connection_sync *sis, sfe_sync_reason_t reason, - u64 now_jiffies) -{ - struct sfe_ipv6_connection_match *original_cm; - struct sfe_ipv6_connection_match *reply_cm; - - /* - * Fill in the update message. - */ - sis->is_v6 = 1; - sis->protocol = c->protocol; - sis->src_ip.ip6[0] = c->src_ip[0]; - sis->src_ip_xlate.ip6[0] = c->src_ip_xlate[0]; - sis->dest_ip.ip6[0] = c->dest_ip[0]; - sis->dest_ip_xlate.ip6[0] = c->dest_ip_xlate[0]; - sis->src_port = c->src_port; - sis->src_port_xlate = c->src_port_xlate; - sis->dest_port = c->dest_port; - sis->dest_port_xlate = c->dest_port_xlate; - - original_cm = c->original_match; - reply_cm = c->reply_match; - sis->src_td_max_window = original_cm->protocol_state.tcp.max_win; - sis->src_td_end = original_cm->protocol_state.tcp.end; - sis->src_td_max_end = original_cm->protocol_state.tcp.max_end; - sis->dest_td_max_window = reply_cm->protocol_state.tcp.max_win; - sis->dest_td_end = reply_cm->protocol_state.tcp.end; - sis->dest_td_max_end = reply_cm->protocol_state.tcp.max_end; - - sis->src_new_packet_count = original_cm->rx_packet_count; - sis->src_new_byte_count = original_cm->rx_byte_count; - sis->dest_new_packet_count = reply_cm->rx_packet_count; - sis->dest_new_byte_count = reply_cm->rx_byte_count; - - sfe_ipv6_connection_match_update_summary_stats(original_cm); - sfe_ipv6_connection_match_update_summary_stats(reply_cm); - - sis->src_dev = original_cm->match_dev; - sis->src_packet_count = original_cm->rx_packet_count64; - sis->src_byte_count = original_cm->rx_byte_count64; - - sis->dest_dev = reply_cm->match_dev; - sis->dest_packet_count = reply_cm->rx_packet_count64; - sis->dest_byte_count = reply_cm->rx_byte_count64; - - sis->reason = reason; - - /* - * Get the time increment since our last sync. - */ - sis->delta_jiffies = now_jiffies - c->last_sync_jiffies; - c->last_sync_jiffies = now_jiffies; -} - -/* - * sfe_ipv6_flush_connection() - * Flush a connection and free all associated resources. - * - * We need to be called with bottom halves disabled locally as we need to acquire - * the connection hash lock and release it again. In general we're actually called - * from within a BH and so we're fine, but we're also called when connections are - * torn down. - */ -static void sfe_ipv6_flush_connection(struct sfe_ipv6 *si, - struct sfe_ipv6_connection *c, - sfe_sync_reason_t reason) -{ - struct sfe_connection_sync sis; - u64 now_jiffies; - sfe_sync_rule_callback_t sync_rule_callback; - - rcu_read_lock(); - spin_lock_bh(&si->lock); - si->connection_flushes++; - sync_rule_callback = rcu_dereference(si->sync_rule_callback); - spin_unlock_bh(&si->lock); - - if (sync_rule_callback) { - /* - * Generate a sync message and then sync. - */ - now_jiffies = get_jiffies_64(); - sfe_ipv6_gen_sync_connection(si, c, &sis, reason, now_jiffies); - sync_rule_callback(&sis); - } - - rcu_read_unlock(); - - /* - * Release our hold of the source and dest devices and free the memory - * for our connection objects. - */ - dev_put(c->original_dev); - dev_put(c->reply_dev); - kfree(c->original_match); - kfree(c->reply_match); - kfree(c); -} - -/* - * sfe_ipv6_recv_udp() - * Handle UDP packet receives and forwarding. - */ -static int sfe_ipv6_recv_udp(struct sfe_ipv6 *si, struct sk_buff *skb, struct net_device *dev, - unsigned int len, struct sfe_ipv6_ip_hdr *iph, unsigned int ihl, bool flush_on_find) -{ - struct sfe_ipv6_udp_hdr *udph; - struct sfe_ipv6_addr *src_ip; - struct sfe_ipv6_addr *dest_ip; - __be16 src_port; - __be16 dest_port; - struct sfe_ipv6_connection_match *cm; - struct net_device *xmit_dev; - - /* - * Is our packet too short to contain a valid UDP header? - */ - if (!pskb_may_pull(skb, (sizeof(struct sfe_ipv6_udp_hdr) + ihl))) { - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_UDP_HEADER_INCOMPLETE]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("packet too short for UDP header\n"); - return 0; - } - - /* - * Read the IP address and port information. Read the IP header data first - * because we've almost certainly got that in the cache. We may not yet have - * the UDP header cached though so allow more time for any prefetching. - */ - src_ip = &iph->saddr; - dest_ip = &iph->daddr; - - udph = (struct sfe_ipv6_udp_hdr *)(skb->data + ihl); - src_port = udph->source; - dest_port = udph->dest; - - spin_lock_bh(&si->lock); - - /* - * Look for a connection match. - */ -#ifdef CONFIG_NF_FLOW_COOKIE - cm = si->sfe_flow_cookie_table[skb->flow_cookie & SFE_FLOW_COOKIE_MASK].match; - if (unlikely(!cm)) { - cm = sfe_ipv6_find_connection_match(si, dev, IPPROTO_UDP, src_ip, src_port, dest_ip, dest_port); - } -#else - cm = sfe_ipv6_find_connection_match(si, dev, IPPROTO_UDP, src_ip, src_port, dest_ip, dest_port); -#endif - if (unlikely(!cm)) { - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_UDP_NO_CONNECTION]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("no connection found\n"); - return 0; - } - - /* - * If our packet has beern marked as "flush on find" we can't actually - * forward it in the fast path, but now that we've found an associated - * connection we can flush that out before we process the packet. - */ - if (unlikely(flush_on_find)) { - struct sfe_ipv6_connection *c = cm->connection; - sfe_ipv6_remove_connection(si, c); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_UDP_IP_OPTIONS_OR_INITIAL_FRAGMENT]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("flush on find\n"); - sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; - } - -#ifdef CONFIG_XFRM - /* - * We can't accelerate the flow on this direction, just let it go - * through the slow path. - */ - if (unlikely(!cm->flow_accel)) { - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - return 0; - } -#endif - - /* - * Does our hop_limit allow forwarding? - */ - if (unlikely(iph->hop_limit < 2)) { - struct sfe_ipv6_connection *c = cm->connection; - sfe_ipv6_remove_connection(si, c); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_UDP_SMALL_TTL]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("hop_limit too low\n"); - sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; - } - - /* - * If our packet is larger than the MTU of the transmit interface then - * we can't forward it easily. - */ - if (unlikely(len > cm->xmit_dev_mtu)) { - struct sfe_ipv6_connection *c = cm->connection; - sfe_ipv6_remove_connection(si, c); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_UDP_NEEDS_FRAGMENTATION]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("larger than mtu\n"); - sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; - } - - /* - * From this point on we're good to modify the packet. - */ - - /* - * Check if skb was cloned. If it was, unshare it. Because - * the data area is going to be written in this path and we don't want to - * change the cloned skb's data section. - */ - if (unlikely(skb_cloned(skb))) { - DEBUG_TRACE("%px: skb is a cloned skb\n", skb); - skb = skb_unshare(skb, GFP_ATOMIC); - if (!skb) { - DEBUG_WARN("Failed to unshare the cloned skb\n"); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_CLONED_SKB_UNSHARE_ERROR]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - return 0; - } - - /* - * Update the iph and udph pointers with the unshared skb's data area. - */ - iph = (struct sfe_ipv6_ip_hdr *)skb->data; - udph = (struct sfe_ipv6_udp_hdr *)(skb->data + ihl); - } - - /* - * Update DSCP - */ - if (unlikely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_DSCP_REMARK)) { - sfe_ipv6_change_dsfield(iph, cm->dscp); - } - - /* - * Decrement our hop_limit. - */ - iph->hop_limit -= 1; - - /* - * Do we have to perform translations of the source address/port? - */ - if (unlikely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_SRC)) { - u16 udp_csum; - - iph->saddr = cm->xlate_src_ip[0]; - udph->source = cm->xlate_src_port; - - /* - * Do we have a non-zero UDP checksum? If we do then we need - * to update it. - */ - udp_csum = udph->check; - if (likely(udp_csum)) { - u32 sum = udp_csum + cm->xlate_src_csum_adjustment; - sum = (sum & 0xffff) + (sum >> 16); - udph->check = (u16)sum; - } - } - - /* - * Do we have to perform translations of the destination address/port? - */ - if (unlikely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_DEST)) { - u16 udp_csum; - - iph->daddr = cm->xlate_dest_ip[0]; - udph->dest = cm->xlate_dest_port; - - /* - * Do we have a non-zero UDP checksum? If we do then we need - * to update it. - */ - udp_csum = udph->check; - if (likely(udp_csum)) { - u32 sum = udp_csum + cm->xlate_dest_csum_adjustment; - sum = (sum & 0xffff) + (sum >> 16); - udph->check = (u16)sum; - } - } - - /* - * Update traffic stats. - */ - cm->rx_packet_count++; - cm->rx_byte_count += len; - - /* - * If we're not already on the active list then insert ourselves at the tail - * of the current list. - */ - if (unlikely(!cm->active)) { - cm->active = true; - cm->active_prev = si->active_tail; - if (likely(si->active_tail)) { - si->active_tail->active_next = cm; - } else { - si->active_head = cm; - } - si->active_tail = cm; - } - - xmit_dev = cm->xmit_dev; - skb->dev = xmit_dev; - - /* - * Check to see if we need to write a header. - */ - if (likely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_L2_HDR)) { - if (unlikely(!(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR))) { - dev_hard_header(skb, xmit_dev, ETH_P_IPV6, - cm->xmit_dest_mac, cm->xmit_src_mac, len); - } else { - /* - * For the simple case we write this really fast. - */ - struct sfe_ipv6_eth_hdr *eth = (struct sfe_ipv6_eth_hdr *)__skb_push(skb, ETH_HLEN); - eth->h_proto = htons(ETH_P_IPV6); - eth->h_dest[0] = cm->xmit_dest_mac[0]; - eth->h_dest[1] = cm->xmit_dest_mac[1]; - eth->h_dest[2] = cm->xmit_dest_mac[2]; - eth->h_source[0] = cm->xmit_src_mac[0]; - eth->h_source[1] = cm->xmit_src_mac[1]; - eth->h_source[2] = cm->xmit_src_mac[2]; - } - } - - /* - * Update priority of skb. - */ - if (unlikely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_PRIORITY_REMARK)) { - skb->priority = cm->priority; - } - - /* - * Mark outgoing packet. - */ - skb->mark = cm->connection->mark; - if (skb->mark) { - DEBUG_TRACE("SKB MARK is NON ZERO %x\n", skb->mark); - } - - si->packets_forwarded++; - spin_unlock_bh(&si->lock); - - /* - * We're going to check for GSO flags when we transmit the packet so - * start fetching the necessary cache line now. - */ - prefetch(skb_shinfo(skb)); - - /* - * Mark that this packet has been fast forwarded. - */ - skb->fast_forwarded = 1; - - /* - * Send the packet on its way. - */ - dev_queue_xmit(skb); - - return 1; -} - -/* - * sfe_ipv6_process_tcp_option_sack() - * Parse TCP SACK option and update ack according - */ -static bool sfe_ipv6_process_tcp_option_sack(const struct sfe_ipv6_tcp_hdr *th, const u32 data_offs, - u32 *ack) -{ - u32 length = sizeof(struct sfe_ipv6_tcp_hdr); - u8 *ptr = (u8 *)th + length; - - /* - * Ignore processing if TCP packet has only TIMESTAMP option. - */ - if (likely(data_offs == length + TCPOLEN_TIMESTAMP + 1 + 1) - && likely(ptr[0] == TCPOPT_NOP) - && likely(ptr[1] == TCPOPT_NOP) - && likely(ptr[2] == TCPOPT_TIMESTAMP) - && likely(ptr[3] == TCPOLEN_TIMESTAMP)) { - return true; - } - - /* - * TCP options. Parse SACK option. - */ - while (length < data_offs) { - u8 size; - u8 kind; - - ptr = (u8 *)th + length; - kind = *ptr; - - /* - * NOP, for padding - * Not in the switch because to fast escape and to not calculate size - */ - if (kind == TCPOPT_NOP) { - length++; - continue; - } - - if (kind == TCPOPT_SACK) { - u32 sack = 0; - u8 re = 1 + 1; - - size = *(ptr + 1); - if ((size < (1 + 1 + TCPOLEN_SACK_PERBLOCK)) - || ((size - (1 + 1)) % (TCPOLEN_SACK_PERBLOCK)) - || (size > (data_offs - length))) { - return false; - } - - re += 4; - while (re < size) { - u32 sack_re; - u8 *sptr = ptr + re; - sack_re = (sptr[0] << 24) | (sptr[1] << 16) | (sptr[2] << 8) | sptr[3]; - if (sack_re > sack) { - sack = sack_re; - } - re += TCPOLEN_SACK_PERBLOCK; - } - if (sack > *ack) { - *ack = sack; - } - length += size; - continue; - } - if (kind == TCPOPT_EOL) { - return true; - } - size = *(ptr + 1); - if (size < 2) { - return false; - } - length += size; - } - - return true; -} - -/* - * sfe_ipv6_recv_tcp() - * Handle TCP packet receives and forwarding. - */ -static int sfe_ipv6_recv_tcp(struct sfe_ipv6 *si, struct sk_buff *skb, struct net_device *dev, - unsigned int len, struct sfe_ipv6_ip_hdr *iph, unsigned int ihl, bool flush_on_find) -{ - struct sfe_ipv6_tcp_hdr *tcph; - struct sfe_ipv6_addr *src_ip; - struct sfe_ipv6_addr *dest_ip; - __be16 src_port; - __be16 dest_port; - struct sfe_ipv6_connection_match *cm; - struct sfe_ipv6_connection_match *counter_cm; - u32 flags; - struct net_device *xmit_dev; - - /* - * Is our packet too short to contain a valid UDP header? - */ - if (!pskb_may_pull(skb, (sizeof(struct sfe_ipv6_tcp_hdr) + ihl))) { - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_HEADER_INCOMPLETE]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("packet too short for TCP header\n"); - return 0; - } - - /* - * Read the IP address and port information. Read the IP header data first - * because we've almost certainly got that in the cache. We may not yet have - * the TCP header cached though so allow more time for any prefetching. - */ - src_ip = &iph->saddr; - dest_ip = &iph->daddr; - - tcph = (struct sfe_ipv6_tcp_hdr *)(skb->data + ihl); - src_port = tcph->source; - dest_port = tcph->dest; - flags = tcp_flag_word(tcph); - - spin_lock_bh(&si->lock); - - /* - * Look for a connection match. - */ -#ifdef CONFIG_NF_FLOW_COOKIE - cm = si->sfe_flow_cookie_table[skb->flow_cookie & SFE_FLOW_COOKIE_MASK].match; - if (unlikely(!cm)) { - cm = sfe_ipv6_find_connection_match(si, dev, IPPROTO_TCP, src_ip, src_port, dest_ip, dest_port); - } -#else - cm = sfe_ipv6_find_connection_match(si, dev, IPPROTO_TCP, src_ip, src_port, dest_ip, dest_port); -#endif - if (unlikely(!cm)) { - /* - * We didn't get a connection but as TCP is connection-oriented that - * may be because this is a non-fast connection (not running established). - * For diagnostic purposes we differentiate this here. - */ - if (likely((flags & (TCP_FLAG_SYN | TCP_FLAG_RST | TCP_FLAG_FIN | TCP_FLAG_ACK)) == TCP_FLAG_ACK)) { - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_NO_CONNECTION_FAST_FLAGS]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("no connection found - fast flags\n"); - return 0; - } - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_NO_CONNECTION_SLOW_FLAGS]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("no connection found - slow flags: 0x%x\n", - flags & (TCP_FLAG_SYN | TCP_FLAG_RST | TCP_FLAG_FIN | TCP_FLAG_ACK)); - return 0; - } - - /* - * If our packet has beern marked as "flush on find" we can't actually - * forward it in the fast path, but now that we've found an associated - * connection we can flush that out before we process the packet. - */ - if (unlikely(flush_on_find)) { - struct sfe_ipv6_connection *c = cm->connection; - sfe_ipv6_remove_connection(si, c); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_IP_OPTIONS_OR_INITIAL_FRAGMENT]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("flush on find\n"); - sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; - } - -#ifdef CONFIG_XFRM - /* - * We can't accelerate the flow on this direction, just let it go - * through the slow path. - */ - if (unlikely(!cm->flow_accel)) { - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - return 0; - } -#endif - - /* - * Does our hop_limit allow forwarding? - */ - if (unlikely(iph->hop_limit < 2)) { - struct sfe_ipv6_connection *c = cm->connection; - sfe_ipv6_remove_connection(si, c); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_SMALL_TTL]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("hop_limit too low\n"); - sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; - } - - /* - * If our packet is larger than the MTU of the transmit interface then - * we can't forward it easily. - */ - if (unlikely((len > cm->xmit_dev_mtu) && !skb_is_gso(skb))) { - struct sfe_ipv6_connection *c = cm->connection; - sfe_ipv6_remove_connection(si, c); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_NEEDS_FRAGMENTATION]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("larger than mtu\n"); - sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; - } - - /* - * Look at our TCP flags. Anything missing an ACK or that has RST, SYN or FIN - * set is not a fast path packet. - */ - if (unlikely((flags & (TCP_FLAG_SYN | TCP_FLAG_RST | TCP_FLAG_FIN | TCP_FLAG_ACK)) != TCP_FLAG_ACK)) { - struct sfe_ipv6_connection *c = cm->connection; - sfe_ipv6_remove_connection(si, c); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_FLAGS]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("TCP flags: 0x%x are not fast\n", - flags & (TCP_FLAG_SYN | TCP_FLAG_RST | TCP_FLAG_FIN | TCP_FLAG_ACK)); - sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; - } - - counter_cm = cm->counter_match; - - /* - * Are we doing sequence number checking? - */ - if (likely(!(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK))) { - u32 seq; - u32 ack; - u32 sack; - u32 data_offs; - u32 end; - u32 left_edge; - u32 scaled_win; - u32 max_end; - - /* - * Is our sequence fully past the right hand edge of the window? - */ - seq = ntohl(tcph->seq); - if (unlikely((s32)(seq - (cm->protocol_state.tcp.max_end + 1)) > 0)) { - struct sfe_ipv6_connection *c = cm->connection; - sfe_ipv6_remove_connection(si, c); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_SEQ_EXCEEDS_RIGHT_EDGE]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("seq: %u exceeds right edge: %u\n", - seq, cm->protocol_state.tcp.max_end + 1); - sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; - } - - /* - * Check that our TCP data offset isn't too short. - */ - data_offs = tcph->doff << 2; - if (unlikely(data_offs < sizeof(struct sfe_ipv6_tcp_hdr))) { - struct sfe_ipv6_connection *c = cm->connection; - sfe_ipv6_remove_connection(si, c); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_SMALL_DATA_OFFS]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("TCP data offset: %u, too small\n", data_offs); - sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; - } - - /* - * Update ACK according to any SACK option. - */ - ack = ntohl(tcph->ack_seq); - sack = ack; - if (unlikely(!sfe_ipv6_process_tcp_option_sack(tcph, data_offs, &sack))) { - struct sfe_ipv6_connection *c = cm->connection; - sfe_ipv6_remove_connection(si, c); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_BAD_SACK]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("TCP option SACK size is wrong\n"); - sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; - } - - /* - * Check that our TCP data offset isn't past the end of the packet. - */ - data_offs += sizeof(struct sfe_ipv6_ip_hdr); - if (unlikely(len < data_offs)) { - struct sfe_ipv6_connection *c = cm->connection; - sfe_ipv6_remove_connection(si, c); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_BIG_DATA_OFFS]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("TCP data offset: %u, past end of packet: %u\n", - data_offs, len); - sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; - } - - end = seq + len - data_offs; - - /* - * Is our sequence fully before the left hand edge of the window? - */ - if (unlikely((s32)(end - (cm->protocol_state.tcp.end - - counter_cm->protocol_state.tcp.max_win - 1)) < 0)) { - struct sfe_ipv6_connection *c = cm->connection; - sfe_ipv6_remove_connection(si, c); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_SEQ_BEFORE_LEFT_EDGE]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("seq: %u before left edge: %u\n", - end, cm->protocol_state.tcp.end - counter_cm->protocol_state.tcp.max_win - 1); - sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; - } - - /* - * Are we acking data that is to the right of what has been sent? - */ - if (unlikely((s32)(sack - (counter_cm->protocol_state.tcp.end + 1)) > 0)) { - struct sfe_ipv6_connection *c = cm->connection; - sfe_ipv6_remove_connection(si, c); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_ACK_EXCEEDS_RIGHT_EDGE]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("ack: %u exceeds right edge: %u\n", - sack, counter_cm->protocol_state.tcp.end + 1); - sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; - } - - /* - * Is our ack too far before the left hand edge of the window? - */ - left_edge = counter_cm->protocol_state.tcp.end - - cm->protocol_state.tcp.max_win - - SFE_IPV6_TCP_MAX_ACK_WINDOW - - 1; - if (unlikely((s32)(sack - left_edge) < 0)) { - struct sfe_ipv6_connection *c = cm->connection; - sfe_ipv6_remove_connection(si, c); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_ACK_BEFORE_LEFT_EDGE]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("ack: %u before left edge: %u\n", sack, left_edge); - sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; - } - - /* - * Have we just seen the largest window size yet for this connection? If yes - * then we need to record the new value. - */ - scaled_win = ntohs(tcph->window) << cm->protocol_state.tcp.win_scale; - scaled_win += (sack - ack); - if (unlikely(cm->protocol_state.tcp.max_win < scaled_win)) { - cm->protocol_state.tcp.max_win = scaled_win; - } - - /* - * If our sequence and/or ack numbers have advanced then record the new state. - */ - if (likely((s32)(end - cm->protocol_state.tcp.end) >= 0)) { - cm->protocol_state.tcp.end = end; - } - - max_end = sack + scaled_win; - if (likely((s32)(max_end - counter_cm->protocol_state.tcp.max_end) >= 0)) { - counter_cm->protocol_state.tcp.max_end = max_end; - } - } - - /* - * From this point on we're good to modify the packet. - */ - - /* - * Check if skb was cloned. If it was, unshare it. Because - * the data area is going to be written in this path and we don't want to - * change the cloned skb's data section. - */ - if (unlikely(skb_cloned(skb))) { - DEBUG_TRACE("%px: skb is a cloned skb\n", skb); - skb = skb_unshare(skb, GFP_ATOMIC); - if (!skb) { - DEBUG_WARN("Failed to unshare the cloned skb\n"); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_CLONED_SKB_UNSHARE_ERROR]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - return 0; - } - - /* - * Update the iph and tcph pointers with the unshared skb's data area. - */ - iph = (struct sfe_ipv6_ip_hdr *)skb->data; - tcph = (struct sfe_ipv6_tcp_hdr *)(skb->data + ihl); - } - - /* - * Update DSCP - */ - if (unlikely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_DSCP_REMARK)) { - sfe_ipv6_change_dsfield(iph, cm->dscp); - } - - /* - * Decrement our hop_limit. - */ - iph->hop_limit -= 1; - - /* - * Do we have to perform translations of the source address/port? - */ - if (unlikely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_SRC)) { - u16 tcp_csum; - u32 sum; - - iph->saddr = cm->xlate_src_ip[0]; - tcph->source = cm->xlate_src_port; - - /* - * Do we have a non-zero UDP checksum? If we do then we need - * to update it. - */ - tcp_csum = tcph->check; - sum = tcp_csum + cm->xlate_src_csum_adjustment; - sum = (sum & 0xffff) + (sum >> 16); - tcph->check = (u16)sum; - } - - /* - * Do we have to perform translations of the destination address/port? - */ - if (unlikely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_DEST)) { - u16 tcp_csum; - u32 sum; - - iph->daddr = cm->xlate_dest_ip[0]; - tcph->dest = cm->xlate_dest_port; - - /* - * Do we have a non-zero UDP checksum? If we do then we need - * to update it. - */ - tcp_csum = tcph->check; - sum = tcp_csum + cm->xlate_dest_csum_adjustment; - sum = (sum & 0xffff) + (sum >> 16); - tcph->check = (u16)sum; - } - - /* - * Update traffic stats. - */ - cm->rx_packet_count++; - cm->rx_byte_count += len; - - /* - * If we're not already on the active list then insert ourselves at the tail - * of the current list. - */ - if (unlikely(!cm->active)) { - cm->active = true; - cm->active_prev = si->active_tail; - if (likely(si->active_tail)) { - si->active_tail->active_next = cm; - } else { - si->active_head = cm; - } - si->active_tail = cm; - } - - xmit_dev = cm->xmit_dev; - skb->dev = xmit_dev; - - /* - * Check to see if we need to write a header. - */ - if (likely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_L2_HDR)) { - if (unlikely(!(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR))) { - dev_hard_header(skb, xmit_dev, ETH_P_IPV6, - cm->xmit_dest_mac, cm->xmit_src_mac, len); - } else { - /* - * For the simple case we write this really fast. - */ - struct sfe_ipv6_eth_hdr *eth = (struct sfe_ipv6_eth_hdr *)__skb_push(skb, ETH_HLEN); - eth->h_proto = htons(ETH_P_IPV6); - eth->h_dest[0] = cm->xmit_dest_mac[0]; - eth->h_dest[1] = cm->xmit_dest_mac[1]; - eth->h_dest[2] = cm->xmit_dest_mac[2]; - eth->h_source[0] = cm->xmit_src_mac[0]; - eth->h_source[1] = cm->xmit_src_mac[1]; - eth->h_source[2] = cm->xmit_src_mac[2]; - } - } - - /* - * Update priority of skb. - */ - if (unlikely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_PRIORITY_REMARK)) { - skb->priority = cm->priority; - } - - /* - * Mark outgoing packet - */ - skb->mark = cm->connection->mark; - if (skb->mark) { - DEBUG_TRACE("SKB MARK is NON ZERO %x\n", skb->mark); - } - - si->packets_forwarded++; - spin_unlock_bh(&si->lock); - - /* - * We're going to check for GSO flags when we transmit the packet so - * start fetching the necessary cache line now. - */ - prefetch(skb_shinfo(skb)); - - /* - * Mark that this packet has been fast forwarded. - */ - skb->fast_forwarded = 1; - - /* - * Send the packet on its way. - */ - dev_queue_xmit(skb); - - return 1; -} - -/* - * sfe_ipv6_recv_icmp() - * Handle ICMP packet receives. - * - * ICMP packets aren't handled as a "fast path" and always have us process them - * through the default Linux stack. What we do need to do is look for any errors - * about connections we are handling in the fast path. If we find any such - * connections then we want to flush their state so that the ICMP error path - * within Linux has all of the correct state should it need it. - */ -static int sfe_ipv6_recv_icmp(struct sfe_ipv6 *si, struct sk_buff *skb, struct net_device *dev, - unsigned int len, struct sfe_ipv6_ip_hdr *iph, unsigned int ihl) -{ - struct icmp6hdr *icmph; - struct sfe_ipv6_ip_hdr *icmp_iph; - struct sfe_ipv6_udp_hdr *icmp_udph; - struct sfe_ipv6_tcp_hdr *icmp_tcph; - struct sfe_ipv6_addr *src_ip; - struct sfe_ipv6_addr *dest_ip; - __be16 src_port; - __be16 dest_port; - struct sfe_ipv6_connection_match *cm; - struct sfe_ipv6_connection *c; - u8 next_hdr; - - /* - * Is our packet too short to contain a valid ICMP header? - */ - len -= ihl; - if (!pskb_may_pull(skb, ihl + sizeof(struct icmp6hdr))) { - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_ICMP_HEADER_INCOMPLETE]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("packet too short for ICMP header\n"); - return 0; - } - - /* - * We only handle "destination unreachable" and "time exceeded" messages. - */ - icmph = (struct icmp6hdr *)(skb->data + ihl); - if ((icmph->icmp6_type != ICMPV6_DEST_UNREACH) - && (icmph->icmp6_type != ICMPV6_TIME_EXCEED)) { - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_ICMP_UNHANDLED_TYPE]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("unhandled ICMP type: 0x%x\n", icmph->icmp6_type); - return 0; - } - - /* - * Do we have the full embedded IP header? - * We should have 8 bytes of next L4 header - that's enough to identify - * the connection. - */ - len -= sizeof(struct icmp6hdr); - ihl += sizeof(struct icmp6hdr); - if (!pskb_may_pull(skb, ihl + sizeof(struct sfe_ipv6_ip_hdr) + sizeof(struct sfe_ipv6_ext_hdr))) { - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_ICMP_IPV6_HEADER_INCOMPLETE]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("Embedded IP header not complete\n"); - return 0; - } - - /* - * Is our embedded IP version wrong? - */ - icmp_iph = (struct sfe_ipv6_ip_hdr *)(icmph + 1); - if (unlikely(icmp_iph->version != 6)) { - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_ICMP_IPV6_NON_V6]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("IP version: %u\n", icmp_iph->version); - return 0; - } - - len -= sizeof(struct sfe_ipv6_ip_hdr); - ihl += sizeof(struct sfe_ipv6_ip_hdr); - next_hdr = icmp_iph->nexthdr; - while (unlikely(sfe_ipv6_is_ext_hdr(next_hdr))) { - struct sfe_ipv6_ext_hdr *ext_hdr; - unsigned int ext_hdr_len; - - ext_hdr = (struct sfe_ipv6_ext_hdr *)(skb->data + ihl); - if (next_hdr == SFE_IPV6_EXT_HDR_FRAG) { - struct sfe_ipv6_frag_hdr *frag_hdr = (struct sfe_ipv6_frag_hdr *)ext_hdr; - unsigned int frag_off = ntohs(frag_hdr->frag_off); - - if (frag_off & SFE_IPV6_FRAG_OFFSET) { - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_NON_INITIAL_FRAGMENT]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("non-initial fragment\n"); - return 0; - } - } - - ext_hdr_len = ext_hdr->hdr_len; - ext_hdr_len <<= 3; - ext_hdr_len += sizeof(struct sfe_ipv6_ext_hdr); - len -= ext_hdr_len; - ihl += ext_hdr_len; - /* - * We should have 8 bytes of next header - that's enough to identify - * the connection. - */ - if (!pskb_may_pull(skb, ihl + sizeof(struct sfe_ipv6_ext_hdr))) { - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_HEADER_INCOMPLETE]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("extension header %d not completed\n", next_hdr); - return 0; - } - - next_hdr = ext_hdr->next_hdr; - } - - /* - * Handle the embedded transport layer header. - */ - switch (next_hdr) { - case IPPROTO_UDP: - icmp_udph = (struct sfe_ipv6_udp_hdr *)(skb->data + ihl); - src_port = icmp_udph->source; - dest_port = icmp_udph->dest; - break; - - case IPPROTO_TCP: - icmp_tcph = (struct sfe_ipv6_tcp_hdr *)(skb->data + ihl); - src_port = icmp_tcph->source; - dest_port = icmp_tcph->dest; - break; - - default: - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_ICMP_IPV6_UNHANDLED_PROTOCOL]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("Unhandled embedded IP protocol: %u\n", next_hdr); - return 0; - } - - src_ip = &icmp_iph->saddr; - dest_ip = &icmp_iph->daddr; - - spin_lock_bh(&si->lock); - - /* - * Look for a connection match. Note that we reverse the source and destination - * here because our embedded message contains a packet that was sent in the - * opposite direction to the one in which we just received it. It will have - * been sent on the interface from which we received it though so that's still - * ok to use. - */ - cm = sfe_ipv6_find_connection_match(si, dev, icmp_iph->nexthdr, dest_ip, dest_port, src_ip, src_port); - if (unlikely(!cm)) { - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_ICMP_NO_CONNECTION]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("no connection found\n"); - return 0; - } - - /* - * We found a connection so now remove it from the connection list and flush - * its state. - */ - c = cm->connection; - sfe_ipv6_remove_connection(si, c); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_ICMP_FLUSHED_CONNECTION]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); - return 0; -} - -/* - * sfe_ipv6_recv() - * Handle packet receives and forwaring. - * - * Returns 1 if the packet is forwarded or 0 if it isn't. - */ -int sfe_ipv6_recv(struct net_device *dev, struct sk_buff *skb) -{ - struct sfe_ipv6 *si = &__si6; - unsigned int len; - unsigned int payload_len; - unsigned int ihl = sizeof(struct sfe_ipv6_ip_hdr); - bool flush_on_find = false; - struct sfe_ipv6_ip_hdr *iph; - u8 next_hdr; - - /* - * Check that we have space for an IP header and an uplayer header here. - */ - len = skb->len; - if (!pskb_may_pull(skb, ihl + sizeof(struct sfe_ipv6_ext_hdr))) { - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_HEADER_INCOMPLETE]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("len: %u is too short\n", len); - return 0; - } - - /* - * Is our IP version wrong? - */ - iph = (struct sfe_ipv6_ip_hdr *)skb->data; - if (unlikely(iph->version != 6)) { - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_NON_V6]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("IP version: %u\n", iph->version); - return 0; - } - - /* - * Does our datagram fit inside the skb? - */ - payload_len = ntohs(iph->payload_len); - if (unlikely(payload_len > (len - ihl))) { - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_DATAGRAM_INCOMPLETE]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("payload_len: %u, exceeds len: %u\n", payload_len, (len - (unsigned int)sizeof(struct sfe_ipv6_ip_hdr))); - return 0; - } - - next_hdr = iph->nexthdr; - while (unlikely(sfe_ipv6_is_ext_hdr(next_hdr))) { - struct sfe_ipv6_ext_hdr *ext_hdr; - unsigned int ext_hdr_len; - - ext_hdr = (struct sfe_ipv6_ext_hdr *)(skb->data + ihl); - if (next_hdr == SFE_IPV6_EXT_HDR_FRAG) { - struct sfe_ipv6_frag_hdr *frag_hdr = (struct sfe_ipv6_frag_hdr *)ext_hdr; - unsigned int frag_off = ntohs(frag_hdr->frag_off); - - if (frag_off & SFE_IPV6_FRAG_OFFSET) { - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_NON_INITIAL_FRAGMENT]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("non-initial fragment\n"); - return 0; - } - } - - ext_hdr_len = ext_hdr->hdr_len; - ext_hdr_len <<= 3; - ext_hdr_len += sizeof(struct sfe_ipv6_ext_hdr); - ihl += ext_hdr_len; - if (!pskb_may_pull(skb, ihl + sizeof(struct sfe_ipv6_ext_hdr))) { - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_HEADER_INCOMPLETE]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("extension header %d not completed\n", next_hdr); - return 0; - } - - flush_on_find = true; - next_hdr = ext_hdr->next_hdr; - } - - if (IPPROTO_UDP == next_hdr) { - return sfe_ipv6_recv_udp(si, skb, dev, len, iph, ihl, flush_on_find); - } - - if (IPPROTO_TCP == next_hdr) { - return sfe_ipv6_recv_tcp(si, skb, dev, len, iph, ihl, flush_on_find); - } - - if (IPPROTO_ICMPV6 == next_hdr) { - return sfe_ipv6_recv_icmp(si, skb, dev, len, iph, ihl); - } - - spin_lock_bh(&si->lock); - si->exception_events[SFE_IPV6_EXCEPTION_EVENT_UNHANDLED_PROTOCOL]++; - si->packets_not_forwarded++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("not UDP, TCP or ICMP: %u\n", next_hdr); - return 0; -} - -/* - * sfe_ipv6_update_tcp_state() - * update TCP window variables. - */ -static void -sfe_ipv6_update_tcp_state(struct sfe_ipv6_connection *c, - struct sfe_connection_create *sic) -{ - struct sfe_ipv6_connection_match *orig_cm; - struct sfe_ipv6_connection_match *repl_cm; - struct sfe_ipv6_tcp_connection_match *orig_tcp; - struct sfe_ipv6_tcp_connection_match *repl_tcp; - - orig_cm = c->original_match; - repl_cm = c->reply_match; - orig_tcp = &orig_cm->protocol_state.tcp; - repl_tcp = &repl_cm->protocol_state.tcp; - - /* update orig */ - if (orig_tcp->max_win < sic->src_td_max_window) { - orig_tcp->max_win = sic->src_td_max_window; - } - if ((s32)(orig_tcp->end - sic->src_td_end) < 0) { - orig_tcp->end = sic->src_td_end; - } - if ((s32)(orig_tcp->max_end - sic->src_td_max_end) < 0) { - orig_tcp->max_end = sic->src_td_max_end; - } - - /* update reply */ - if (repl_tcp->max_win < sic->dest_td_max_window) { - repl_tcp->max_win = sic->dest_td_max_window; - } - if ((s32)(repl_tcp->end - sic->dest_td_end) < 0) { - repl_tcp->end = sic->dest_td_end; - } - if ((s32)(repl_tcp->max_end - sic->dest_td_max_end) < 0) { - repl_tcp->max_end = sic->dest_td_max_end; - } - - /* update match flags */ - orig_cm->flags &= ~SFE_IPV6_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; - repl_cm->flags &= ~SFE_IPV6_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; - if (sic->flags & SFE_CREATE_FLAG_NO_SEQ_CHECK) { - orig_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; - repl_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; - } -} - -/* - * sfe_ipv6_update_protocol_state() - * update protocol specified state machine. - */ -static void -sfe_ipv6_update_protocol_state(struct sfe_ipv6_connection *c, - struct sfe_connection_create *sic) -{ - switch (sic->protocol) { - case IPPROTO_TCP: - sfe_ipv6_update_tcp_state(c, sic); - break; - } -} - -/* - * sfe_ipv6_update_rule() - * update forwarding rule after rule is created. - */ -void sfe_ipv6_update_rule(struct sfe_connection_create *sic) -{ - struct sfe_ipv6_connection *c; - struct sfe_ipv6 *si = &__si6; - - spin_lock_bh(&si->lock); - - c = sfe_ipv6_find_connection(si, - sic->protocol, - sic->src_ip.ip6, - sic->src_port, - sic->dest_ip.ip6, - sic->dest_port); - if (c != NULL) { - sfe_ipv6_update_protocol_state(c, sic); - } - - spin_unlock_bh(&si->lock); -} - -/* - * sfe_ipv6_create_rule() - * Create a forwarding rule. - */ -int sfe_ipv6_create_rule(struct sfe_connection_create *sic) -{ - struct sfe_ipv6 *si = &__si6; - struct sfe_ipv6_connection *c; - struct sfe_ipv6_connection_match *original_cm; - struct sfe_ipv6_connection_match *reply_cm; - struct net_device *dest_dev; - struct net_device *src_dev; - - dest_dev = sic->dest_dev; - src_dev = sic->src_dev; - - if (unlikely((dest_dev->reg_state != NETREG_REGISTERED) || - (src_dev->reg_state != NETREG_REGISTERED))) { - return -EINVAL; - } - - spin_lock_bh(&si->lock); - si->connection_create_requests++; - - /* - * Check to see if there is already a flow that matches the rule we're - * trying to create. If there is then we can't create a new one. - */ - c = sfe_ipv6_find_connection(si, - sic->protocol, - sic->src_ip.ip6, - sic->src_port, - sic->dest_ip.ip6, - sic->dest_port); - if (c != NULL) { - si->connection_create_collisions++; - - /* - * If we already have the flow then it's likely that this - * request to create the connection rule contains more - * up-to-date information. Check and update accordingly. - */ - sfe_ipv6_update_protocol_state(c, sic); - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("connection already exists - mark: %08x, p: %d\n" - " s: %s:%pxM:%pI6:%u, d: %s:%pxM:%pI6:%u\n", - sic->mark, sic->protocol, - sic->src_dev->name, sic->src_mac, sic->src_ip.ip6, ntohs(sic->src_port), - sic->dest_dev->name, sic->dest_mac, sic->dest_ip.ip6, ntohs(sic->dest_port)); - return -EADDRINUSE; - } - - /* - * Allocate the various connection tracking objects. - */ - c = (struct sfe_ipv6_connection *)kmalloc(sizeof(struct sfe_ipv6_connection), GFP_ATOMIC); - if (unlikely(!c)) { - spin_unlock_bh(&si->lock); - return -ENOMEM; - } - - original_cm = (struct sfe_ipv6_connection_match *)kmalloc(sizeof(struct sfe_ipv6_connection_match), GFP_ATOMIC); - if (unlikely(!original_cm)) { - spin_unlock_bh(&si->lock); - kfree(c); - return -ENOMEM; - } - - reply_cm = (struct sfe_ipv6_connection_match *)kmalloc(sizeof(struct sfe_ipv6_connection_match), GFP_ATOMIC); - if (unlikely(!reply_cm)) { - spin_unlock_bh(&si->lock); - kfree(original_cm); - kfree(c); - return -ENOMEM; - } - - /* - * Fill in the "original" direction connection matching object. - * Note that the transmit MAC address is "dest_mac_xlate" because - * we always know both ends of a connection by their translated - * addresses and not their public addresses. - */ - original_cm->match_dev = src_dev; - original_cm->match_protocol = sic->protocol; - original_cm->match_src_ip[0] = sic->src_ip.ip6[0]; - original_cm->match_src_port = sic->src_port; - original_cm->match_dest_ip[0] = sic->dest_ip.ip6[0]; - original_cm->match_dest_port = sic->dest_port; - original_cm->xlate_src_ip[0] = sic->src_ip_xlate.ip6[0]; - original_cm->xlate_src_port = sic->src_port_xlate; - original_cm->xlate_dest_ip[0] = sic->dest_ip_xlate.ip6[0]; - original_cm->xlate_dest_port = sic->dest_port_xlate; - original_cm->rx_packet_count = 0; - original_cm->rx_packet_count64 = 0; - original_cm->rx_byte_count = 0; - original_cm->rx_byte_count64 = 0; - original_cm->xmit_dev = dest_dev; - original_cm->xmit_dev_mtu = sic->dest_mtu; - memcpy(original_cm->xmit_src_mac, dest_dev->dev_addr, ETH_ALEN); - memcpy(original_cm->xmit_dest_mac, sic->dest_mac_xlate, ETH_ALEN); - original_cm->connection = c; - original_cm->counter_match = reply_cm; - original_cm->flags = 0; - if (sic->flags & SFE_CREATE_FLAG_REMARK_PRIORITY) { - original_cm->priority = sic->src_priority; - original_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_PRIORITY_REMARK; - } - if (sic->flags & SFE_CREATE_FLAG_REMARK_DSCP) { - original_cm->dscp = sic->src_dscp << SFE_IPV6_DSCP_SHIFT; - original_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_DSCP_REMARK; - } -#ifdef CONFIG_NF_FLOW_COOKIE - original_cm->flow_cookie = 0; -#endif -#ifdef CONFIG_XFRM - original_cm->flow_accel = sic->original_accel; -#endif - original_cm->active_next = NULL; - original_cm->active_prev = NULL; - original_cm->active = false; - - /* - * For PPP links we don't write an L2 header. For everything else we do. - */ - if (!(dest_dev->flags & IFF_POINTOPOINT)) { - original_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_L2_HDR; - - /* - * If our dev writes Ethernet headers then we can write a really fast - * version. - */ - if (dest_dev->header_ops) { - if (dest_dev->header_ops->create == eth_header) { - original_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR; - } - } - } - - /* - * Fill in the "reply" direction connection matching object. - */ - reply_cm->match_dev = dest_dev; - reply_cm->match_protocol = sic->protocol; - reply_cm->match_src_ip[0] = sic->dest_ip_xlate.ip6[0]; - reply_cm->match_src_port = sic->dest_port_xlate; - reply_cm->match_dest_ip[0] = sic->src_ip_xlate.ip6[0]; - reply_cm->match_dest_port = sic->src_port_xlate; - reply_cm->xlate_src_ip[0] = sic->dest_ip.ip6[0]; - reply_cm->xlate_src_port = sic->dest_port; - reply_cm->xlate_dest_ip[0] = sic->src_ip.ip6[0]; - reply_cm->xlate_dest_port = sic->src_port; - reply_cm->rx_packet_count = 0; - reply_cm->rx_packet_count64 = 0; - reply_cm->rx_byte_count = 0; - reply_cm->rx_byte_count64 = 0; - reply_cm->xmit_dev = src_dev; - reply_cm->xmit_dev_mtu = sic->src_mtu; - memcpy(reply_cm->xmit_src_mac, src_dev->dev_addr, ETH_ALEN); - memcpy(reply_cm->xmit_dest_mac, sic->src_mac, ETH_ALEN); - reply_cm->connection = c; - reply_cm->counter_match = original_cm; - reply_cm->flags = 0; - if (sic->flags & SFE_CREATE_FLAG_REMARK_PRIORITY) { - reply_cm->priority = sic->dest_priority; - reply_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_PRIORITY_REMARK; - } - if (sic->flags & SFE_CREATE_FLAG_REMARK_DSCP) { - reply_cm->dscp = sic->dest_dscp << SFE_IPV6_DSCP_SHIFT; - reply_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_DSCP_REMARK; - } -#ifdef CONFIG_NF_FLOW_COOKIE - reply_cm->flow_cookie = 0; -#endif -#ifdef CONFIG_XFRM - reply_cm->flow_accel = sic->reply_accel; -#endif - reply_cm->active_next = NULL; - reply_cm->active_prev = NULL; - reply_cm->active = false; - - /* - * For PPP links we don't write an L2 header. For everything else we do. - */ - if (!(src_dev->flags & IFF_POINTOPOINT)) { - reply_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_L2_HDR; - - /* - * If our dev writes Ethernet headers then we can write a really fast - * version. - */ - if (src_dev->header_ops) { - if (src_dev->header_ops->create == eth_header) { - reply_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR; - } - } - } - - - if (!sfe_ipv6_addr_equal(sic->dest_ip.ip6, sic->dest_ip_xlate.ip6) || sic->dest_port != sic->dest_port_xlate) { - original_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_DEST; - reply_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_SRC; - } - - if (!sfe_ipv6_addr_equal(sic->src_ip.ip6, sic->src_ip_xlate.ip6) || sic->src_port != sic->src_port_xlate) { - original_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_SRC; - reply_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_DEST; - } - - c->protocol = sic->protocol; - c->src_ip[0] = sic->src_ip.ip6[0]; - c->src_ip_xlate[0] = sic->src_ip_xlate.ip6[0]; - c->src_port = sic->src_port; - c->src_port_xlate = sic->src_port_xlate; - c->original_dev = src_dev; - c->original_match = original_cm; - c->dest_ip[0] = sic->dest_ip.ip6[0]; - c->dest_ip_xlate[0] = sic->dest_ip_xlate.ip6[0]; - c->dest_port = sic->dest_port; - c->dest_port_xlate = sic->dest_port_xlate; - c->reply_dev = dest_dev; - c->reply_match = reply_cm; - c->mark = sic->mark; - c->debug_read_seq = 0; - c->last_sync_jiffies = get_jiffies_64(); - - /* - * Take hold of our source and dest devices for the duration of the connection. - */ - dev_hold(c->original_dev); - dev_hold(c->reply_dev); - - /* - * Initialize the protocol-specific information that we track. - */ - switch (sic->protocol) { - case IPPROTO_TCP: - original_cm->protocol_state.tcp.win_scale = sic->src_td_window_scale; - original_cm->protocol_state.tcp.max_win = sic->src_td_max_window ? sic->src_td_max_window : 1; - original_cm->protocol_state.tcp.end = sic->src_td_end; - original_cm->protocol_state.tcp.max_end = sic->src_td_max_end; - reply_cm->protocol_state.tcp.win_scale = sic->dest_td_window_scale; - reply_cm->protocol_state.tcp.max_win = sic->dest_td_max_window ? sic->dest_td_max_window : 1; - reply_cm->protocol_state.tcp.end = sic->dest_td_end; - reply_cm->protocol_state.tcp.max_end = sic->dest_td_max_end; - if (sic->flags & SFE_CREATE_FLAG_NO_SEQ_CHECK) { - original_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; - reply_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; - } - break; - } - - sfe_ipv6_connection_match_compute_translations(original_cm); - sfe_ipv6_connection_match_compute_translations(reply_cm); - sfe_ipv6_insert_connection(si, c); - - spin_unlock_bh(&si->lock); - - /* - * We have everything we need! - */ - DEBUG_INFO("new connection - mark: %08x, p: %d\n" - " s: %s:%pxM(%pxM):%pI6(%pI6):%u(%u)\n" - " d: %s:%pxM(%pxM):%pI6(%pI6):%u(%u)\n", - sic->mark, sic->protocol, - sic->src_dev->name, sic->src_mac, sic->src_mac_xlate, - sic->src_ip.ip6, sic->src_ip_xlate.ip6, ntohs(sic->src_port), ntohs(sic->src_port_xlate), - dest_dev->name, sic->dest_mac, sic->dest_mac_xlate, - sic->dest_ip.ip6, sic->dest_ip_xlate.ip6, ntohs(sic->dest_port), ntohs(sic->dest_port_xlate)); - - return 0; -} - -/* - * sfe_ipv6_destroy_rule() - * Destroy a forwarding rule. - */ -void sfe_ipv6_destroy_rule(struct sfe_connection_destroy *sid) -{ - struct sfe_ipv6 *si = &__si6; - struct sfe_ipv6_connection *c; - - spin_lock_bh(&si->lock); - si->connection_destroy_requests++; - - /* - * Check to see if we have a flow that matches the rule we're trying - * to destroy. If there isn't then we can't destroy it. - */ - c = sfe_ipv6_find_connection(si, sid->protocol, sid->src_ip.ip6, sid->src_port, - sid->dest_ip.ip6, sid->dest_port); - if (!c) { - si->connection_destroy_misses++; - spin_unlock_bh(&si->lock); - - DEBUG_TRACE("connection does not exist - p: %d, s: %pI6:%u, d: %pI6:%u\n", - sid->protocol, sid->src_ip.ip6, ntohs(sid->src_port), - sid->dest_ip.ip6, ntohs(sid->dest_port)); - return; - } - - /* - * Remove our connection details from the hash tables. - */ - sfe_ipv6_remove_connection(si, c); - spin_unlock_bh(&si->lock); - - sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_DESTROY); - - DEBUG_INFO("connection destroyed - p: %d, s: %pI6:%u, d: %pI6:%u\n", - sid->protocol, sid->src_ip.ip6, ntohs(sid->src_port), - sid->dest_ip.ip6, ntohs(sid->dest_port)); -} - -/* - * sfe_ipv6_register_sync_rule_callback() - * Register a callback for rule synchronization. - */ -void sfe_ipv6_register_sync_rule_callback(sfe_sync_rule_callback_t sync_rule_callback) -{ - struct sfe_ipv6 *si = &__si6; - - spin_lock_bh(&si->lock); - rcu_assign_pointer(si->sync_rule_callback, sync_rule_callback); - spin_unlock_bh(&si->lock); -} - -/* - * sfe_ipv6_get_debug_dev() - */ -static ssize_t sfe_ipv6_get_debug_dev(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct sfe_ipv6 *si = &__si6; - ssize_t count; - int num; - - spin_lock_bh(&si->lock); - num = si->debug_dev; - spin_unlock_bh(&si->lock); - - count = snprintf(buf, (ssize_t)PAGE_SIZE, "%d\n", num); - return count; -} - -/* - * sfe_ipv6_destroy_all_rules_for_dev() - * Destroy all connections that match a particular device. - * - * If we pass dev as NULL then this destroys all connections. - */ -void sfe_ipv6_destroy_all_rules_for_dev(struct net_device *dev) -{ - struct sfe_ipv6 *si = &__si6; - struct sfe_ipv6_connection *c; - -another_round: - spin_lock_bh(&si->lock); - - for (c = si->all_connections_head; c; c = c->all_connections_next) { - /* - * Does this connection relate to the device we are destroying? - */ - if (!dev - || (dev == c->original_dev) - || (dev == c->reply_dev)) { - break; - } - } - - if (c) { - sfe_ipv6_remove_connection(si, c); - } - - spin_unlock_bh(&si->lock); - - if (c) { - sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_DESTROY); - goto another_round; - } -} - -/* - * sfe_ipv6_periodic_sync() - */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) -static void sfe_ipv6_periodic_sync(unsigned long arg) -#else -static void sfe_ipv6_periodic_sync(struct timer_list *tl) -#endif -{ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) - struct sfe_ipv6 *si = (struct sfe_ipv6 *)arg; -#else - struct sfe_ipv6 *si = from_timer(si, tl, timer); -#endif - u64 now_jiffies; - int quota; - sfe_sync_rule_callback_t sync_rule_callback; - - now_jiffies = get_jiffies_64(); - - rcu_read_lock(); - sync_rule_callback = rcu_dereference(si->sync_rule_callback); - if (!sync_rule_callback) { - rcu_read_unlock(); - goto done; - } - - spin_lock_bh(&si->lock); - sfe_ipv6_update_summary_stats(si); - - /* - * Get an estimate of the number of connections to parse in this sync. - */ - quota = (si->num_connections + 63) / 64; - - /* - * Walk the "active" list and sync the connection state. - */ - while (quota--) { - struct sfe_ipv6_connection_match *cm; - struct sfe_ipv6_connection_match *counter_cm; - struct sfe_ipv6_connection *c; - struct sfe_connection_sync sis; - - cm = si->active_head; - if (!cm) { - break; - } - - /* - * There's a possibility that our counter match is in the active list too. - * If it is then remove it. - */ - counter_cm = cm->counter_match; - if (counter_cm->active) { - counter_cm->active = false; - - /* - * We must have a connection preceding this counter match - * because that's the one that got us to this point, so we don't have - * to worry about removing the head of the list. - */ - counter_cm->active_prev->active_next = counter_cm->active_next; - - if (likely(counter_cm->active_next)) { - counter_cm->active_next->active_prev = counter_cm->active_prev; - } else { - si->active_tail = counter_cm->active_prev; - } - - counter_cm->active_next = NULL; - counter_cm->active_prev = NULL; - } - - /* - * Now remove the head of the active scan list. - */ - cm->active = false; - si->active_head = cm->active_next; - if (likely(cm->active_next)) { - cm->active_next->active_prev = NULL; - } else { - si->active_tail = NULL; - } - cm->active_next = NULL; - - /* - * Sync the connection state. - */ - c = cm->connection; - sfe_ipv6_gen_sync_connection(si, c, &sis, SFE_SYNC_REASON_STATS, now_jiffies); - - /* - * We don't want to be holding the lock when we sync! - */ - spin_unlock_bh(&si->lock); - sync_rule_callback(&sis); - spin_lock_bh(&si->lock); - } - - spin_unlock_bh(&si->lock); - rcu_read_unlock(); - -done: - mod_timer(&si->timer, jiffies + ((HZ + 99) / 100)); -} - -/* - * sfe_ipv6_debug_dev_read_start() - * Generate part of the XML output. - */ -static bool sfe_ipv6_debug_dev_read_start(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, - int *total_read, struct sfe_ipv6_debug_xml_write_state *ws) -{ - int bytes_read; - - si->debug_read_seq++; - - bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\n"); - if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { - return false; - } - - *length -= bytes_read; - *total_read += bytes_read; - - ws->state++; - return true; -} - -/* - * sfe_ipv6_debug_dev_read_connections_start() - * Generate part of the XML output. - */ -static bool sfe_ipv6_debug_dev_read_connections_start(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, - int *total_read, struct sfe_ipv6_debug_xml_write_state *ws) -{ - int bytes_read; - - bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n"); - if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { - return false; - } - - *length -= bytes_read; - *total_read += bytes_read; - - ws->state++; - return true; -} - -/* - * sfe_ipv6_debug_dev_read_connections_connection() - * Generate part of the XML output. - */ -static bool sfe_ipv6_debug_dev_read_connections_connection(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, - int *total_read, struct sfe_ipv6_debug_xml_write_state *ws) -{ - struct sfe_ipv6_connection *c; - struct sfe_ipv6_connection_match *original_cm; - struct sfe_ipv6_connection_match *reply_cm; - int bytes_read; - int protocol; - struct net_device *src_dev; - struct sfe_ipv6_addr src_ip; - struct sfe_ipv6_addr src_ip_xlate; - __be16 src_port; - __be16 src_port_xlate; - u64 src_rx_packets; - u64 src_rx_bytes; - struct net_device *dest_dev; - struct sfe_ipv6_addr dest_ip; - struct sfe_ipv6_addr dest_ip_xlate; - __be16 dest_port; - __be16 dest_port_xlate; - u64 dest_rx_packets; - u64 dest_rx_bytes; - u64 last_sync_jiffies; - u32 mark, src_priority, dest_priority, src_dscp, dest_dscp; -#ifdef CONFIG_NF_FLOW_COOKIE - int src_flow_cookie, dst_flow_cookie; -#endif - - spin_lock_bh(&si->lock); - - for (c = si->all_connections_head; c; c = c->all_connections_next) { - if (c->debug_read_seq < si->debug_read_seq) { - c->debug_read_seq = si->debug_read_seq; - break; - } - } - - /* - * If there were no connections then move to the next state. - */ - if (!c) { - spin_unlock_bh(&si->lock); - ws->state++; - return true; - } - - original_cm = c->original_match; - reply_cm = c->reply_match; - - protocol = c->protocol; - src_dev = c->original_dev; - src_ip = c->src_ip[0]; - src_ip_xlate = c->src_ip_xlate[0]; - src_port = c->src_port; - src_port_xlate = c->src_port_xlate; - src_priority = original_cm->priority; - src_dscp = original_cm->dscp >> SFE_IPV6_DSCP_SHIFT; - - sfe_ipv6_connection_match_update_summary_stats(original_cm); - sfe_ipv6_connection_match_update_summary_stats(reply_cm); - - src_rx_packets = original_cm->rx_packet_count64; - src_rx_bytes = original_cm->rx_byte_count64; - dest_dev = c->reply_dev; - dest_ip = c->dest_ip[0]; - dest_ip_xlate = c->dest_ip_xlate[0]; - dest_port = c->dest_port; - dest_port_xlate = c->dest_port_xlate; - dest_priority = reply_cm->priority; - dest_dscp = reply_cm->dscp >> SFE_IPV6_DSCP_SHIFT; - dest_rx_packets = reply_cm->rx_packet_count64; - dest_rx_bytes = reply_cm->rx_byte_count64; - last_sync_jiffies = get_jiffies_64() - c->last_sync_jiffies; - mark = c->mark; -#ifdef CONFIG_NF_FLOW_COOKIE - src_flow_cookie = original_cm->flow_cookie; - dst_flow_cookie = reply_cm->flow_cookie; -#endif - spin_unlock_bh(&si->lock); - - bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\t\n", - protocol, - src_dev->name, - &src_ip, &src_ip_xlate, - ntohs(src_port), ntohs(src_port_xlate), - src_priority, src_dscp, - src_rx_packets, src_rx_bytes, - dest_dev->name, - &dest_ip, &dest_ip_xlate, - ntohs(dest_port), ntohs(dest_port_xlate), - dest_priority, dest_dscp, - dest_rx_packets, dest_rx_bytes, -#ifdef CONFIG_NF_FLOW_COOKIE - src_flow_cookie, dst_flow_cookie, -#endif - last_sync_jiffies, mark); - - if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { - return false; - } - - *length -= bytes_read; - *total_read += bytes_read; - - return true; -} - -/* - * sfe_ipv6_debug_dev_read_connections_end() - * Generate part of the XML output. - */ -static bool sfe_ipv6_debug_dev_read_connections_end(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, - int *total_read, struct sfe_ipv6_debug_xml_write_state *ws) -{ - int bytes_read; - - bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n"); - if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { - return false; - } - - *length -= bytes_read; - *total_read += bytes_read; - - ws->state++; - return true; -} - -/* - * sfe_ipv6_debug_dev_read_exceptions_start() - * Generate part of the XML output. - */ -static bool sfe_ipv6_debug_dev_read_exceptions_start(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, - int *total_read, struct sfe_ipv6_debug_xml_write_state *ws) -{ - int bytes_read; - - bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n"); - if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { - return false; - } - - *length -= bytes_read; - *total_read += bytes_read; - - ws->state++; - return true; -} - -/* - * sfe_ipv6_debug_dev_read_exceptions_exception() - * Generate part of the XML output. - */ -static bool sfe_ipv6_debug_dev_read_exceptions_exception(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, - int *total_read, struct sfe_ipv6_debug_xml_write_state *ws) -{ - u64 ct; - - spin_lock_bh(&si->lock); - ct = si->exception_events64[ws->iter_exception]; - spin_unlock_bh(&si->lock); - - if (ct) { - int bytes_read; - - bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, - "\t\t\n", - sfe_ipv6_exception_events_string[ws->iter_exception], - ct); - if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { - return false; - } - - *length -= bytes_read; - *total_read += bytes_read; - } - - ws->iter_exception++; - if (ws->iter_exception >= SFE_IPV6_EXCEPTION_EVENT_LAST) { - ws->iter_exception = 0; - ws->state++; - } - - return true; -} - -/* - * sfe_ipv6_debug_dev_read_exceptions_end() - * Generate part of the XML output. - */ -static bool sfe_ipv6_debug_dev_read_exceptions_end(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, - int *total_read, struct sfe_ipv6_debug_xml_write_state *ws) -{ - int bytes_read; - - bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n"); - if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { - return false; - } - - *length -= bytes_read; - *total_read += bytes_read; - - ws->state++; - return true; -} - -/* - * sfe_ipv6_debug_dev_read_stats() - * Generate part of the XML output. - */ -static bool sfe_ipv6_debug_dev_read_stats(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, - int *total_read, struct sfe_ipv6_debug_xml_write_state *ws) -{ - int bytes_read; - unsigned int num_connections; - u64 packets_forwarded; - u64 packets_not_forwarded; - u64 connection_create_requests; - u64 connection_create_collisions; - u64 connection_destroy_requests; - u64 connection_destroy_misses; - u64 connection_flushes; - u64 connection_match_hash_hits; - u64 connection_match_hash_reorders; - - spin_lock_bh(&si->lock); - sfe_ipv6_update_summary_stats(si); - - num_connections = si->num_connections; - packets_forwarded = si->packets_forwarded64; - packets_not_forwarded = si->packets_not_forwarded64; - connection_create_requests = si->connection_create_requests64; - connection_create_collisions = si->connection_create_collisions64; - connection_destroy_requests = si->connection_destroy_requests64; - connection_destroy_misses = si->connection_destroy_misses64; - connection_flushes = si->connection_flushes64; - connection_match_hash_hits = si->connection_match_hash_hits64; - connection_match_hash_reorders = si->connection_match_hash_reorders64; - spin_unlock_bh(&si->lock); - - bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n", - num_connections, - packets_forwarded, - packets_not_forwarded, - connection_create_requests, - connection_create_collisions, - connection_destroy_requests, - connection_destroy_misses, - connection_flushes, - connection_match_hash_hits, - connection_match_hash_reorders); - if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { - return false; - } - - *length -= bytes_read; - *total_read += bytes_read; - - ws->state++; - return true; -} - -/* - * sfe_ipv6_debug_dev_read_end() - * Generate part of the XML output. - */ -static bool sfe_ipv6_debug_dev_read_end(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, - int *total_read, struct sfe_ipv6_debug_xml_write_state *ws) -{ - int bytes_read; - - bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\n"); - if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { - return false; - } - - *length -= bytes_read; - *total_read += bytes_read; - - ws->state++; - return true; -} - -/* - * Array of write functions that write various XML elements that correspond to - * our XML output state machine. - */ -static sfe_ipv6_debug_xml_write_method_t sfe_ipv6_debug_xml_write_methods[SFE_IPV6_DEBUG_XML_STATE_DONE] = { - sfe_ipv6_debug_dev_read_start, - sfe_ipv6_debug_dev_read_connections_start, - sfe_ipv6_debug_dev_read_connections_connection, - sfe_ipv6_debug_dev_read_connections_end, - sfe_ipv6_debug_dev_read_exceptions_start, - sfe_ipv6_debug_dev_read_exceptions_exception, - sfe_ipv6_debug_dev_read_exceptions_end, - sfe_ipv6_debug_dev_read_stats, - sfe_ipv6_debug_dev_read_end, -}; - -/* - * sfe_ipv6_debug_dev_read() - * Send info to userspace upon read request from user - */ -static ssize_t sfe_ipv6_debug_dev_read(struct file *filp, char *buffer, size_t length, loff_t *offset) -{ - char msg[CHAR_DEV_MSG_SIZE]; - int total_read = 0; - struct sfe_ipv6_debug_xml_write_state *ws; - struct sfe_ipv6 *si = &__si6; - - ws = (struct sfe_ipv6_debug_xml_write_state *)filp->private_data; - while ((ws->state != SFE_IPV6_DEBUG_XML_STATE_DONE) && (length > CHAR_DEV_MSG_SIZE)) { - if ((sfe_ipv6_debug_xml_write_methods[ws->state])(si, buffer, msg, &length, &total_read, ws)) { - continue; - } - } - - return total_read; -} - -/* - * sfe_ipv6_debug_dev_write() - * Write to char device resets some stats - */ -static ssize_t sfe_ipv6_debug_dev_write(struct file *filp, const char *buffer, size_t length, loff_t *offset) -{ - struct sfe_ipv6 *si = &__si6; - - spin_lock_bh(&si->lock); - sfe_ipv6_update_summary_stats(si); - - si->packets_forwarded64 = 0; - si->packets_not_forwarded64 = 0; - si->connection_create_requests64 = 0; - si->connection_create_collisions64 = 0; - si->connection_destroy_requests64 = 0; - si->connection_destroy_misses64 = 0; - si->connection_flushes64 = 0; - si->connection_match_hash_hits64 = 0; - si->connection_match_hash_reorders64 = 0; - spin_unlock_bh(&si->lock); - - return length; -} - -/* - * sfe_ipv6_debug_dev_open() - */ -static int sfe_ipv6_debug_dev_open(struct inode *inode, struct file *file) -{ - struct sfe_ipv6_debug_xml_write_state *ws; - - ws = (struct sfe_ipv6_debug_xml_write_state *)file->private_data; - if (ws) { - return 0; - } - - ws = kzalloc(sizeof(struct sfe_ipv6_debug_xml_write_state), GFP_KERNEL); - if (!ws) { - return -ENOMEM; - } - - ws->state = SFE_IPV6_DEBUG_XML_STATE_START; - file->private_data = ws; - - return 0; -} - -/* - * sfe_ipv6_debug_dev_release() - */ -static int sfe_ipv6_debug_dev_release(struct inode *inode, struct file *file) -{ - struct sfe_ipv6_debug_xml_write_state *ws; - - ws = (struct sfe_ipv6_debug_xml_write_state *)file->private_data; - if (ws) { - /* - * We've finished with our output so free the write state. - */ - kfree(ws); - } - - return 0; -} - -/* - * File operations used in the debug char device - */ -static struct file_operations sfe_ipv6_debug_dev_fops = { - .read = sfe_ipv6_debug_dev_read, - .write = sfe_ipv6_debug_dev_write, - .open = sfe_ipv6_debug_dev_open, - .release = sfe_ipv6_debug_dev_release -}; - -#ifdef CONFIG_NF_FLOW_COOKIE -/* - * sfe_ipv6_register_flow_cookie_cb - * register a function in SFE to let SFE use this function to configure flow cookie for a flow - * - * Hardware driver which support flow cookie should register a callback function in SFE. Then SFE - * can use this function to configure flow cookie for a flow. - * return: 0, success; !=0, fail - */ -int sfe_ipv6_register_flow_cookie_cb(sfe_ipv6_flow_cookie_set_func_t cb) -{ - struct sfe_ipv6 *si = &__si6; - - BUG_ON(!cb); - - if (si->flow_cookie_set_func) { - return -1; - } - - rcu_assign_pointer(si->flow_cookie_set_func, cb); - return 0; -} - -/* - * sfe_ipv6_unregister_flow_cookie_cb - * unregister function which is used to configure flow cookie for a flow - * - * return: 0, success; !=0, fail - */ -int sfe_ipv6_unregister_flow_cookie_cb(sfe_ipv6_flow_cookie_set_func_t cb) -{ - struct sfe_ipv6 *si = &__si6; - - RCU_INIT_POINTER(si->flow_cookie_set_func, NULL); - return 0; -} - -/* - * sfe_ipv6_get_flow_cookie() - */ -static ssize_t sfe_ipv6_get_flow_cookie(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct sfe_ipv6 *si = &__si6; - return snprintf(buf, (ssize_t)PAGE_SIZE, "%d\n", si->flow_cookie_enable); -} - -/* - * sfe_ipv6_set_flow_cookie() - */ -static ssize_t sfe_ipv6_set_flow_cookie(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - struct sfe_ipv6 *si = &__si6; - strict_strtol(buf, 0, (long int *)&si->flow_cookie_enable); - - return size; -} - -/* - * sysfs attributes. - */ -static const struct device_attribute sfe_ipv6_flow_cookie_attr = - __ATTR(flow_cookie_enable, S_IWUSR | S_IRUGO, sfe_ipv6_get_flow_cookie, sfe_ipv6_set_flow_cookie); -#endif /*CONFIG_NF_FLOW_COOKIE*/ - -/* - * sfe_ipv6_init() - */ -static int __init sfe_ipv6_init(void) -{ - struct sfe_ipv6 *si = &__si6; - int result = -1; - - DEBUG_INFO("SFE IPv6 init\n"); - - /* - * Create sys/sfe_ipv6 - */ - si->sys_sfe_ipv6 = kobject_create_and_add("sfe_ipv6", NULL); - if (!si->sys_sfe_ipv6) { - DEBUG_ERROR("failed to register sfe_ipv6\n"); - goto exit1; - } - - /* - * Create files, one for each parameter supported by this module. - */ - result = sysfs_create_file(si->sys_sfe_ipv6, &sfe_ipv6_debug_dev_attr.attr); - if (result) { - DEBUG_ERROR("failed to register debug dev file: %d\n", result); - goto exit2; - } - -#ifdef CONFIG_NF_FLOW_COOKIE - result = sysfs_create_file(si->sys_sfe_ipv6, &sfe_ipv6_flow_cookie_attr.attr); - if (result) { - DEBUG_ERROR("failed to register flow cookie enable file: %d\n", result); - goto exit3; - } -#endif /* CONFIG_NF_FLOW_COOKIE */ - - /* - * Register our debug char device. - */ - result = register_chrdev(0, "sfe_ipv6", &sfe_ipv6_debug_dev_fops); - if (result < 0) { - DEBUG_ERROR("Failed to register chrdev: %d\n", result); - goto exit4; - } - - si->debug_dev = result; - - /* - * Create a timer to handle periodic statistics. - */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) - setup_timer(&si->timer, sfe_ipv6_periodic_sync, (unsigned long)si); -#else - timer_setup(&si->timer, sfe_ipv6_periodic_sync, 0); -#endif - mod_timer(&si->timer, jiffies + ((HZ + 99) / 100)); - - spin_lock_init(&si->lock); - - return 0; - -exit4: -#ifdef CONFIG_NF_FLOW_COOKIE - sysfs_remove_file(si->sys_sfe_ipv6, &sfe_ipv6_flow_cookie_attr.attr); - -exit3: -#endif /* CONFIG_NF_FLOW_COOKIE */ - sysfs_remove_file(si->sys_sfe_ipv6, &sfe_ipv6_debug_dev_attr.attr); - -exit2: - kobject_put(si->sys_sfe_ipv6); - -exit1: - return result; -} - -/* - * sfe_ipv6_exit() - */ -static void __exit sfe_ipv6_exit(void) -{ - struct sfe_ipv6 *si = &__si6; - - DEBUG_INFO("SFE IPv6 exit\n"); - - /* - * Destroy all connections. - */ - sfe_ipv6_destroy_all_rules_for_dev(NULL); - - del_timer_sync(&si->timer); - - unregister_chrdev(si->debug_dev, "sfe_ipv6"); - -#ifdef CONFIG_NF_FLOW_COOKIE - sysfs_remove_file(si->sys_sfe_ipv6, &sfe_ipv6_flow_cookie_attr.attr); -#endif /* CONFIG_NF_FLOW_COOKIE */ - sysfs_remove_file(si->sys_sfe_ipv6, &sfe_ipv6_debug_dev_attr.attr); - - kobject_put(si->sys_sfe_ipv6); -} - -module_init(sfe_ipv6_init) -module_exit(sfe_ipv6_exit) - -EXPORT_SYMBOL(sfe_ipv6_recv); -EXPORT_SYMBOL(sfe_ipv6_create_rule); -EXPORT_SYMBOL(sfe_ipv6_destroy_rule); -EXPORT_SYMBOL(sfe_ipv6_destroy_all_rules_for_dev); -EXPORT_SYMBOL(sfe_ipv6_register_sync_rule_callback); -EXPORT_SYMBOL(sfe_ipv6_mark_rule); -EXPORT_SYMBOL(sfe_ipv6_update_rule); -#ifdef CONFIG_NF_FLOW_COOKIE -EXPORT_SYMBOL(sfe_ipv6_register_flow_cookie_cb); -EXPORT_SYMBOL(sfe_ipv6_unregister_flow_cookie_cb); -#endif - -MODULE_DESCRIPTION("Shortcut Forwarding Engine - IPv6 support"); -MODULE_LICENSE("Dual BSD/GPL"); - diff --git a/root/package/lean/shortcut-fe/simulated-driver/Makefile b/root/package/lean/shortcut-fe/simulated-driver/Makefile deleted file mode 100644 index ecf9c41b..00000000 --- a/root/package/lean/shortcut-fe/simulated-driver/Makefile +++ /dev/null @@ -1,60 +0,0 @@ -# -# Copyright (c) 2015,2016 The Linux Foundation. All rights reserved. -# Permission to use, copy, modify, and/or distribute this software for -# any purpose with or without fee is hereby granted, provided that the -# above copyright notice and this permission notice appear in all copies. -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -include $(TOPDIR)/rules.mk -include $(INCLUDE_DIR)/kernel.mk - -PKG_NAME:=shortcut-fe-simulated-driver -PKG_RELEASE:=1 - -PKG_SOURCE_URL:=https://source.codeaurora.org/quic/qsdk/oss/lklm/shortcut-fe -PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2021-03-17 -PKG_SOURCE_VERSION:=697977d8d0ccf0ab596e5692d08608a75dd7f33d -PKG_MIRROR_HASH:=659fa82a431e15af797a6c7069faeee02810453ad8b576c51c29f95a1761a045 - -include $(INCLUDE_DIR)/package.mk - -define KernelPackage/shortcut-fe-drv - SECTION:=kernel - CATEGORY:=Kernel modules - SUBMENU:=Network Support - DEPENDS:=@TARGET_ipq806x||TARGET_ipq807x +kmod-shortcut-fe - KCONFIG:= \ - CONFIG_NET_CLS_ACT=y \ - CONFIG_XFRM=y - TITLE:=Simulated sfe driver for ECM - FILES:=$(PKG_BUILD_DIR)/simulated-driver/shortcut-fe-drv.ko -endef - -define KernelPackage/shortcut-fe-drv/Description -Simulated sfe driver which act as an adapter to convert message -between a connection manager and the SFE core engine. -endef - -define Build/Compile - $(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \ - $(KERNEL_MAKE_FLAGS) \ - $(PKG_MAKE_FLAGS) \ - M="$(PKG_BUILD_DIR)/simulated-driver" \ - EXTRA_CFLAGS="-DSFE_SUPPORT_IPV6" \ - modules -endef - -define Build/InstallDev - $(INSTALL_DIR) $(1)/usr/include/shortcut-fe - $(CP) -rf $(PKG_BUILD_DIR)/simulated-driver/sfe_drv.h $(1)/usr/include/shortcut-fe -endef - -$(eval $(call KernelPackage,shortcut-fe-drv)) diff --git a/root/package/lean/shortcut-fe/simulated-driver/patches/200-nss-qdisc-support.patch b/root/package/lean/shortcut-fe/simulated-driver/patches/200-nss-qdisc-support.patch deleted file mode 100644 index 638ad8a8..00000000 --- a/root/package/lean/shortcut-fe/simulated-driver/patches/200-nss-qdisc-support.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- ./simulated-driver/sfe_drv.c.orig 2020-06-16 12:49:47.680153371 +0800 -+++ ./simulated-driver/sfe_drv.c 2020-06-16 12:50:18.540153371 +0800 -@@ -1167,7 +1167,7 @@ int sfe_drv_recv(struct sk_buff *skb) - * If ingress Qdisc configured, and packet not processed by ingress Qdisc yet - * We can not accelerate this packet. - */ -- if (dev->ingress_queue && !(skb->tc_verd & TC_NCLS)) { -+ if (dev->ingress_queue && !(skb->tc_verd_qca_nss & TC_NCLS)) { - return 0; - } - #endif From 81c1667a06de1b756289cd5b01d35960e4e25e79 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Sun, 27 Nov 2022 00:24:52 +0800 Subject: [PATCH 069/102] Update config --- config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config b/config index cfa8b64d..70bb5fcc 100644 --- a/config +++ b/config @@ -28,8 +28,8 @@ CONFIG_BUSYBOX_CONFIG_FEATURE_VI_UNDO_QUEUE_MAX=32 CONFIG_BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_PARALLEL=y CONFIG_BUSYBOX_CONFIG_IOSTAT=y CONFIG_BUSYBOX_CONFIG_LOADKMAP=y -CONFIG_BUSYBOX_CONFIG_LSPCI=y -CONFIG_BUSYBOX_CONFIG_LSUSB=y +# CONFIG_BUSYBOX_CONFIG_LSPCI is not set +# CONFIG_BUSYBOX_CONFIG_LSUSB is not set CONFIG_BUSYBOX_CONFIG_NOHUP=y CONFIG_BUSYBOX_CONFIG_PKILL=y CONFIG_BUSYBOX_CONFIG_STAT=y From b01e33ef2365e52576c16de90039030a2862dfde Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Sun, 27 Nov 2022 03:12:47 +0800 Subject: [PATCH 070/102] fix --- .github/FUNDING.yml | 0 .github/ISSUE_TEMPLATE/enhancement.md | 0 .github/ISSUE_TEMPLATE/feature_request.md | 0 .github/ISSUE_TEMPLATE/hardware_support.md | 0 .github/ISSUE_TEMPLATE/help.md | 0 .github/ISSUE_TEMPLATE/issue.md | 0 .github/ISSUE_TEMPLATE/question.md | 0 .github/PULL_REQUEST_TEMPLATE.md | 0 .github/workflows/stale.yml | 0 .gitignore | 0 CLA-entity.md | 0 CLA-individual.md | 0 CODE_OF_CONDUCT.md | 0 CONTRIBUTING.md | 0 LICENSE | 0 README.md | 0 config | 0 config-4018 | 0 config-bpi-r1 | 0 config-bpi-r2 | 0 config-bpi-r64 | 0 config-cm520-79f | 0 config-espressobin | 0 config-espressobin1 | 0 config-l1000 | 0 config-nanopi_neo | 0 config-p2w_r619ac | 0 config-r2s | 0 config-r4s | 0 config-r7800 | 0 config-rpi2 | 0 config-rpi3 | 0 config-rpi4 | 0 config-ubnt-erx | 0 config-wrt3200acm | 0 config-wrt32x | 0 config-x86 | 0 config-x86_64 | 0 config-zbt4019 | 0 contributors/example.md | 0 deploy_rsa.enc | Bin patches/950-0785-fixcm4soundboss2.patch | 0 patches/bbr2.patch | 0 patches/check-rsync.patch | 0 patches/download-ipv4.patch | 0 patches/gtime.patch | 0 patches/images.patch | 0 patches/ipt-nat6.patch | 0 patches/luci-occitan.patch | 0 patches/nanqinlang.patch | 0 patches/nocheck.patch | 0 patches/package-too-long.patch | 0 patches/remove_abi.patch | 0 patches/smsc75xx.patch | 0 patches/uefi.patch | 0 root/include/kernel-version.mk | 0 root/package/base-files/files/bin/config_generate | 0 root/package/base-files/files/etc/banner | 0 root/package/base-files/files/etc/shadow | 0 .../src/of-platdata/nanopi-r2s-rk3328/dt-plat.c | 0 .../firmware/ipq-wifi/board-pangu_l1000.qca4019 | Bin root/package/kernel/linux/modules/crypto.mk | 0 root/package/kernel/linux/modules/fs.mk | 0 root/package/kernel/linux/modules/input.mk | 0 root/package/kernel/linux/modules/netfilter.mk | 0 root/package/kernel/linux/modules/other.mk | 0 root/package/kernel/linux/modules/sound.mk | 0 .../mwlwifi/patches/002-remove-fallthrough.patch | 0 .../config/firewall/patches/fullconenat.patch | 0 root/package/utils/sysupgrade-helper/src/MAKEALL | 0 .../src/arch/blackfin/cpu/bootrom-asm-offsets.awk | 0 .../src/drivers/net/nss/synopGMAC_Dev.c | 0 .../src/drivers/net/nss/synopGMAC_Dev.h | 0 .../drivers/net/nss/synopGMAC_network_interface.c | 0 .../src/drivers/net/nss/synopGMAC_plat.h | 0 .../src/drivers/net/nss/uboot_skb.c | 0 .../src/drivers/net/nss/uboot_skb.h | 0 root/package/utils/sysupgrade-helper/src/mkconfig | 0 .../utils/sysupgrade-helper/src/tools/checkpatch.pl | 0 .../utils/sysupgrade-helper/src/tools/checkstack.pl | 0 .../sysupgrade-helper/src/tools/gcc-version.sh | 0 .../utils/sysupgrade-helper/src/tools/img2brec.sh | 0 .../utils/sysupgrade-helper/src/tools/jtagconsole | 0 .../utils/sysupgrade-helper/src/tools/netconsole | 0 .../utils/sysupgrade-helper/src/tools/pack.py | 0 .../sysupgrade-helper/src/tools/patman/patman.py | 0 .../src/tools/scripts/make-asm-offsets | 0 .../sysupgrade-helper/src/tools/setlocalversion | 0 root/scripts/mkits-rutx.sh | 0 ...ARM-dts-Add-bcm2711-rpi-cm4antrouter5g.dts.patch | 0 .../950-0785-ARM-dts-Add-bcm2711-rpi-cm4.dts.patch | 0 .../backport-5.14/011-kbuild-export-SUBARCH.patch | 0 ...nft_flow_offload-handle-netdevice-events-f.patch | 0 ...0-MIPS-uasm-Enable-muhu-opcode-for-MIPS-R6.patch | 0 ...Add-workaround-for-Loongson-2F-nop-CPU-err.patch | 0 ...6-02-mips-bpf-Add-eBPF-JIT-for-32-bit-MIPS.patch | 0 ...-mips-bpf-Add-new-eBPF-JIT-for-64-bit-MIPS.patch | 0 ...ips-bpf-Add-JIT-workarounds-for-CPU-errata.patch | 0 .../050-v5.16-05-mips-bpf-Enable-eBPF-JITs.patch | 0 ...ips-bpf-Remove-old-BPF-JIT-implementations.patch | 0 ...-v5.16-0001-net-bgmac-improve-handling-PHY.patch | 0 ...002-net-bgmac-support-MDIO-described-in-DT.patch | 0 ...803x-add-support-for-qca-8327-internal-phy.patch | 0 ...-at803x-add-support-for-qca-8327-A-variant.patch | 0 ...803x-add-resume-suspend-function-to-qca83x.patch | 0 ...803x-fix-spacing-and-improve-name-for-83xx.patch | 0 ...-net-phy-at803x-fix-resume-for-QCA8327-phy.patch | 0 ...-at803x-add-DAC-amplitude-fix-for-8327-phy.patch | 0 ...803x-enable-prefer-master-for-83xx-interna.patch | 0 ...-net-phy-at803x-better-describe-debug-regs.patch | 0 ....16-01-dsa-qca8k-add-mac-power-sel-support.patch | 0 ...s-net-dsa-qca8k-Add-SGMII-clock-phase-prop.patch | 0 ...a-qca8k-add-support-for-sgmii-falling-edge.patch | 0 ...s-net-dsa-qca8k-Document-support-for-CPU-p.patch | 0 ...5-net-dsa-qca8k-add-support-for-cpu-port-6.patch | 0 ...a8k-rework-rgmii-delay-logic-and-scan-for-.patch | 0 ...s-net-dsa-qca8k-Document-qca-sgmii-enable-.patch | 0 ...et-dsa-qca8k-add-explicit-SGMII-PLL-enable.patch | 0 ...s-net-dsa-qca8k-Document-qca-led-open-drai.patch | 0 ...t-dsa-qca8k-add-support-for-pws-config-reg.patch | 0 ...s-net-dsa-qca8k-document-support-for-qca83.patch | 0 ...6-12-net-dsa-qca8k-add-support-for-QCA8328.patch | 0 ...sa-qca8k-set-internal-delay-also-for-sgmii.patch | 0 ...qca8k-move-port-config-to-dedicated-struct.patch | 0 ...s-net-ipq8064-mdio-fix-warning-with-new-qc.patch | 0 ...dings-net-dsa-qca8k-convert-to-YAML-schema.patch | 0 ...-fix-delay-applied-to-wrong-cpu-in-parse-p.patch | 0 ...-tidy-for-loop-in-setup-and-add-cpu-port-c.patch | 0 ...-make-sure-pad0-mac06-exchange-is-disabled.patch | 0 root/target/linux/generic/config-4.14 | 0 root/target/linux/generic/config-4.19 | 0 root/target/linux/generic/config-4.9 | 0 root/target/linux/generic/config-5.14 | 0 root/target/linux/generic/config-5.15 | 0 root/target/linux/generic/config-5.4 | 0 .../generic/files/drivers/net/phy/b53/b53_common.c | 0 .../linux/generic/hack-4.14/690-mptcp_v0.94.patch | 0 .../generic/hack-4.14/998-ndpi-netfilter.patch | 0 .../hack-4.14/999-stop-promiscuous-info.patch | 0 .../linux/generic/hack-4.19/690-mptcp_v0.95.patch | 0 .../linux/generic/hack-4.19/691-mptcp_ecf.patch | 0 .../generic/hack-4.19/692-tcp_nanqinlang.patch | 0 .../generic/hack-4.19/998-ndpi-netfilter.patch | 0 .../generic/hack-4.19/999-f2fs-ioerrorfix.patch | 0 .../hack-4.19/999-stop-promiscuous-info.patch | 0 .../linux/generic/hack-4.9/690-mptcp_v0.93.patch | 0 .../linux/generic/hack-5.14/204-module_strip.patch | 0 .../hack-5.14/210-darwin_scripts_include.patch | 0 .../hack-5.14/211-darwin-uuid-typedef-clash.patch | 0 .../generic/hack-5.14/212-tools_portability.patch | 0 .../hack-5.14/214-spidev_h_portability.patch | 0 .../linux/generic/hack-5.14/220-gc_sections.patch | 0 .../generic/hack-5.14/221-module_exports.patch | 0 .../hack-5.14/230-openwrt_lzma_options.patch | 0 .../hack-5.14/249-udp-tunnel-selection.patch | 0 .../generic/hack-5.14/250-netfilter_depends.patch | 0 .../linux/generic/hack-5.14/251-kconfig.patch | 0 .../hack-5.14/260-crypto_test_dependencies.patch | 0 .../generic/hack-5.14/261-lib-arc4-unhide.patch | 0 .../linux/generic/hack-5.14/280-rfkill-stubs.patch | 0 ...S-r4k_cache-use-more-efficient-cache-blast.patch | 0 .../hack-5.14/301-mips_image_cmdline_hack.patch | 0 .../hack-5.14/321-powerpc_crtsavres_prereq.patch | 0 .../420-mtd-set-rootfs-to-be-root-dev.patch | 0 .../linux/generic/hack-5.14/531-debloat_lzma.patch | 0 .../640-bridge-only-accept-EAP-locally.patch | 0 ...-netfilter-connmark-introduce-set-dscpmark.patch | 0 .../650-netfilter-add-xt_FLOWOFFLOAD-target.patch | 0 .../hack-5.14/651-wireless_mesh_header.patch | 0 .../generic/hack-5.14/660-fq_codel_defaults.patch | 0 .../hack-5.14/661-use_fq_codel_by_default.patch | 0 .../hack-5.14/700-swconfig_switch_drivers.patch | 0 .../710-net-dsa-mv88e6xxx-default-VID-1.patch | 0 ...11-net-dsa-mv88e6xxx-disable-ATU-violation.patch | 0 .../hack-5.14/773-bgmac-add-srab-switch.patch | 0 .../hack-5.14/780-net-ipheth-fix-RX-EOVERFLOW.patch | 0 .../hack-5.14/800-GPIO-add-named-gpio-exports.patch | 0 .../generic/hack-5.14/901-debloat_sock_diag.patch | 0 .../linux/generic/hack-5.14/902-debloat_proc.patch | 0 .../generic/hack-5.14/904-debloat_dma_buf.patch | 0 .../generic/hack-5.14/910-kobject_uevent.patch | 0 .../911-kobject_add_broadcast_uevent.patch | 0 .../linux/generic/hack-5.15/220-gc_sections.patch | 0 .../linux/generic/hack-5.4/690-mptcp_v0.96.patch | 0 .../linux/generic/hack-5.4/692-tcp_nanqinlang.patch | 0 .../linux/generic/hack-5.4/693-tcp_bbr2.patch | 0 .../hack-5.4/999-stop-promiscuous-info.patch | 0 ...-only-include-asm-rwonce.h-for-kernel-code.patch | 0 .../101-Use-stddefs.h-instead-of-compiler.h.patch | 0 ...process-negative-stack-offsets-on-stack-tr.patch | 0 ...oc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch | 0 .../130-add-linux-spidev-compatible-si3210.patch | 0 ...0-bridge_allow_receiption_on_disabled_port.patch | 0 ...90-rtc-rs5c372-support_alarms_up_to_1_week.patch | 0 ...-let_the_alarm_to_be_used_as_wakeup_source.patch | 0 .../pending-5.14/201-extra_optimization.patch | 0 .../pending-5.14/203-kallsyms_uncompressed.patch | 0 .../pending-5.14/205-backtrace_module_info.patch | 0 ...-unsane-filenames-from-deps_initramfs-list.patch | 0 ...261-enable_wilink_platform_without_drivers.patch | 0 .../270-platform-mikrotik-build-bits.patch | 0 .../pending-5.14/300-mips_expose_boot_raw.patch | 0 .../pending-5.14/302-mips_no_branch_likely.patch | 0 .../pending-5.14/305-mips_module_reloc.patch | 0 .../pending-5.14/307-mips_highmem_offset.patch | 0 .../generic/pending-5.14/308-mips32r2_tune.patch | 0 ...S-Add-CPU-option-reporting-to-proc-cpuinfo.patch | 0 .../310-arm_module_unresolved_weak_sym.patch | 0 ...-Accept-command-line-parameters-from-users.patch | 0 .../pending-5.14/332-arc-add-OWRTDTB-section.patch | 0 ...arc-enable-unaligned-access-in-kernel-mode.patch | 0 ...able-kernel-XZ-compression-option-on-PPC_8.patch | 0 .../pending-5.14/400-mtd-mtdsplit-support.patch | 0 ...redboot-add-of_match_table-with-DT-binding.patch | 0 .../430-mtd-add-myloader-partition-parser.patch | 0 ...xpart-check-for-bad-blocks-when-calculatin.patch | 0 ...2-mtd-bcm47xxpart-detect-T_Meter-partition.patch | 0 .../435-mtd-add-routerbootpart-parser-config.patch | 0 .../460-mtd-cfi_cmdset_0002-no-erase_suspend.patch | 0 ...i_cmdset_0002-add-buffer-write-cmd-timeout.patch | 0 .../465-m25p80-mx-disable-software-protection.patch | 0 ...r-support-limiting-4K-sectors-support-base.patch | 0 .../476-mtd-spi-nor-add-eon-en25q128.patch | 0 .../479-mtd-spi-nor-add-xtx-xt25f128b.patch | 0 ...spi-nor-add-support-for-Gigadevice-GD25D05.patch | 0 .../pending-5.14/483-mtd-spi-nor-add-gd25q512.patch | 0 ...ttach-mtd-device-named-ubi-or-data-on-boot.patch | 0 ...ubi-auto-create-ubiblock-device-for-rootfs.patch | 0 ...o-mounting-ubi0-rootfs-in-init-do_mounts.c.patch | 0 ...i-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch | 0 .../494-mtd-ubi-add-EOF-marker-support.patch | 0 .../495-mtd-core-add-get_mtd_device_by_node.patch | 0 ...ndings-add-bindings-for-mtd-concat-devices.patch | 0 ...mtdconcat-add-dt-driver-for-concat-devices.patch | 0 .../pending-5.14/500-fs_cdrom_dependencies.patch | 0 .../530-jffs2_make_lzma_available.patch | 0 .../generic/pending-5.14/532-jffs2_eofdetect.patch | 0 .../600-netfilter_conntrack_flush.patch | 0 .../610-netfilter_match_bypass_default_checks.patch | 0 .../611-netfilter_match_bypass_default_table.patch | 0 .../612-netfilter_match_reduce_memory_access.patch | 0 .../613-netfilter_optional_tcp_window_check.patch | 0 ...hed-codel-do-not-defer-queue-length-update.patch | 0 .../pending-5.14/630-packet_socket_type.patch | 0 .../generic/pending-5.14/655-increase_skb_pad.patch | 0 .../666-Add-support-for-MAP-E-FMRs-mesh-mode.patch | 0 ...ejecting-with-source-address-failed-policy.patch | 0 ...e-defines-for-_POLICY_FAILED-until-all-cod.patch | 0 ...680-NET-skip-GRO-for-foreign-MAC-addresses.patch | 0 ...d-mac-address-support-to-of_get_mac_addres.patch | 0 ...2-of_net-add-mac-address-increment-support.patch | 0 .../683-of_net-add-mac-address-to-of-tree.patch | 0 ...et-mtk_eth_soc-avoid-creating-duplicate-of.patch | 0 ...y-add-detach-callback-to-struct-phy_driver.patch | 0 .../735-net-phy-at803x-fix-at8033-sgmii-mode.patch | 0 .../760-net-dsa-mv88e6xxx-fix-vlan-setup.patch | 0 .../761-net-dsa-mt7530-Support-EEE-features.patch | 0 ...6xxx-Request-assisted-learning-on-CPU-port.patch | 0 ...oC-device-struct-copy-its-DMA-params-to-th.patch | 0 .../810-pci_disable_common_quirks.patch | 0 .../811-pci_disable_usb_common_quirks.patch | 0 ...o-fix-problem-with-platfom-data-in-w1-gpio.patch | 0 .../generic/pending-5.14/834-ledtrig-libata.patch | 0 .../840-hwrng-bcm2835-set-quality-to-1000.patch | 0 .../generic/pending-5.14/920-mangle_bootargs.patch | 0 ...rop-interrupt-provider-address-cells-check.patch | 0 ...e-.rename2-and-add-RENAME_WHITEOUT-support.patch | 0 .../141-jffs2-add-RENAME_EXCHANGE-support.patch | 0 .../pending-5.15/142-jffs2-add-splice-ops.patch | 0 .../pending-5.15/420-mtd-redboot_space.patch | 0 ...-spi-nor-rework-broken-flash-reset-support.patch | 0 ...3-mtd-spinand-add-support-for-xtx-xt26g0xa.patch | 0 .../484-mtd-spi-nor-add-esmt-f25l16pa.patch | 0 ...o-mounting-ubi0-rootfs-in-init-do_mounts.c.patch | 0 ...2-of_net-add-mac-address-increment-support.patch | 0 .../683-of_net-add-mac-address-to-of-tree.patch | 0 ...dge-add-knob-for-filtering-rx-tx-BPDU-pack.patch | 0 ...od-add-missing-linux-if_ether.h-for-ETH_AL.patch | 0 .../generic/pending-5.15/930-qcom-qmi-helpers.patch | 0 ...-net-add-support-for-threaded-NAPI-polling.patch | 0 .../linux/ipq40xx/base-files/bin/board_detect | 0 .../target/linux/ipq40xx/base-files/bin/board_modem | 0 .../target/linux/ipq40xx/base-files/bin/board_track | 0 .../linux/ipq40xx/base-files/bin/config_generate | 0 root/target/linux/ipq40xx/base-files/bin/ipcalc.sh | 0 .../linux/ipq40xx/base-files/etc/board.d/01_leds | 0 .../linux/ipq40xx/base-files/etc/board.d/02_network | 0 .../ipq40xx/base-files/etc/board.d/03_gpio_switches | 0 .../ipq40xx/base-files/etc/board.d/1-board_json | 0 .../target/linux/ipq40xx/base-files/etc/init.d/boot | 0 .../target/linux/ipq40xx/base-files/etc/init.d/done | 0 .../linux/ipq40xx/base-files/etc/init.d/gpio_switch | 0 root/target/linux/ipq40xx/base-files/etc/init.d/led | 0 .../ipq40xx/base-files/etc/init.d/modem_tracker | 0 .../linux/ipq40xx/base-files/etc/init.d/ntpserver | 0 .../linux/ipq40xx/base-files/etc/init.d/powerctl | 0 .../ipq40xx/base-files/etc/init.d/set-irq-affinity | 0 .../linux/ipq40xx/base-files/etc/init.d/sysctl | 0 .../linux/ipq40xx/base-files/etc/init.d/sysfixtime | 0 .../linux/ipq40xx/base-files/etc/init.d/system | 0 .../linux/ipq40xx/base-files/etc/init.d/umount | 0 .../base-files/lib/functions/teltonika-defaults.sh | 0 .../base-files/lib/functions/teltonika-functions.sh | 0 .../linux/ipq40xx/base-files/lib/upgrade/linksys.sh | 0 .../linux/ipq40xx/base-files/lib/upgrade/stage2 | 0 root/target/linux/ipq40xx/base-files/sbin/mctl | 0 root/target/linux/ipq40xx/base-files/sbin/mnf_info | 0 .../files/arch/arm/boot/dts/qcom-ipq4019-l1000.dts | 0 .../files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts | 0 ...d-add-driver-support-for-MT7621-nand-flash.patch | 0 root/target/linux/rockchip/Makefile | 0 .../rockchip/armv8/base-files/etc/board.d/01_leds | 0 .../armv8/base-files/etc/board.d/02_network | 0 .../etc/hotplug.d/net/40-net-smp-affinity | 0 root/target/linux/rockchip/armv8/config-5.14 | 0 root/target/linux/rockchip/armv8/config-5.15 | 0 .../arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts | 0 .../arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts | 0 root/target/linux/rockchip/image/armv8.mk | 0 .../linux/rockchip/image/nanopi-r4s.bootscript | 0 ...k3399-Add-support-for-FriendlyARM-NanoPi-R.patch | 0 ...et-usb-r8152-add-LED-configuration-from-OF.patch | 0 ...ings-net-add-RTL8152-binding-documentation.patch | 0 ...ts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch | 0 .../100-rockchip-use-system-LED-for-OpenWrt.patch | 0 ...p-add-usb3-controller-node-for-RK3328-SoCs.patch | 0 ...102-rockchip-enable-LAN-port-on-NanoPi-R2S.patch | 0 ...chip-add-OF-node-for-USB-eth-on-NanoPi-R2S.patch | 0 .../patches-5.14/105-rockchip-rock-pi-4.patch | 0 ...ts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch | 0 .../100-rockchip-use-system-LED-for-OpenWrt.patch | 0 ...chip-add-OF-node-for-USB-eth-on-NanoPi-R2S.patch | 0 ...k3399-Add-support-for-FriendlyARM-NanoPi-R.patch | 0 .../base-files/etc/uci-defaults/99-switch-config | 0 .../linux/sunxi/base-files/sbin/swconfig-wrapper.sh | 0 root/target/linux/sunxi/config-5.14 | 0 root/target/linux/x86/64/config-5.14 | 0 root/target/linux/x86/config-4.19 | 0 root/target/linux/x86/config-5.14 | 0 .../012-pcengines-apu2-detect-apuv4-board.patch | 0 .../x86/patches-5.14/100-fix_cs5535_clockevt.patch | 0 .../990-mptcp-fullmesh-raise-addresses-limit.patch | 0 sign.sh | 0 343 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 .github/FUNDING.yml mode change 100755 => 100644 .github/ISSUE_TEMPLATE/enhancement.md mode change 100755 => 100644 .github/ISSUE_TEMPLATE/feature_request.md mode change 100755 => 100644 .github/ISSUE_TEMPLATE/hardware_support.md mode change 100755 => 100644 .github/ISSUE_TEMPLATE/help.md mode change 100755 => 100644 .github/ISSUE_TEMPLATE/issue.md mode change 100755 => 100644 .github/ISSUE_TEMPLATE/question.md mode change 100755 => 100644 .github/PULL_REQUEST_TEMPLATE.md mode change 100755 => 100644 .github/workflows/stale.yml mode change 100755 => 100644 .gitignore mode change 100755 => 100644 CLA-entity.md mode change 100755 => 100644 CLA-individual.md mode change 100755 => 100644 CODE_OF_CONDUCT.md mode change 100755 => 100644 CONTRIBUTING.md mode change 100755 => 100644 LICENSE mode change 100755 => 100644 README.md mode change 100755 => 100644 config mode change 100755 => 100644 config-4018 mode change 100755 => 100644 config-bpi-r1 mode change 100755 => 100644 config-bpi-r2 mode change 100755 => 100644 config-bpi-r64 mode change 100755 => 100644 config-cm520-79f mode change 100755 => 100644 config-espressobin mode change 100755 => 100644 config-espressobin1 mode change 100755 => 100644 config-l1000 mode change 100755 => 100644 config-nanopi_neo mode change 100755 => 100644 config-p2w_r619ac mode change 100755 => 100644 config-r2s mode change 100755 => 100644 config-r4s mode change 100755 => 100644 config-r7800 mode change 100755 => 100644 config-rpi2 mode change 100755 => 100644 config-rpi3 mode change 100755 => 100644 config-rpi4 mode change 100755 => 100644 config-ubnt-erx mode change 100755 => 100644 config-wrt3200acm mode change 100755 => 100644 config-wrt32x mode change 100755 => 100644 config-x86 mode change 100755 => 100644 config-x86_64 mode change 100755 => 100644 config-zbt4019 mode change 100755 => 100644 contributors/example.md mode change 100755 => 100644 deploy_rsa.enc mode change 100755 => 100644 patches/950-0785-fixcm4soundboss2.patch mode change 100755 => 100644 patches/bbr2.patch mode change 100755 => 100644 patches/check-rsync.patch mode change 100755 => 100644 patches/download-ipv4.patch mode change 100755 => 100644 patches/gtime.patch mode change 100755 => 100644 patches/images.patch mode change 100755 => 100644 patches/ipt-nat6.patch mode change 100755 => 100644 patches/luci-occitan.patch mode change 100755 => 100644 patches/nanqinlang.patch mode change 100755 => 100644 patches/nocheck.patch mode change 100755 => 100644 patches/package-too-long.patch mode change 100755 => 100644 patches/remove_abi.patch mode change 100755 => 100644 patches/smsc75xx.patch mode change 100755 => 100644 patches/uefi.patch mode change 100755 => 100644 root/include/kernel-version.mk mode change 100755 => 100644 root/package/base-files/files/bin/config_generate mode change 100755 => 100644 root/package/base-files/files/etc/banner mode change 100755 => 100644 root/package/base-files/files/etc/shadow mode change 100755 => 100644 root/package/boot/uboot-rockchip/src/of-platdata/nanopi-r2s-rk3328/dt-plat.c mode change 100755 => 100644 root/package/firmware/ipq-wifi/board-pangu_l1000.qca4019 mode change 100755 => 100644 root/package/kernel/linux/modules/crypto.mk mode change 100755 => 100644 root/package/kernel/linux/modules/fs.mk mode change 100755 => 100644 root/package/kernel/linux/modules/input.mk mode change 100755 => 100644 root/package/kernel/linux/modules/netfilter.mk mode change 100755 => 100644 root/package/kernel/linux/modules/other.mk mode change 100755 => 100644 root/package/kernel/linux/modules/sound.mk mode change 100755 => 100644 root/package/kernel/mwlwifi/patches/002-remove-fallthrough.patch mode change 100755 => 100644 root/package/network/config/firewall/patches/fullconenat.patch mode change 100755 => 100644 root/package/utils/sysupgrade-helper/src/MAKEALL mode change 100755 => 100644 root/package/utils/sysupgrade-helper/src/arch/blackfin/cpu/bootrom-asm-offsets.awk mode change 100755 => 100644 root/package/utils/sysupgrade-helper/src/drivers/net/nss/synopGMAC_Dev.c mode change 100755 => 100644 root/package/utils/sysupgrade-helper/src/drivers/net/nss/synopGMAC_Dev.h mode change 100755 => 100644 root/package/utils/sysupgrade-helper/src/drivers/net/nss/synopGMAC_network_interface.c mode change 100755 => 100644 root/package/utils/sysupgrade-helper/src/drivers/net/nss/synopGMAC_plat.h mode change 100755 => 100644 root/package/utils/sysupgrade-helper/src/drivers/net/nss/uboot_skb.c mode change 100755 => 100644 root/package/utils/sysupgrade-helper/src/drivers/net/nss/uboot_skb.h mode change 100755 => 100644 root/package/utils/sysupgrade-helper/src/mkconfig mode change 100755 => 100644 root/package/utils/sysupgrade-helper/src/tools/checkpatch.pl mode change 100755 => 100644 root/package/utils/sysupgrade-helper/src/tools/checkstack.pl mode change 100755 => 100644 root/package/utils/sysupgrade-helper/src/tools/gcc-version.sh mode change 100755 => 100644 root/package/utils/sysupgrade-helper/src/tools/img2brec.sh mode change 100755 => 100644 root/package/utils/sysupgrade-helper/src/tools/jtagconsole mode change 100755 => 100644 root/package/utils/sysupgrade-helper/src/tools/netconsole mode change 100755 => 100644 root/package/utils/sysupgrade-helper/src/tools/pack.py mode change 100755 => 100644 root/package/utils/sysupgrade-helper/src/tools/patman/patman.py mode change 100755 => 100644 root/package/utils/sysupgrade-helper/src/tools/scripts/make-asm-offsets mode change 100755 => 100644 root/package/utils/sysupgrade-helper/src/tools/setlocalversion mode change 100755 => 100644 root/scripts/mkits-rutx.sh mode change 100755 => 100644 root/target/linux/bcm27xx/patches-5.15/950-0785-ARM-dts-Add-bcm2711-rpi-cm4antrouter5g.dts.patch mode change 100755 => 100644 root/target/linux/bcm27xx/patches-5.4/950-0785-ARM-dts-Add-bcm2711-rpi-cm4.dts.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.14/011-kbuild-export-SUBARCH.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.14/343-netfilter-nft_flow_offload-handle-netdevice-events-f.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/050-v5.16-00-MIPS-uasm-Enable-muhu-opcode-for-MIPS-R6.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/050-v5.16-01-mips-uasm-Add-workaround-for-Loongson-2F-nop-CPU-err.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/050-v5.16-02-mips-bpf-Add-eBPF-JIT-for-32-bit-MIPS.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/050-v5.16-03-mips-bpf-Add-new-eBPF-JIT-for-64-bit-MIPS.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/050-v5.16-04-mips-bpf-Add-JIT-workarounds-for-CPU-errata.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/050-v5.16-05-mips-bpf-Enable-eBPF-JITs.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/050-v5.16-06-mips-bpf-Remove-old-BPF-JIT-implementations.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/734-v5.16-0001-net-bgmac-improve-handling-PHY.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/734-v5.16-0002-net-bgmac-support-MDIO-described-in-DT.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/742-v5.16-net-phy-at803x-add-support-for-qca-8327-internal-phy.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/745-v5.16-01-net-phy-at803x-add-support-for-qca-8327-A-variant.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/745-v5.16-02-net-phy-at803x-add-resume-suspend-function-to-qca83x.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/745-v5.16-03-net-phy-at803x-fix-spacing-and-improve-name-for-83xx.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/746-v5.16-01-net-phy-at803x-fix-resume-for-QCA8327-phy.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/746-v5.16-02-net-phy-at803x-add-DAC-amplitude-fix-for-8327-phy.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/746-v5.16-03-net-phy-at803x-enable-prefer-master-for-83xx-interna.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/746-v5.16-04-net-phy-at803x-better-describe-debug-regs.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-01-dsa-qca8k-add-mac-power-sel-support.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-02-dt-bindings-net-dsa-qca8k-Add-SGMII-clock-phase-prop.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-03-net-dsa-qca8k-add-support-for-sgmii-falling-edge.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-04-dt-bindings-net-dsa-qca8k-Document-support-for-CPU-p.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-05-net-dsa-qca8k-add-support-for-cpu-port-6.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-06-net-dsa-qca8k-rework-rgmii-delay-logic-and-scan-for-.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-07-dt-bindings-net-dsa-qca8k-Document-qca-sgmii-enable-.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-08-net-dsa-qca8k-add-explicit-SGMII-PLL-enable.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-09-dt-bindings-net-dsa-qca8k-Document-qca-led-open-drai.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-10-net-dsa-qca8k-add-support-for-pws-config-reg.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-11-dt-bindings-net-dsa-qca8k-document-support-for-qca83.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-12-net-dsa-qca8k-add-support-for-QCA8328.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-13-net-dsa-qca8k-set-internal-delay-also-for-sgmii.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-14-net-dsa-qca8k-move-port-config-to-dedicated-struct.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-15-dt-bindings-net-ipq8064-mdio-fix-warning-with-new-qc.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/747-v5.16-16-dt-bindings-net-dsa-qca8k-convert-to-YAML-schema.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/748-v5.16-net-dsa-qca8k-fix-delay-applied-to-wrong-cpu-in-parse-p.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/749-v5.16-net-dsa-qca8k-tidy-for-loop-in-setup-and-add-cpu-port-c.patch mode change 100755 => 100644 root/target/linux/generic/backport-5.15/750-v5.16-net-dsa-qca8k-make-sure-pad0-mac06-exchange-is-disabled.patch mode change 100755 => 100644 root/target/linux/generic/config-4.14 mode change 100755 => 100644 root/target/linux/generic/config-4.19 mode change 100755 => 100644 root/target/linux/generic/config-4.9 mode change 100755 => 100644 root/target/linux/generic/config-5.14 mode change 100755 => 100644 root/target/linux/generic/config-5.15 mode change 100755 => 100644 root/target/linux/generic/config-5.4 mode change 100755 => 100644 root/target/linux/generic/files/drivers/net/phy/b53/b53_common.c mode change 100755 => 100644 root/target/linux/generic/hack-4.14/690-mptcp_v0.94.patch mode change 100755 => 100644 root/target/linux/generic/hack-4.14/998-ndpi-netfilter.patch mode change 100755 => 100644 root/target/linux/generic/hack-4.14/999-stop-promiscuous-info.patch mode change 100755 => 100644 root/target/linux/generic/hack-4.19/690-mptcp_v0.95.patch mode change 100755 => 100644 root/target/linux/generic/hack-4.19/691-mptcp_ecf.patch mode change 100755 => 100644 root/target/linux/generic/hack-4.19/692-tcp_nanqinlang.patch mode change 100755 => 100644 root/target/linux/generic/hack-4.19/998-ndpi-netfilter.patch mode change 100755 => 100644 root/target/linux/generic/hack-4.19/999-f2fs-ioerrorfix.patch mode change 100755 => 100644 root/target/linux/generic/hack-4.19/999-stop-promiscuous-info.patch mode change 100755 => 100644 root/target/linux/generic/hack-4.9/690-mptcp_v0.93.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/204-module_strip.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/210-darwin_scripts_include.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/211-darwin-uuid-typedef-clash.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/212-tools_portability.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/214-spidev_h_portability.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/220-gc_sections.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/221-module_exports.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/230-openwrt_lzma_options.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/249-udp-tunnel-selection.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/250-netfilter_depends.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/251-kconfig.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/260-crypto_test_dependencies.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/261-lib-arc4-unhide.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/280-rfkill-stubs.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/300-MIPS-r4k_cache-use-more-efficient-cache-blast.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/301-mips_image_cmdline_hack.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/321-powerpc_crtsavres_prereq.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/420-mtd-set-rootfs-to-be-root-dev.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/531-debloat_lzma.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/640-bridge-only-accept-EAP-locally.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/645-netfilter-connmark-introduce-set-dscpmark.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/650-netfilter-add-xt_FLOWOFFLOAD-target.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/651-wireless_mesh_header.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/660-fq_codel_defaults.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/661-use_fq_codel_by_default.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/700-swconfig_switch_drivers.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/710-net-dsa-mv88e6xxx-default-VID-1.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/773-bgmac-add-srab-switch.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/780-net-ipheth-fix-RX-EOVERFLOW.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/800-GPIO-add-named-gpio-exports.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/901-debloat_sock_diag.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/902-debloat_proc.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/904-debloat_dma_buf.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/910-kobject_uevent.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.14/911-kobject_add_broadcast_uevent.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.15/220-gc_sections.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.4/690-mptcp_v0.96.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.4/692-tcp_nanqinlang.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.4/693-tcp_bbr2.patch mode change 100755 => 100644 root/target/linux/generic/hack-5.4/999-stop-promiscuous-info.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/100-compiler.h-only-include-asm-rwonce.h-for-kernel-code.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/101-Use-stddefs.h-instead-of-compiler.h.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/102-MIPS-only-process-negative-stack-offsets-on-stack-tr.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/130-add-linux-spidev-compatible-si3210.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/150-bridge_allow_receiption_on_disabled_port.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/190-rtc-rs5c372-support_alarms_up_to_1_week.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/191-rtc-rs5c372-let_the_alarm_to_be_used_as_wakeup_source.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/201-extra_optimization.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/203-kallsyms_uncompressed.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/205-backtrace_module_info.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/240-remove-unsane-filenames-from-deps_initramfs-list.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/261-enable_wilink_platform_without_drivers.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/270-platform-mikrotik-build-bits.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/300-mips_expose_boot_raw.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/302-mips_no_branch_likely.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/305-mips_module_reloc.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/307-mips_highmem_offset.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/308-mips32r2_tune.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/309-MIPS-Add-CPU-option-reporting-to-proc-cpuinfo.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/310-arm_module_unresolved_weak_sym.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/332-arc-add-OWRTDTB-section.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/333-arc-enable-unaligned-access-in-kernel-mode.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/342-powerpc-Enable-kernel-XZ-compression-option-on-PPC_8.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/400-mtd-mtdsplit-support.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/419-mtd-redboot-add-of_match_table-with-DT-binding.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/430-mtd-add-myloader-partition-parser.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/431-mtd-bcm47xxpart-check-for-bad-blocks-when-calculatin.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/432-mtd-bcm47xxpart-detect-T_Meter-partition.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/435-mtd-add-routerbootpart-parser-config.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/460-mtd-cfi_cmdset_0002-no-erase_suspend.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/461-mtd-cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/465-m25p80-mx-disable-software-protection.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/476-mtd-spi-nor-add-eon-en25q128.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/479-mtd-spi-nor-add-xtx-xt25f128b.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/482-mtd-spi-nor-add-support-for-Gigadevice-GD25D05.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/483-mtd-spi-nor-add-gd25q512.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/491-ubi-auto-create-ubiblock-device-for-rootfs.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/494-mtd-ubi-add-EOF-marker-support.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/495-mtd-core-add-get_mtd_device_by_node.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/496-dt-bindings-add-bindings-for-mtd-concat-devices.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/500-fs_cdrom_dependencies.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/530-jffs2_make_lzma_available.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/532-jffs2_eofdetect.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/600-netfilter_conntrack_flush.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/610-netfilter_match_bypass_default_checks.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/611-netfilter_match_bypass_default_table.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/612-netfilter_match_reduce_memory_access.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/613-netfilter_optional_tcp_window_check.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/620-net_sched-codel-do-not-defer-queue-length-update.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/630-packet_socket_type.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/655-increase_skb_pad.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/671-net-provide-defines-for-_POLICY_FAILED-until-all-cod.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/680-NET-skip-GRO-for-foreign-MAC-addresses.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/681-NET-add-mtd-mac-address-support-to-of_get_mac_addres.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/682-of_net-add-mac-address-increment-support.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/683-of_net-add-mac-address-to-of-tree.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/700-net-ethernet-mtk_eth_soc-avoid-creating-duplicate-of.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/703-phy-add-detach-callback-to-struct-phy_driver.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/735-net-phy-at803x-fix-at8033-sgmii-mode.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/760-net-dsa-mv88e6xxx-fix-vlan-setup.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/761-net-dsa-mt7530-Support-EEE-features.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/800-bcma-get-SoC-device-struct-copy-its-DMA-params-to-th.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/810-pci_disable_common_quirks.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/811-pci_disable_usb_common_quirks.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/820-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/834-ledtrig-libata.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/840-hwrng-bcm2835-set-quality-to-1000.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.14/920-mangle_bootargs.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.15/050-dtc-checks-Drop-interrupt-provider-address-cells-check.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.15/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.15/141-jffs2-add-RENAME_EXCHANGE-support.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.15/142-jffs2-add-splice-ops.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.15/420-mtd-redboot_space.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.15/481-mtd-spi-nor-rework-broken-flash-reset-support.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.15/483-mtd-spinand-add-support-for-xtx-xt26g0xa.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.15/484-mtd-spi-nor-add-esmt-f25l16pa.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.15/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.15/682-of_net-add-mac-address-increment-support.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.15/683-of_net-add-mac-address-to-of-tree.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.15/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.15/780-ARM-kirkwood-add-missing-linux-if_ether.h-for-ETH_AL.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.15/930-qcom-qmi-helpers.patch mode change 100755 => 100644 root/target/linux/generic/pending-5.4/690-net-add-support-for-threaded-NAPI-polling.patch mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/bin/board_detect mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/bin/board_modem mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/bin/board_track mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/bin/config_generate mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/bin/ipcalc.sh mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/etc/board.d/01_leds mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/etc/board.d/02_network mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/etc/board.d/03_gpio_switches mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/etc/board.d/1-board_json mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/etc/init.d/boot mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/etc/init.d/done mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/etc/init.d/gpio_switch mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/etc/init.d/led mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/etc/init.d/modem_tracker mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/etc/init.d/ntpserver mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/etc/init.d/powerctl mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/etc/init.d/set-irq-affinity mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/etc/init.d/sysctl mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/etc/init.d/sysfixtime mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/etc/init.d/system mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/etc/init.d/umount mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/lib/functions/teltonika-defaults.sh mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/lib/functions/teltonika-functions.sh mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/lib/upgrade/linksys.sh mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/lib/upgrade/stage2 mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/sbin/mctl mode change 100755 => 100644 root/target/linux/ipq40xx/base-files/sbin/mnf_info mode change 100755 => 100644 root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-l1000.dts mode change 100755 => 100644 root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts mode change 100755 => 100644 root/target/linux/ramips/patches-5.15/410-mtd-rawnand-add-driver-support-for-MT7621-nand-flash.patch mode change 100755 => 100644 root/target/linux/rockchip/Makefile mode change 100755 => 100644 root/target/linux/rockchip/armv8/base-files/etc/board.d/01_leds mode change 100755 => 100644 root/target/linux/rockchip/armv8/base-files/etc/board.d/02_network mode change 100755 => 100644 root/target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity mode change 100755 => 100644 root/target/linux/rockchip/armv8/config-5.14 mode change 100755 => 100644 root/target/linux/rockchip/armv8/config-5.15 mode change 100755 => 100644 root/target/linux/rockchip/files-5.14/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts mode change 100755 => 100644 root/target/linux/rockchip/files-5.15/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts mode change 100755 => 100644 root/target/linux/rockchip/image/armv8.mk mode change 100755 => 100644 root/target/linux/rockchip/image/nanopi-r4s.bootscript mode change 100755 => 100644 root/target/linux/rockchip/patches-5.10/004-v5.13-rockchip-rk3399-Add-support-for-FriendlyARM-NanoPi-R.patch mode change 100755 => 100644 root/target/linux/rockchip/patches-5.14/002-net-usb-r8152-add-LED-configuration-from-OF.patch mode change 100755 => 100644 root/target/linux/rockchip/patches-5.14/003-dt-bindings-net-add-RTL8152-binding-documentation.patch mode change 100755 => 100644 root/target/linux/rockchip/patches-5.14/005-arm64-dts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch mode change 100755 => 100644 root/target/linux/rockchip/patches-5.14/100-rockchip-use-system-LED-for-OpenWrt.patch mode change 100755 => 100644 root/target/linux/rockchip/patches-5.14/101-dts-rockchip-add-usb3-controller-node-for-RK3328-SoCs.patch mode change 100755 => 100644 root/target/linux/rockchip/patches-5.14/102-rockchip-enable-LAN-port-on-NanoPi-R2S.patch mode change 100755 => 100644 root/target/linux/rockchip/patches-5.14/103-arm64-rockchip-add-OF-node-for-USB-eth-on-NanoPi-R2S.patch mode change 100755 => 100644 root/target/linux/rockchip/patches-5.14/105-rockchip-rock-pi-4.patch mode change 100755 => 100644 root/target/linux/rockchip/patches-5.15/005-arm64-dts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch mode change 100755 => 100644 root/target/linux/rockchip/patches-5.15/100-rockchip-use-system-LED-for-OpenWrt.patch mode change 100755 => 100644 root/target/linux/rockchip/patches-5.15/103-arm64-rockchip-add-OF-node-for-USB-eth-on-NanoPi-R2S.patch mode change 100755 => 100644 root/target/linux/rockchip/patches-5.4/007-v5.13-rockchip-rk3399-Add-support-for-FriendlyARM-NanoPi-R.patch mode change 100755 => 100644 root/target/linux/sunxi/base-files/etc/uci-defaults/99-switch-config mode change 100755 => 100644 root/target/linux/sunxi/base-files/sbin/swconfig-wrapper.sh mode change 100755 => 100644 root/target/linux/sunxi/config-5.14 mode change 100755 => 100644 root/target/linux/x86/64/config-5.14 mode change 100755 => 100644 root/target/linux/x86/config-4.19 mode change 100755 => 100644 root/target/linux/x86/config-5.14 mode change 100755 => 100644 root/target/linux/x86/patches-5.14/012-pcengines-apu2-detect-apuv4-board.patch mode change 100755 => 100644 root/target/linux/x86/patches-5.14/100-fix_cs5535_clockevt.patch mode change 100755 => 100644 root/target/linux/x86/patches-5.4/990-mptcp-fullmesh-raise-addresses-limit.patch mode change 100755 => 100644 sign.sh diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml old mode 100755 new mode 100644 diff --git a/.github/ISSUE_TEMPLATE/enhancement.md b/.github/ISSUE_TEMPLATE/enhancement.md old mode 100755 new mode 100644 diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md old mode 100755 new mode 100644 diff --git a/.github/ISSUE_TEMPLATE/hardware_support.md b/.github/ISSUE_TEMPLATE/hardware_support.md old mode 100755 new mode 100644 diff --git a/.github/ISSUE_TEMPLATE/help.md b/.github/ISSUE_TEMPLATE/help.md old mode 100755 new mode 100644 diff --git a/.github/ISSUE_TEMPLATE/issue.md b/.github/ISSUE_TEMPLATE/issue.md old mode 100755 new mode 100644 diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md old mode 100755 new mode 100644 diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md old mode 100755 new mode 100644 diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml old mode 100755 new mode 100644 diff --git a/.gitignore b/.gitignore old mode 100755 new mode 100644 diff --git a/CLA-entity.md b/CLA-entity.md old mode 100755 new mode 100644 diff --git a/CLA-individual.md b/CLA-individual.md old mode 100755 new mode 100644 diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md old mode 100755 new mode 100644 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md old mode 100755 new mode 100644 diff --git a/LICENSE b/LICENSE old mode 100755 new mode 100644 diff --git a/README.md b/README.md old mode 100755 new mode 100644 diff --git a/config b/config old mode 100755 new mode 100644 diff --git a/config-4018 b/config-4018 old mode 100755 new mode 100644 diff --git a/config-bpi-r1 b/config-bpi-r1 old mode 100755 new mode 100644 diff --git a/config-bpi-r2 b/config-bpi-r2 old mode 100755 new mode 100644 diff --git a/config-bpi-r64 b/config-bpi-r64 old mode 100755 new mode 100644 diff --git a/config-cm520-79f b/config-cm520-79f old mode 100755 new mode 100644 diff --git a/config-espressobin b/config-espressobin old mode 100755 new mode 100644 diff --git a/config-espressobin1 b/config-espressobin1 old mode 100755 new mode 100644 diff --git a/config-l1000 b/config-l1000 old mode 100755 new mode 100644 diff --git a/config-nanopi_neo b/config-nanopi_neo old mode 100755 new mode 100644 diff --git a/config-p2w_r619ac b/config-p2w_r619ac old mode 100755 new mode 100644 diff --git a/config-r2s b/config-r2s old mode 100755 new mode 100644 diff --git a/config-r4s b/config-r4s old mode 100755 new mode 100644 diff --git a/config-r7800 b/config-r7800 old mode 100755 new mode 100644 diff --git a/config-rpi2 b/config-rpi2 old mode 100755 new mode 100644 diff --git a/config-rpi3 b/config-rpi3 old mode 100755 new mode 100644 diff --git a/config-rpi4 b/config-rpi4 old mode 100755 new mode 100644 diff --git a/config-ubnt-erx b/config-ubnt-erx old mode 100755 new mode 100644 diff --git a/config-wrt3200acm b/config-wrt3200acm old mode 100755 new mode 100644 diff --git a/config-wrt32x b/config-wrt32x old mode 100755 new mode 100644 diff --git a/config-x86 b/config-x86 old mode 100755 new mode 100644 diff --git a/config-x86_64 b/config-x86_64 old mode 100755 new mode 100644 diff --git a/config-zbt4019 b/config-zbt4019 old mode 100755 new mode 100644 diff --git a/contributors/example.md b/contributors/example.md old mode 100755 new mode 100644 diff --git a/deploy_rsa.enc b/deploy_rsa.enc old mode 100755 new mode 100644 diff --git a/patches/950-0785-fixcm4soundboss2.patch b/patches/950-0785-fixcm4soundboss2.patch old mode 100755 new mode 100644 diff --git a/patches/bbr2.patch b/patches/bbr2.patch old mode 100755 new mode 100644 diff --git a/patches/check-rsync.patch b/patches/check-rsync.patch old mode 100755 new mode 100644 diff --git a/patches/download-ipv4.patch b/patches/download-ipv4.patch old mode 100755 new mode 100644 diff --git a/patches/gtime.patch b/patches/gtime.patch old mode 100755 new mode 100644 diff --git a/patches/images.patch b/patches/images.patch old mode 100755 new mode 100644 diff --git a/patches/ipt-nat6.patch b/patches/ipt-nat6.patch old mode 100755 new mode 100644 diff --git a/patches/luci-occitan.patch b/patches/luci-occitan.patch old mode 100755 new mode 100644 diff --git a/patches/nanqinlang.patch b/patches/nanqinlang.patch old mode 100755 new mode 100644 diff --git a/patches/nocheck.patch b/patches/nocheck.patch old mode 100755 new mode 100644 diff --git a/patches/package-too-long.patch b/patches/package-too-long.patch old mode 100755 new mode 100644 diff --git a/patches/remove_abi.patch b/patches/remove_abi.patch old mode 100755 new mode 100644 diff --git a/patches/smsc75xx.patch b/patches/smsc75xx.patch old mode 100755 new mode 100644 diff --git a/patches/uefi.patch b/patches/uefi.patch old mode 100755 new mode 100644 diff --git a/root/include/kernel-version.mk b/root/include/kernel-version.mk old mode 100755 new mode 100644 diff --git a/root/package/base-files/files/bin/config_generate b/root/package/base-files/files/bin/config_generate old mode 100755 new mode 100644 diff --git a/root/package/base-files/files/etc/banner b/root/package/base-files/files/etc/banner old mode 100755 new mode 100644 diff --git a/root/package/base-files/files/etc/shadow b/root/package/base-files/files/etc/shadow old mode 100755 new mode 100644 diff --git a/root/package/boot/uboot-rockchip/src/of-platdata/nanopi-r2s-rk3328/dt-plat.c b/root/package/boot/uboot-rockchip/src/of-platdata/nanopi-r2s-rk3328/dt-plat.c old mode 100755 new mode 100644 diff --git a/root/package/firmware/ipq-wifi/board-pangu_l1000.qca4019 b/root/package/firmware/ipq-wifi/board-pangu_l1000.qca4019 old mode 100755 new mode 100644 diff --git a/root/package/kernel/linux/modules/crypto.mk b/root/package/kernel/linux/modules/crypto.mk old mode 100755 new mode 100644 diff --git a/root/package/kernel/linux/modules/fs.mk b/root/package/kernel/linux/modules/fs.mk old mode 100755 new mode 100644 diff --git a/root/package/kernel/linux/modules/input.mk b/root/package/kernel/linux/modules/input.mk old mode 100755 new mode 100644 diff --git a/root/package/kernel/linux/modules/netfilter.mk b/root/package/kernel/linux/modules/netfilter.mk old mode 100755 new mode 100644 diff --git a/root/package/kernel/linux/modules/other.mk b/root/package/kernel/linux/modules/other.mk old mode 100755 new mode 100644 diff --git a/root/package/kernel/linux/modules/sound.mk b/root/package/kernel/linux/modules/sound.mk old mode 100755 new mode 100644 diff --git a/root/package/kernel/mwlwifi/patches/002-remove-fallthrough.patch b/root/package/kernel/mwlwifi/patches/002-remove-fallthrough.patch old mode 100755 new mode 100644 diff --git a/root/package/network/config/firewall/patches/fullconenat.patch b/root/package/network/config/firewall/patches/fullconenat.patch old mode 100755 new mode 100644 diff --git a/root/package/utils/sysupgrade-helper/src/MAKEALL b/root/package/utils/sysupgrade-helper/src/MAKEALL old mode 100755 new mode 100644 diff --git a/root/package/utils/sysupgrade-helper/src/arch/blackfin/cpu/bootrom-asm-offsets.awk b/root/package/utils/sysupgrade-helper/src/arch/blackfin/cpu/bootrom-asm-offsets.awk old mode 100755 new mode 100644 diff --git a/root/package/utils/sysupgrade-helper/src/drivers/net/nss/synopGMAC_Dev.c b/root/package/utils/sysupgrade-helper/src/drivers/net/nss/synopGMAC_Dev.c old mode 100755 new mode 100644 diff --git a/root/package/utils/sysupgrade-helper/src/drivers/net/nss/synopGMAC_Dev.h b/root/package/utils/sysupgrade-helper/src/drivers/net/nss/synopGMAC_Dev.h old mode 100755 new mode 100644 diff --git a/root/package/utils/sysupgrade-helper/src/drivers/net/nss/synopGMAC_network_interface.c b/root/package/utils/sysupgrade-helper/src/drivers/net/nss/synopGMAC_network_interface.c old mode 100755 new mode 100644 diff --git a/root/package/utils/sysupgrade-helper/src/drivers/net/nss/synopGMAC_plat.h b/root/package/utils/sysupgrade-helper/src/drivers/net/nss/synopGMAC_plat.h old mode 100755 new mode 100644 diff --git a/root/package/utils/sysupgrade-helper/src/drivers/net/nss/uboot_skb.c b/root/package/utils/sysupgrade-helper/src/drivers/net/nss/uboot_skb.c old mode 100755 new mode 100644 diff --git a/root/package/utils/sysupgrade-helper/src/drivers/net/nss/uboot_skb.h b/root/package/utils/sysupgrade-helper/src/drivers/net/nss/uboot_skb.h old mode 100755 new mode 100644 diff --git a/root/package/utils/sysupgrade-helper/src/mkconfig b/root/package/utils/sysupgrade-helper/src/mkconfig old mode 100755 new mode 100644 diff --git a/root/package/utils/sysupgrade-helper/src/tools/checkpatch.pl b/root/package/utils/sysupgrade-helper/src/tools/checkpatch.pl old mode 100755 new mode 100644 diff --git a/root/package/utils/sysupgrade-helper/src/tools/checkstack.pl b/root/package/utils/sysupgrade-helper/src/tools/checkstack.pl old mode 100755 new mode 100644 diff --git a/root/package/utils/sysupgrade-helper/src/tools/gcc-version.sh b/root/package/utils/sysupgrade-helper/src/tools/gcc-version.sh old mode 100755 new mode 100644 diff --git a/root/package/utils/sysupgrade-helper/src/tools/img2brec.sh b/root/package/utils/sysupgrade-helper/src/tools/img2brec.sh old mode 100755 new mode 100644 diff --git a/root/package/utils/sysupgrade-helper/src/tools/jtagconsole b/root/package/utils/sysupgrade-helper/src/tools/jtagconsole old mode 100755 new mode 100644 diff --git a/root/package/utils/sysupgrade-helper/src/tools/netconsole b/root/package/utils/sysupgrade-helper/src/tools/netconsole old mode 100755 new mode 100644 diff --git a/root/package/utils/sysupgrade-helper/src/tools/pack.py b/root/package/utils/sysupgrade-helper/src/tools/pack.py old mode 100755 new mode 100644 diff --git a/root/package/utils/sysupgrade-helper/src/tools/patman/patman.py b/root/package/utils/sysupgrade-helper/src/tools/patman/patman.py old mode 100755 new mode 100644 diff --git a/root/package/utils/sysupgrade-helper/src/tools/scripts/make-asm-offsets b/root/package/utils/sysupgrade-helper/src/tools/scripts/make-asm-offsets old mode 100755 new mode 100644 diff --git a/root/package/utils/sysupgrade-helper/src/tools/setlocalversion b/root/package/utils/sysupgrade-helper/src/tools/setlocalversion old mode 100755 new mode 100644 diff --git a/root/scripts/mkits-rutx.sh b/root/scripts/mkits-rutx.sh old mode 100755 new mode 100644 diff --git a/root/target/linux/bcm27xx/patches-5.15/950-0785-ARM-dts-Add-bcm2711-rpi-cm4antrouter5g.dts.patch b/root/target/linux/bcm27xx/patches-5.15/950-0785-ARM-dts-Add-bcm2711-rpi-cm4antrouter5g.dts.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/bcm27xx/patches-5.4/950-0785-ARM-dts-Add-bcm2711-rpi-cm4.dts.patch b/root/target/linux/bcm27xx/patches-5.4/950-0785-ARM-dts-Add-bcm2711-rpi-cm4.dts.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.14/011-kbuild-export-SUBARCH.patch b/root/target/linux/generic/backport-5.14/011-kbuild-export-SUBARCH.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.14/343-netfilter-nft_flow_offload-handle-netdevice-events-f.patch b/root/target/linux/generic/backport-5.14/343-netfilter-nft_flow_offload-handle-netdevice-events-f.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/050-v5.16-00-MIPS-uasm-Enable-muhu-opcode-for-MIPS-R6.patch b/root/target/linux/generic/backport-5.15/050-v5.16-00-MIPS-uasm-Enable-muhu-opcode-for-MIPS-R6.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/050-v5.16-01-mips-uasm-Add-workaround-for-Loongson-2F-nop-CPU-err.patch b/root/target/linux/generic/backport-5.15/050-v5.16-01-mips-uasm-Add-workaround-for-Loongson-2F-nop-CPU-err.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/050-v5.16-02-mips-bpf-Add-eBPF-JIT-for-32-bit-MIPS.patch b/root/target/linux/generic/backport-5.15/050-v5.16-02-mips-bpf-Add-eBPF-JIT-for-32-bit-MIPS.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/050-v5.16-03-mips-bpf-Add-new-eBPF-JIT-for-64-bit-MIPS.patch b/root/target/linux/generic/backport-5.15/050-v5.16-03-mips-bpf-Add-new-eBPF-JIT-for-64-bit-MIPS.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/050-v5.16-04-mips-bpf-Add-JIT-workarounds-for-CPU-errata.patch b/root/target/linux/generic/backport-5.15/050-v5.16-04-mips-bpf-Add-JIT-workarounds-for-CPU-errata.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/050-v5.16-05-mips-bpf-Enable-eBPF-JITs.patch b/root/target/linux/generic/backport-5.15/050-v5.16-05-mips-bpf-Enable-eBPF-JITs.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/050-v5.16-06-mips-bpf-Remove-old-BPF-JIT-implementations.patch b/root/target/linux/generic/backport-5.15/050-v5.16-06-mips-bpf-Remove-old-BPF-JIT-implementations.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/734-v5.16-0001-net-bgmac-improve-handling-PHY.patch b/root/target/linux/generic/backport-5.15/734-v5.16-0001-net-bgmac-improve-handling-PHY.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/734-v5.16-0002-net-bgmac-support-MDIO-described-in-DT.patch b/root/target/linux/generic/backport-5.15/734-v5.16-0002-net-bgmac-support-MDIO-described-in-DT.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/742-v5.16-net-phy-at803x-add-support-for-qca-8327-internal-phy.patch b/root/target/linux/generic/backport-5.15/742-v5.16-net-phy-at803x-add-support-for-qca-8327-internal-phy.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/745-v5.16-01-net-phy-at803x-add-support-for-qca-8327-A-variant.patch b/root/target/linux/generic/backport-5.15/745-v5.16-01-net-phy-at803x-add-support-for-qca-8327-A-variant.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/745-v5.16-02-net-phy-at803x-add-resume-suspend-function-to-qca83x.patch b/root/target/linux/generic/backport-5.15/745-v5.16-02-net-phy-at803x-add-resume-suspend-function-to-qca83x.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/745-v5.16-03-net-phy-at803x-fix-spacing-and-improve-name-for-83xx.patch b/root/target/linux/generic/backport-5.15/745-v5.16-03-net-phy-at803x-fix-spacing-and-improve-name-for-83xx.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/746-v5.16-01-net-phy-at803x-fix-resume-for-QCA8327-phy.patch b/root/target/linux/generic/backport-5.15/746-v5.16-01-net-phy-at803x-fix-resume-for-QCA8327-phy.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/746-v5.16-02-net-phy-at803x-add-DAC-amplitude-fix-for-8327-phy.patch b/root/target/linux/generic/backport-5.15/746-v5.16-02-net-phy-at803x-add-DAC-amplitude-fix-for-8327-phy.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/746-v5.16-03-net-phy-at803x-enable-prefer-master-for-83xx-interna.patch b/root/target/linux/generic/backport-5.15/746-v5.16-03-net-phy-at803x-enable-prefer-master-for-83xx-interna.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/746-v5.16-04-net-phy-at803x-better-describe-debug-regs.patch b/root/target/linux/generic/backport-5.15/746-v5.16-04-net-phy-at803x-better-describe-debug-regs.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-01-dsa-qca8k-add-mac-power-sel-support.patch b/root/target/linux/generic/backport-5.15/747-v5.16-01-dsa-qca8k-add-mac-power-sel-support.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-02-dt-bindings-net-dsa-qca8k-Add-SGMII-clock-phase-prop.patch b/root/target/linux/generic/backport-5.15/747-v5.16-02-dt-bindings-net-dsa-qca8k-Add-SGMII-clock-phase-prop.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-03-net-dsa-qca8k-add-support-for-sgmii-falling-edge.patch b/root/target/linux/generic/backport-5.15/747-v5.16-03-net-dsa-qca8k-add-support-for-sgmii-falling-edge.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-04-dt-bindings-net-dsa-qca8k-Document-support-for-CPU-p.patch b/root/target/linux/generic/backport-5.15/747-v5.16-04-dt-bindings-net-dsa-qca8k-Document-support-for-CPU-p.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-05-net-dsa-qca8k-add-support-for-cpu-port-6.patch b/root/target/linux/generic/backport-5.15/747-v5.16-05-net-dsa-qca8k-add-support-for-cpu-port-6.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-06-net-dsa-qca8k-rework-rgmii-delay-logic-and-scan-for-.patch b/root/target/linux/generic/backport-5.15/747-v5.16-06-net-dsa-qca8k-rework-rgmii-delay-logic-and-scan-for-.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-07-dt-bindings-net-dsa-qca8k-Document-qca-sgmii-enable-.patch b/root/target/linux/generic/backport-5.15/747-v5.16-07-dt-bindings-net-dsa-qca8k-Document-qca-sgmii-enable-.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-08-net-dsa-qca8k-add-explicit-SGMII-PLL-enable.patch b/root/target/linux/generic/backport-5.15/747-v5.16-08-net-dsa-qca8k-add-explicit-SGMII-PLL-enable.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-09-dt-bindings-net-dsa-qca8k-Document-qca-led-open-drai.patch b/root/target/linux/generic/backport-5.15/747-v5.16-09-dt-bindings-net-dsa-qca8k-Document-qca-led-open-drai.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-10-net-dsa-qca8k-add-support-for-pws-config-reg.patch b/root/target/linux/generic/backport-5.15/747-v5.16-10-net-dsa-qca8k-add-support-for-pws-config-reg.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-11-dt-bindings-net-dsa-qca8k-document-support-for-qca83.patch b/root/target/linux/generic/backport-5.15/747-v5.16-11-dt-bindings-net-dsa-qca8k-document-support-for-qca83.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-12-net-dsa-qca8k-add-support-for-QCA8328.patch b/root/target/linux/generic/backport-5.15/747-v5.16-12-net-dsa-qca8k-add-support-for-QCA8328.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-13-net-dsa-qca8k-set-internal-delay-also-for-sgmii.patch b/root/target/linux/generic/backport-5.15/747-v5.16-13-net-dsa-qca8k-set-internal-delay-also-for-sgmii.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-14-net-dsa-qca8k-move-port-config-to-dedicated-struct.patch b/root/target/linux/generic/backport-5.15/747-v5.16-14-net-dsa-qca8k-move-port-config-to-dedicated-struct.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-15-dt-bindings-net-ipq8064-mdio-fix-warning-with-new-qc.patch b/root/target/linux/generic/backport-5.15/747-v5.16-15-dt-bindings-net-ipq8064-mdio-fix-warning-with-new-qc.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/747-v5.16-16-dt-bindings-net-dsa-qca8k-convert-to-YAML-schema.patch b/root/target/linux/generic/backport-5.15/747-v5.16-16-dt-bindings-net-dsa-qca8k-convert-to-YAML-schema.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/748-v5.16-net-dsa-qca8k-fix-delay-applied-to-wrong-cpu-in-parse-p.patch b/root/target/linux/generic/backport-5.15/748-v5.16-net-dsa-qca8k-fix-delay-applied-to-wrong-cpu-in-parse-p.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/749-v5.16-net-dsa-qca8k-tidy-for-loop-in-setup-and-add-cpu-port-c.patch b/root/target/linux/generic/backport-5.15/749-v5.16-net-dsa-qca8k-tidy-for-loop-in-setup-and-add-cpu-port-c.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/backport-5.15/750-v5.16-net-dsa-qca8k-make-sure-pad0-mac06-exchange-is-disabled.patch b/root/target/linux/generic/backport-5.15/750-v5.16-net-dsa-qca8k-make-sure-pad0-mac06-exchange-is-disabled.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/config-4.14 b/root/target/linux/generic/config-4.14 old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/config-4.19 b/root/target/linux/generic/config-4.19 old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/config-4.9 b/root/target/linux/generic/config-4.9 old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/config-5.14 b/root/target/linux/generic/config-5.14 old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/config-5.15 b/root/target/linux/generic/config-5.15 old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/config-5.4 b/root/target/linux/generic/config-5.4 old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/files/drivers/net/phy/b53/b53_common.c b/root/target/linux/generic/files/drivers/net/phy/b53/b53_common.c old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-4.14/690-mptcp_v0.94.patch b/root/target/linux/generic/hack-4.14/690-mptcp_v0.94.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-4.14/998-ndpi-netfilter.patch b/root/target/linux/generic/hack-4.14/998-ndpi-netfilter.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-4.14/999-stop-promiscuous-info.patch b/root/target/linux/generic/hack-4.14/999-stop-promiscuous-info.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-4.19/690-mptcp_v0.95.patch b/root/target/linux/generic/hack-4.19/690-mptcp_v0.95.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-4.19/691-mptcp_ecf.patch b/root/target/linux/generic/hack-4.19/691-mptcp_ecf.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-4.19/692-tcp_nanqinlang.patch b/root/target/linux/generic/hack-4.19/692-tcp_nanqinlang.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-4.19/998-ndpi-netfilter.patch b/root/target/linux/generic/hack-4.19/998-ndpi-netfilter.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-4.19/999-f2fs-ioerrorfix.patch b/root/target/linux/generic/hack-4.19/999-f2fs-ioerrorfix.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-4.19/999-stop-promiscuous-info.patch b/root/target/linux/generic/hack-4.19/999-stop-promiscuous-info.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-4.9/690-mptcp_v0.93.patch b/root/target/linux/generic/hack-4.9/690-mptcp_v0.93.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/204-module_strip.patch b/root/target/linux/generic/hack-5.14/204-module_strip.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/210-darwin_scripts_include.patch b/root/target/linux/generic/hack-5.14/210-darwin_scripts_include.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/211-darwin-uuid-typedef-clash.patch b/root/target/linux/generic/hack-5.14/211-darwin-uuid-typedef-clash.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/212-tools_portability.patch b/root/target/linux/generic/hack-5.14/212-tools_portability.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/214-spidev_h_portability.patch b/root/target/linux/generic/hack-5.14/214-spidev_h_portability.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/220-gc_sections.patch b/root/target/linux/generic/hack-5.14/220-gc_sections.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/221-module_exports.patch b/root/target/linux/generic/hack-5.14/221-module_exports.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/230-openwrt_lzma_options.patch b/root/target/linux/generic/hack-5.14/230-openwrt_lzma_options.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/249-udp-tunnel-selection.patch b/root/target/linux/generic/hack-5.14/249-udp-tunnel-selection.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/250-netfilter_depends.patch b/root/target/linux/generic/hack-5.14/250-netfilter_depends.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/251-kconfig.patch b/root/target/linux/generic/hack-5.14/251-kconfig.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/260-crypto_test_dependencies.patch b/root/target/linux/generic/hack-5.14/260-crypto_test_dependencies.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/261-lib-arc4-unhide.patch b/root/target/linux/generic/hack-5.14/261-lib-arc4-unhide.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/280-rfkill-stubs.patch b/root/target/linux/generic/hack-5.14/280-rfkill-stubs.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/300-MIPS-r4k_cache-use-more-efficient-cache-blast.patch b/root/target/linux/generic/hack-5.14/300-MIPS-r4k_cache-use-more-efficient-cache-blast.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/301-mips_image_cmdline_hack.patch b/root/target/linux/generic/hack-5.14/301-mips_image_cmdline_hack.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/321-powerpc_crtsavres_prereq.patch b/root/target/linux/generic/hack-5.14/321-powerpc_crtsavres_prereq.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/420-mtd-set-rootfs-to-be-root-dev.patch b/root/target/linux/generic/hack-5.14/420-mtd-set-rootfs-to-be-root-dev.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/531-debloat_lzma.patch b/root/target/linux/generic/hack-5.14/531-debloat_lzma.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/640-bridge-only-accept-EAP-locally.patch b/root/target/linux/generic/hack-5.14/640-bridge-only-accept-EAP-locally.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/645-netfilter-connmark-introduce-set-dscpmark.patch b/root/target/linux/generic/hack-5.14/645-netfilter-connmark-introduce-set-dscpmark.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/650-netfilter-add-xt_FLOWOFFLOAD-target.patch b/root/target/linux/generic/hack-5.14/650-netfilter-add-xt_FLOWOFFLOAD-target.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/651-wireless_mesh_header.patch b/root/target/linux/generic/hack-5.14/651-wireless_mesh_header.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/660-fq_codel_defaults.patch b/root/target/linux/generic/hack-5.14/660-fq_codel_defaults.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/661-use_fq_codel_by_default.patch b/root/target/linux/generic/hack-5.14/661-use_fq_codel_by_default.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/700-swconfig_switch_drivers.patch b/root/target/linux/generic/hack-5.14/700-swconfig_switch_drivers.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/710-net-dsa-mv88e6xxx-default-VID-1.patch b/root/target/linux/generic/hack-5.14/710-net-dsa-mv88e6xxx-default-VID-1.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch b/root/target/linux/generic/hack-5.14/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/773-bgmac-add-srab-switch.patch b/root/target/linux/generic/hack-5.14/773-bgmac-add-srab-switch.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/780-net-ipheth-fix-RX-EOVERFLOW.patch b/root/target/linux/generic/hack-5.14/780-net-ipheth-fix-RX-EOVERFLOW.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/800-GPIO-add-named-gpio-exports.patch b/root/target/linux/generic/hack-5.14/800-GPIO-add-named-gpio-exports.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/901-debloat_sock_diag.patch b/root/target/linux/generic/hack-5.14/901-debloat_sock_diag.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/902-debloat_proc.patch b/root/target/linux/generic/hack-5.14/902-debloat_proc.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/904-debloat_dma_buf.patch b/root/target/linux/generic/hack-5.14/904-debloat_dma_buf.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/910-kobject_uevent.patch b/root/target/linux/generic/hack-5.14/910-kobject_uevent.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.14/911-kobject_add_broadcast_uevent.patch b/root/target/linux/generic/hack-5.14/911-kobject_add_broadcast_uevent.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.15/220-gc_sections.patch b/root/target/linux/generic/hack-5.15/220-gc_sections.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.4/690-mptcp_v0.96.patch b/root/target/linux/generic/hack-5.4/690-mptcp_v0.96.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.4/692-tcp_nanqinlang.patch b/root/target/linux/generic/hack-5.4/692-tcp_nanqinlang.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.4/693-tcp_bbr2.patch b/root/target/linux/generic/hack-5.4/693-tcp_bbr2.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/hack-5.4/999-stop-promiscuous-info.patch b/root/target/linux/generic/hack-5.4/999-stop-promiscuous-info.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/100-compiler.h-only-include-asm-rwonce.h-for-kernel-code.patch b/root/target/linux/generic/pending-5.14/100-compiler.h-only-include-asm-rwonce.h-for-kernel-code.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/101-Use-stddefs.h-instead-of-compiler.h.patch b/root/target/linux/generic/pending-5.14/101-Use-stddefs.h-instead-of-compiler.h.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/102-MIPS-only-process-negative-stack-offsets-on-stack-tr.patch b/root/target/linux/generic/pending-5.14/102-MIPS-only-process-negative-stack-offsets-on-stack-tr.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch b/root/target/linux/generic/pending-5.14/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/130-add-linux-spidev-compatible-si3210.patch b/root/target/linux/generic/pending-5.14/130-add-linux-spidev-compatible-si3210.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/150-bridge_allow_receiption_on_disabled_port.patch b/root/target/linux/generic/pending-5.14/150-bridge_allow_receiption_on_disabled_port.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/190-rtc-rs5c372-support_alarms_up_to_1_week.patch b/root/target/linux/generic/pending-5.14/190-rtc-rs5c372-support_alarms_up_to_1_week.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/191-rtc-rs5c372-let_the_alarm_to_be_used_as_wakeup_source.patch b/root/target/linux/generic/pending-5.14/191-rtc-rs5c372-let_the_alarm_to_be_used_as_wakeup_source.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/201-extra_optimization.patch b/root/target/linux/generic/pending-5.14/201-extra_optimization.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/203-kallsyms_uncompressed.patch b/root/target/linux/generic/pending-5.14/203-kallsyms_uncompressed.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/205-backtrace_module_info.patch b/root/target/linux/generic/pending-5.14/205-backtrace_module_info.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/240-remove-unsane-filenames-from-deps_initramfs-list.patch b/root/target/linux/generic/pending-5.14/240-remove-unsane-filenames-from-deps_initramfs-list.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/261-enable_wilink_platform_without_drivers.patch b/root/target/linux/generic/pending-5.14/261-enable_wilink_platform_without_drivers.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/270-platform-mikrotik-build-bits.patch b/root/target/linux/generic/pending-5.14/270-platform-mikrotik-build-bits.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/300-mips_expose_boot_raw.patch b/root/target/linux/generic/pending-5.14/300-mips_expose_boot_raw.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/302-mips_no_branch_likely.patch b/root/target/linux/generic/pending-5.14/302-mips_no_branch_likely.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/305-mips_module_reloc.patch b/root/target/linux/generic/pending-5.14/305-mips_module_reloc.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/307-mips_highmem_offset.patch b/root/target/linux/generic/pending-5.14/307-mips_highmem_offset.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/308-mips32r2_tune.patch b/root/target/linux/generic/pending-5.14/308-mips32r2_tune.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/309-MIPS-Add-CPU-option-reporting-to-proc-cpuinfo.patch b/root/target/linux/generic/pending-5.14/309-MIPS-Add-CPU-option-reporting-to-proc-cpuinfo.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/310-arm_module_unresolved_weak_sym.patch b/root/target/linux/generic/pending-5.14/310-arm_module_unresolved_weak_sym.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch b/root/target/linux/generic/pending-5.14/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/332-arc-add-OWRTDTB-section.patch b/root/target/linux/generic/pending-5.14/332-arc-add-OWRTDTB-section.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/333-arc-enable-unaligned-access-in-kernel-mode.patch b/root/target/linux/generic/pending-5.14/333-arc-enable-unaligned-access-in-kernel-mode.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/342-powerpc-Enable-kernel-XZ-compression-option-on-PPC_8.patch b/root/target/linux/generic/pending-5.14/342-powerpc-Enable-kernel-XZ-compression-option-on-PPC_8.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/400-mtd-mtdsplit-support.patch b/root/target/linux/generic/pending-5.14/400-mtd-mtdsplit-support.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/419-mtd-redboot-add-of_match_table-with-DT-binding.patch b/root/target/linux/generic/pending-5.14/419-mtd-redboot-add-of_match_table-with-DT-binding.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/430-mtd-add-myloader-partition-parser.patch b/root/target/linux/generic/pending-5.14/430-mtd-add-myloader-partition-parser.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/431-mtd-bcm47xxpart-check-for-bad-blocks-when-calculatin.patch b/root/target/linux/generic/pending-5.14/431-mtd-bcm47xxpart-check-for-bad-blocks-when-calculatin.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/432-mtd-bcm47xxpart-detect-T_Meter-partition.patch b/root/target/linux/generic/pending-5.14/432-mtd-bcm47xxpart-detect-T_Meter-partition.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/435-mtd-add-routerbootpart-parser-config.patch b/root/target/linux/generic/pending-5.14/435-mtd-add-routerbootpart-parser-config.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/460-mtd-cfi_cmdset_0002-no-erase_suspend.patch b/root/target/linux/generic/pending-5.14/460-mtd-cfi_cmdset_0002-no-erase_suspend.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/461-mtd-cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch b/root/target/linux/generic/pending-5.14/461-mtd-cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/465-m25p80-mx-disable-software-protection.patch b/root/target/linux/generic/pending-5.14/465-m25p80-mx-disable-software-protection.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch b/root/target/linux/generic/pending-5.14/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/476-mtd-spi-nor-add-eon-en25q128.patch b/root/target/linux/generic/pending-5.14/476-mtd-spi-nor-add-eon-en25q128.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/479-mtd-spi-nor-add-xtx-xt25f128b.patch b/root/target/linux/generic/pending-5.14/479-mtd-spi-nor-add-xtx-xt25f128b.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/482-mtd-spi-nor-add-support-for-Gigadevice-GD25D05.patch b/root/target/linux/generic/pending-5.14/482-mtd-spi-nor-add-support-for-Gigadevice-GD25D05.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/483-mtd-spi-nor-add-gd25q512.patch b/root/target/linux/generic/pending-5.14/483-mtd-spi-nor-add-gd25q512.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch b/root/target/linux/generic/pending-5.14/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/491-ubi-auto-create-ubiblock-device-for-rootfs.patch b/root/target/linux/generic/pending-5.14/491-ubi-auto-create-ubiblock-device-for-rootfs.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch b/root/target/linux/generic/pending-5.14/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch b/root/target/linux/generic/pending-5.14/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/494-mtd-ubi-add-EOF-marker-support.patch b/root/target/linux/generic/pending-5.14/494-mtd-ubi-add-EOF-marker-support.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/495-mtd-core-add-get_mtd_device_by_node.patch b/root/target/linux/generic/pending-5.14/495-mtd-core-add-get_mtd_device_by_node.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/496-dt-bindings-add-bindings-for-mtd-concat-devices.patch b/root/target/linux/generic/pending-5.14/496-dt-bindings-add-bindings-for-mtd-concat-devices.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch b/root/target/linux/generic/pending-5.14/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/500-fs_cdrom_dependencies.patch b/root/target/linux/generic/pending-5.14/500-fs_cdrom_dependencies.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/530-jffs2_make_lzma_available.patch b/root/target/linux/generic/pending-5.14/530-jffs2_make_lzma_available.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/532-jffs2_eofdetect.patch b/root/target/linux/generic/pending-5.14/532-jffs2_eofdetect.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/600-netfilter_conntrack_flush.patch b/root/target/linux/generic/pending-5.14/600-netfilter_conntrack_flush.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/610-netfilter_match_bypass_default_checks.patch b/root/target/linux/generic/pending-5.14/610-netfilter_match_bypass_default_checks.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/611-netfilter_match_bypass_default_table.patch b/root/target/linux/generic/pending-5.14/611-netfilter_match_bypass_default_table.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/612-netfilter_match_reduce_memory_access.patch b/root/target/linux/generic/pending-5.14/612-netfilter_match_reduce_memory_access.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/613-netfilter_optional_tcp_window_check.patch b/root/target/linux/generic/pending-5.14/613-netfilter_optional_tcp_window_check.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/620-net_sched-codel-do-not-defer-queue-length-update.patch b/root/target/linux/generic/pending-5.14/620-net_sched-codel-do-not-defer-queue-length-update.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/630-packet_socket_type.patch b/root/target/linux/generic/pending-5.14/630-packet_socket_type.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/655-increase_skb_pad.patch b/root/target/linux/generic/pending-5.14/655-increase_skb_pad.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch b/root/target/linux/generic/pending-5.14/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch b/root/target/linux/generic/pending-5.14/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/671-net-provide-defines-for-_POLICY_FAILED-until-all-cod.patch b/root/target/linux/generic/pending-5.14/671-net-provide-defines-for-_POLICY_FAILED-until-all-cod.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/680-NET-skip-GRO-for-foreign-MAC-addresses.patch b/root/target/linux/generic/pending-5.14/680-NET-skip-GRO-for-foreign-MAC-addresses.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/681-NET-add-mtd-mac-address-support-to-of_get_mac_addres.patch b/root/target/linux/generic/pending-5.14/681-NET-add-mtd-mac-address-support-to-of_get_mac_addres.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/682-of_net-add-mac-address-increment-support.patch b/root/target/linux/generic/pending-5.14/682-of_net-add-mac-address-increment-support.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/683-of_net-add-mac-address-to-of-tree.patch b/root/target/linux/generic/pending-5.14/683-of_net-add-mac-address-to-of-tree.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/700-net-ethernet-mtk_eth_soc-avoid-creating-duplicate-of.patch b/root/target/linux/generic/pending-5.14/700-net-ethernet-mtk_eth_soc-avoid-creating-duplicate-of.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/703-phy-add-detach-callback-to-struct-phy_driver.patch b/root/target/linux/generic/pending-5.14/703-phy-add-detach-callback-to-struct-phy_driver.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/735-net-phy-at803x-fix-at8033-sgmii-mode.patch b/root/target/linux/generic/pending-5.14/735-net-phy-at803x-fix-at8033-sgmii-mode.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/760-net-dsa-mv88e6xxx-fix-vlan-setup.patch b/root/target/linux/generic/pending-5.14/760-net-dsa-mv88e6xxx-fix-vlan-setup.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/761-net-dsa-mt7530-Support-EEE-features.patch b/root/target/linux/generic/pending-5.14/761-net-dsa-mt7530-Support-EEE-features.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch b/root/target/linux/generic/pending-5.14/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/800-bcma-get-SoC-device-struct-copy-its-DMA-params-to-th.patch b/root/target/linux/generic/pending-5.14/800-bcma-get-SoC-device-struct-copy-its-DMA-params-to-th.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/810-pci_disable_common_quirks.patch b/root/target/linux/generic/pending-5.14/810-pci_disable_common_quirks.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/811-pci_disable_usb_common_quirks.patch b/root/target/linux/generic/pending-5.14/811-pci_disable_usb_common_quirks.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/820-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch b/root/target/linux/generic/pending-5.14/820-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/834-ledtrig-libata.patch b/root/target/linux/generic/pending-5.14/834-ledtrig-libata.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/840-hwrng-bcm2835-set-quality-to-1000.patch b/root/target/linux/generic/pending-5.14/840-hwrng-bcm2835-set-quality-to-1000.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.14/920-mangle_bootargs.patch b/root/target/linux/generic/pending-5.14/920-mangle_bootargs.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.15/050-dtc-checks-Drop-interrupt-provider-address-cells-check.patch b/root/target/linux/generic/pending-5.15/050-dtc-checks-Drop-interrupt-provider-address-cells-check.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.15/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch b/root/target/linux/generic/pending-5.15/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.15/141-jffs2-add-RENAME_EXCHANGE-support.patch b/root/target/linux/generic/pending-5.15/141-jffs2-add-RENAME_EXCHANGE-support.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.15/142-jffs2-add-splice-ops.patch b/root/target/linux/generic/pending-5.15/142-jffs2-add-splice-ops.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.15/420-mtd-redboot_space.patch b/root/target/linux/generic/pending-5.15/420-mtd-redboot_space.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.15/481-mtd-spi-nor-rework-broken-flash-reset-support.patch b/root/target/linux/generic/pending-5.15/481-mtd-spi-nor-rework-broken-flash-reset-support.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.15/483-mtd-spinand-add-support-for-xtx-xt26g0xa.patch b/root/target/linux/generic/pending-5.15/483-mtd-spinand-add-support-for-xtx-xt26g0xa.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.15/484-mtd-spi-nor-add-esmt-f25l16pa.patch b/root/target/linux/generic/pending-5.15/484-mtd-spi-nor-add-esmt-f25l16pa.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.15/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch b/root/target/linux/generic/pending-5.15/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.15/682-of_net-add-mac-address-increment-support.patch b/root/target/linux/generic/pending-5.15/682-of_net-add-mac-address-increment-support.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.15/683-of_net-add-mac-address-to-of-tree.patch b/root/target/linux/generic/pending-5.15/683-of_net-add-mac-address-to-of-tree.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.15/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch b/root/target/linux/generic/pending-5.15/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.15/780-ARM-kirkwood-add-missing-linux-if_ether.h-for-ETH_AL.patch b/root/target/linux/generic/pending-5.15/780-ARM-kirkwood-add-missing-linux-if_ether.h-for-ETH_AL.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.15/930-qcom-qmi-helpers.patch b/root/target/linux/generic/pending-5.15/930-qcom-qmi-helpers.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/generic/pending-5.4/690-net-add-support-for-threaded-NAPI-polling.patch b/root/target/linux/generic/pending-5.4/690-net-add-support-for-threaded-NAPI-polling.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/bin/board_detect b/root/target/linux/ipq40xx/base-files/bin/board_detect old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/bin/board_modem b/root/target/linux/ipq40xx/base-files/bin/board_modem old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/bin/board_track b/root/target/linux/ipq40xx/base-files/bin/board_track old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/bin/config_generate b/root/target/linux/ipq40xx/base-files/bin/config_generate old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/bin/ipcalc.sh b/root/target/linux/ipq40xx/base-files/bin/ipcalc.sh old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/etc/board.d/01_leds b/root/target/linux/ipq40xx/base-files/etc/board.d/01_leds old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/etc/board.d/02_network b/root/target/linux/ipq40xx/base-files/etc/board.d/02_network old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/etc/board.d/03_gpio_switches b/root/target/linux/ipq40xx/base-files/etc/board.d/03_gpio_switches old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/etc/board.d/1-board_json b/root/target/linux/ipq40xx/base-files/etc/board.d/1-board_json old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/etc/init.d/boot b/root/target/linux/ipq40xx/base-files/etc/init.d/boot old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/etc/init.d/done b/root/target/linux/ipq40xx/base-files/etc/init.d/done old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/etc/init.d/gpio_switch b/root/target/linux/ipq40xx/base-files/etc/init.d/gpio_switch old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/etc/init.d/led b/root/target/linux/ipq40xx/base-files/etc/init.d/led old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/etc/init.d/modem_tracker b/root/target/linux/ipq40xx/base-files/etc/init.d/modem_tracker old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/etc/init.d/ntpserver b/root/target/linux/ipq40xx/base-files/etc/init.d/ntpserver old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/etc/init.d/powerctl b/root/target/linux/ipq40xx/base-files/etc/init.d/powerctl old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/etc/init.d/set-irq-affinity b/root/target/linux/ipq40xx/base-files/etc/init.d/set-irq-affinity old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/etc/init.d/sysctl b/root/target/linux/ipq40xx/base-files/etc/init.d/sysctl old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/etc/init.d/sysfixtime b/root/target/linux/ipq40xx/base-files/etc/init.d/sysfixtime old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/etc/init.d/system b/root/target/linux/ipq40xx/base-files/etc/init.d/system old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/etc/init.d/umount b/root/target/linux/ipq40xx/base-files/etc/init.d/umount old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/lib/functions/teltonika-defaults.sh b/root/target/linux/ipq40xx/base-files/lib/functions/teltonika-defaults.sh old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/lib/functions/teltonika-functions.sh b/root/target/linux/ipq40xx/base-files/lib/functions/teltonika-functions.sh old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/lib/upgrade/linksys.sh b/root/target/linux/ipq40xx/base-files/lib/upgrade/linksys.sh old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/lib/upgrade/stage2 b/root/target/linux/ipq40xx/base-files/lib/upgrade/stage2 old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/sbin/mctl b/root/target/linux/ipq40xx/base-files/sbin/mctl old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/base-files/sbin/mnf_info b/root/target/linux/ipq40xx/base-files/sbin/mnf_info old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-l1000.dts b/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-l1000.dts old mode 100755 new mode 100644 diff --git a/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts b/root/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-z4019.dts old mode 100755 new mode 100644 diff --git a/root/target/linux/ramips/patches-5.15/410-mtd-rawnand-add-driver-support-for-MT7621-nand-flash.patch b/root/target/linux/ramips/patches-5.15/410-mtd-rawnand-add-driver-support-for-MT7621-nand-flash.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/Makefile b/root/target/linux/rockchip/Makefile old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/armv8/base-files/etc/board.d/01_leds b/root/target/linux/rockchip/armv8/base-files/etc/board.d/01_leds old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/armv8/base-files/etc/board.d/02_network b/root/target/linux/rockchip/armv8/base-files/etc/board.d/02_network old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity b/root/target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/armv8/config-5.14 b/root/target/linux/rockchip/armv8/config-5.14 old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/armv8/config-5.15 b/root/target/linux/rockchip/armv8/config-5.15 old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/files-5.14/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts b/root/target/linux/rockchip/files-5.14/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/files-5.15/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts b/root/target/linux/rockchip/files-5.15/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/image/armv8.mk b/root/target/linux/rockchip/image/armv8.mk old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/image/nanopi-r4s.bootscript b/root/target/linux/rockchip/image/nanopi-r4s.bootscript old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/patches-5.10/004-v5.13-rockchip-rk3399-Add-support-for-FriendlyARM-NanoPi-R.patch b/root/target/linux/rockchip/patches-5.10/004-v5.13-rockchip-rk3399-Add-support-for-FriendlyARM-NanoPi-R.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/patches-5.14/002-net-usb-r8152-add-LED-configuration-from-OF.patch b/root/target/linux/rockchip/patches-5.14/002-net-usb-r8152-add-LED-configuration-from-OF.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/patches-5.14/003-dt-bindings-net-add-RTL8152-binding-documentation.patch b/root/target/linux/rockchip/patches-5.14/003-dt-bindings-net-add-RTL8152-binding-documentation.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/patches-5.14/005-arm64-dts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch b/root/target/linux/rockchip/patches-5.14/005-arm64-dts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/patches-5.14/100-rockchip-use-system-LED-for-OpenWrt.patch b/root/target/linux/rockchip/patches-5.14/100-rockchip-use-system-LED-for-OpenWrt.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/patches-5.14/101-dts-rockchip-add-usb3-controller-node-for-RK3328-SoCs.patch b/root/target/linux/rockchip/patches-5.14/101-dts-rockchip-add-usb3-controller-node-for-RK3328-SoCs.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/patches-5.14/102-rockchip-enable-LAN-port-on-NanoPi-R2S.patch b/root/target/linux/rockchip/patches-5.14/102-rockchip-enable-LAN-port-on-NanoPi-R2S.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/patches-5.14/103-arm64-rockchip-add-OF-node-for-USB-eth-on-NanoPi-R2S.patch b/root/target/linux/rockchip/patches-5.14/103-arm64-rockchip-add-OF-node-for-USB-eth-on-NanoPi-R2S.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/patches-5.14/105-rockchip-rock-pi-4.patch b/root/target/linux/rockchip/patches-5.14/105-rockchip-rock-pi-4.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/patches-5.15/005-arm64-dts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch b/root/target/linux/rockchip/patches-5.15/005-arm64-dts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/patches-5.15/100-rockchip-use-system-LED-for-OpenWrt.patch b/root/target/linux/rockchip/patches-5.15/100-rockchip-use-system-LED-for-OpenWrt.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/patches-5.15/103-arm64-rockchip-add-OF-node-for-USB-eth-on-NanoPi-R2S.patch b/root/target/linux/rockchip/patches-5.15/103-arm64-rockchip-add-OF-node-for-USB-eth-on-NanoPi-R2S.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/patches-5.4/007-v5.13-rockchip-rk3399-Add-support-for-FriendlyARM-NanoPi-R.patch b/root/target/linux/rockchip/patches-5.4/007-v5.13-rockchip-rk3399-Add-support-for-FriendlyARM-NanoPi-R.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/sunxi/base-files/etc/uci-defaults/99-switch-config b/root/target/linux/sunxi/base-files/etc/uci-defaults/99-switch-config old mode 100755 new mode 100644 diff --git a/root/target/linux/sunxi/base-files/sbin/swconfig-wrapper.sh b/root/target/linux/sunxi/base-files/sbin/swconfig-wrapper.sh old mode 100755 new mode 100644 diff --git a/root/target/linux/sunxi/config-5.14 b/root/target/linux/sunxi/config-5.14 old mode 100755 new mode 100644 diff --git a/root/target/linux/x86/64/config-5.14 b/root/target/linux/x86/64/config-5.14 old mode 100755 new mode 100644 diff --git a/root/target/linux/x86/config-4.19 b/root/target/linux/x86/config-4.19 old mode 100755 new mode 100644 diff --git a/root/target/linux/x86/config-5.14 b/root/target/linux/x86/config-5.14 old mode 100755 new mode 100644 diff --git a/root/target/linux/x86/patches-5.14/012-pcengines-apu2-detect-apuv4-board.patch b/root/target/linux/x86/patches-5.14/012-pcengines-apu2-detect-apuv4-board.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/x86/patches-5.14/100-fix_cs5535_clockevt.patch b/root/target/linux/x86/patches-5.14/100-fix_cs5535_clockevt.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/x86/patches-5.4/990-mptcp-fullmesh-raise-addresses-limit.patch b/root/target/linux/x86/patches-5.4/990-mptcp-fullmesh-raise-addresses-limit.patch old mode 100755 new mode 100644 diff --git a/sign.sh b/sign.sh old mode 100755 new mode 100644 From 3f043697723987c108041d23ec00042824980a54 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Sun, 27 Nov 2022 03:15:59 +0800 Subject: [PATCH 071/102] fixx --- .../boot/arm-trusted-firmware-rockchip-vendor/pack-firmware.sh | 0 .../306-rockchip-rk3399-Add-support-for-Rongpin-king3399.patch | 0 .../files/arch/arm64/boot/dts/rockchip/rk3399-king3399.dts | 0 3 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 root/package/boot/arm-trusted-firmware-rockchip-vendor/pack-firmware.sh mode change 100755 => 100644 root/package/boot/uboot-rockchip/patches/306-rockchip-rk3399-Add-support-for-Rongpin-king3399.patch mode change 100755 => 100644 root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3399-king3399.dts diff --git a/root/package/boot/arm-trusted-firmware-rockchip-vendor/pack-firmware.sh b/root/package/boot/arm-trusted-firmware-rockchip-vendor/pack-firmware.sh old mode 100755 new mode 100644 diff --git a/root/package/boot/uboot-rockchip/patches/306-rockchip-rk3399-Add-support-for-Rongpin-king3399.patch b/root/package/boot/uboot-rockchip/patches/306-rockchip-rk3399-Add-support-for-Rongpin-king3399.patch old mode 100755 new mode 100644 diff --git a/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3399-king3399.dts b/root/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3399-king3399.dts old mode 100755 new mode 100644 From 17922ecc3d6fff416ac7768186b8af7d85d599ed Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Sun, 27 Nov 2022 03:21:38 +0800 Subject: [PATCH 072/102] Revert "Merge branch 'test' into develop" This reverts commit ab773230631f7b5d29993e023a2afd0114a8a329, reversing changes made to 0ceb2bb3dd8d5128da40f4edb419ab3c13433937. --- .../utils/sysupgrade-helper/src/MAKEALL | 790 ---- .../arch/blackfin/cpu/bootrom-asm-offsets.awk | 41 - .../src/drivers/net/nss/synopGMAC_Dev.c | 1692 --------- .../src/drivers/net/nss/synopGMAC_Dev.h | 2240 ----------- .../net/nss/synopGMAC_network_interface.c | 1526 -------- .../src/drivers/net/nss/synopGMAC_plat.h | 149 - .../src/drivers/net/nss/uboot_skb.c | 128 - .../src/drivers/net/nss/uboot_skb.h | 53 - .../utils/sysupgrade-helper/src/mkconfig | 181 - .../sysupgrade-helper/src/tools/checkpatch.pl | 3343 ----------------- .../sysupgrade-helper/src/tools/checkstack.pl | 171 - .../src/tools/gcc-version.sh | 32 - .../sysupgrade-helper/src/tools/img2brec.sh | 388 -- .../sysupgrade-helper/src/tools/jtagconsole | 39 - .../sysupgrade-helper/src/tools/netconsole | 59 - .../utils/sysupgrade-helper/src/tools/pack.py | 1854 --------- .../src/tools/patman/patman.py | 153 - .../src/tools/scripts/make-asm-offsets | 27 - .../src/tools/setlocalversion | 177 - ...s-Add-bcm2711-rpi-cm4antrouter5g.dts.patch | 317 -- ...dd-support-for-threaded-NAPI-polling.patch | 344 -- .../linux/ipq40xx/base-files/bin/board_detect | 14 - .../linux/ipq40xx/base-files/bin/board_modem | 307 -- .../linux/ipq40xx/base-files/bin/board_track | 47 - .../ipq40xx/base-files/bin/config_generate | 665 ---- .../linux/ipq40xx/base-files/bin/ipcalc.sh | 71 - .../base-files/etc/board.d/1-board_json | 207 - .../linux/ipq40xx/base-files/etc/init.d/boot | 70 - .../linux/ipq40xx/base-files/etc/init.d/done | 13 - .../ipq40xx/base-files/etc/init.d/gpio_switch | 66 - .../linux/ipq40xx/base-files/etc/init.d/led | 140 - .../base-files/etc/init.d/modem_tracker | 37 - .../ipq40xx/base-files/etc/init.d/ntpserver | 28 - .../ipq40xx/base-files/etc/init.d/powerctl | 32 - .../base-files/etc/init.d/set-irq-affinity | 22 - .../ipq40xx/base-files/etc/init.d/sysctl | 46 - .../ipq40xx/base-files/etc/init.d/sysfixtime | 34 - .../ipq40xx/base-files/etc/init.d/system | 45 - .../ipq40xx/base-files/etc/init.d/umount | 13 - .../lib/functions/teltonika-defaults.sh | 284 -- .../lib/functions/teltonika-functions.sh | 10 - .../ipq40xx/base-files/lib/upgrade/stage2 | 138 - .../target/linux/ipq40xx/base-files/sbin/mctl | 120 - .../linux/ipq40xx/base-files/sbin/mnf_info | 10 - 44 files changed, 16123 deletions(-) delete mode 100644 root/package/utils/sysupgrade-helper/src/MAKEALL delete mode 100644 root/package/utils/sysupgrade-helper/src/arch/blackfin/cpu/bootrom-asm-offsets.awk delete mode 100644 root/package/utils/sysupgrade-helper/src/drivers/net/nss/synopGMAC_Dev.c delete mode 100644 root/package/utils/sysupgrade-helper/src/drivers/net/nss/synopGMAC_Dev.h delete mode 100644 root/package/utils/sysupgrade-helper/src/drivers/net/nss/synopGMAC_network_interface.c delete mode 100644 root/package/utils/sysupgrade-helper/src/drivers/net/nss/synopGMAC_plat.h delete mode 100644 root/package/utils/sysupgrade-helper/src/drivers/net/nss/uboot_skb.c delete mode 100644 root/package/utils/sysupgrade-helper/src/drivers/net/nss/uboot_skb.h delete mode 100644 root/package/utils/sysupgrade-helper/src/mkconfig delete mode 100644 root/package/utils/sysupgrade-helper/src/tools/checkpatch.pl delete mode 100644 root/package/utils/sysupgrade-helper/src/tools/checkstack.pl delete mode 100644 root/package/utils/sysupgrade-helper/src/tools/gcc-version.sh delete mode 100644 root/package/utils/sysupgrade-helper/src/tools/img2brec.sh delete mode 100644 root/package/utils/sysupgrade-helper/src/tools/jtagconsole delete mode 100644 root/package/utils/sysupgrade-helper/src/tools/netconsole delete mode 100644 root/package/utils/sysupgrade-helper/src/tools/pack.py delete mode 100644 root/package/utils/sysupgrade-helper/src/tools/patman/patman.py delete mode 100644 root/package/utils/sysupgrade-helper/src/tools/scripts/make-asm-offsets delete mode 100644 root/package/utils/sysupgrade-helper/src/tools/setlocalversion delete mode 100644 root/target/linux/bcm27xx/patches-5.15/950-0785-ARM-dts-Add-bcm2711-rpi-cm4antrouter5g.dts.patch delete mode 100644 root/target/linux/generic/pending-5.4/690-net-add-support-for-threaded-NAPI-polling.patch delete mode 100644 root/target/linux/ipq40xx/base-files/bin/board_detect delete mode 100644 root/target/linux/ipq40xx/base-files/bin/board_modem delete mode 100644 root/target/linux/ipq40xx/base-files/bin/board_track delete mode 100644 root/target/linux/ipq40xx/base-files/bin/config_generate delete mode 100644 root/target/linux/ipq40xx/base-files/bin/ipcalc.sh delete mode 100644 root/target/linux/ipq40xx/base-files/etc/board.d/1-board_json delete mode 100644 root/target/linux/ipq40xx/base-files/etc/init.d/boot delete mode 100644 root/target/linux/ipq40xx/base-files/etc/init.d/done delete mode 100644 root/target/linux/ipq40xx/base-files/etc/init.d/gpio_switch delete mode 100644 root/target/linux/ipq40xx/base-files/etc/init.d/led delete mode 100644 root/target/linux/ipq40xx/base-files/etc/init.d/modem_tracker delete mode 100644 root/target/linux/ipq40xx/base-files/etc/init.d/ntpserver delete mode 100644 root/target/linux/ipq40xx/base-files/etc/init.d/powerctl delete mode 100644 root/target/linux/ipq40xx/base-files/etc/init.d/set-irq-affinity delete mode 100644 root/target/linux/ipq40xx/base-files/etc/init.d/sysctl delete mode 100644 root/target/linux/ipq40xx/base-files/etc/init.d/sysfixtime delete mode 100644 root/target/linux/ipq40xx/base-files/etc/init.d/system delete mode 100644 root/target/linux/ipq40xx/base-files/etc/init.d/umount delete mode 100644 root/target/linux/ipq40xx/base-files/lib/functions/teltonika-defaults.sh delete mode 100644 root/target/linux/ipq40xx/base-files/lib/functions/teltonika-functions.sh delete mode 100644 root/target/linux/ipq40xx/base-files/lib/upgrade/stage2 delete mode 100644 root/target/linux/ipq40xx/base-files/sbin/mctl delete mode 100644 root/target/linux/ipq40xx/base-files/sbin/mnf_info diff --git a/root/package/utils/sysupgrade-helper/src/MAKEALL b/root/package/utils/sysupgrade-helper/src/MAKEALL deleted file mode 100644 index 2e8b9973..00000000 --- a/root/package/utils/sysupgrade-helper/src/MAKEALL +++ /dev/null @@ -1,790 +0,0 @@ -#!/bin/bash -# Tool mainly for U-Boot Quality Assurance: build one or more board -# configurations with minimal verbosity, showing only warnings and -# errors. - -usage() -{ - # if exiting with 0, write to stdout, else write to stderr - local ret=${1:-0} - [ "${ret}" -eq 1 ] && exec 1>&2 - cat <<-EOF - Usage: MAKEALL [options] [--] [boards-to-build] - - Options: - -a ARCH, --arch ARCH Build all boards with arch ARCH - -c CPU, --cpu CPU Build all boards with cpu CPU - -v VENDOR, --vendor VENDOR Build all boards with vendor VENDOR - -s SOC, --soc SOC Build all boards with soc SOC - -l, --list List all targets to be built - -m, --maintainers List all targets and maintainer email - -M, --mails List all targets and all affilated emails - -h, --help This help output - - Selections by these options are logically ANDed; if the same option - is used repeatedly, such selections are ORed. So "-v FOO -v BAR" - will select all configurations where the vendor is either FOO or - BAR. Any additional arguments specified on the command line are - always build additionally. See the boards.cfg file for more info. - - If no boards are specified, then the default is "powerpc". - - Environment variables: - BUILD_NCPUS number of parallel make jobs (default: auto) - CROSS_COMPILE cross-compiler toolchain prefix (default: "") - MAKEALL_LOGDIR output all logs to here (default: ./LOG/) - BUILD_DIR output build directory (default: ./) - BUILD_NBUILDS number of parallel targets (default: 1) - - Examples: - - build all Power Architecture boards: - MAKEALL -a powerpc - MAKEALL --arch powerpc - MAKEALL powerpc - - build all PowerPC boards manufactured by vendor "esd": - MAKEALL -a powerpc -v esd - - build all PowerPC boards manufactured either by "keymile" or "siemens": - MAKEALL -a powerpc -v keymile -v siemens - - build all Freescale boards with MPC83xx CPUs, plus all 4xx boards: - MAKEALL -c mpc83xx -v freescale 4xx - EOF - exit ${ret} -} - -SHORT_OPTS="ha:c:v:s:lmM" -LONG_OPTS="help,arch:,cpu:,vendor:,soc:,list,maintainers,mails" - -# Option processing based on util-linux-2.13/getopt-parse.bash - -# Note that we use `"$@"' to let each command-line parameter expand to a -# separate word. The quotes around `$@' are essential! -# We need TEMP as the `eval set --' would nuke the return value of -# getopt. -TEMP=`getopt -o ${SHORT_OPTS} --long ${LONG_OPTS} \ - -n 'MAKEALL' -- "$@"` - -[ $? != 0 ] && usage 1 - -# Note the quotes around `$TEMP': they are essential! -eval set -- "$TEMP" - -SELECTED='' -ONLY_LIST='' -PRINT_MAINTS='' -MAINTAINERS_ONLY='' - -while true ; do - case "$1" in - -a|--arch) - # echo "Option ARCH: argument \`$2'" - if [ "$opt_a" ] ; then - opt_a="${opt_a%)} || \$2 == \"$2\")" - else - opt_a="(\$2 == \"$2\")" - fi - SELECTED='y' - shift 2 ;; - -c|--cpu) - # echo "Option CPU: argument \`$2'" - if [ "$opt_c" ] ; then - opt_c="${opt_c%)} || \$3 == \"$2\")" - else - opt_c="(\$3 == \"$2\")" - fi - SELECTED='y' - shift 2 ;; - -s|--soc) - # echo "Option SoC: argument \`$2'" - if [ "$opt_s" ] ; then - opt_s="${opt_s%)} || \$6 == \"$2\")" - else - opt_s="(\$6 == \"$2\")" - fi - SELECTED='y' - shift 2 ;; - -v|--vendor) - # echo "Option VENDOR: argument \`$2'" - if [ "$opt_v" ] ; then - opt_v="${opt_v%)} || \$5 == \"$2\")" - else - opt_v="(\$5 == \"$2\")" - fi - SELECTED='y' - shift 2 ;; - -l|--list) - ONLY_LIST='y' - shift ;; - -m|--maintainers) - ONLY_LIST='y' - PRINT_MAINTS='y' - MAINTAINERS_ONLY='y' - shift ;; - -M|--mails) - ONLY_LIST='y' - PRINT_MAINTS='y' - shift ;; - -h|--help) - usage ;; - --) - shift ; break ;; - *) - echo "Internal error!" >&2 ; exit 1 ;; - esac -done -# echo "Remaining arguments:" -# for arg do echo '--> '"\`$arg'" ; done - -FILTER="\$1 !~ /^#/" -[ "$opt_a" ] && FILTER="${FILTER} && $opt_a" -[ "$opt_c" ] && FILTER="${FILTER} && $opt_c" -[ "$opt_s" ] && FILTER="${FILTER} && $opt_s" -[ "$opt_v" ] && FILTER="${FILTER} && $opt_v" - -if [ "$SELECTED" ] ; then - SELECTED=$(awk '('"$FILTER"') { print $1 }' boards.cfg) - - # Make sure some boards from boards.cfg are actually found - if [ -z "$SELECTED" ] ; then - echo "Error: No boards selected, invalid arguments" - exit 1 - fi -fi - -######################################################################### - -# Print statistics when we exit -trap exit 1 2 3 15 -trap print_stats 0 - -# Determine number of CPU cores if no default was set -: ${BUILD_NCPUS:="`getconf _NPROCESSORS_ONLN`"} - -if [ "$BUILD_NCPUS" -gt 1 ] -then - JOBS="-j $((BUILD_NCPUS + 1))" -else - JOBS="" -fi - - -if [ "${CROSS_COMPILE}" ] ; then - MAKE="make CROSS_COMPILE=${CROSS_COMPILE}" -else - MAKE=make -fi - -if [ "${MAKEALL_LOGDIR}" ] ; then - LOG_DIR=${MAKEALL_LOGDIR} -else - LOG_DIR="LOG" -fi - -: ${BUILD_NBUILDS:=1} -BUILD_MANY=0 - -if [ "${BUILD_NBUILDS}" -gt 1 ] ; then - BUILD_MANY=1 - : ${BUILD_DIR:=./build} - mkdir -p "${BUILD_DIR}/ERR" - find "${BUILD_DIR}/ERR/" -type f -exec rm -f {} + -fi - -: ${BUILD_DIR:=.} - -OUTPUT_PREFIX="${BUILD_DIR}" - -[ -d ${LOG_DIR} ] || mkdir "${LOG_DIR}" || exit 1 -find "${LOG_DIR}/" -type f -exec rm -f {} + - -LIST="" - -# Keep track of the number of builds and errors -ERR_CNT=0 -ERR_LIST="" -WRN_CNT=0 -WRN_LIST="" -TOTAL_CNT=0 -CURRENT_CNT=0 -OLDEST_IDX=1 -RC=0 - -# Helper funcs for parsing boards.cfg -boards_by_field() -{ - awk \ - -v field="$1" \ - -v select="$2" \ - '($1 !~ /^#/ && $field == select) { print $1 }' \ - boards.cfg -} -boards_by_arch() { boards_by_field 2 "$@" ; } -boards_by_cpu() { boards_by_field 3 "$@" ; } -boards_by_soc() { boards_by_field 6 "$@" ; } - -######################################################################### -## MPC5xx Systems -######################################################################### - -LIST_5xx="$(boards_by_cpu mpc5xx)" - -######################################################################### -## MPC5xxx Systems -######################################################################### - -LIST_5xxx="$(boards_by_cpu mpc5xxx)" - -######################################################################### -## MPC512x Systems -######################################################################### - -LIST_512x="$(boards_by_cpu mpc512x)" - -######################################################################### -## MPC8xx Systems -######################################################################### - -LIST_8xx="$(boards_by_cpu mpc8xx)" - -######################################################################### -## PPC4xx Systems -######################################################################### - -LIST_4xx="$(boards_by_cpu ppc4xx)" - -######################################################################### -## MPC8220 Systems -######################################################################### - -LIST_8220="$(boards_by_cpu mpc8220)" - -######################################################################### -## MPC824x Systems -######################################################################### - -LIST_824x="$(boards_by_cpu mpc824x)" - -######################################################################### -## MPC8260 Systems (includes 8250, 8255 etc.) -######################################################################### - -LIST_8260="$(boards_by_cpu mpc8260)" - -######################################################################### -## MPC83xx Systems (includes 8349, etc.) -######################################################################### - -LIST_83xx="$(boards_by_cpu mpc83xx)" - -######################################################################### -## MPC85xx Systems (includes 8540, 8560 etc.) -######################################################################### - -LIST_85xx="$(boards_by_cpu mpc85xx)" - -######################################################################### -## MPC86xx Systems -######################################################################### - -LIST_86xx="$(boards_by_cpu mpc86xx)" - -######################################################################### -## 74xx/7xx Systems -######################################################################### - -LIST_74xx_7xx="$(boards_by_cpu 74xx_7xx)" - -######################################################################### -## PowerPC groups -######################################################################### - -LIST_TSEC=" \ - ${LIST_83xx} \ - ${LIST_85xx} \ - ${LIST_86xx} \ -" - -LIST_powerpc=" \ - ${LIST_5xx} \ - ${LIST_512x} \ - ${LIST_5xxx} \ - ${LIST_8xx} \ - ${LIST_8220} \ - ${LIST_824x} \ - ${LIST_8260} \ - ${LIST_83xx} \ - ${LIST_85xx} \ - ${LIST_86xx} \ - ${LIST_4xx} \ - ${LIST_74xx_7xx}\ -" - -# Alias "ppc" -> "powerpc" to not break compatibility with older scripts -# still using "ppc" instead of "powerpc" -LIST_ppc=" \ - ${LIST_powerpc} \ -" - -######################################################################### -## StrongARM Systems -######################################################################### - -LIST_SA="$(boards_by_cpu sa1100)" - -######################################################################### -## ARM9 Systems -######################################################################### - -LIST_ARM9="$(boards_by_cpu arm920t) \ - $(boards_by_cpu arm926ejs) \ - $(boards_by_cpu arm925t) \ -" - -######################################################################### -## ARM11 Systems -######################################################################### -LIST_ARM11="$(boards_by_cpu arm1136)" - -######################################################################### -## ARMV7 Systems -######################################################################### - -LIST_ARMV7="$(boards_by_cpu armv7)" - -######################################################################### -## AT91 Systems -######################################################################### - -LIST_at91="$(boards_by_soc at91)" - -######################################################################### -## Xscale Systems -######################################################################### - -LIST_pxa="$(boards_by_cpu pxa)" - -LIST_ixp="$(boards_by_cpu ixp)" - -######################################################################### -## ARM groups -######################################################################### - -LIST_arm=" \ - ${LIST_SA} \ - ${LIST_ARM9} \ - ${LIST_ARM10} \ - ${LIST_ARM11} \ - ${LIST_ARMV7} \ - ${LIST_at91} \ - ${LIST_pxa} \ - ${LIST_ixp} \ -" - -######################################################################### -## MIPS Systems (default = big endian) -######################################################################### - -LIST_mips4kc=" \ - incaip \ - qemu_mips \ - vct_platinum \ - vct_platinum_small \ - vct_platinum_onenand \ - vct_platinum_onenand_small \ - vct_platinumavc \ - vct_platinumavc_small \ - vct_platinumavc_onenand \ - vct_platinumavc_onenand_small \ - vct_premium \ - vct_premium_small \ - vct_premium_onenand \ - vct_premium_onenand_small \ -" - -LIST_au1xx0=" \ - dbau1000 \ - dbau1100 \ - dbau1500 \ - dbau1550 \ - gth2 \ -" - -LIST_mips=" \ - ${LIST_mips4kc} \ - ${LIST_mips5kc} \ - ${LIST_au1xx0} \ -" - -######################################################################### -## MIPS Systems (little endian) -######################################################################### - -LIST_xburst_el=" \ - qi_lb60 \ -" - -LIST_au1xx0_el=" \ - dbau1550_el \ - pb1000 \ -" -LIST_mips_el=" \ - ${LIST_xburst_el} \ - ${LIST_au1xx0_el} \ -" -######################################################################### -## OpenRISC Systems -######################################################################### - -LIST_openrisc="$(boards_by_arch openrisc)" - -######################################################################### -## x86 Systems -######################################################################### - -LIST_x86="$(boards_by_arch x86)" - -######################################################################### -## Nios-II Systems -######################################################################### - -LIST_nios2="$(boards_by_arch nios2)" - -######################################################################### -## MicroBlaze Systems -######################################################################### - -LIST_microblaze="$(boards_by_arch microblaze)" - -######################################################################### -## ColdFire Systems -######################################################################### - -LIST_m68k="$(boards_by_arch m68k) - EB+MCF-EV123 \ - EB+MCF-EV123_internal \ - M52277EVB \ - M5235EVB \ - M54451EVB \ - M54455EVB \ -" -LIST_coldfire=${LIST_m68k} - -######################################################################### -## AVR32 Systems -######################################################################### - -LIST_avr32="$(boards_by_arch avr32)" - -######################################################################### -## Blackfin Systems -######################################################################### - -LIST_blackfin="$(boards_by_arch blackfin)" - -######################################################################### -## SH Systems -######################################################################### - -LIST_sh2="$(boards_by_cpu sh2)" -LIST_sh3="$(boards_by_cpu sh3)" -LIST_sh4="$(boards_by_cpu sh4)" - -LIST_sh="$(boards_by_arch sh)" - -######################################################################### -## SPARC Systems -######################################################################### - -LIST_sparc="$(boards_by_arch sparc)" - -######################################################################### -## NDS32 Systems -######################################################################### - -LIST_nds32="$(boards_by_arch nds32)" - -#----------------------------------------------------------------------- - -get_target_location() { - local target=$1 - local BOARD_NAME="" - local CONFIG_NAME="" - local board="" - local vendor="" - - # Automatic mode - local line=`egrep -i "^[[:space:]]*${target}[[:space:]]" boards.cfg` - - if [ -z "${line}" ] ; then echo "" ; return ; fi - - set ${line} - - # add default board name if needed - [ $# = 3 ] && set ${line} ${1} - - CONFIG_NAME="${1%_config}" - - [ "${BOARD_NAME}" ] || BOARD_NAME="${1%_config}" - - if [ "$4" = "-" ] ; then - board=${BOARD_NAME} - else - board="$4" - fi - - [ $# -gt 4 ] && [ "$5" != "-" ] && vendor="$5" - [ $# -gt 6 ] && [ "$7" != "-" ] && { - tmp="${7%:*}" - if [ "$tmp" ] ; then - CONFIG_NAME="$tmp" - fi - } - - # Assign board directory to BOARDIR variable - if [ -z "${vendor}" ] ; then - BOARDDIR=${board} - else - BOARDDIR=${vendor}/${board} - fi - - echo "${CONFIG_NAME}:${BOARDDIR}" -} - -get_target_maintainers() { - local name=`echo $1 | cut -d : -f 1` - - if ! grep -qsi "[[:blank:]]${name}[[:blank:]]" MAINTAINERS ; then - echo "" - return ; - fi - - local line=`tac MAINTAINERS | grep -ni "[[:blank:]]${name}[[:blank:]]" | cut -d : -f 1` - local mail=`tac MAINTAINERS | tail -n +${line} | \ - sed -n ":start /.*@.*/ { b mail } ; n ; b start ; :mail /.*@.*/ { p ; n ; b mail } ; q" | \ - sed "s/^.*.*$//"` - echo "$mail" -} - -list_target() { - if [ "$PRINT_MAINTS" != 'y' ] ; then - echo "$1" - return - fi - - echo -n "$1:" - - local loc=`get_target_location $1` - - if [ -z "${loc}" ] ; then echo "ERROR" ; return ; fi - - local maintainers_result=`get_target_maintainers ${loc} | tr " " "\n"` - - if [ "$MAINTAINERS_ONLY" != 'y' ] ; then - - local dir=`echo ${loc} | cut -d ":" -f 2` - local cfg=`echo ${loc} | cut -d ":" -f 1` - local git_result=`git log --format=%aE board/${dir} \ - include/configs/${cfg}.h | grep "@"` - local git_result_recent=`echo ${git_result} | tr " " "\n" | \ - head -n 3` - local git_result_top=`echo ${git_result} | tr " " "\n" | \ - sort | uniq -c | sort -nr | head -n 3 | \ - sed "s/^ \+[0-9]\+ \+//"` - - echo -e "$git_result_recent\n$git_result_top\n$maintainers_result" | \ - sort -u | tr "\n" " " | sed "s/ $//" ; - else - echo -e "$maintainers_result" | sort -u | tr "\n" " " | \ - sed "s/ $//" ; - fi - - echo "" -} - -# Each finished build will have a file called ${donep}${n}, -# where n is the index of the build. Each build -# we've already noted as finished will have ${skipp}${n}. -# The code managing the build process will use this information -# to ensure that only BUILD_NBUILDS builds are in flight at once -donep="${LOG_DIR}/._done_" -skipp="${LOG_DIR}/._skip_" - -build_target() { - target=$1 - build_idx=$2 - - if [ "$ONLY_LIST" == 'y' ] ; then - list_target ${target} - return - fi - - if [ $BUILD_MANY == 1 ] ; then - output_dir="${OUTPUT_PREFIX}/${target}" - mkdir -p "${output_dir}" - else - output_dir="${OUTPUT_PREFIX}" - fi - - export BUILD_DIR="${output_dir}" - - ${MAKE} distclean >/dev/null - ${MAKE} -s ${target}_config - - ${MAKE} ${JOBS} all \ - >${LOG_DIR}/$target.MAKELOG 2> ${LOG_DIR}/$target.ERR - - # Check for 'make' errors - if [ ${PIPESTATUS[0]} -ne 0 ] ; then - RC=1 - fi - - if [ $BUILD_MANY == 1 ] ; then - ${MAKE} tidy - - if [ -s ${LOG_DIR}/${target}.ERR ] ; then - cp ${LOG_DIR}/${target}.ERR ${OUTPUT_PREFIX}/ERR/${target} - else - rm ${LOG_DIR}/${target}.ERR - fi - else - if [ -s ${LOG_DIR}/${target}.ERR ] ; then - if grep -iw error ${LOG_DIR}/${target}.ERR ; then - : $(( ERR_CNT += 1 )) - ERR_LIST="${ERR_LIST} $target" - else - : $(( WRN_CNT += 1 )) - WRN_LIST="${WRN_LIST} $target" - fi - else - rm ${LOG_DIR}/${target}.ERR - fi - fi - - OBJS=${output_dir}/u-boot - if [ -e ${output_dir}/spl/u-boot-spl ]; then - OBJS="${OBJS} ${output_dir}/spl/u-boot-spl" - fi - - ${CROSS_COMPILE}size ${OBJS} | tee -a ${LOG_DIR}/$target.MAKELOG - - [ -e "${LOG_DIR}/${target}.ERR" ] && cat "${LOG_DIR}/${target}.ERR" - - touch "${donep}${build_idx}" -} - -manage_builds() { - search_idx=${OLDEST_IDX} - if [ "$ONLY_LIST" == 'y' ] ; then return ; fi - - while true; do - if [ -e "${donep}${search_idx}" ] ; then - : $(( CURRENT_CNT-- )) - [ ${OLDEST_IDX} -eq ${search_idx} ] && - : $(( OLDEST_IDX++ )) - - # Only want to count it once - rm -f "${donep}${search_idx}" - touch "${skipp}${search_idx}" - elif [ -e "${skipp}${search_idx}" ] ; then - [ ${OLDEST_IDX} -eq ${search_idx} ] && - : $(( OLDEST_IDX++ )) - fi - : $(( search_idx++ )) - if [ ${search_idx} -gt ${TOTAL_CNT} ] ; then - if [ ${CURRENT_CNT} -ge ${BUILD_NBUILDS} ] ; then - search_idx=${OLDEST_IDX} - sleep 1 - else - break - fi - fi - done -} - -build_targets() { - for t in "$@" ; do - # If a LIST_xxx var exists, use it. But avoid variable - # expansion in the eval when a board name contains certain - # characters that the shell interprets. - case ${t} in - *[-+=]*) list= ;; - *) list=$(eval echo '${LIST_'$t'}') ;; - esac - if [ -n "${list}" ] ; then - build_targets ${list} - else - : $((TOTAL_CNT += 1)) - : $((CURRENT_CNT += 1)) - rm -f "${donep}${TOTAL_CNT}" - rm -f "${skipp}${TOTAL_CNT}" - if [ $BUILD_MANY == 1 ] ; then - build_target ${t} ${TOTAL_CNT} & - else - build_target ${t} ${TOTAL_CNT} - fi - fi - - # We maintain a running count of all the builds we have done. - # Each finished build will have a file called ${donep}${n}, - # where n is the index of the build. Each build - # we've already noted as finished will have ${skipp}${n}. - # We track the current index via TOTAL_CNT, and the oldest - # index. When we exceed the maximum number of parallel builds, - # We look from oldest to current for builds that have completed, - # and update the current count and oldest index as appropriate. - # If we've gone through the entire list, wait a second, and - # reprocess the entire list until we find a build that has - # completed - if [ ${CURRENT_CNT} -ge ${BUILD_NBUILDS} ] ; then - manage_builds - fi - done -} - -#----------------------------------------------------------------------- - -kill_children() { - kill -- "-$1" - - exit -} - -print_stats() { - if [ "$ONLY_LIST" == 'y' ] ; then return ; fi - - rm -f ${donep}* ${skipp}* - - if [ $BUILD_MANY == 1 ] && [ -e "${OUTPUT_PREFIX}/ERR" ] ; then - ERR_LIST=`grep -iwl error ${OUTPUT_PREFIX}/ERR/*` - ERR_LIST=`for f in $ERR_LIST ; do echo -n " $(basename $f)" ; done` - ERR_CNT=`echo $ERR_LIST | wc -w | awk '{print $1}'` - WRN_LIST=`grep -iwL error ${OUTPUT_PREFIX}/ERR/*` - WRN_LIST=`for f in $WRN_LIST ; do echo -n " $(basename $f)" ; done` - WRN_CNT=`echo $WRN_LIST | wc -w | awk '{print $1}'` - fi - - echo "" - echo "--------------------- SUMMARY ----------------------------" - echo "Boards compiled: ${TOTAL_CNT}" - if [ ${ERR_CNT} -gt 0 ] ; then - echo "Boards with errors: ${ERR_CNT} (${ERR_LIST} )" - fi - if [ ${WRN_CNT} -gt 0 ] ; then - echo "Boards with warnings but no errors: ${WRN_CNT} (${WRN_LIST} )" - fi - echo "----------------------------------------------------------" - - if [ $BUILD_MANY == 1 ] ; then - kill_children $$ & - fi - - exit $RC -} - -#----------------------------------------------------------------------- - -# Build target groups selected by options, plus any command line args -set -- ${SELECTED} "$@" -# run PowerPC by default -[ $# = 0 ] && set -- powerpc -build_targets "$@" -wait diff --git a/root/package/utils/sysupgrade-helper/src/arch/blackfin/cpu/bootrom-asm-offsets.awk b/root/package/utils/sysupgrade-helper/src/arch/blackfin/cpu/bootrom-asm-offsets.awk deleted file mode 100644 index 1d618242..00000000 --- a/root/package/utils/sysupgrade-helper/src/arch/blackfin/cpu/bootrom-asm-offsets.awk +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/gawk -f -BEGIN { - print "/* DO NOT EDIT: AUTOMATICALLY GENERATED" - print " * Input files: bootrom-asm-offsets.awk bootrom-asm-offsets.c.in" - print " * DO NOT EDIT: AUTOMATICALLY GENERATED" - print " */" - print "" - system("cat bootrom-asm-offsets.c.in") - print "{" -} - -{ - /* find a structure definition */ - if ($0 ~ /typedef struct .* {/) { - delete members; - i = 0; - - /* extract each member of the structure */ - while (1) { - getline - if ($1 == "}") - break; - gsub(/[*;]/, ""); - members[i++] = $NF; - } - - /* grab the structure's name */ - struct = $NF; - sub(/;$/, "", struct); - - /* output the DEFINE() macros */ - while (i-- > 0) - print "\tDEFINE(" struct ", " members[i] ");" - print "" - } -} - -END { - print "\treturn 0;" - print "}" -} diff --git a/root/package/utils/sysupgrade-helper/src/drivers/net/nss/synopGMAC_Dev.c b/root/package/utils/sysupgrade-helper/src/drivers/net/nss/synopGMAC_Dev.c deleted file mode 100644 index 121717f9..00000000 --- a/root/package/utils/sysupgrade-helper/src/drivers/net/nss/synopGMAC_Dev.c +++ /dev/null @@ -1,1692 +0,0 @@ - -/* * Copyright (c) 2012 - 2013 The Linux Foundation. All rights reserved.* */ - -/* \file - * This file defines the synopsys GMAC device dependent functions. - * Most of the operations on the GMAC device are available in this file. - * Functions for initiliasing and accessing MAC/DMA/PHY registers and the DMA descriptors - * are encapsulated in this file. The functions are platform/host/OS independent. - * These functions in turn use the low level device dependent (HAL) functions to - * access the register space. - * \internal - * ------------------------REVISION HISTORY--------------------------------- - * Synopsys 01/Aug/2007 Created - */ -#include "synopGMAC_Dev.h" -#include -#include - -extern uint16_t mii_read_reg(synopGMACdevice *gmacdev, uint32_t phy, uint32_t reg); -/* - * Function to read the Phy register. The access to phy register - * is a slow process as the data is moved accross MDI/MDO interface - * @param[in] pointer to Register Base (It is the mac base in our case) . - * @param[in] PhyBase register is the index of one of supported 32 PHY devices. - * @param[in] Register offset is the index of one of the 32 phy register. - * @param[out] u16 data read from the respective phy register (only valid iff return value is 0). - * \return Returns 0 on success else return the error status. - */ -s32 synopGMAC_read_phy_reg(u32 *RegBase,u32 PhyBase, u32 RegOffset, u16 * data) -{ - u32 addr; - u32 loop_variable; - - addr = ((PhyBase << GmiiDevShift) & GmiiDevMask) | ((RegOffset << GmiiRegShift) & GmiiRegMask); - addr = addr | GmiiBusy ; //Gmii busy bit - synopGMACWriteReg(RegBase,GmacGmiiAddr,addr); //write the address from where the data to be read in GmiiGmiiAddr register of synopGMAC ip - - //Wait till the busy bit gets cleared with in a certain amount of time - for (loop_variable = 0; loop_variable < DEFAULT_LOOP_VARIABLE; loop_variable++) { - if (!(synopGMACReadReg(RegBase,GmacGmiiAddr) & GmiiBusy)){ - break; - } - __udelay(0xFFFFF); - } - if(loop_variable < DEFAULT_LOOP_VARIABLE) - *data = (u16)(synopGMACReadReg(RegBase, GmacGmiiData) & 0xFFFF); - else{ - TR("Error::: PHY not responding Busy bit didnot get cleared !!!!!!\n"); - BUG(); - return -ESYNOPGMACPHYERR; - } - return -ESYNOPGMACNOERR; -} - -/* - * Function to write to the Phy register. The access to phy register - * is a slow process as the data is moved accross MDI/MDO interface - * @param[in] pointer to Register Base (It is the mac base in our case) . - * @param[in] PhyBase register is the index of one of supported 32 PHY devices. - * @param[in] Register offset is the index of one of the 32 phy register. - * @param[in] data to be written to the respective phy register. - * \return Returns 0 on success else return the error status. - */ -s32 synopGMAC_write_phy_reg(u32 *RegBase, u32 PhyBase, u32 RegOffset, u16 data) -{ - u32 addr; - u32 loop_variable; - - synopGMACWriteReg(RegBase,GmacGmiiData,data); // write the data in to GmacGmiiData register of synopGMAC ip - - addr = ((PhyBase << GmiiDevShift) & GmiiDevMask) | ((RegOffset << GmiiRegShift) & GmiiRegMask) | GmiiWrite; - - addr = addr | GmiiBusy ; //set Gmii clk to 20-35 Mhz and Gmii busy bit - - synopGMACWriteReg(RegBase,GmacGmiiAddr,addr); - for (loop_variable = 0; loop_variable < DEFAULT_LOOP_VARIABLE; loop_variable++) { - if (!(synopGMACReadReg(RegBase,GmacGmiiAddr) & GmiiBusy)){ - break; - } - __udelay(DEFAULT_DELAY_VARIABLE); - } - - if (loop_variable < DEFAULT_LOOP_VARIABLE) { - return -ESYNOPGMACNOERR; - } else { - TR("Error::: PHY not responding Busy bit didnot get cleared !!!!!!\n"); - return -ESYNOPGMACPHYERR; - } -} - -/* - * Function to read the GMAC IP Version and populates the same in device data structure. - * @param[in] pointer to synopGMACdevice. - * \return Always return 0. - */ - -s32 synopGMAC_read_version (synopGMACdevice * gmacdev) -{ - u32 data = 0; - data = synopGMACReadReg((u32 *)gmacdev->MacBase, GmacVersion ); - gmacdev->Version = data; - TR("The synopGMAC version: %08x\n",data); - return 0; -} - -/* - * Function to reset the GMAC core. - * This reests the DMA and GMAC core. After reset all the registers holds their respective reset value - * @param[in] pointer to synopGMACdevice. - * \return 0 on success else return the error status. - */ -void synopGMAC_reset (synopGMACdevice * gmacdev ) -{ - u32 data = 0; - - synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaBusMode ,DmaResetOn); - do { - __udelay(DEFAULT_LOOP_VARIABLE); - data = synopGMACReadReg((u32 *)gmacdev->DmaBase, DmaBusMode); - } while (data & DmaResetOn); - -} - -/* - * Function to program DMA bus mode register. - * - * The Bus Mode register is programmed with the value given. The bits to be set are - * bit wise or'ed and sent as the second argument to this function. - * @param[in] pointer to synopGMACdevice. - * @param[in] the data to be programmed. - * \return 0 on success else return the error status. - */ -s32 synopGMAC_dma_bus_mode_init(synopGMACdevice * gmacdev, u32 init_value ) -{ - synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaBusMode ,init_value); - return 0; -} - -/* - * Function to program DMA Control register. - * - * The Dma Control register is programmed with the value given. The bits to be set are - * bit wise or'ed and sent as the second argument to this function. - * @param[in] pointer to synopGMACdevice. - * @param[in] the data to be programmed. - * \return 0 on success else return the error status. - */ -s32 synopGMAC_dma_control_init(synopGMACdevice * gmacdev, u32 init_value) -{ - synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaControl, init_value); - return 0; -} - - -/*Gmac configuration functions*/ - -/* - * Enable the watchdog timer on the receiver. - * When enabled, Gmac enables Watchdog timer, and GMAC allows no more than - * 2048 bytes of data (10,240 if Jumbo frame enabled). - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_wd_enable(synopGMACdevice * gmacdev) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacConfig, GmacWatchdog); -} - -/* - * Enables the Jabber frame support. - * When enabled, GMAC disabled the jabber timer, and can transfer 16,384 byte frames. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_jab_enable(synopGMACdevice * gmacdev) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacConfig, GmacJabber); -} - -/* - * Enables Frame bursting (Only in Half Duplex Mode). - * When enabled, GMAC allows frame bursting in GMII Half Duplex mode. - * Reserved in 10/100 and Full-Duplex configurations. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_frame_burst_enable(synopGMACdevice * gmacdev) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacConfig, GmacFrameBurst); -} - - -/* - * Disable Jumbo frame support. - * When Disabled GMAC does not supports jumbo frames. - * Giant frame error is reported in receive frame status. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_jumbo_frame_disable(synopGMACdevice * gmacdev) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacConfig, GmacJumboFrame); -} - -/* - * Selects the GMII port. - * When called GMII (1000Mbps) port is selected (programmable only in 10/100/1000 Mbps configuration). - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_select_gmii(synopGMACdevice * gmacdev) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacConfig, GmacSelectGmii); -} - -/* - * Selects the MII port. - * When called MII (10/100Mbps) port is selected (programmable only in 10/100/1000 Mbps configuration). - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_select_mii(synopGMACdevice * gmacdev) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacConfig, GmacMiiGmii); - if (gmacdev->Speed == SPEED100) { - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacConfig, GmacFESpeed100); - } else { - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacConfig, GmacFESpeed100); - } -} - -/* - * Enables Receive Own bit (Only in Half Duplex Mode). - * When enaled GMAC receives all the packets given by phy while transmitting. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_rx_own_enable(synopGMACdevice * gmacdev) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacConfig, GmacRxOwn); -} - -/* - * Disables Receive Own bit (Only in Half Duplex Mode). - * When enaled GMAC disables the reception of frames when gmii_txen_o is asserted. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_rx_own_disable(synopGMACdevice * gmacdev) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacConfig, GmacRxOwn); -} - -/* - * Sets the GMAC in Normal mode. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_loopback_off(synopGMACdevice * gmacdev) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacConfig, GmacLoopback); -} - -/* - * Sets the GMAC core in Full-Duplex mode. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_set_full_duplex(synopGMACdevice * gmacdev) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacConfig, GmacDuplex); -} - -/* - * Sets the GMAC core in Half-Duplex mode. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_set_half_duplex(synopGMACdevice * gmacdev) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacConfig, GmacDuplex); -} - -/* - * GMAC tries retransmission (Only in Half Duplex mode). - * If collision occurs on the GMII/MII, GMAC attempt retries based on the - * back off limit configured. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - * \note This function is tightly coupled with synopGMAC_back_off_limit(synopGMACdevice *, u32). - */ -void synopGMAC_retry_enable(synopGMACdevice * gmacdev) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacConfig, GmacRetry); -} - -/* - * GMAC tries only one transmission (Only in Half Duplex mode). - * If collision occurs on the GMII/MII, GMAC will ignore the current frami - * transmission and report a frame abort with excessive collision in tranmit frame status. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_retry_disable(synopGMACdevice * gmacdev) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacConfig, GmacRetry); -} - -/* - * GMAC doesnot strips the Pad/FCS field of incoming frames. - * GMAC will pass all the incoming frames to Host unmodified. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_pad_crc_strip_disable(synopGMACdevice * gmacdev) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacConfig, GmacPadCrcStrip); -} - -/* - * GMAC programmed with the back off limit value. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - * \note This function is tightly coupled with synopGMAC_retry_enable(synopGMACdevice * gmacdev) - */ -void synopGMAC_back_off_limit(synopGMACdevice * gmacdev, u32 value) -{ - u32 data; - data = synopGMACReadReg((u32 *)gmacdev->MacBase, GmacConfig); - data &= (~GmacBackoffLimit); - data |= value; - synopGMACWriteReg((u32 *)gmacdev->MacBase, GmacConfig,data); -} - -/* - * Disables the Deferral check in GMAC (Only in Half Duplex mode). - * GMAC defers until the CRS signal goes inactive. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_deferral_check_disable(synopGMACdevice * gmacdev) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacConfig, GmacDeferralCheck); -} - -/* - * Enable the reception of frames on GMII/MII. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_rx_enable(synopGMACdevice * gmacdev) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacConfig, GmacRx); -} - -/* - * Disable the reception of frames on GMII/MII. - * GMAC receive state machine is disabled after completion of reception of current frame. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_rx_disable(synopGMACdevice * gmacdev) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacConfig, GmacRx); - -} - -/* - * Enable the transmission of frames on GMII/MII. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_tx_enable(synopGMACdevice * gmacdev) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacConfig, GmacTx); -} - -/* - * Disable the transmission of frames on GMII/MII. - * GMAC transmit state machine is disabled after completion of transmission of current frame. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_tx_disable(synopGMACdevice * gmacdev) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacConfig, GmacTx); -} - -/*Receive frame filter configuration functions*/ - -/* - * Enables reception of all the frames to application. - * GMAC passes all the frames received to application irrespective of whether they - * pass SA/DA address filtering or not. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_frame_filter_enable(synopGMACdevice * gmacdev) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacFrameFilter, GmacFilter); -} - -/* - * Disables Source address filtering. - * When disabled GMAC forwards the received frames with updated SAMatch bit in RxStatus. - * @param[in] pointer to synopGMACdevice. - * \return void. - */ -void synopGMAC_src_addr_filter_disable(synopGMACdevice * gmacdev) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacFrameFilter, GmacSrcAddrFilter); -} -/* - * Enables the normal Destination address filtering. - * @param[in] pointer to synopGMACdevice. - * \return void. - */ -void synopGMAC_dst_addr_filter_normal(synopGMACdevice * gmacdev) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacFrameFilter, GmacDestAddrFilterNor); -} - -/* - * Enables forwarding of control frames. - * When set forwards all the control frames (incl. unicast and multicast PAUSE frames). - * @param[in] pointer to synopGMACdevice. - * \return void. - * \note Depends on RFE of FlowControlRegister[2] - */ -void synopGMAC_set_pass_control(synopGMACdevice * gmacdev,u32 passcontrol) -{ - u32 data; - data = synopGMACReadReg((u32 *)gmacdev->MacBase, GmacFrameFilter); - data &= (~GmacPassControl); - data |= passcontrol; - synopGMACWriteReg((u32 *)gmacdev->MacBase,GmacFrameFilter,data); -} - -/* - * Enables Broadcast frames. - * When enabled Address filtering module passes all incoming broadcast frames. - * @param[in] pointer to synopGMACdevice. - * \return void. - */ -void synopGMAC_broadcast_enable(synopGMACdevice * gmacdev) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacFrameFilter, GmacBroadcast); -} - -/* - * Disable Multicast frames. - * When disabled multicast frame filtering depends on HMC bit. - * @param[in] pointer to synopGMACdevice. - * \return void. - */ -void synopGMAC_multicast_disable(synopGMACdevice * gmacdev) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacFrameFilter, GmacMulticastFilter); -} - -/* - * Disables multicast hash filtering. - * When disabled GMAC performs perfect destination address filtering for multicast frames, it compares - * DA field with the value programmed in DA register. - * @param[in] pointer to synopGMACdevice. - * \return void. - */ -void synopGMAC_multicast_hash_filter_disable(synopGMACdevice * gmacdev) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacFrameFilter, GmacMcastHashFilter); -} - -/* - * Enables promiscous mode. - * When enabled Address filter modules pass all incoming frames regardless of their Destination - * and source addresses. - * @param[in] pointer to synopGMACdevice. - * \return void. - */ -void synopGMAC_promisc_enable(synopGMACdevice * gmacdev) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacFrameFilter, GmacPromiscuousMode); -} - -#if 0 -/* - * Enables unicast hash filtering. - * When enabled GMAC performs the destination address filtering of unicast frames according to the hash table. - * @param[in] pointer to synopGMACdevice. - * \return void. - */ -void synopGMAC_unicast_hash_filter_enable(synopGMACdevice * gmacdev) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacFrameFilter, GmacUcastHashFilter); -} -#endif - -/* - * Disables multicast hash filtering. - * When disabled GMAC performs perfect destination address filtering for unicast frames, it compares - * DA field with the value programmed in DA register. - * @param[in] pointer to synopGMACdevice. - * \return void. - */ -void synopGMAC_unicast_hash_filter_disable(synopGMACdevice * gmacdev) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacFrameFilter, GmacUcastHashFilter); -} - -#if 0 - -/*Flow control configuration functions*/ - -/* - * Enables detection of pause frames with stations unicast address. - * When enabled GMAC detects the pause frames with stations unicast address in addition to the - * detection of pause frames with unique multicast address. - * @param[in] pointer to synopGMACdevice. - * \return void. - */ -void synopGMAC_unicast_pause_frame_detect_enable(synopGMACdevice * gmacdev) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacFlowControl, GmacUnicastPauseFrame); -} - -#endif - -/* - * Disables detection of pause frames with stations unicast address. - * When disabled GMAC only detects with the unique multicast address (802.3x). - * @param[in] pointer to synopGMACdevice. - * \return void. - */ -void synopGMAC_unicast_pause_frame_detect_disable(synopGMACdevice * gmacdev) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacFlowControl, GmacUnicastPauseFrame); -} - -/* - * Rx flow control enable. - * When Enabled GMAC will decode the rx pause frame and disable the tx for a specified time. - * @param[in] pointer to synopGMACdevice. - * \return void. - */ -void synopGMAC_rx_flow_control_enable(synopGMACdevice * gmacdev) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacFlowControl, GmacRxFlowControl); -} - - -/* - * Rx flow control disable. - * When disabled GMAC will not decode pause frame. - * @param[in] pointer to synopGMACdevice. - * \return void. - */ -void synopGMAC_rx_flow_control_disable(synopGMACdevice * gmacdev) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacFlowControl, GmacRxFlowControl); -} - -/* - * Tx flow control enable. - * When Enabled - * - In full duplex GMAC enables flow control operation to transmit pause frames. - * - In Half duplex GMAC enables the back pressure operation - * @param[in] pointer to synopGMACdevice. - * \return void. - */ -void synopGMAC_tx_flow_control_enable(synopGMACdevice * gmacdev) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacFlowControl, GmacTxFlowControl); -} - -/* - * Tx flow control disable. - * When Disabled - * - In full duplex GMAC will not transmit any pause frames. - * - In Half duplex GMAC disables the back pressure feature. - * @param[in] pointer to synopGMACdevice. - * \return void. - */ -void synopGMAC_tx_flow_control_disable(synopGMACdevice * gmacdev) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacFlowControl, GmacTxFlowControl); -} - -/* - * Initiate Flowcontrol operation. - * When Set - * - In full duplex GMAC initiates pause control frame. - * - In Half duplex GMAC initiates back pressure function. - * @param[in] pointer to synopGMACdevice. - * \return void. - */ -void synopGMAC_tx_activate_flow_control(synopGMACdevice * gmacdev) -{ - //In case of full duplex check for this bit to b'0. if it is read as b'1 indicates that - //control frame transmission is in progress. - if(gmacdev->Speed == FULLDUPLEX){ - if(!synopGMACCheckBits((u32 *)gmacdev->MacBase, GmacFlowControl, GmacFlowControlBackPressure)) - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacFlowControl, GmacFlowControlBackPressure); - } else{ //if half duplex mode - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacFlowControl, GmacFlowControlBackPressure); - } -} - -/* - * stops Flowcontrol operation. - * @param[in] pointer to synopGMACdevice. - * \return void. - */ -void synopGMAC_tx_deactivate_flow_control(synopGMACdevice * gmacdev) -{ - //In full duplex this bit is automatically cleared after transmitting a pause control frame. - if(gmacdev->Speed == HALFDUPLEX){ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacFlowControl, GmacFlowControlBackPressure); - } -} - -/* - * This enables the pause frame generation after programming the appropriate registers. - * Teh Ubicom design has only 4K FIFO. The activation is set at (full -) 2k and deactivation - * is set at (full -) 3k. These may have to tweaked if found any issues - * @param[in] pointer to synopGMACdevice. - * \return void. - */ -void synopGMAC_pause_control(synopGMACdevice *gmacdev) -{ - u32 omr_reg; - u32 mac_flow_control_reg; - omr_reg = synopGMACReadReg((u32 *)gmacdev->DmaBase, DmaControl); - omr_reg |= DmaRxFlowCtrlAct3K | DmaRxFlowCtrlDeact4K |DmaEnHwFlowCtrl; - synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaControl, omr_reg); - - mac_flow_control_reg = synopGMACReadReg((u32 *)gmacdev->MacBase, GmacFlowControl); - mac_flow_control_reg |= GmacRxFlowControl | GmacTxFlowControl | 0xFFFF0000; - synopGMACWriteReg((u32 *)gmacdev->MacBase, GmacFlowControl, mac_flow_control_reg); -} - -/* - * Example mac initialization sequence. - * This function calls the initialization routines to initialize the GMAC register. - * One can change the functions invoked here to have different configuration as per the requirement - * @param[in] pointer to synopGMACdevice. - * \return Returns 0 on success. - */ -s32 synopGMAC_mac_init(synopGMACdevice * gmacdev) -{ - u32 PHYreg; - - synopGMAC_wd_enable(gmacdev); - synopGMAC_jab_enable(gmacdev); - synopGMAC_frame_burst_enable(gmacdev); - synopGMAC_jumbo_frame_disable(gmacdev); - synopGMAC_loopback_off(gmacdev); - gmacdev->Speed = ipq806x_get_link_speed(gmacdev->phyid); - gmacdev->DuplexMode = ipq806x_get_duplex(gmacdev->phyid); - - if (gmacdev->Speed == SPEED1000) { - synopGMAC_select_gmii(gmacdev); - } else { - synopGMAC_select_mii(gmacdev); - } - - if (gmacdev->DuplexMode == FULLDUPLEX) { - synopGMAC_set_full_duplex(gmacdev); - synopGMAC_rx_own_enable(gmacdev); - synopGMAC_retry_disable(gmacdev); - } else { - synopGMAC_set_half_duplex(gmacdev); - synopGMAC_rx_own_disable(gmacdev); - synopGMAC_retry_enable(gmacdev); - } - - synopGMAC_pad_crc_strip_disable(gmacdev); - synopGMAC_back_off_limit(gmacdev, GmacBackoffLimit0); - synopGMAC_deferral_check_disable(gmacdev); - synopGMAC_tx_enable(gmacdev); - synopGMAC_rx_enable(gmacdev); - - /*Frame Filter Configuration*/ - synopGMAC_frame_filter_enable(gmacdev); - synopGMAC_set_pass_control(gmacdev, GmacPassControl0); - synopGMAC_broadcast_enable(gmacdev); - synopGMAC_src_addr_filter_disable(gmacdev); - synopGMAC_multicast_disable(gmacdev); - synopGMAC_dst_addr_filter_normal(gmacdev); - synopGMAC_multicast_hash_filter_disable(gmacdev); - synopGMAC_promisc_enable(gmacdev); - synopGMAC_unicast_hash_filter_disable(gmacdev); - - /*Flow Control Configuration*/ - synopGMAC_unicast_pause_frame_detect_disable(gmacdev); - if (gmacdev->DuplexMode == FULLDUPLEX) { - synopGMAC_rx_flow_control_disable(gmacdev); - synopGMAC_tx_flow_control_disable(gmacdev); - } else { - synopGMAC_rx_flow_control_disable(gmacdev); - synopGMAC_tx_flow_control_disable(gmacdev); - - /*To set PHY register to enable CRS on Transmit*/ - synopGMACWriteReg((u32 *)gmacdev->MacBase, GmacGmiiAddr, GmiiBusy | 0x00000408); - PHYreg = synopGMACReadReg((u32 *)gmacdev->MacBase, GmacGmiiData); - synopGMACWriteReg((u32 *)gmacdev->MacBase, GmacGmiiData, PHYreg | 0x00000800); - synopGMACWriteReg((u32 *)gmacdev->MacBase, GmacGmiiAddr, GmiiBusy | 0x0000040a); - } - - synopGMACWriteReg((u32 *)gmacdev->MacBase, GmacConfig, \ - GmacFrameBurstEnable | GmacJumboFrameEnable | GmacSelectMii \ - | GmacFullDuplex | GmacTxEnable | GmacRxEnable); - synopGMACWriteReg((u32 *)gmacdev->MacBase, GmacFrameFilter, \ - GmacFilterOff | GmacPromiscuousModeOn); - - return 0; -} - -/* - * Checks and initialze phy. - * This function checks whether the phy initialization is complete. - * @param[in] pointer to synopGMACdevice. - * \return 0 if success else returns the error number. - */ -s32 synopGMAC_check_phy_init (synopGMACdevice * gmacdev) -{ - u16 data; - s32 status = -ESYNOPGMACNOERR; - s32 loop_count; - - loop_count = DEFAULT_LOOP_VARIABLE; - while (loop_count-- > 0) - { - status = synopGMAC_read_phy_reg((u32 *)gmacdev->MacBase, gmacdev->PhyBase, - PHY_STATUS_REG, &data); - if(status) - return status; - - if ((data & Mii_AutoNegCmplt) != 0) { - TR("Autonegotiation Complete\n"); - break; - } - } - - status = synopGMAC_read_phy_reg((u32 *)gmacdev->MacBase, gmacdev->PhyBase, - PHY_SPECIFIC_STATUS_REG, &data); - if(status) - return status; - - if((data & Mii_phy_status_link_up) == 0){ - TR("No Link\n"); - gmacdev->LinkState = LINKDOWN; - return -ESYNOPGMACPHYERR; - } - else{ - gmacdev->LinkState = LINKUP; - TR("Link UP\n"); - } - - status = synopGMAC_read_phy_reg((u32 *)gmacdev->MacBase, gmacdev->PhyBase, - PHY_SPECIFIC_STATUS_REG, &data); - if(status) - return status; - - gmacdev->DuplexMode = (data & Mii_phy_status_full_duplex) ? FULLDUPLEX: HALFDUPLEX ; - TR("Link is up in %s mode\n",(gmacdev->DuplexMode == FULLDUPLEX) ? "FULL DUPLEX": "HALF DUPLEX"); - - /*if not set to Master configuration in case of Half duplex mode set it manually as Master*/ - if(gmacdev->DuplexMode == HALFDUPLEX){ - status = synopGMAC_read_phy_reg((u32 *)gmacdev->MacBase, gmacdev->PhyBase, - PHY_CONTROL_REG, &data); - if(status) - return status; - - status = synopGMAC_write_phy_reg((u32 *)gmacdev->MacBase, gmacdev->PhyBase, - PHY_CONTROL_REG, data | Mii_Manual_Master_Config ); - if(status) - return status; - } - - status = synopGMAC_read_phy_reg((u32 *)gmacdev->MacBase,gmacdev->PhyBase,PHY_SPECIFIC_STATUS_REG, &data); - if(status) - return status; - if (data & Mii_phy_status_speed_1000) - gmacdev->Speed = SPEED1000; - else if(data & Mii_phy_status_speed_100) - gmacdev->Speed = SPEED100; - else - gmacdev->Speed = SPEED10; - - if (gmacdev->Speed == SPEED1000) - TR("Link is with 1000M Speed \n"); - if (gmacdev->Speed == SPEED100) - TR("Link is with 100M Speed \n"); - if (gmacdev->Speed == SPEED10) - TR("Link is with 10M Speed \n"); - - return -ESYNOPGMACNOERR; -} - -s32 synopGMAC_check_link(synopGMACdevice *gmacdev) -{ - uint16_t lnkstat ; - - lnkstat = mii_read_reg(gmacdev, gmacdev->PhyBase, MII_BMSR); - - if (lnkstat & 0x4) - { - printf("\r\n LINKUP LINKstat %x ***********\r\n ", lnkstat); - return LINKUP; - } - else - { - printf("\r\n**LINKDOWN** LINKstat %x *********\r\n ", lnkstat); - return LINKDOWN; - } -} - -/* - * Sets the Mac address in to GMAC register. - * This function sets the MAC address to the MAC register in question. - * @param[in] pointer to synopGMACdevice to populate mac dma and phy addresses. - * @param[in] Register offset for Mac address high - * @param[in] Register offset for Mac address low - * @param[in] buffer containing mac address to be programmed. - * \return 0 upon success. Error code upon failure. - */ -s32 synopGMAC_set_mac_addr(synopGMACdevice *gmacdev, u32 MacHigh, u32 MacLow, u8 *MacAddr) -{ - u32 data; - - data = (MacAddr[5] << 8) | MacAddr[4]; - synopGMACWriteReg((u32 *)gmacdev->MacBase,MacHigh,data); - data = (MacAddr[3] << 24) | (MacAddr[2] << 16) | (MacAddr[1] << 8) | MacAddr[0] ; - synopGMACWriteReg((u32 *)gmacdev->MacBase, MacLow, data); - return 0; -} - -/* - * Get the Mac address in to the address specified. - * The mac register contents are read and written to buffer passed. - * @param[in] pointer to synopGMACdevice to populate mac dma and phy addresses. - * @param[in] Register offset for Mac address high - * @param[in] Register offset for Mac address low - * @param[out] buffer containing the device mac address. - * \return 0 upon success. Error code upon failure. - */ -s32 synopGMAC_get_mac_addr(synopGMACdevice *gmacdev, u32 MacHigh, u32 MacLow, u8 *MacAddr) -{ - u32 data; - - data = synopGMACReadReg((u32 *)gmacdev->MacBase, MacHigh); - MacAddr[5] = (data >> 8) & 0xff; - MacAddr[4] = (data) & 0xff; - - data = synopGMACReadReg((u32 *)gmacdev->MacBase, MacLow); - MacAddr[3] = (data >> 24) & 0xff; - MacAddr[2] = (data >> 16) & 0xff; - MacAddr[1] = (data >> 8 ) & 0xff; - MacAddr[0] = (data ) & 0xff; - - return 0; -} - -/* - * Attaches the synopGMAC device structure to the hardware. - * Device structure is populated with MAC/DMA and PHY base addresses. - * @param[in] pointer to synopGMACdevice to populate mac dma and phy addresses. - * @param[in] GMAC IP mac base address. - * @param[in] GMAC IP dma base address. - * @param[in] GMAC IP phy base address. - * \return 0 upon success. Error code upon failure. - * \note This is important function. No kernel api provided by Synopsys - */ - -s32 synopGMAC_attach (synopGMACdevice * gmacdev, u32 regBase) -{ - /*Make sure the Device data strucure is cleared before we proceed further*/ - memset((void *)gmacdev, 0, sizeof(synopGMACdevice)); - /*Populate the mac and dma base addresses*/ - gmacdev->NbrBase = regBase; - - gmacdev->MacBase = regBase + MACBASE; - gmacdev->DmaBase = regBase + DMABASE; - - if (gboard_param->machid == MACH_TYPE_IPQ806X_RUMI3) - gmacdev->PhyBase = GMAC0_MDIO_ID; - - return 0; -} - - -s32 synopGMAC_init_tx_rx_desc_queue(synopGMACdevice *gmacdev) -{ - s32 i; - for (i =0; i < gmacdev -> TxDescCount; i++) { - synopGMAC_tx_desc_init_ring(gmacdev->TxDesc + i, i == gmacdev->TxDescCount-1); - } - - for (i =0; i < gmacdev -> RxDescCount; i++) { - synopGMAC_rx_desc_init_ring(gmacdev->RxDesc + i, i == gmacdev->RxDescCount-1); - } - - gmacdev->TxNext = 0; - gmacdev->TxBusy = 0; - gmacdev->RxNext = 0; - gmacdev->RxBusy = 0; - - return -ESYNOPGMACNOERR; -} - -/* - * Programs the DmaRxBaseAddress with the Rx descriptor base address. - * Rx Descriptor's base address is available in the gmacdev structure. This function progrms the - * Dma Rx Base address with the starting address of the descriptor ring or chain. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_init_rx_desc_base(synopGMACdevice *gmacdev) -{ - synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaRxBaseAddr, (u32)gmacdev->RxDescDma); -} - -/* - * Programs the DmaTxBaseAddress with the Tx descriptor base address. - * Tx Descriptor's base address is available in the gmacdev structure. This function progrms the - * Dma Tx Base address with the starting address of the descriptor ring or chain. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_init_tx_desc_base(synopGMACdevice *gmacdev) -{ - synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaTxBaseAddr, (u32)gmacdev->TxDescDma); -} - -/* - * Makes the Dma as owner for this descriptor. - * This function sets the own bit of status field of the DMA descriptor, - * indicating the DMA is the owner for this descriptor. - * @param[in] pointer to DmaDesc structure. - * \return returns void. - */ -void synopGMAC_set_owner_dma(DmaDesc *desc) -{ - desc->status |= DescOwnByDma; -} - -/* - * set tx descriptor to indicate SOF. - * This Descriptor contains the start of ethernet frame. - * @param[in] pointer to DmaDesc structure. - * \return returns void. - */ -void synopGMAC_set_desc_sof(DmaDesc *desc) -{ - #ifdef ENH_DESC - desc->status |= DescTxFirst;//ENH_DESC - #else - desc->length |= DescTxFirst; - #endif -} - -/* - * set tx descriptor to indicate EOF. - * This descriptor contains the End of ethernet frame. - * @param[in] pointer to DmaDesc structure. - * \return returns void. - */ -void synopGMAC_set_desc_eof(DmaDesc *desc) -{ - #ifdef ENH_DESC - desc->status |= DescTxLast;//ENH_DESC - #else - desc->length |= DescTxLast; - #endif -} - -/* - * checks whether this descriptor contains start of frame. - * This function is to check whether the descriptor's data buffer - * contains a fresh ethernet frame? - * @param[in] pointer to DmaDesc structure. - * \return returns true if SOF in current descriptor, else returns fail. - */ -bool synopGMAC_is_sof_in_rx_desc(DmaDesc *desc) -{ - return ((desc->status & DescRxFirst) == DescRxFirst); -} - -/* - * checks whether this descriptor contains end of frame. - * This function is to check whether the descriptor's data buffer - * contains end of ethernet frame? - * @param[in] pointer to DmaDesc structure. - * \return returns true if SOF in current descriptor, else returns fail. - */ -bool synopGMAC_is_eof_in_rx_desc(DmaDesc *desc) -{ - return ((desc->status & DescRxLast) == DescRxLast); -} - -/* - * checks whether destination address filter failed in the rx frame. - * @param[in] pointer to DmaDesc structure. - * \return returns true if Failed, false if not. - */ -bool synopGMAC_is_da_filter_failed(DmaDesc *desc) -{ - return ((desc->status & DescDAFilterFail) == DescDAFilterFail); -} - -/* - * checks whether source address filter failed in the rx frame. - * @param[in] pointer to DmaDesc structure. - * \return returns true if Failed, false if not. - */ -bool synopGMAC_is_sa_filter_failed(DmaDesc *desc) -{ - return ((desc->status & DescSAFilterFail) == DescSAFilterFail); -} - -/* - * Checks whether the tx is aborted due to collisions. - * @param[in] pointer to DmaDesc structure. - * \return returns true if collisions, else returns false. - */ -bool synopGMAC_is_tx_aborted(u32 status) -{ - return (((status & DescTxLateCollision) == DescTxLateCollision) | ((status & DescTxExcCollisions) == DescTxExcCollisions)); - -} - -/* - * Checks whether the tx carrier error. - * @param[in] pointer to DmaDesc structure. - * \return returns true if carrier error occured, else returns falser. - */ -bool synopGMAC_is_tx_carrier_error(u32 status) -{ - return (((status & DescTxLostCarrier) == DescTxLostCarrier) | ((status & DescTxNoCarrier) == DescTxNoCarrier)); -} - -/* - * Check for damaged frame due to overflow or collision. - * Retruns true if rx frame was damaged due to buffer overflow in MTL or late collision in half duplex mode. - * @param[in] pointer to DmaDesc structure. - * \return returns true if error else returns false. - */ -bool synopGMAC_is_rx_frame_damaged(u32 status) -{ -//bool synopGMAC_dma_rx_collisions(u32 status) - return (((status & DescRxDamaged) == DescRxDamaged) | ((status & DescRxCollision) == DescRxCollision)); -} - -/* - * Check for damaged frame due to collision. - * Retruns true if rx frame was damaged due to late collision in half duplex mode. - * @param[in] pointer to DmaDesc structure. - * \return returns true if error else returns false. - */ -bool synopGMAC_is_rx_frame_collision(u32 status) -{ -//bool synopGMAC_dma_rx_collisions(u32 status) - return ((status & DescRxCollision) == DescRxCollision); -} - -/* - * Check for receive CRC error. - * Retruns true if rx frame CRC error occured. - * @param[in] pointer to DmaDesc structure. - * \return returns true if error else returns false. - */ -bool synopGMAC_is_rx_crc(u32 status) -{ -//u32 synopGMAC_dma_rx_crc(u32 status) - return ((status & DescRxCrc) == DescRxCrc); -} - -/* - * Indicates rx frame has non integer multiple of bytes. (odd nibbles). - * Retruns true if dribbling error in rx frame. - * @param[in] pointer to DmaDesc structure. - * \return returns true if error else returns false. - */ -bool synopGMAC_is_frame_dribbling_errors(u32 status) -{ - return ((status & DescRxDribbling) == DescRxDribbling); -} - -/* - * Indicates error in rx frame length. - * Retruns true if received frame length doesnot match with the length field - * @param[in] pointer to DmaDesc structure. - * \return returns true if error else returns false. - */ -bool synopGMAC_is_rx_frame_length_errors(u32 status) -{ - return((status & DescRxLengthError) == DescRxLengthError); -} - -/* - * Driver Api to get the descriptor field information. - * This returns the status, dma-able address of buffer1, the length of buffer1, virtual address of buffer1 - * dma-able address of buffer2, length of buffer2, virtural adddress of buffer2. - * @param[in] pointer to DmaDesc structure. - * @param[out] pointer to status field fo descriptor. - * @param[out] dma-able address of buffer1. - * @param[out] length of buffer1. - * @param[out] virtual address of buffer1. - * @param[out] dma-able address of buffer2. - * @param[out] length of buffer2. - * @param[out] virtual address of buffer2. - * \return returns void. - */ -void synopGMAC_get_desc_data(DmaDesc * desc, u32 * Status, u32 * Buffer1, u32 * Length1, u32 * Data1) -{ - - /* - * The first time, we map the descriptor as DMA_TO_DEVICE. - * Then we only wait for changes from device, so we use DMA_FROM_DEVICE. - */ - - if (Status != 0) - *Status = desc->status; - - if (Buffer1 != 0) - *Buffer1 = desc->buffer1; - if (Length1 != 0) - *Length1 = (desc->length & DescSize1Mask) >> DescSize1Shift; - if (Data1 != 0) - *Data1 = desc->data1; -} - -/* - * Enable the DMA Reception. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_enable_dma_rx(synopGMACdevice * gmacdev) -{ - u32 data; - data = synopGMACReadReg((u32 *)gmacdev->DmaBase, DmaControl); - data |= DmaRxStart; - synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaControl ,data); -} - -/* - * Enable the DMA Transmission. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_enable_dma_tx(synopGMACdevice * gmacdev) -{ - u32 data; - data = synopGMACReadReg((u32 *)gmacdev->DmaBase, DmaControl); - data |= DmaTxStart; - synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaControl ,data); -} - -/* - * Take ownership of this Descriptor. - * The function is same for both the ring mode and the chain mode DMA structures. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_take_desc_ownership(DmaDesc * desc) -{ - if (desc) { - desc->status &= ~DescOwnByDma; //Clear the DMA own bit - } -} - -/* - * Take ownership of all the rx Descriptors. - * This function is called when there is fatal error in DMA transmission. - * When called it takes the ownership of all the rx descriptor in rx descriptor pool/queue from DMA. - * The function is same for both the ring mode and the chain mode DMA structures. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - * \note Make sure to disable the transmission before calling this function, otherwise may result in racing situation. - */ -void synopGMAC_take_desc_ownership_rx(synopGMACdevice * gmacdev) -{ - s32 i; - DmaDesc *desc; - desc = gmacdev->RxDesc; - for (i = 0; i < gmacdev->RxDescCount; i++) { - synopGMAC_take_desc_ownership(desc + i); - } -} - -/* - * Take ownership of all the rx Descriptors. - * This function is called when there is fatal error in DMA transmission. - * When called it takes the ownership of all the tx descriptor in tx descriptor pool/queue from DMA. - * The function is same for both the ring mode and the chain mode DMA structures. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - * \note Make sure to disable the transmission before calling this function, otherwise may result in racing situation. - */ -void synopGMAC_take_desc_ownership_tx(synopGMACdevice * gmacdev) -{ - s32 i; - DmaDesc *desc; - desc = gmacdev->TxDesc; - for (i = 0; i < gmacdev->TxDescCount; i++) { - synopGMAC_take_desc_ownership(desc + i); - } -} - - -/* - * Enables the ip checksum offloading in receive path. - * When set GMAC calculates 16 bit 1's complement of all received ethernet frame payload. - * It also checks IPv4 Header checksum is correct. GMAC core appends the 16 bit checksum calculated - * for payload of IP datagram and appends it to Ethernet frame transferred to the application. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_enable_rx_chksum_offload(synopGMACdevice *gmacdev) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacConfig, GmacRxIpcOffload); -} - - -/* - * Disable the DMA for Transmission. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ - -void synopGMAC_disable_dma_tx(synopGMACdevice * gmacdev) -{ - u32 data; - - data = synopGMACReadReg((u32 *)gmacdev->DmaBase, DmaControl); - data &= (~DmaTxStart); - synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaControl ,data); -} - -/* - * Disable the DMA for Reception. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_disable_dma_rx(synopGMACdevice * gmacdev) -{ - u32 data; - - data = synopGMACReadReg((u32 *)gmacdev->DmaBase, DmaControl); - data &= (~DmaRxStart); - synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaControl ,data); -} - -/* - * Checks whether the packet received is a magic packet?. - * @param[in] pointer to synopGMACdevice. - * \return returns True if magic packet received else returns false. - */ -bool synopGMAC_is_magic_packet_received(synopGMACdevice *gmacdev) -{ - u32 data; - data = synopGMACReadReg((u32 *)gmacdev->MacBase, GmacPmtCtrlStatus); - return ((data & GmacPmtMagicPktReceived) == GmacPmtMagicPktReceived); -} - -/* - * Checks whether the packet received is a wakeup frame?. - * @param[in] pointer to synopGMACdevice. - * \return returns true if wakeup frame received else returns false. - */ -bool synopGMAC_is_wakeup_frame_received(synopGMACdevice *gmacdev) -{ - u32 data; - data = synopGMACReadReg((u32 *)gmacdev->MacBase, GmacPmtCtrlStatus); - return ((data & GmacPmtWakeupFrameReceived) == GmacPmtWakeupFrameReceived); -} - -/* - * Disables the assertion of PMT interrupt. - * This disables the assertion of PMT interrupt due to Magic Pkt or Wakeup frame - * reception. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_pmt_int_disable(synopGMACdevice *gmacdev) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacInterruptMask, GmacPmtIntMask); -} - -/* - * Instruct the DMA to drop the packets fails tcp ip checksum. - * This is to instruct the receive DMA engine to drop the recevied packet if they - * fails the tcp/ip checksum in hardware. Valid only when full checksum offloading is enabled(type-2). - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_rx_tcpip_chksum_drop_enable(synopGMACdevice *gmacdev) -{ - synopGMACClearBits((u32 *)gmacdev->DmaBase, DmaControl, DmaDisableDropTcpCs); -} - - -/* - * Disable the MMC Rx interrupt. - * The MMC rx interrupts are masked out as per the mask specified. - * @param[in] pointer to synopGMACdevice. - * @param[in] rx interrupt bit mask for which interrupts needs to be disabled. - * \return returns void. - */ -void synopGMAC_disable_mmc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacMmcIntrMaskRx, mask); -} - -/* - * Disable the MMC ipc rx checksum offload interrupt. - * The MMC ipc rx checksum offload interrupts are masked out as per the mask specified. - * @param[in] pointer to synopGMACdevice. - * @param[in] rx interrupt bit mask for which interrupts needs to be disabled. - * \return returns void. - */ -void synopGMAC_disable_mmc_ipc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacMmcRxIpcIntrMask, mask); -} - - -/* - * Disable the MMC Tx interrupt. - * The MMC tx interrupts are masked out as per the mask specified. - * @param[in] pointer to synopGMACdevice. - * @param[in] tx interrupt bit mask for which interrupts needs to be disabled. - * \return returns void. - */ -void synopGMAC_disable_mmc_tx_interrupt(synopGMACdevice *gmacdev, u32 mask) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacMmcIntrMaskTx, mask); -} - - - - -#if 0 - -/*******************PMT APIs***************************************/ - -/* - * Enables the assertion of PMT interrupt. - * This enables the assertion of PMT interrupt due to Magic Pkt or Wakeup frame - * reception. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_pmt_int_enable(synopGMACdevice *gmacdev) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacInterruptMask, GmacPmtIntMask); -} - -/* - * Disables the assertion of PMT interrupt. - * This disables the assertion of PMT interrupt due to Magic Pkt or Wakeup frame - * reception. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_pmt_int_disable(synopGMACdevice *gmacdev) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacInterruptMask, GmacPmtIntMask); -} - -/* - * Enables the power down mode of GMAC. - * This function puts the Gmac in power down mode. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_power_down_enable(synopGMACdevice *gmacdev) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacPmtCtrlStatus, GmacPmtPowerDown); -} - -/* - * Disables the powerd down setting of GMAC. - * If the driver wants to bring up the GMAC from powerdown mode, even though the magic packet or the - * wake up frames received from the network, this function should be called. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_power_down_disable(synopGMACdevice *gmacdev) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacPmtCtrlStatus, GmacPmtPowerDown); -} - -/* - * Enables GMAC to look for Magic packet. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_magic_packet_enable(synopGMACdevice *gmacdev) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacPmtCtrlStatus, GmacPmtMagicPktEnable); -} - -/* - * Enables GMAC to look for wake up frame. - * Wake up frame is defined by the user. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_wakeup_frame_enable(synopGMACdevice *gmacdev) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacPmtCtrlStatus, GmacPmtWakeupFrameEnable); -} - -/* - * Enables wake-up frame filter to handle unicast packets. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_pmt_unicast_enable(synopGMACdevice *gmacdev) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase,GmacPmtCtrlStatus,GmacPmtGlobalUnicast); -} - -/* - * Checks whether the packet received is a magic packet?. - * @param[in] pointer to synopGMACdevice. - * \return returns True if magic packet received else returns false. - */ -bool synopGMAC_is_magic_packet_received(synopGMACdevice *gmacdev) -{ - u32 data; - data = synopGMACReadReg((u32 *)gmacdev->MacBase, GmacPmtCtrlStatus); - return ((data & GmacPmtMagicPktReceived) == GmacPmtMagicPktReceived); -} - -/* - * Checks whether the packet received is a wakeup frame?. - * @param[in] pointer to synopGMACdevice. - * \return returns true if wakeup frame received else returns false. - */ -bool synopGMAC_is_wakeup_frame_received(synopGMACdevice *gmacdev) -{ - u32 data; - data = synopGMACReadReg((u32 *)gmacdev->MacBase, GmacPmtCtrlStatus); - return ((data & GmacPmtWakeupFrameReceived) == GmacPmtWakeupFrameReceived); -} - -/* - * Populates the remote wakeup frame registers. - * Consecutive 8 writes to GmacWakeupAddr writes the wakeup frame filter registers. - * Before commensing a new write, frame filter pointer is reset to 0x0000. - * A small delay is introduced to allow frame filter pointer reset operation. - * @param[in] pointer to synopGMACdevice. - * @param[in] pointer to frame filter contents array. - * \return returns void. - */ -void synopGMAC_write_wakeup_frame_register(synopGMACdevice *gmacdev, u32 * filter_contents) -{ - s32 i; - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacPmtCtrlStatus, GmacPmtFrmFilterPtrReset); - __udelay(10); - for (i = 0; i < WAKEUP_REG_LENGTH; i++) - synopGMACWriteReg((u32 *)gmacdev->MacBase, GmacWakeupAddr, *(filter_contents + i)); -} - -/*******************PMT APIs***************************************/ - -/*******************MMC APIs***************************************/ - -/* - * Freezes the MMC counters. - * This function call freezes the MMC counters. None of the MMC counters are updated - * due to any tx or rx frames until synopGMAC_mmc_counters_resume is called. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_mmc_counters_stop(synopGMACdevice *gmacdev) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacMmcCntrl, GmacMmcCounterFreeze); -} - -/* - * Resumes the MMC counter updation. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_mmc_counters_resume(synopGMACdevice *gmacdev) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacMmcCntrl, GmacMmcCounterFreeze); -} - -/* - * Configures the MMC in Self clearing mode. - * Programs MMC interface so that counters are cleared when the counters are read. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_mmc_counters_set_selfclear(synopGMACdevice *gmacdev) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacMmcCntrl, GmacMmcCounterResetOnRead); -} - -/* - * Configures the MMC in non-Self clearing mode. - * Programs MMC interface so that counters are cleared when the counters are read. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_mmc_counters_reset_selfclear(synopGMACdevice *gmacdev) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacMmcCntrl, GmacMmcCounterResetOnRead); -} - -/* - * Configures the MMC to stop rollover. - * Programs MMC interface so that counters will not rollover after reaching maximum value. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_mmc_counters_disable_rollover(synopGMACdevice *gmacdev) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacMmcCntrl, GmacMmcCounterStopRollover); -} - -/* - * Configures the MMC to rollover. - * Programs MMC interface so that counters will rollover after reaching maximum value. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_mmc_counters_enable_rollover(synopGMACdevice *gmacdev) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacMmcCntrl, GmacMmcCounterStopRollover); -} - -/* - * Read the MMC Counter. - * @param[in] pointer to synopGMACdevice. - * @param[in] the counter to be read. - * \return returns the read count value. - */ -u32 synopGMAC_read_mmc_counter(synopGMACdevice *gmacdev, u32 counter) -{ - return( synopGMACReadReg((u32 *)gmacdev->MacBase, counter)); -} - -/* - * Read the MMC Rx interrupt status. - * @param[in] pointer to synopGMACdevice. - * \return returns the Rx interrupt status. - */ -u32 synopGMAC_read_mmc_rx_int_status(synopGMACdevice *gmacdev) -{ - return( synopGMACReadReg((u32 *)gmacdev->MacBase, GmacMmcIntrRx)); -} - -/* - * Read the MMC Tx interrupt status. - * @param[in] pointer to synopGMACdevice. - * \return returns the Tx interrupt status. - */ -u32 synopGMAC_read_mmc_tx_int_status(synopGMACdevice *gmacdev) -{ - return( synopGMACReadReg((u32 *)gmacdev->MacBase, GmacMmcIntrTx)); -} - -/* - * Disable the MMC Tx interrupt. - * The MMC tx interrupts are masked out as per the mask specified. - * @param[in] pointer to synopGMACdevice. - * @param[in] tx interrupt bit mask for which interrupts needs to be disabled. - * \return returns void. - */ -void synopGMAC_disable_mmc_tx_interrupt(synopGMACdevice *gmacdev, u32 mask) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacMmcIntrMaskTx, mask); -} - -/* - * Enable the MMC Tx interrupt. - * The MMC tx interrupts are enabled as per the mask specified. - * @param[in] pointer to synopGMACdevice. - * @param[in] tx interrupt bit mask for which interrupts needs to be enabled. - * \return returns void. - */ -void synopGMAC_enable_mmc_tx_interrupt(synopGMACdevice *gmacdev, u32 mask) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacMmcIntrMaskTx, mask); -} - -/* - * Disable the MMC Rx interrupt. - * The MMC rx interrupts are masked out as per the mask specified. - * @param[in] pointer to synopGMACdevice. - * @param[in] rx interrupt bit mask for which interrupts needs to be disabled. - * \return returns void. - */ -void synopGMAC_disable_mmc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacMmcIntrMaskRx, mask); -} - -/* - * Enable the MMC Rx interrupt. - * The MMC rx interrupts are enabled as per the mask specified. - * @param[in] pointer to synopGMACdevice. - * @param[in] rx interrupt bit mask for which interrupts needs to be enabled. - * \return returns void. - */ -void synopGMAC_enable_mmc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacMmcIntrMaskRx, mask); -} - -/* - * Disable the MMC ipc rx checksum offload interrupt. - * The MMC ipc rx checksum offload interrupts are masked out as per the mask specified. - * @param[in] pointer to synopGMACdevice. - * @param[in] rx interrupt bit mask for which interrupts needs to be disabled. - * \return returns void. - */ -void synopGMAC_disable_mmc_ipc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacMmcRxIpcIntrMask, mask); -} - -/* - * Enable the MMC ipc rx checksum offload interrupt. - * The MMC ipc rx checksum offload interrupts are enabled as per the mask specified. - * @param[in] pointer to synopGMACdevice. - * @param[in] rx interrupt bit mask for which interrupts needs to be enabled. - * \return returns void. - */ -void synopGMAC_enable_mmc_ipc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacMmcRxIpcIntrMask, mask); -} - -/*******************MMC APIs***************************************/ - -/*******************Ip checksum offloading APIs***************************************/ - -/* - * Enables the ip checksum offloading in receive path. - * When set GMAC calculates 16 bit 1's complement of all received ethernet frame payload. - * It also checks IPv4 Header checksum is correct. GMAC core appends the 16 bit checksum calculated - * for payload of IP datagram and appends it to Ethernet frame transferred to the application. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_enable_rx_chksum_offload(synopGMACdevice *gmacdev) -{ - synopGMACSetBits((u32 *)gmacdev->MacBase, GmacConfig, GmacRxIpcOffload); -} - -/* - * Disable the ip checksum offloading in receive path. - * Ip checksum offloading is disabled in the receive path. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_disable_rx_Ipchecksum_offload(synopGMACdevice *gmacdev) -{ - synopGMACClearBits((u32 *)gmacdev->MacBase, GmacConfig, GmacRxIpcOffload); -} - -/* - * Instruct the DMA to drop the packets fails tcp ip checksum. - * This is to instruct the receive DMA engine to drop the recevied packet if they - * fails the tcp/ip checksum in hardware. Valid only when full checksum offloading is enabled(type-2). - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_rx_tcpip_chksum_drop_enable(synopGMACdevice *gmacdev) -{ - synopGMACClearBits((u32 *)gmacdev->DmaBase, DmaControl, DmaDisableDropTcpCs); -} - -/* - * Instruct the DMA not to drop the packets even if it fails tcp ip checksum. - * This is to instruct the receive DMA engine to allow the packets even if recevied packet - * fails the tcp/ip checksum in hardware. Valid only when full checksum offloading is enabled(type-2). - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -void synopGMAC_rx_tcpip_chksum_drop_disable(synopGMACdevice *gmacdev) -{ - synopGMACSetBits((u32 *)gmacdev->DmaBase, DmaControl, DmaDisableDropTcpCs); -} - -#endif diff --git a/root/package/utils/sysupgrade-helper/src/drivers/net/nss/synopGMAC_Dev.h b/root/package/utils/sysupgrade-helper/src/drivers/net/nss/synopGMAC_Dev.h deleted file mode 100644 index 7bee279b..00000000 --- a/root/package/utils/sysupgrade-helper/src/drivers/net/nss/synopGMAC_Dev.h +++ /dev/null @@ -1,2240 +0,0 @@ -/* * Copyright (c) 2012 The Linux Foundation. All rights reserved.* */ - -/*\file - * This file defines the function prototypes for the Synopsys GMAC device and the - * Marvell 88E1011/88E1011S integrated 10/100/1000 Gigabit Ethernet Transceiver. - * Since the phy register mapping are standardised, the phy register map and the - * bit definitions remain the same for other phy as well. - * This also defines some of the Ethernet related parmeters. - * \internal - * -----------------------------REVISION HISTORY------------------------------------ - * Synopsys 01/Aug/2007 Created - */ - - -#ifndef SYNOP_GMAC_DEV_H -#define SYNOP_GMAC_DEV_H 1 - -#include "synopGMAC_plat.h" - -#define GMAC_POLL_BUDGET 64 -#include "../../../board/qcom/ipq806x_cdp/ipq806x_cdp.h" -/* - * SynopGMAC can support up to 32 phys - */ -enum GMACPhyBase -{ - PHY0 = 0, // The device can support 32 phys, but we use first phy only - PHY1 = 1, - PHY31 = 31, -}; -/* -#define NSS_GMAC0_MDIO_ID 4 -#define NSS_GMAC1_MDIO_ID 6 -*/ -#define DEFAULT_PHY_BASE PHY0 // We use First Phy -#define MACBASE 0x0000 // The Mac Base address offset is 0x0000 -#define DMABASE 0x1000 // Dma base address starts with an offset 0x1000 - -#define TRANSMIT_DESC_SIZE 32 //Tx Descriptors needed in the Descriptor pool/queue -#define RECEIVE_DESC_SIZE 32 //Rx Descriptors needed in the Descriptor pool/queue - -#define ENH_DESC -#define ENH_DESC_8W -#define IPC_OFFLOAD - -enum dma_data_direction { - DMA_BIDIRECTIONAL = 0, - DMA_TO_DEVICE = 1, - DMA_FROM_DEVICE = 2, -}; - -#define VLAN_ETH_FRAME_LEN 1518 // Max. octets in payload for VLAN frame -#define ETH_ZLEN 60 -#define ETH_HLEN 12 -#define ETH_FCS_LEN 4 -#define VLAN_HLEN 4 -#define NET_IP_ALIGN 2 - -#define ETHERNET_EXTRA (NET_IP_ALIGN + 2 * CACHE_LINE_SIZE) -#define ETH_MAX_FRAME_LEN (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN + ((4 - NET_IP_ALIGN) & 0x3)) -#define ETH_JUMBO_FRAME_LEN 9000 //Jumbo frame payload size - -/* -DMA Descriptor Structure -The structure is common for both receive and transmit descriptors -The descriptor is of 4 words, but our structrue contains 6 words where -last two words are to hold the virtual address of the network buffer pointers -for driver's use -From the GMAC core release 3.50a onwards, the Enhanced Descriptor structure got changed. -The descriptor (both transmit and receive) are of 8 words each rather the 4 words of normal -descriptor structure. -Whenever IEEE 1588 Timestamping is enabled TX/RX DESC6 provides the lower 32 bits of Timestamp value and - TX/RX DESC7 provides the upper 32 bits of Timestamp value -In addition to this whenever extended status bit is set (RX DESC0 bit 0), RX DESC4 contains the extended status information -*/ - -#define DESC_FLUSH_SIZE (((32 + CACHE_LINE_SIZE - 1) / CACHE_LINE_SIZE) * CACHE_LINE_SIZE) - // multiple of cache line. -#ifdef ENH_DESC_8W -typedef struct DmaDescStruct -{ - volatile u32 status; /* Status */ - volatile u32 length; /* Buffer 1 and Buffer 2 length */ - volatile u32 buffer1; /* Network Buffer 1 pointer (Dma-able) */ - volatile u32 data1; /* This holds virtual address of buffer1, not used by DMA */ - /* This data below is used only by driver */ - volatile u32 extstatus; /* Extended status of a Rx Descriptor */ - volatile u32 reserved1; /* Reserved word */ - volatile u32 timestamplow; /* Lower 32 bits of the 64 bit timestamp value */ - volatile u32 timestamphigh; /* Higher 32 bits of the 64 bit timestamp value */ -} DmaDesc; -#else -typedef struct DmaDescStruct -{ - volatile u32 status; /* Status */ - volatile u32 length; /* Buffer 1 and Buffer 2 length */ - volatile u32 buffer1; /* Network Buffer 1 pointer (Dma-able) */ - volatile u32 rsvd_buffer2; /* Network Buffer 2 pointer or next descriptor pointer (chain mode) */ - /* This data below is used only by driver */ - u32 data1; /* This holds virtual address of buffer1, not used by DMA */ - u32 pad2[3]; -} DmaDesc; -#endif - -enum DescMode -{ - RINGMODE = 0x00000001, - CHAINMODE = 0x00000002, -}; - -/* - * synopGMAC device data - */ -typedef struct synopGMACDeviceStruct -{ - u32 NbrBase; /* base address of NBR registers */ - u32 MacBase; /* base address of MAC registers */ - u32 DmaBase; /* base address of DMA registers */ - u32 PhyBase; /* PHY device address on MII interface */ - u32 Version; /* Gmac Revision version */ - - dma_addr_t TxDescDma; /* Dma-able address of first tx descriptor either in ring or chain mode, this is used by the GMAC device */ - dma_addr_t RxDescDma; /* Dma-albe address of first rx descriptor either in ring or chain mode, this is used by the GMAC device */ - DmaDesc *TxDesc; /* start address of TX descriptors ring or chain, this is used by the driver */ - DmaDesc *RxDesc; /* start address of RX descriptors ring or chain, this is used by the driver */ - - volatile u32 BusyTxDesc;/* Number of Tx Descriptors owned by DMA at any given time*/ - volatile u32 BusyRxDesc;/* Number of Rx Descriptors owned by DMA at any given time*/ - - u32 RxDescCount; /* number of rx descriptors in the tx descriptor queue/pool */ - u32 TxDescCount; /* number of tx descriptors in the rx descriptor queue/pool */ - - u32 TxBusy; /* index of the tx descriptor owned by DMA, is obtained by synopGMAC_get_tx_qptr() */ - u32 TxNext; /* index of the tx descriptor next available with driver, given to DMA by synopGMAC_set_tx_qptr() */ - u32 RxBusy; /* index of the rx descriptor owned by DMA, obtained by synopGMAC_get_rx_qptr() */ - u32 RxNext; /* index of the rx descriptor next available with driver, given to DMA by synopGMAC_set_rx_qptr() */ - - DmaDesc * TxBusyDesc; /* Tx Descriptor address corresponding to the index TxBusy */ - DmaDesc * TxNextDesc; /* Tx Descriptor address corresponding to the index TxNext */ - DmaDesc * RxBusyDesc; /* Rx Descriptor address corresponding to the index TxBusy */ - DmaDesc * RxNextDesc; /* Rx Descriptor address corresponding to the index RxNext */ - - /* - * Phy related stuff - */ - u32 ClockDivMdc; /* Clock divider value programmed in the hardware */ - u32 LinkState; /* Link status as reported by the Marvel Phy */ - u32 DuplexMode; /* Duplex mode of the Phy */ - u32 Speed; /* Speed of the Phy */ - u32 LoopBackMode; /* Loopback status of the Phy */ - - struct eth_device *synopGMACnetdev; - - u32 synopGMACMappedAddr; /* GMAC port address */ - u32 GMAC_Power_down; /* indicate to ISR whether the interrupts occured in the process of powering down */ - - u32 macid; - u32 phyid; - u32 phy_mii_type; - u32 state; - -} synopGMACdevice; - -/* - * Below is "88E1011/88E1011S Integrated 10/100/1000 Gigabit Ethernet Transceiver" - * Register and their layouts. This Phy has been used in the Dot Aster GMAC Phy daughter. - * Since the Phy register map is standard, this map hardly changes to a different Ppy - */ -enum MiiRegisters -{ - PHY_CONTROL_REG = 0x0000, /*Control Register*/ - PHY_STATUS_REG = 0x0001, /*Status Register */ - PHY_ID_HI_REG = 0x0002, /*PHY Identifier High Register*/ - PHY_ID_LOW_REG = 0x0003, /*PHY Identifier High Register*/ - PHY_AN_ADV_REG = 0x0004, /*Auto-Negotiation Advertisement Register*/ - PHY_LNK_PART_ABl_REG = 0x0005, /*Link Partner Ability Register (Base Page)*/ - PHY_AN_EXP_REG = 0x0006, /*Auto-Negotiation Expansion Register*/ - PHY_AN_NXT_PAGE_TX_REG = 0x0007, /*Next Page Transmit Register*/ - PHY_LNK_PART_NXT_PAGE_REG = 0x0008, /*Link Partner Next Page Register*/ - PHY_1000BT_CTRL_REG = 0x0009, /*1000BASE-T Control Register*/ - PHY_1000BT_STATUS_REG = 0x000a, /*1000BASE-T Status Register*/ - PHY_SPECIFIC_CTRL_REG = 0x0010, /*Phy specific control register*/ - PHY_SPECIFIC_STATUS_REG = 0x0011, /*Phy specific status register*/ - PHY_INTERRUPT_ENABLE_REG = 0x0012, /*Phy interrupt enable register*/ - PHY_INTERRUPT_STATUS_REG = 0x0013, /*Phy interrupt status register*/ - PHY_EXT_PHY_SPC_CTRL = 0x0014, /*Extended Phy specific control*/ - PHY_RX_ERR_COUNTER = 0x0015, /*Receive Error Counter*/ - PHY_EXT_ADDR_CBL_DIAG = 0x0016, /*Extended address for cable diagnostic register*/ - PHY_LED_CONTROL = 0x0018, /*LED Control*/ - PHY_MAN_LED_OVERIDE = 0x0019, /*Manual LED override register*/ - PHY_EXT_PHY_SPC_CTRL2 = 0x001a, /*Extended Phy specific control 2*/ - PHY_EXT_PHY_SPC_STATUS = 0x001b, /*Extended Phy specific status*/ - PHY_CBL_DIAG_REG = 0x001c, /*Cable diagnostic registers*/ -}; - - -/* This is Control register layout. Control register is of 16 bit wide. -*/ - -enum Mii_GEN_CTRL -{ /* Description bits R/W default value */ - Mii_reset = 0x8000, - Mii_Speed_10 = 0x0000, /* 10 Mbps 6:13 RW */ - Mii_Speed_100 = 0x2000, /* 100 Mbps 6:13 RW */ - Mii_Speed_1000 = 0x0040, /* 1000 Mbit/s 6:13 RW */ - - Mii_Duplex = 0x0100, /* Full Duplex mode 8 RW */ - - Mii_Manual_Master_Config = 0x0800, /* Manual Master Config 11 RW */ - - Mii_Loopback = 0x4000, /* Enable Loop back 14 RW */ - Mii_NoLoopback = 0x0000, /* Enable Loop back 14 RW */ -}; - -enum Mii_Phy_Status -{ - Mii_phy_status_speed_10 = 0x0000, - Mii_phy_status_speed_100 = 0x4000, - Mii_phy_status_speed_1000 = 0x8000, - - Mii_phy_status_full_duplex = 0x2000, - Mii_phy_status_half_duplex = 0x0000, - - Mii_phy_status_link_up = 0x0400, -}; -/* This is Status register layout. Status register is of 16 bit wide. -*/ -enum Mii_GEN_STATUS -{ - Mii_AutoNegCmplt = 0x0020, /* Autonegotiation completed 5 RW */ - Mii_Link = 0x0004, /* Link status 2 RW */ -}; - -enum Mii_Link_Status -{ - LINKDOWN = 0, - LINKUP = 1, -}; - -enum Mii_Duplex_Mode -{ - HALFDUPLEX = 1, - FULLDUPLEX = 2, -}; -enum Mii_Link_Speed -{ - SPEED10 = 1, - SPEED100 = 2, - SPEED1000 = 3, -}; - -enum Mii_Loop_Back -{ - NOLOOPBACK = 0, - LOOPBACK = 1, -}; - -/********************************************************** - * GMAC registers Map - * For Pci based system address is BARx + GmacRegisterBase - * For any other system translation is done accordingly - **********************************************************/ -enum GmacRegisters -{ - GmacConfig = 0x0000, /* Mac config Register */ - GmacFrameFilter = 0x0004, /* Mac frame filtering controls */ - GmacHashHigh = 0x0008, /* Multi-cast hash table high */ - GmacHashLow = 0x000C, /* Multi-cast hash table low */ - GmacGmiiAddr = 0x0010, /* GMII address Register(ext. Phy) */ - GmacGmiiData = 0x0014, /* GMII data Register(ext. Phy) */ - GmacFlowControl = 0x0018, /* Flow control Register */ - GmacVlan = 0x001C, /* VLAN tag Register (IEEE 802.1Q) */ - - GmacVersion = 0x0020, /* GMAC Core Version Register */ - GmacWakeupAddr = 0x0028, /* GMAC wake-up frame filter adrress reg */ - GmacPmtCtrlStatus = 0x002C, /* PMT control and status register */ - - GmacInterruptStatus = 0x0038, /* Mac Interrupt ststus register */ - GmacInterruptMask = 0x003C, /* Mac Interrupt Mask register */ - - GmacAddr0High = 0x0040, /* Mac address0 high Register */ - GmacAddr0Low = 0x0044, /* Mac address0 low Register */ - GmacAddr1High = 0x0048, /* Mac address1 high Register */ - GmacAddr1Low = 0x004C, /* Mac address1 low Register */ - GmacAddr2High = 0x0050, /* Mac address2 high Register */ - GmacAddr2Low = 0x0054, /* Mac address2 low Register */ - GmacAddr3High = 0x0058, /* Mac address3 high Register */ - GmacAddr3Low = 0x005C, /* Mac address3 low Register */ - GmacAddr4High = 0x0060, /* Mac address4 high Register */ - GmacAddr4Low = 0x0064, /* Mac address4 low Register */ - GmacAddr5High = 0x0068, /* Mac address5 high Register */ - GmacAddr5Low = 0x006C, /* Mac address5 low Register */ - GmacAddr6High = 0x0070, /* Mac address6 high Register */ - GmacAddr6Low = 0x0074, /* Mac address6 low Register */ - GmacAddr7High = 0x0078, /* Mac address7 high Register */ - GmacAddr7Low = 0x007C, /* Mac address7 low Register */ - GmacAddr8High = 0x0080, /* Mac address8 high Register */ - GmacAddr8Low = 0x0084, /* Mac address8 low Register */ - GmacAddr9High = 0x0088, /* Mac address9 high Register */ - GmacAddr9Low = 0x008C, /* Mac address9 low Register */ - GmacAddr10High = 0x0090, /* Mac address10 high Register */ - GmacAddr10Low = 0x0094, /* Mac address10 low Register */ - GmacAddr11High = 0x0098, /* Mac address11 high Register */ - GmacAddr11Low = 0x009C, /* Mac address11 low Register */ - GmacAddr12High = 0x00A0, /* Mac address12 high Register */ - GmacAddr12Low = 0x00A4, /* Mac address12 low Register */ - GmacAddr13High = 0x00A8, /* Mac address13 high Register */ - GmacAddr13Low = 0x00AC, /* Mac address13 low Register */ - GmacAddr14High = 0x00B0, /* Mac address14 high Register */ - GmacAddr14Low = 0x00B4, /* Mac address14 low Register */ - GmacAddr15High = 0x00B8, /* Mac address15 high Register */ - GmacAddr15Low = 0x00BC, /* Mac address15 low Register */ - - /*Time Stamp Register Map*/ - GmacTSControl = 0x0700, /* Controls the Timestamp update logic : only when IEEE 1588 time stamping is enabled in corekit */ - - GmacTSSubSecIncr = 0x0704, /* 8 bit value by which sub second register is incremented : only when IEEE 1588 time stamping without external timestamp input */ - - GmacTSHigh = 0x0708, /* 32 bit seconds(MS) : only when IEEE 1588 time stamping without external timestamp input */ - GmacTSLow = 0x070C, /* 32 bit nano seconds(MS) : only when IEEE 1588 time stamping without external timestamp input */ - - GmacTSHighUpdate = 0x0710, /* 32 bit seconds(MS) to be written/added/subtracted : only when IEEE 1588 time stamping without external timestamp input */ - GmacTSLowUpdate = 0x0714, /* 32 bit nano seconds(MS) to be writeen/added/subtracted : only when IEEE 1588 time stamping without external timestamp input */ - - GmacTSAddend = 0x0718, /* Used by Software to readjust the clock frequency linearly : only when IEEE 1588 time stamping without external timestamp input */ - - GmacTSTargetTimeHigh = 0x071C, /* 32 bit seconds(MS) to be compared with system time : only when IEEE 1588 time stamping without external timestamp input */ - GmacTSTargetTimeLow = 0x0720, /* 32 bit nano seconds(MS) to be compared with system time : only when IEEE 1588 time stamping without external timestamp input */ - - GmacTSHighWord = 0x0724, /* Time Stamp Higher Word Register (Version 2 only); only lower 16 bits are valid */ - - GmacTSStatus = 0x0728, /* Time Stamp Status Register */ -}; - -/********************************************************** - * GMAC Network interface registers - * This explains the Register's Layout - - * FES is Read only by default and is enabled only when Tx - * Config Parameter is enabled for RGMII/SGMII interface - * during CoreKit Config. - - * DM is Read only with value 1'b1 in Full duplex only Config - **********************************************************/ - -/* GmacConfig = 0x0000, Mac config Register Layout */ -enum GmacConfigReg -{ - /* Bit description Bits R/W Reset value */ - GmacWatchdog = 0x00800000, - GmacWatchdogDisable = 0x00800000, /* (WD)Disable watchdog timer on Rx 23 RW */ - GmacWatchdogEnable = 0x00000000, /* Enable watchdog timer 0 */ - - GmacJabber = 0x00400000, - GmacJabberDisable = 0x00400000, /* (JD)Disable jabber timer on Tx 22 RW */ - GmacJabberEnable = 0x00000000, /* Enable jabber timer 0 */ - - GmacFrameBurst = 0x00200000, - GmacFrameBurstEnable = 0x00200000, /* (BE)Enable frame bursting during Tx 21 RW */ - GmacFrameBurstDisable = 0x00000000, /* Disable frame bursting 0 */ - - GmacJumboFrame = 0x00100000, - GmacJumboFrameEnable = 0x00100000, /* (JE)Enable jumbo frame for Tx 20 RW */ - GmacJumboFrameDisable = 0x00000000, /* Disable jumbo frame 0 */ - - GmacInterFrameGap7 = 0x000E0000, /* (IFG) Config7 - 40 bit times 19:17 RW */ - GmacInterFrameGap6 = 0x000C0000, /* (IFG) Config6 - 48 bit times */ - GmacInterFrameGap5 = 0x000A0000, /* (IFG) Config5 - 56 bit times */ - GmacInterFrameGap4 = 0x00080000, /* (IFG) Config4 - 64 bit times */ - GmacInterFrameGap3 = 0x00040000, /* (IFG) Config3 - 72 bit times */ - GmacInterFrameGap2 = 0x00020000, /* (IFG) Config2 - 80 bit times */ - GmacInterFrameGap1 = 0x00010000, /* (IFG) Config1 - 88 bit times */ - GmacInterFrameGap0 = 0x00000000, /* (IFG) Config0 - 96 bit times 000 */ - - GmacDisableCrs = 0x00010000, - GmacMiiGmii = 0x00008000, - GmacSelectMii = 0x00008000, /* (PS)Port Select-MII mode 15 RW */ - GmacSelectGmii = 0x00000000, /* GMII mode 0 */ - - GmacFESpeed100 = 0x00004000, /*(FES)Fast Ethernet speed 100Mbps 14 RW */ - GmacFESpeed10 = 0x00000000, /* 10Mbps 0 */ - - GmacRxOwn = 0x00002000, - GmacDisableRxOwn = 0x00002000, /* (DO)Disable receive own packets 13 RW */ - GmacEnableRxOwn = 0x00000000, /* Enable receive own packets 0 */ - - GmacLoopback = 0x00001000, - GmacLoopbackOn = 0x00001000, /* (LM)Loopback mode for GMII/MII 12 RW */ - GmacLoopbackOff = 0x00000000, /* Normal mode 0 */ - - GmacDuplex = 0x00000800, - GmacFullDuplex = 0x00000800, /* (DM)Full duplex mode 11 RW */ - GmacHalfDuplex = 0x00000000, /* Half duplex mode 0 */ - - GmacRxIpcOffload = 0x00000400, /*IPC checksum offload 10 RW 0 */ - - GmacRetry = 0x00000200, - GmacRetryDisable = 0x00000200, /* (DR)Disable Retry 9 RW */ - GmacRetryEnable = 0x00000000, /* Enable retransmission as per BL 0 */ - - GmacLinkUp = 0x00000100, /* (LUD)Link UP 8 RW */ - GmacLinkDown = 0x00000100, /* Link Down 0 */ - - GmacPadCrcStrip = 0x00000080, - GmacPadCrcStripEnable = 0x00000080, /* (ACS) Automatic Pad/Crc strip enable 7 RW */ - GmacPadCrcStripDisable = 0x00000000, /* Automatic Pad/Crc stripping disable 0 */ - - GmacBackoffLimit = 0x00000060, - GmacBackoffLimit3 = 0x00000060, /* (BL)Back-off limit in HD mode 6:5 RW */ - GmacBackoffLimit2 = 0x00000040, /* */ - GmacBackoffLimit1 = 0x00000020, /* */ - GmacBackoffLimit0 = 0x00000000, /* 00 */ - - GmacDeferralCheck = 0x00000010, - GmacDeferralCheckEnable = 0x00000010, /* (DC)Deferral check enable in HD mode 4 RW */ - GmacDeferralCheckDisable = 0x00000000, /* Deferral check disable 0 */ - - GmacTx = 0x00000008, - GmacTxEnable = 0x00000008, /* (TE)Transmitter enable 3 RW */ - GmacTxDisable = 0x00000000, /* Transmitter disable 0 */ - - GmacRx = 0x00000004, - GmacRxEnable = 0x00000004, /* (RE)Receiver enable 2 RW */ - GmacRxDisable = 0x00000000, /* Receiver disable 0 */ -}; - -/* GmacFrameFilter = 0x0004, Mac frame filtering controls Register Layout*/ -enum GmacFrameFilterReg -{ - GmacFilter = 0x80000000, - GmacFilterOff = 0x80000000, /* (RA)Receive all incoming packets 31 RW */ - GmacFilterOn = 0x00000000, /* Receive filtered packets only 0 */ - - GmacHashPerfectFilter = 0x00000400, /*Hash or Perfect Filter enable 10 RW 0 */ - - GmacSrcAddrFilter = 0x00000200, - GmacSrcAddrFilterEnable = 0x00000200, /* (SAF)Source Address Filter enable 9 RW */ - GmacSrcAddrFilterDisable = 0x00000000, /* 0 */ - - GmacSrcInvaAddrFilter = 0x00000100, - GmacSrcInvAddrFilterEn = 0x00000100, /* (SAIF)Inv Src Addr Filter enable 8 RW */ - GmacSrcInvAddrFilterDis = 0x00000000, /* 0 */ - - GmacPassControl = 0x000000C0, - GmacPassControl3 = 0x000000C0, /* (PCS)Forwards ctrl frms that pass AF 7:6 RW */ - GmacPassControl2 = 0x00000080, /* Forwards all control frames */ - GmacPassControl1 = 0x00000040, /* Does not pass control frames */ - GmacPassControl0 = 0x00000000, /* Does not pass control frames 00 */ - - GmacBroadcast = 0x00000020, - GmacBroadcastDisable = 0x00000020, /* (DBF)Disable Rx of broadcast frames 5 RW */ - GmacBroadcastEnable = 0x00000000, /* Enable broadcast frames 0 */ - - GmacMulticastFilter = 0x00000010, - GmacMulticastFilterOff = 0x00000010, /* (PM) Pass all multicast packets 4 RW */ - GmacMulticastFilterOn = 0x00000000, /* Pass filtered multicast packets 0 */ - - GmacDestAddrFilter = 0x00000008, - GmacDestAddrFilterInv = 0x00000008, /* (DAIF)Inverse filtering for DA 3 RW */ - GmacDestAddrFilterNor = 0x00000000, /* Normal filtering for DA 0 */ - - GmacMcastHashFilter = 0x00000004, - GmacMcastHashFilterOn = 0x00000004, /* (HMC)perfom multicast hash filtering 2 RW */ - GmacMcastHashFilterOff = 0x00000000, /* perfect filtering only 0 */ - - GmacUcastHashFilter = 0x00000002, - GmacUcastHashFilterOn = 0x00000002, /* (HUC)Unicast Hash filtering only 1 RW */ - GmacUcastHashFilterOff = 0x00000000, /* perfect filtering only 0 */ - - GmacPromiscuousMode = 0x00000001, - GmacPromiscuousModeOn = 0x00000001, /* Receive all frames 0 RW */ - GmacPromiscuousModeOff = 0x00000000, /* Receive filtered packets only 0 */ -}; - - -/*GmacGmiiAddr = 0x0010, GMII address Register(ext. Phy) Layout */ -enum GmacGmiiAddrReg -{ - GmiiDevMask = 0x0000F800, /* (PA)GMII device address 15:11 RW 0x00 */ - GmiiDevShift = 11, - - GmiiRegMask = 0x000007C0, /* (GR)GMII register in selected Phy 10:6 RW 0x00 */ - GmiiRegShift = 6, - - GmiiCsrClkMask = 0x0000003C, /*CSR Clock bit Mask 4:2 */ - GmiiCsrClk5 = 0x00000014, /* (CR)CSR Clock Range 250-300 MHz 4:2 RW 000 */ - GmiiCsrClk4 = 0x00000010, /* 150-250 MHz */ - GmiiCsrClk3 = 0x0000000C, /* 35-60 MHz */ - GmiiCsrClk2 = 0x00000008, /* 20-35 MHz */ - GmiiCsrClk1 = 0x00000004, /* 100-150 MHz */ - GmiiCsrClk0 = 0x00000000, /* 60-100 MHz */ - - GmiiWrite = 0x00000002, /* (GW)Write to register 1 RW */ - GmiiRead = 0x00000000, /* Read from register 0 */ - - GmiiBusy = 0x00000001, /* (GB)GMII interface is busy 0 RW 0 */ -}; - -/* GmacGmiiData = 0x0014, GMII data Register(ext. Phy) Layout */ -enum GmacGmiiDataReg -{ - GmiiDataMask = 0x0000FFFF, /* (GD)GMII Data 15:0 RW 0x0000 */ -}; - - -/*GmacFlowControl = 0x0018, Flow control Register Layout */ -enum GmacFlowControlReg -{ - GmacPauseTimeMask = 0xFFFF0000, /* (PT) PAUSE TIME field in the control frame 31:16 RW 0x0000 */ - GmacPauseTimeShift = 16, - - GmacPauseLowThresh = 0x00000030, - GmacPauseLowThresh3 = 0x00000030, /* (PLT)thresh for pause tmr 256 slot time 5:4 RW */ - GmacPauseLowThresh2 = 0x00000020, /* 144 slot time */ - GmacPauseLowThresh1 = 0x00000010, /* 28 slot time */ - GmacPauseLowThresh0 = 0x00000000, /* 4 slot time 000 */ - - GmacUnicastPauseFrame = 0x00000008, - GmacUnicastPauseFrameOn = 0x00000008, /* (UP)Detect pause frame with unicast addr. 3 RW */ - GmacUnicastPauseFrameOff = 0x00000000, /* Detect only pause frame with multicast addr. 0 */ - - GmacRxFlowControl = 0x00000004, - GmacRxFlowControlEnable = 0x00000004, /* (RFE)Enable Rx flow control 2 RW */ - GmacRxFlowControlDisable = 0x00000000, /* Disable Rx flow control 0 */ - - GmacTxFlowControl = 0x00000002, - GmacTxFlowControlEnable = 0x00000002, /* (TFE)Enable Tx flow control 1 RW */ - GmacTxFlowControlDisable = 0x00000000, /* Disable flow control 0 */ - - GmacFlowControlBackPressure= 0x00000001, - GmacSendPauseFrame = 0x00000001, /* (FCB/PBA)send pause frm/Apply back pressure 0 RW 0 */ -}; - -/* GmacInterruptStatus = 0x0038, Mac Interrupt ststus register */ -enum GmacInterruptStatusBitDefinition -{ - GmacTSIntSts = 0x00000200, /* set if int generated due to TS (Read Time Stamp Status Register to know details)*/ - GmacMmcRxChksumOffload = 0x00000080, /* set if int generated in MMC RX CHECKSUM OFFLOAD int register */ - GmacMmcTxIntSts = 0x00000040, /* set if int generated in MMC TX Int register */ - GmacMmcRxIntSts = 0x00000020, /* set if int generated in MMC RX Int register */ - GmacMmcIntSts = 0x00000010, /* set if any of the above bit [7:5] is set */ - GmacPmtIntSts = 0x00000008, /* set whenver magic pkt/wake-on-lan frame is received */ - GmacPcsAnComplete = 0x00000004, /* set when AN is complete in TBI/RTBI/SGMIII phy interface */ - GmacPcsLnkStsChange = 0x00000002, /* set if any lnk status change in TBI/RTBI/SGMII interface */ - GmacRgmiiIntSts = 0x00000001, /* set if any change in lnk status of RGMII interface */ - -}; - -/* GmacInterruptMask = 0x003C, Mac Interrupt Mask register */ -enum GmacInterruptMaskBitDefinition -{ - GmacTSIntMask = 0x00000200, /* when set disables the time stamp interrupt generation */ - GmacPmtIntMask = 0x00000008, /* when set Disables the assertion of PMT interrupt */ - GmacPcsAnIntMask = 0x00000004, /* When set disables the assertion of PCS AN complete interrupt */ - GmacPcsLnkStsIntMask = 0x00000002, /* when set disables the assertion of PCS lnk status change interrupt */ - GmacRgmiiIntMask = 0x00000001, /* when set disables the assertion of RGMII int */ -}; - -/********************************************************** - * GMAC DMA registers - * For Pci based system address is BARx + GmaDmaBase - * For any other system translation is done accordingly - **********************************************************/ - -enum DmaRegisters -{ - DmaBusMode = 0x0000, /* CSR0 - Bus Mode Register */ - DmaTxPollDemand = 0x0004, /* CSR1 - Transmit Poll Demand Register */ - DmaRxPollDemand = 0x0008, /* CSR2 - Receive Poll Demand Register */ - DmaRxBaseAddr = 0x000C, /* CSR3 - Receive Descriptor list base address */ - DmaTxBaseAddr = 0x0010, /* CSR4 - Transmit Descriptor list base address */ - DmaStatus = 0x0014, /* CSR5 - Dma status Register */ - DmaControl = 0x0018, /* CSR6 - Dma Operation Mode Register */ - DmaInterrupt = 0x001C, /* CSR7 - Interrupt enable */ - DmaMissedFr = 0x0020, /* CSR8 - Missed Frame & Buffer overflow Counter */ - DmaTxCurrDesc = 0x0048, /* - Current host Tx Desc Register */ - DmaRxCurrDesc = 0x004C, /* - Current host Rx Desc Register */ - DmaTxCurrAddr = 0x0050, /* CSR20 - Current host transmit buffer address */ - DmaRxCurrAddr = 0x0054, /* CSR21 - Current host receive buffer address */ -}; - -/********************************************************** - * DMA Engine registers Layout - **********************************************************/ - -/*DmaBusMode = 0x0000, CSR0 - Bus Mode */ -enum DmaBusModeReg -{ /* Bit description Bits R/W Reset value */ - DmaFixedBurstEnable = 0x00010000, /* (FB)Fixed Burst SINGLE, INCR4, INCR8 or INCR16 16 RW */ - DmaFixedBurstDisable = 0x00000000, /* SINGLE, INCR 0 */ - - DmaTxPriorityRatio11 = 0x00000000, /* (PR)TX:RX DMA priority ratio 1:1 15:14 RW 00 */ - DmaTxPriorityRatio21 = 0x00004000, /* (PR)TX:RX DMA priority ratio 2:1 */ - DmaTxPriorityRatio31 = 0x00008000, /* (PR)TX:RX DMA priority ratio 3:1 */ - DmaTxPriorityRatio41 = 0x0000C000, /* (PR)TX:RX DMA priority ratio 4:1 */ - - DmaBurstLengthx8 = 0x01000000, /* When set mutiplies the PBL by 8 24 RW 0 */ - - DmaBurstLength256 = 0x01002000, /*(DmaBurstLengthx8 | DmaBurstLength32) = 256 [24]:13:8 */ - DmaBurstLength128 = 0x01001000, /*(DmaBurstLengthx8 | DmaBurstLength16) = 128 [24]:13:8 */ - DmaBurstLength64 = 0x01000800, /*(DmaBurstLengthx8 | DmaBurstLength8) = 64 [24]:13:8 */ - DmaBurstLength32 = 0x00002000, /* (PBL) programmable Dma burst length = 32 13:8 RW */ - DmaBurstLength16 = 0x00001000, /* Dma burst length = 16 */ - DmaBurstLength8 = 0x00000800, /* Dma burst length = 8 */ - DmaBurstLength4 = 0x00000400, /* Dma burst length = 4 */ - DmaBurstLength2 = 0x00000200, /* Dma burst length = 2 */ - DmaBurstLength1 = 0x00000100, /* Dma burst length = 1 */ - DmaBurstLength0 = 0x00000000, /* Dma burst length = 0 0x00 */ - - DmaDescriptor8Words = 0x00000080, /* Enh Descriptor works 1=> 8 word descriptor 7 0 */ - DmaDescriptor4Words = 0x00000000, /* Enh Descriptor works 0=> 4 word descriptor 7 0 */ - - DmaDescriptorSkip16 = 0x00000040, /* (DSL)Descriptor skip length (no.of dwords) 6:2 RW */ - DmaDescriptorSkip8 = 0x00000020, /* between two unchained descriptors */ - DmaDescriptorSkip4 = 0x00000010, /* */ - DmaDescriptorSkip2 = 0x00000008, /* */ - DmaDescriptorSkip1 = 0x00000004, /* */ - DmaDescriptorSkip0 = 0x00000000, /* 0x00 */ - - DmaArbitRr = 0x00000000, /* (DA) DMA RR arbitration 1 RW 0 */ - DmaArbitPr = 0x00000002, /* Rx has priority over Tx */ - - DmaResetOn = 0x00000001, /* (SWR)Software Reset DMA engine 0 RW */ - DmaResetOff = 0x00000000, /* 0 */ -}; - - -/*DmaStatus = 0x0014, CSR5 - Dma status Register */ -enum DmaStatusReg -{ - /*Bit 28 27 and 26 indicate whether the interrupt due to PMT GMACMMC or GMAC LINE Remaining bits are DMA interrupts*/ - GmacPmtIntr = 0x10000000, /* (GPI)Gmac subsystem interrupt 28 RO 0 */ - GmacMmcIntr = 0x08000000, /* (GMI)Gmac MMC subsystem interrupt 27 RO 0 */ - GmacLineIntfIntr = 0x04000000, /* Line interface interrupt 26 RO 0 */ - - DmaErrorBit2 = 0x02000000, /* (EB)Error bits 0-data buffer, 1-desc. access 25 RO 0 */ - DmaErrorBit1 = 0x01000000, /* (EB)Error bits 0-write trnsf, 1-read transfr 24 RO 0 */ - DmaErrorBit0 = 0x00800000, /* (EB)Error bits 0-Rx DMA, 1-Tx DMA 23 RO 0 */ - - DmaTxState = 0x00700000, /* (TS)Transmit process state 22:20 RO */ - DmaTxStopped = 0x00000000, /* Stopped - Reset or Stop Tx Command issued 000 */ - DmaTxFetching = 0x00100000, /* Running - fetching the Tx descriptor */ - DmaTxWaiting = 0x00200000, /* Running - waiting for status */ - DmaTxReading = 0x00300000, /* Running - reading the data from host memory */ - DmaTxSuspended = 0x00600000, /* Suspended - Tx Descriptor unavailabe */ - DmaTxClosing = 0x00700000, /* Running - closing Rx descriptor */ - - DmaRxState = 0x000E0000, /* (RS)Receive process state 19:17 RO */ - DmaRxStopped = 0x00000000, /* Stopped - Reset or Stop Rx Command issued 000 */ - DmaRxFetching = 0x00020000, /* Running - fetching the Rx descriptor */ - DmaRxWaiting = 0x00060000, /* Running - waiting for packet */ - DmaRxSuspended = 0x00080000, /* Suspended - Rx Descriptor unavailable */ - DmaRxClosing = 0x000A0000, /* Running - closing descriptor */ - DmaRxQueuing = 0x000E0000, /* Running - queuing the recieve frame into host memory */ - - DmaIntNormal = 0x00010000, /* (NIS)Normal interrupt summary 16 RW 0 */ - DmaIntAbnormal = 0x00008000, /* (AIS)Abnormal interrupt summary 15 RW 0 */ - - DmaIntEarlyRx = 0x00004000, /* Early receive interrupt (Normal) RW 0 */ - DmaIntBusError = 0x00002000, /* Fatal bus error (Abnormal) RW 0 */ - DmaIntEarlyTx = 0x00000400, /* Early transmit interrupt (Abnormal) RW 0 */ - DmaIntRxWdogTO = 0x00000200, /* Receive Watchdog Timeout (Abnormal) RW 0 */ - DmaIntRxStopped = 0x00000100, /* Receive process stopped (Abnormal) RW 0 */ - DmaIntRxNoBuffer = 0x00000080, /* Receive buffer unavailable (Abnormal) RW 0 */ - DmaIntRxCompleted = 0x00000040, /* Completion of frame reception (Normal) RW 0 */ - DmaIntTxUnderflow = 0x00000020, /* Transmit underflow (Abnormal) RW 0 */ - DmaIntRcvOverflow = 0x00000010, /* Receive Buffer overflow interrupt RW 0 */ - DmaIntTxJabberTO = 0x00000008, /* Transmit Jabber Timeout (Abnormal) RW 0 */ - DmaIntTxNoBuffer = 0x00000004, /* Transmit buffer unavailable (Normal) RW 0 */ - DmaIntTxStopped = 0x00000002, /* Transmit process stopped (Abnormal) RW 0 */ - DmaIntTxCompleted = 0x00000001, /* Transmit completed (Normal) RW 0 */ -}; - -/*DmaControl = 0x0018, CSR6 - Dma Operation Mode Register */ -enum DmaControlReg -{ - DmaDisableDropTcpCs = 0x04000000, /* (DT) Dis. drop. of tcp/ip CS error frames 26 RW 0 */ - - DmaStoreAndForward = 0x00200000, /* (SF)Store and forward 21 RW 0 */ - DmaFlushTxFifo = 0x00100000, /* (FTF)Tx FIFO controller is reset to default 20 RW 0 */ - - DmaTxThreshCtrl = 0x0001C000, /* (TTC)Controls thre Threh of MTL tx Fifo 16:14 RW */ - DmaTxThreshCtrl16 = 0x0001C000, /* (TTC)Controls thre Threh of MTL tx Fifo 16 16:14 RW */ - DmaTxThreshCtrl24 = 0x00018000, /* (TTC)Controls thre Threh of MTL tx Fifo 24 16:14 RW */ - DmaTxThreshCtrl32 = 0x00014000, /* (TTC)Controls thre Threh of MTL tx Fifo 32 16:14 RW */ - DmaTxThreshCtrl40 = 0x00010000, /* (TTC)Controls thre Threh of MTL tx Fifo 40 16:14 RW */ - DmaTxThreshCtrl256 = 0x0000c000, /* (TTC)Controls thre Threh of MTL tx Fifo 256 16:14 RW */ - DmaTxThreshCtrl192 = 0x00008000, /* (TTC)Controls thre Threh of MTL tx Fifo 192 16:14 RW */ - DmaTxThreshCtrl128 = 0x00004000, /* (TTC)Controls thre Threh of MTL tx Fifo 128 16:14 RW */ - DmaTxThreshCtrl64 = 0x00000000, /* (TTC)Controls thre Threh of MTL tx Fifo 64 16:14 RW 000 */ - - DmaTxStart = 0x00002000, /* (ST)Start/Stop transmission 13 RW 0 */ - - DmaRxFlowCtrlDeact = 0x00401800, /* (RFD)Rx flow control deact. threhold [22]:12:11 RW */ - DmaRxFlowCtrlDeact1K = 0x00000000, /* (RFD)Rx flow control deact. threhold (1kbytes) [22]:12:11 RW 00 */ - DmaRxFlowCtrlDeact2K = 0x00000800, /* (RFD)Rx flow control deact. threhold (2kbytes) [22]:12:11 RW */ - DmaRxFlowCtrlDeact3K = 0x00001000, /* (RFD)Rx flow control deact. threhold (3kbytes) [22]:12:11 RW */ - DmaRxFlowCtrlDeact4K = 0x00001800, /* (RFD)Rx flow control deact. threhold (4kbytes) [22]:12:11 RW */ - DmaRxFlowCtrlDeact5K = 0x00400000, /* (RFD)Rx flow control deact. threhold (4kbytes) [22]:12:11 RW */ - DmaRxFlowCtrlDeact6K = 0x00400800, /* (RFD)Rx flow control deact. threhold (4kbytes) [22]:12:11 RW */ - DmaRxFlowCtrlDeact7K = 0x00401000, /* (RFD)Rx flow control deact. threhold (4kbytes) [22]:12:11 RW */ - - DmaRxFlowCtrlAct = 0x00800600, /* (RFA)Rx flow control Act. threhold [23]:10:09 RW */ - DmaRxFlowCtrlAct1K = 0x00000000, /* (RFA)Rx flow control Act. threhold (1kbytes) [23]:10:09 RW 00 */ - DmaRxFlowCtrlAct2K = 0x00000200, /* (RFA)Rx flow control Act. threhold (2kbytes) [23]:10:09 RW */ - DmaRxFlowCtrlAct3K = 0x00000400, /* (RFA)Rx flow control Act. threhold (3kbytes) [23]:10:09 RW */ - DmaRxFlowCtrlAct4K = 0x00000600, /* (RFA)Rx flow control Act. threhold (4kbytes) [23]:10:09 RW */ - DmaRxFlowCtrlAct5K = 0x00800000, /* (RFA)Rx flow control Act. threhold (5kbytes) [23]:10:09 RW */ - DmaRxFlowCtrlAct6K = 0x00800200, /* (RFA)Rx flow control Act. threhold (6kbytes) [23]:10:09 RW */ - DmaRxFlowCtrlAct7K = 0x00800400, /* (RFA)Rx flow control Act. threhold (7kbytes) [23]:10:09 RW */ - - DmaRxThreshCtrl = 0x00000018, /* (RTC)Controls thre Threh of MTL rx Fifo 4:3 RW */ - DmaRxThreshCtrl64 = 0x00000000, /* (RTC)Controls thre Threh of MTL tx Fifo 64 4:3 RW */ - DmaRxThreshCtrl32 = 0x00000008, /* (RTC)Controls thre Threh of MTL tx Fifo 32 4:3 RW */ - DmaRxThreshCtrl96 = 0x00000010, /* (RTC)Controls thre Threh of MTL tx Fifo 96 4:3 RW */ - DmaRxThreshCtrl128 = 0x00000018, /* (RTC)Controls thre Threh of MTL tx Fifo 128 4:3 RW */ - - DmaEnHwFlowCtrl = 0x00000100, /* (EFC)Enable HW flow control 8 RW */ - DmaDisHwFlowCtrl = 0x00000000, /* Disable HW flow control 0 */ - - DmaFwdErrorFrames = 0x00000080, /* (FEF)Forward error frames 7 RW 0 */ - DmaFwdUnderSzFrames = 0x00000040, /* (FUF)Forward undersize frames 6 RW 0 */ - DmaTxSecondFrame = 0x00000004, /* (OSF)Operate on second frame 4 RW 0 */ - DmaRxStart = 0x00000002, /* (SR)Start/Stop reception 1 RW 0 */ -}; - - -/*DmaInterrupt = 0x001C, CSR7 - Interrupt enable Register Layout */ -enum DmaInterruptReg -{ - DmaIeNormal = DmaIntNormal , /* Normal interrupt enable RW 0 */ - DmaIeAbnormal = DmaIntAbnormal , /* Abnormal interrupt enable RW 0 */ - - DmaIeEarlyRx = DmaIntEarlyRx , /* Early receive interrupt enable RW 0 */ - DmaIeBusError = DmaIntBusError , /* Fatal bus error enable RW 0 */ - DmaIeEarlyTx = DmaIntEarlyTx , /* Early transmit interrupt enable RW 0 */ - DmaIeRxWdogTO = DmaIntRxWdogTO , /* Receive Watchdog Timeout enable RW 0 */ - DmaIeRxStopped = DmaIntRxStopped , /* Receive process stopped enable RW 0 */ - DmaIeRxNoBuffer = DmaIntRxNoBuffer , /* Receive buffer unavailable enable RW 0 */ - DmaIeRxCompleted = DmaIntRxCompleted, /* Completion of frame reception enable RW 0 */ - DmaIeTxUnderflow = DmaIntTxUnderflow, /* Transmit underflow enable RW 0 */ - - DmaIeRxOverflow = DmaIntRcvOverflow, /* Receive Buffer overflow interrupt RW 0 */ - DmaIeTxJabberTO = DmaIntTxJabberTO , /* Transmit Jabber Timeout enable RW 0 */ - DmaIeTxNoBuffer = DmaIntTxNoBuffer , /* Transmit buffer unavailable enable RW 0 */ - DmaIeTxStopped = DmaIntTxStopped , /* Transmit process stopped enable RW 0 */ - DmaIeTxCompleted = DmaIntTxCompleted, /* Transmit completed enable RW 0 */ -}; - - - -/********************************************************** - * DMA Engine descriptors - **********************************************************/ - -/* -**********Enhanced Descritpor structure to support 8K buffer per buffer **************************** - -DmaRxBaseAddr = 0x000C, CSR3 - Receive Descriptor list base address -DmaRxBaseAddr is the pointer to the first Rx Descriptors. the Descriptor format in Little endian with a -32 bit Data bus is as shown below - -Similarly -DmaTxBaseAddr = 0x0010, CSR4 - Transmit Descriptor list base address -DmaTxBaseAddr is the pointer to the first Rx Descriptors. the Descriptor format in Little endian with a -32 bit Data bus is as shown below - -------------------------------------------------------------------------- - RDES0 |OWN (31)| Status | - -------------------------------------------------------------------------- - RDES1 | Ctrl | Res | Byte Count Buffer 2 | Ctrl | Res | Byte Count Buffer 1 | - -------------------------------------------------------------------------- - RDES2 | Buffer 1 Address | - -------------------------------------------------------------------------- - RDES3 | Buffer 2 Address / Next Descriptor Address | - -------------------------------------------------------------------------- - - -------------------------------------------------------------------------- - TDES0 |OWN (31)| Ctrl | Res | Ctrl | Res | Status | - -------------------------------------------------------------------------- - TDES1 | Res | Byte Count Buffer 2 | Res | Byte Count Buffer 1 | - -------------------------------------------------------------------------- - TDES2 | Buffer 1 Address | - -------------------------------------------------------------------------- - TDES3 | Buffer 2 Address / Next Descriptor Address | - -------------------------------------------------------------------------- - -*/ - -enum DmaDescriptorStatus /* status word of DMA descriptor */ -{ - DescOwnByDma = 0x80000000, /* (OWN)Descriptor is owned by DMA engine 31 RW */ - - DescDAFilterFail = 0x40000000, /* (AFM)Rx - DA Filter Fail for the rx frame 30 */ - - DescFrameLengthMask = 0x3FFF0000, /* (FL)Receive descriptor frame length 29:16 */ - DescFrameLengthShift = 16, - - DescError = 0x00008000, /* (ES)Error summary bit - OR of the follo. bits: 15 */ - /* DE || OE || IPC || LC || RWT || RE || CE */ - DescRxTruncated = 0x00004000, /* (DE)Rx - no more descriptors for receive frame 14 */ - DescSAFilterFail = 0x00002000, /* (SAF)Rx - SA Filter Fail for the received frame 13 */ - DescRxLengthError = 0x00001000, /* (LE)Rx - frm size not matching with len field 12 */ - DescRxDamaged = 0x00000800, /* (OE)Rx - frm was damaged due to buffer overflow 11 */ - DescRxVLANTag = 0x00000400, /* (VLAN)Rx - received frame is a VLAN frame 10 */ - DescRxFirst = 0x00000200, /* (FS)Rx - first descriptor of the frame 9 */ - DescRxLast = 0x00000100, /* (LS)Rx - last descriptor of the frame 8 */ - DescRxLongFrame = 0x00000080, /* (Giant Frame)Rx - frame is longer than 1518/1522 7 */ - DescRxCollision = 0x00000040, /* (LC)Rx - late collision occurred during reception 6 */ - DescRxFrameEther = 0x00000020, /* (FT)Rx - Frame type - Ethernet, otherwise 802.3 5 */ - DescRxWatchdog = 0x00000010, /* (RWT)Rx - watchdog timer expired during reception 4 */ - DescRxMiiError = 0x00000008, /* (RE)Rx - error reported by MII interface 3 */ - DescRxDribbling = 0x00000004, /* (DE)Rx - frame contains non int multiple of 8 bits 2 */ - DescRxCrc = 0x00000002, /* (CE)Rx - CRC error 1 */ - - DescRxEXTsts = 0x00000001, /* Extended Status Available (RDES4) 0 */ - - DescTxIntEnable = 0x40000000, /* (IC)Tx - interrupt on completion 30 */ - DescTxLast = 0x20000000, /* (LS)Tx - Last segment of the frame 29 */ - DescTxFirst = 0x10000000, /* (FS)Tx - First segment of the frame 28 */ - DescTxDisableCrc = 0x08000000, /* (DC)Tx - Add CRC disabled (first segment only) 27 */ - DescTxDisablePadd = 0x04000000, /* (DP)disable padding, added by - reyaz 26 */ - - DescTxCisMask = 0x00c00000, /* Tx checksum offloading control mask 23:22 */ - DescTxCisBypass = 0x00000000, /* Checksum bypass */ - DescTxCisIpv4HdrCs = 0x00400000, /* IPv4 header checksum */ - DescTxCisTcpOnlyCs = 0x00800000, /* TCP/UDP/ICMP checksum. Pseudo header checksum is assumed to be present */ - DescTxCisTcpPseudoCs = 0x00c00000, /* TCP/UDP/ICMP checksum fully in hardware including pseudo header */ - - TxDescEndOfRing = 0x00200000, /* (TER)End of descriptors ring 21 */ - TxDescChain = 0x00100000, /* (TCH)Second buffer address is chain address 20 */ - - DescRxChkBit0 = 0x00000001, /*() Rx - Rx Payload Checksum Error 0 */ - DescRxChkBit7 = 0x00000080, /* (IPC CS ERROR)Rx - Ipv4 header checksum error 7 */ - DescRxChkBit5 = 0x00000020, /* (FT)Rx - Frame type - Ethernet, otherwise 802.3 5 */ - - DescRxTSavail = 0x00000080, /* Time stamp available 7 */ - DescRxFrameType = 0x00000020, /* (FT)Rx - Frame type - Ethernet, otherwise 802.3 5 */ - - DescTxIpv4ChkError = 0x00010000, /* (IHE) Tx Ip header error 16 */ - DescTxTimeout = 0x00004000, /* (JT)Tx - Transmit jabber timeout 14 */ - DescTxFrameFlushed = 0x00002000, /* (FF)Tx - DMA/MTL flushed the frame due to SW flush 13 */ - DescTxPayChkError = 0x00001000, /* (PCE) Tx Payload checksum Error 12 */ - DescTxLostCarrier = 0x00000800, /* (LC)Tx - carrier lost during tramsmission 11 */ - DescTxNoCarrier = 0x00000400, /* (NC)Tx - no carrier signal from the tranceiver 10 */ - DescTxLateCollision = 0x00000200, /* (LC)Tx - transmission aborted due to collision 9 */ - DescTxExcCollisions = 0x00000100, /* (EC)Tx - transmission aborted after 16 collisions 8 */ - DescTxVLANFrame = 0x00000080, /* (VF)Tx - VLAN-type frame 7 */ - - DescTxCollMask = 0x00000078, /* (CC)Tx - Collision count 6:3 */ - DescTxCollShift = 3, - - DescTxExcDeferral = 0x00000004, /* (ED)Tx - excessive deferral 2 */ - DescTxUnderflow = 0x00000002, /* (UF)Tx - late data arrival from the memory 1 */ - DescTxDeferred = 0x00000001, /* (DB)Tx - frame transmision deferred 0 */ - - /* - This explains the RDES1/TDES1 bits layout - -------------------------------------------------------------------- - RDES1/TDES1 | Control Bits | Byte Count Buffer 2 | Byte Count Buffer 1 | - -------------------------------------------------------------------- - - */ -// DmaDescriptorLength length word of DMA descriptor - - - RxDisIntCompl = 0x80000000, /* (Disable Rx int on completion) 31 */ - RxDescEndOfRing = 0x00008000, /* (TER)End of descriptors ring 15 */ - RxDescChain = 0x00004000, /* (TCH)Second buffer address is chain address 14 */ - - - //DescSize2Mask = 0x1FFF0000, /* (TBS2) Buffer 2 size 28:16 */ - //DescSize2Shift = 16, - DescSize1Mask = 0x00001FFF, /* (TBS1) Buffer 1 size 12:0 */ - DescSize1Shift = 0, - - - /* - This explains the RDES4 Extended Status bits layout - -------------------------------------------------------------------- - RDES4 | Extended Status | - -------------------------------------------------------------------- - */ - DescRxPtpAvail = 0x00004000, /* PTP snapshot available 14 */ - DescRxPtpVer = 0x00002000, /* When set indicates IEEE1584 Version 2 (else Ver1) 13 */ - DescRxPtpFrameType = 0x00001000, /* PTP frame type Indicates PTP sent over ethernet 12 */ - DescRxPtpMessageType = 0x00000F00, /* Message Type 11:8 */ - DescRxPtpNo = 0x00000000, /* 0000 => No PTP message received */ - DescRxPtpSync = 0x00000100, /* 0001 => Sync (all clock types) received */ - DescRxPtpFollowUp = 0x00000200, /* 0010 => Follow_Up (all clock types) received */ - DescRxPtpDelayReq = 0x00000300, /* 0011 => Delay_Req (all clock types) received */ - DescRxPtpDelayResp = 0x00000400, /* 0100 => Delay_Resp (all clock types) received */ - DescRxPtpPdelayReq = 0x00000500, /* 0101 => Pdelay_Req (in P to P tras clk) or Announce in Ord and Bound clk */ - DescRxPtpPdelayResp = 0x00000600, /* 0110 => Pdealy_Resp(in P to P trans clk) or Management in Ord and Bound clk */ - DescRxPtpPdelayRespFP = 0x00000700, /* 0111 => Pdealy_Resp_Follow_Up (in P to P trans clk) or Signaling in Ord and Bound clk */ - DescRxPtpIPV6 = 0x00000080, /* Received Packet is in IPV6 Packet 7 */ - DescRxPtpIPV4 = 0x00000040, /* Received Packet is in IPV4 Packet 6 */ - - DescRxChkSumBypass = 0x00000020, /* When set indicates checksum offload engine 5 - is bypassed */ - DescRxIpPayloadError = 0x00000010, /* When set indicates 16bit IP payload CS is in error 4 */ - DescRxIpHeaderError = 0x00000008, /* When set indicates 16bit IPV4 header CS is in 3 - error or IP datagram version is not consistent - with Ethernet type value */ - DescRxIpPayloadType = 0x00000007, /* Indicate the type of payload encapsulated 2:0 - in IPdatagram processed by COE (Rx) */ - DescRxIpPayloadUnknown= 0x00000000, /* Unknown or didnot process IP payload */ - DescRxIpPayloadUDP = 0x00000001, /* UDP */ - DescRxIpPayloadTCP = 0x00000002, /* TCP */ - DescRxIpPayloadICMP = 0x00000003, /* ICMP */ - -}; - - -/********************************************************** - * Initial register values - **********************************************************/ -enum InitialRegisters -{ - /* Full-duplex mode with perfect filter on */ - GmacConfigInitFdx1000 = GmacWatchdogEnable | GmacJabberEnable | GmacFrameBurstEnable | GmacJumboFrameDisable - | GmacSelectGmii | GmacEnableRxOwn | GmacLoopbackOff - | GmacFullDuplex | GmacRetryEnable | GmacPadCrcStripDisable - | GmacBackoffLimit0 | GmacDeferralCheckDisable | GmacTxEnable | GmacRxEnable, - - /* Full-duplex mode with perfect filter on */ - GmacConfigInitFdx110 = GmacWatchdogEnable | GmacJabberEnable | GmacFrameBurstEnable | GmacJumboFrameDisable - | GmacSelectMii | GmacEnableRxOwn | GmacLoopbackOff - | GmacFullDuplex | GmacRetryEnable | GmacPadCrcStripDisable - | GmacBackoffLimit0 | GmacDeferralCheckDisable | GmacTxEnable | GmacRxEnable, - - /* Full-duplex mode */ - // CHANGED: Pass control config, dest addr filter normal, added source address filter, multicast & unicast - // Hash filter. - /* = GmacFilterOff | GmacPassControlOff | GmacBroadcastEnable */ - GmacFrameFilterInitFdx = GmacFilterOn | GmacPassControl0 | GmacBroadcastEnable | GmacSrcAddrFilterDisable - | GmacMulticastFilterOn | GmacDestAddrFilterNor | GmacMcastHashFilterOff - | GmacPromiscuousModeOff | GmacUcastHashFilterOff, - - /* Full-duplex mode */ - GmacFlowControlInitFdx = GmacUnicastPauseFrameOff | GmacRxFlowControlEnable | GmacTxFlowControlEnable, - - /* Full-duplex mode */ - GmacGmiiAddrInitFdx = GmiiCsrClk2, - - - /* Half-duplex mode with perfect filter on */ - // CHANGED: Removed Endian configuration, added single bit config for PAD/CRC strip, - /*| GmacSelectMii | GmacLittleEndian | GmacDisableRxOwn | GmacLoopbackOff*/ - GmacConfigInitHdx1000 = GmacWatchdogEnable | GmacJabberEnable | GmacFrameBurstEnable | GmacJumboFrameDisable - | GmacSelectGmii | GmacDisableRxOwn | GmacLoopbackOff - | GmacHalfDuplex | GmacRetryEnable | GmacPadCrcStripDisable - | GmacBackoffLimit0 | GmacDeferralCheckDisable | GmacTxEnable | GmacRxEnable, - - /* Half-duplex mode with perfect filter on */ - GmacConfigInitHdx110 = GmacWatchdogEnable | GmacJabberEnable | GmacFrameBurstEnable | GmacJumboFrameDisable - | GmacSelectMii | GmacDisableRxOwn | GmacLoopbackOff - | GmacHalfDuplex | GmacRetryEnable | GmacPadCrcStripDisable - | GmacBackoffLimit0 | GmacDeferralCheckDisable | GmacTxEnable | GmacRxEnable, - - /* Half-duplex mode */ - GmacFrameFilterInitHdx = GmacFilterOn | GmacPassControl0 | GmacBroadcastEnable | GmacSrcAddrFilterDisable - | GmacMulticastFilterOn | GmacDestAddrFilterNor | GmacMcastHashFilterOff - | GmacUcastHashFilterOff| GmacPromiscuousModeOff, - - /* Half-duplex mode */ - GmacFlowControlInitHdx = GmacUnicastPauseFrameOff | GmacRxFlowControlDisable | GmacTxFlowControlDisable, - - /* Half-duplex mode */ - GmacGmiiAddrInitHdx = GmiiCsrClk2, - - - - /********************************************* - *DMA configurations - **********************************************/ - - DmaBusModeInit = DmaFixedBurstEnable | DmaBurstLength8 | DmaDescriptorSkip2 | DmaResetOff, -// DmaBusModeInit = DmaFixedBurstEnable | DmaBurstLength8 | DmaDescriptorSkip4 | DmaResetOff, - - /* 1000 Mb/s mode */ - DmaControlInit1000 = DmaStoreAndForward,// | DmaTxSecondFrame , - - /* 100 Mb/s mode */ - DmaControlInit100 = DmaStoreAndForward, - - /* 10 Mb/s mode */ - DmaControlInit10 = DmaStoreAndForward, - - /* Interrupt groups */ - DmaIntErrorMask = DmaIntBusError, /* Error */ - DmaIntRxAbnMask = DmaIntRxNoBuffer, /* receiver abnormal interrupt */ - DmaIntRxNormMask = DmaIntRxCompleted, /* receiver normal interrupt */ - DmaIntRxStoppedMask = DmaIntRxStopped, /* receiver stopped */ - DmaIntTxAbnMask = DmaIntTxUnderflow, /* transmitter abnormal interrupt */ - DmaIntTxNormMask = DmaIntTxCompleted, /* transmitter normal interrupt */ - DmaIntTxStoppedMask = DmaIntTxStopped, /* transmitter stopped */ - - DmaIntEnable = DmaIeNormal | DmaIeAbnormal | DmaIntErrorMask - | DmaIntRxAbnMask | DmaIntRxNormMask | DmaIntRxStoppedMask - | DmaIntTxAbnMask | DmaIntTxNormMask | DmaIntTxStoppedMask, - DmaIntDisable = 0, -}; - - -/********************************************************** - * Mac Management Counters (MMC) - **********************************************************/ - -enum MMC_ENABLE -{ - GmacMmcCntrl = 0x0100, /* mmc control for operating mode of MMC */ - GmacMmcIntrRx = 0x0104, /* maintains interrupts generated by rx counters */ - GmacMmcIntrTx = 0x0108, /* maintains interrupts generated by tx counters */ - GmacMmcIntrMaskRx = 0x010C, /* mask for interrupts generated from rx counters */ - GmacMmcIntrMaskTx = 0x0110, /* mask for interrupts generated from tx counters */ -}; -enum MMC_TX -{ - GmacMmcTxOctetCountGb = 0x0114, /*Bytes Tx excl. of preamble and retried bytes (Good or Bad) */ - GmacMmcTxFrameCountGb = 0x0118, /*Frames Tx excl. of retried frames (Good or Bad) */ - GmacMmcTxBcFramesG = 0x011C, /*Broadcast Frames Tx (Good) */ - GmacMmcTxMcFramesG = 0x0120, /*Multicast Frames Tx (Good) */ - - GmacMmcTx64OctetsGb = 0x0124, /*Tx with len 64 bytes excl. of pre and retried (Good or Bad) */ - GmacMmcTx65To127OctetsGb = 0x0128, /*Tx with len >64 bytes <=127 excl. of pre and retried (Good or Bad) */ - GmacMmcTx128To255OctetsGb = 0x012C, /*Tx with len >128 bytes <=255 excl. of pre and retried (Good or Bad) */ - GmacMmcTx256To511OctetsGb = 0x0130, /*Tx with len >256 bytes <=511 excl. of pre and retried (Good or Bad) */ - GmacMmcTx512To1023OctetsGb = 0x0134, /*Tx with len >512 bytes <=1023 excl. of pre and retried (Good or Bad) */ - GmacMmcTx1024ToMaxOctetsGb = 0x0138, /*Tx with len >1024 bytes <=MaxSize excl. of pre and retried (Good or Bad) */ - - GmacMmcTxUcFramesGb = 0x013C, /*Unicast Frames Tx (Good or Bad) */ - GmacMmcTxMcFramesGb = 0x0140, /*Multicast Frames Tx (Good and Bad) */ - GmacMmcTxBcFramesGb = 0x0144, /*Broadcast Frames Tx (Good and Bad) */ - GmacMmcTxUnderFlowError = 0x0148, /*Frames aborted due to Underflow error */ - GmacMmcTxSingleColG = 0x014C, /*Successfully Tx Frames after singel collision in Half duplex mode */ - GmacMmcTxMultiColG = 0x0150, /*Successfully Tx Frames after more than singel collision in Half duplex mode */ - GmacMmcTxDeferred = 0x0154, /*Successfully Tx Frames after a deferral in Half duplex mode */ - GmacMmcTxLateCol = 0x0158, /*Frames aborted due to late collision error */ - GmacMmcTxExessCol = 0x015C, /*Frames aborted due to excessive (16) collision errors */ - GmacMmcTxCarrierError = 0x0160, /*Frames aborted due to carrier sense error (No carrier or Loss of carrier) */ - GmacMmcTxOctetCountG = 0x0164, /*Bytes Tx excl. of preamble and retried bytes (Good) */ - GmacMmcTxFrameCountG = 0x0168, /*Frames Tx (Good) */ - GmacMmcTxExessDef = 0x016C, /*Frames aborted due to excessive deferral errors (deferred for more than 2 max-sized frame times)*/ - - GmacMmcTxPauseFrames = 0x0170, /*Number of good pause frames Tx. */ - GmacMmcTxVlanFramesG = 0x0174, /*Number of good Vlan frames Tx excl. retried frames */ -}; -enum MMC_RX -{ - GmacMmcRxFrameCountGb = 0x0180, /*Frames Rx (Good or Bad) */ - GmacMmcRxOctetCountGb = 0x0184, /*Bytes Rx excl. of preamble and retried bytes (Good or Bad) */ - GmacMmcRxOctetCountG = 0x0188, /*Bytes Rx excl. of preamble and retried bytes (Good) */ - GmacMmcRxBcFramesG = 0x018C, /*Broadcast Frames Rx (Good) */ - GmacMmcRxMcFramesG = 0x0190, /*Multicast Frames Rx (Good) */ - - GmacMmcRxCrcError = 0x0194, /*Number of frames received with CRC error */ - GmacMmcRxAlignError = 0x0198, /*Number of frames received with alignment (dribble) error. Only in 10/100mode */ - GmacMmcRxRuntError = 0x019C, /*Number of frames received with runt (<64 bytes and CRC error) error */ - GmacMmcRxJabberError = 0x01A0, /*Number of frames rx with jabber (>1518/1522 or >9018/9022 and CRC) */ - GmacMmcRxUnderSizeG = 0x01A4, /*Number of frames received with <64 bytes without any error */ - GmacMmcRxOverSizeG = 0x01A8, /*Number of frames received with >1518/1522 bytes without any error */ - - GmacMmcRx64OctetsGb = 0x01AC, /*Rx with len 64 bytes excl. of pre and retried (Good or Bad) */ - GmacMmcRx65To127OctetsGb = 0x01B0, /*Rx with len >64 bytes <=127 excl. of pre and retried (Good or Bad) */ - GmacMmcRx128To255OctetsGb = 0x01B4, /*Rx with len >128 bytes <=255 excl. of pre and retried (Good or Bad) */ - GmacMmcRx256To511OctetsGb = 0x01B8, /*Rx with len >256 bytes <=511 excl. of pre and retried (Good or Bad) */ - GmacMmcRx512To1023OctetsGb = 0x01BC, /*Rx with len >512 bytes <=1023 excl. of pre and retried (Good or Bad) */ - GmacMmcRx1024ToMaxOctetsGb = 0x01C0, /*Rx with len >1024 bytes <=MaxSize excl. of pre and retried (Good or Bad) */ - - GmacMmcRxUcFramesG = 0x01C4, /*Unicast Frames Rx (Good) */ - GmacMmcRxLengthError = 0x01C8, /*Number of frames received with Length type field != frame size */ - GmacMmcRxOutOfRangeType = 0x01CC, /*Number of frames received with length field != valid frame size */ - - GmacMmcRxPauseFrames = 0x01D0, /*Number of good pause frames Rx. */ - GmacMmcRxFifoOverFlow = 0x01D4, /*Number of missed rx frames due to FIFO overflow */ - GmacMmcRxVlanFramesGb = 0x01D8, /*Number of good Vlan frames Rx */ - - GmacMmcRxWatchdobError = 0x01DC, /*Number of frames rx with error due to watchdog timeout error */ -}; -enum MMC_IP_RELATED -{ - GmacMmcRxIpcIntrMask = 0x0200, /*Maintains the mask for interrupt generated from rx IPC statistic counters */ - GmacMmcRxIpcIntr = 0x0208, /*Maintains the interrupt that rx IPC statistic counters generate */ - - GmacMmcRxIpV4FramesG = 0x0210, /*Good IPV4 datagrams received */ - GmacMmcRxIpV4HdrErrFrames = 0x0214, /*Number of IPV4 datagrams received with header errors */ - GmacMmcRxIpV4NoPayFrames = 0x0218, /*Number of IPV4 datagrams received which didnot have TCP/UDP/ICMP payload */ - GmacMmcRxIpV4FragFrames = 0x021C, /*Number of IPV4 datagrams received with fragmentation */ - GmacMmcRxIpV4UdpChkDsblFrames = 0x0220, /*Number of IPV4 datagrams received that had a UDP payload checksum disabled */ - - GmacMmcRxIpV6FramesG = 0x0224, /*Good IPV6 datagrams received */ - GmacMmcRxIpV6HdrErrFrames = 0x0228, /*Number of IPV6 datagrams received with header errors */ - GmacMmcRxIpV6NoPayFrames = 0x022C, /*Number of IPV6 datagrams received which didnot have TCP/UDP/ICMP payload */ - - GmacMmcRxUdpFramesG = 0x0230, /*Number of good IP datagrams with good UDP payload */ - GmacMmcRxUdpErrorFrames = 0x0234, /*Number of good IP datagrams with UDP payload having checksum error */ - - GmacMmcRxTcpFramesG = 0x0238, /*Number of good IP datagrams with good TDP payload */ - GmacMmcRxTcpErrorFrames = 0x023C, /*Number of good IP datagrams with TCP payload having checksum error */ - - GmacMmcRxIcmpFramesG = 0x0240, /*Number of good IP datagrams with good Icmp payload */ - GmacMmcRxIcmpErrorFrames = 0x0244, /*Number of good IP datagrams with Icmp payload having checksum error */ - - GmacMmcRxIpV4OctetsG = 0x0250, /*Good IPV4 datagrams received excl. Ethernet hdr,FCS,Pad,Ip Pad bytes */ - GmacMmcRxIpV4HdrErrorOctets = 0x0254, /*Number of bytes in IPV4 datagram with header errors */ - GmacMmcRxIpV4NoPayOctets = 0x0258, /*Number of bytes in IPV4 datagram with no TCP/UDP/ICMP payload */ - GmacMmcRxIpV4FragOctets = 0x025C, /*Number of bytes received in fragmented IPV4 datagrams */ - GmacMmcRxIpV4UdpChkDsblOctets = 0x0260, /*Number of bytes received in UDP segment that had UDP checksum disabled */ - - GmacMmcRxIpV6OctetsG = 0x0264, /*Good IPV6 datagrams received excl. Ethernet hdr,FCS,Pad,Ip Pad bytes */ - GmacMmcRxIpV6HdrErrorOctets = 0x0268, /*Number of bytes in IPV6 datagram with header errors */ - GmacMmcRxIpV6NoPayOctets = 0x026C, /*Number of bytes in IPV6 datagram with no TCP/UDP/ICMP payload */ - - GmacMmcRxUdpOctetsG = 0x0270, /*Number of bytes in IP datagrams with good UDP payload */ - GmacMmcRxUdpErrorOctets = 0x0274, /*Number of bytes in IP datagrams with UDP payload having checksum error */ - - GmacMmcRxTcpOctetsG = 0x0278, /*Number of bytes in IP datagrams with good TDP payload */ - GmacMmcRxTcpErrorOctets = 0x027C, /*Number of bytes in IP datagrams with TCP payload having checksum error */ - - GmacMmcRxIcmpOctetsG = 0x0280, /*Number of bytes in IP datagrams with good Icmp payload */ - GmacMmcRxIcmpErrorOctets = 0x0284, /*Number of bytes in IP datagrams with Icmp payload having checksum error */ -}; - - -enum MMC_CNTRL_REG_BIT_DESCRIPTIONS -{ - GmacMmcCounterFreeze = 0x00000008, /* when set MMC counters freeze to current value */ - GmacMmcCounterResetOnRead = 0x00000004, /* when set MMC counters will be reset to 0 after read */ - GmacMmcCounterStopRollover = 0x00000002, /* when set counters will not rollover after max value */ - GmacMmcCounterReset = 0x00000001, /* when set all counters wil be reset (automatically cleared after 1 clk) */ - -}; - -enum MMC_RX_INTR_MASK_AND_STATUS_BIT_DESCRIPTIONS -{ - GmacMmcRxWDInt = 0x00800000, /* set when rxwatchdog error reaches half of max value */ - GmacMmcRxVlanInt = 0x00400000, /* set when GmacMmcRxVlanFramesGb counter reaches half of max value */ - GmacMmcRxFifoOverFlowInt = 0x00200000, /* set when GmacMmcRxFifoOverFlow counter reaches half of max value */ - GmacMmcRxPauseFrameInt = 0x00100000, /* set when GmacMmcRxPauseFrames counter reaches half of max value */ - GmacMmcRxOutOfRangeInt = 0x00080000, /* set when GmacMmcRxOutOfRangeType counter reaches half of max value */ - GmacMmcRxLengthErrorInt = 0x00040000, /* set when GmacMmcRxLengthError counter reaches half of max value */ - GmacMmcRxUcFramesInt = 0x00020000, /* set when GmacMmcRxUcFramesG counter reaches half of max value */ - GmacMmcRx1024OctInt = 0x00010000, /* set when GmacMmcRx1024ToMaxOctetsGb counter reaches half of max value */ - GmacMmcRx512OctInt = 0x00008000, /* set when GmacMmcRx512To1023OctetsGb counter reaches half of max value */ - GmacMmcRx256OctInt = 0x00004000, /* set when GmacMmcRx256To511OctetsGb counter reaches half of max value */ - GmacMmcRx128OctInt = 0x00002000, /* set when GmacMmcRx128To255OctetsGb counter reaches half of max value */ - GmacMmcRx65OctInt = 0x00001000, /* set when GmacMmcRx65To127OctetsG counter reaches half of max value */ - GmacMmcRx64OctInt = 0x00000800, /* set when GmacMmcRx64OctetsGb counter reaches half of max value */ - GmacMmcRxOverSizeInt = 0x00000400, /* set when GmacMmcRxOverSizeG counter reaches half of max value */ - GmacMmcRxUnderSizeInt = 0x00000200, /* set when GmacMmcRxUnderSizeG counter reaches half of max value */ - GmacMmcRxJabberErrorInt = 0x00000100, /* set when GmacMmcRxJabberError counter reaches half of max value */ - GmacMmcRxRuntErrorInt = 0x00000080, /* set when GmacMmcRxRuntError counter reaches half of max value */ - GmacMmcRxAlignErrorInt = 0x00000040, /* set when GmacMmcRxAlignError counter reaches half of max value */ - GmacMmcRxCrcErrorInt = 0x00000020, /* set when GmacMmcRxCrcError counter reaches half of max value */ - GmacMmcRxMcFramesInt = 0x00000010, /* set when GmacMmcRxMcFramesG counter reaches half of max value */ - GmacMmcRxBcFramesInt = 0x00000008, /* set when GmacMmcRxBcFramesG counter reaches half of max value */ - GmacMmcRxOctetGInt = 0x00000004, /* set when GmacMmcRxOctetCountG counter reaches half of max value */ - GmacMmcRxOctetGbInt = 0x00000002, /* set when GmacMmcRxOctetCountGb counter reaches half of max value */ - GmacMmcRxFrameInt = 0x00000001, /* set when GmacMmcRxFrameCountGb counter reaches half of max value */ -}; - -enum MMC_TX_INTR_MASK_AND_STATUS_BIT_DESCRIPTIONS -{ - - GmacMmcTxVlanInt = 0x01000000, /* set when GmacMmcTxVlanFramesG counter reaches half of max value */ - GmacMmcTxPauseFrameInt = 0x00800000, /* set when GmacMmcTxPauseFrames counter reaches half of max value */ - GmacMmcTxExessDefInt = 0x00400000, /* set when GmacMmcTxExessDef counter reaches half of max value */ - GmacMmcTxFrameInt = 0x00200000, /* set when GmacMmcTxFrameCount counter reaches half of max value */ - GmacMmcTxOctetInt = 0x00100000, /* set when GmacMmcTxOctetCountG counter reaches half of max value */ - GmacMmcTxCarrierErrorInt = 0x00080000, /* set when GmacMmcTxCarrierError counter reaches half of max value */ - GmacMmcTxExessColInt = 0x00040000, /* set when GmacMmcTxExessCol counter reaches half of max value */ - GmacMmcTxLateColInt = 0x00020000, /* set when GmacMmcTxLateCol counter reaches half of max value */ - GmacMmcTxDeferredInt = 0x00010000, /* set when GmacMmcTxDeferred counter reaches half of max value */ - GmacMmcTxMultiColInt = 0x00008000, /* set when GmacMmcTxMultiColG counter reaches half of max value */ - GmacMmcTxSingleCol = 0x00004000, /* set when GmacMmcTxSingleColG counter reaches half of max value */ - GmacMmcTxUnderFlowErrorInt = 0x00002000, /* set when GmacMmcTxUnderFlowError counter reaches half of max value */ - GmacMmcTxBcFramesGbInt = 0x00001000, /* set when GmacMmcTxBcFramesGb counter reaches half of max value */ - GmacMmcTxMcFramesGbInt = 0x00000800, /* set when GmacMmcTxMcFramesGb counter reaches half of max value */ - GmacMmcTxUcFramesInt = 0x00000400, /* set when GmacMmcTxUcFramesGb counter reaches half of max value */ - GmacMmcTx1024OctInt = 0x00000200, /* set when GmacMmcTx1024ToMaxOctetsGb counter reaches half of max value */ - GmacMmcTx512OctInt = 0x00000100, /* set when GmacMmcTx512To1023OctetsGb counter reaches half of max value */ - GmacMmcTx256OctInt = 0x00000080, /* set when GmacMmcTx256To511OctetsGb counter reaches half of max value */ - GmacMmcTx128OctInt = 0x00000040, /* set when GmacMmcTx128To255OctetsGb counter reaches half of max value */ - GmacMmcTx65OctInt = 0x00000020, /* set when GmacMmcTx65To127OctetsGb counter reaches half of max value */ - GmacMmcTx64OctInt = 0x00000010, /* set when GmacMmcTx64OctetsGb counter reaches half of max value */ - GmacMmcTxMcFramesInt = 0x00000008, /* set when GmacMmcTxMcFramesG counter reaches half of max value */ - GmacMmcTxBcFramesInt = 0x00000004, /* set when GmacMmcTxBcFramesG counter reaches half of max value */ - GmacMmcTxFrameGbInt = 0x00000002, /* set when GmacMmcTxFrameCountGb counter reaches half of max value */ - GmacMmcTxOctetGbInt = 0x00000001, /* set when GmacMmcTxOctetCountGb counter reaches half of max value */ - -}; - - -/********************************************************** - * Power Management (PMT) Block - **********************************************************/ - -/* - * PMT supports the reception of network (remote) wake-up frames and Magic packet frames. - * It generates interrupts for wake-up frames and Magic packets received by GMAC. - * PMT sits in Rx path and is enabled with remote wake-up frame enable and Magic packet enable. - * These enable are in PMT control and Status register and are programmed by apllication. - * - * When power down mode is enabled in PMT, all rx frames are dropped by the core. Core comes - * out of power down mode only when either Magic packe tor a Remote wake-up frame is received - * and the corresponding detection is enabled. - * - * Driver need not be modified to support this feature. Only Api to put the device in to power - * down mode is sufficient - */ - -#define WAKEUP_REG_LENGTH 8 /*This is the reg length for wake up register configuration*/ - -enum GmacPmtCtrlStatusBitDefinition -{ - GmacPmtFrmFilterPtrReset = 0x80000000, /* when set remote wake-up frame filter register pointer to 3'b000 */ - GmacPmtGlobalUnicast = 0x00000200, /* When set enables any unicast packet to be a wake-up frame */ - GmacPmtWakeupFrameReceived = 0x00000040, /* Wake up frame received */ - GmacPmtMagicPktReceived = 0x00000020, /* Magic Packet received */ - GmacPmtWakeupFrameEnable = 0x00000004, /* Wake-up frame enable */ - GmacPmtMagicPktEnable = 0x00000002, /* Magic packet enable */ - GmacPmtPowerDown = 0x00000001, /* Power Down */ -}; - - - - -/********************************************************** - * IEEE 1588-2008 Precision Time Protocol (PTP) Support - **********************************************************/ -enum PTPMessageType -{ - SYNC = 0x0, - Delay_Req = 0x1, - Pdelay_Req = 0x2, - Pdelay_Resp = 0x3, - Follow_up = 0x8, - Delay_Resp = 0x9, - Pdelay_Resp_Follow_Up = 0xA, - Announce = 0xB, - Signaling = 0xC, - Management = 0xD, -}; - - -/* - * IEEE 1588-2008 is the optional module to support Ethernet frame time stamping. - * Sixty four (+16) bit time stamps are given in each frames transmit and receive status. - * The driver assumes the following - * 1. "IEEE 1588 Time Stamping" "TIME_STAMPING"is ENABLED in corekit - * 2. "IEEE 1588 External Time Stamp Input Enable" "EXT_TIME_STAMPING" is DISABLED in corekit - * 3. "IEEE 1588 Advanced Time Stamp support" "ADV_TIME_STAMPING" is ENABLED in corekit - * 4. "IEEE 1588 Higher Word Register Enable" "ADV_TIME_HIGH_WORD" is ENABLED in corekit - */ - -/* GmacTSControl = 0x0700, Controls the Timestamp update logic : only when IEEE 1588 time stamping is enabled in corekit */ -enum GmacTSControlReg -{ - GmacTSENMACADDR = 0x00040000, /* Enable Mac Addr for PTP filtering 18 RW 0 */ - - GmacTSCLKTYPE = 0x00030000, /* Select the type of clock node 17:16 RW 00 */ - /* - TSCLKTYPE TSMSTRENA TSEVNTENA Messages for wihich TS snapshot is taken - 00/01 X 0 SYNC, FOLLOW_UP, DELAY_REQ, DELAY_RESP - 00/01 1 0 DELAY_REQ - 00/01 0 1 SYNC - 10 NA 0 SYNC, FOLLOW_UP, DELAY_REQ, DELAY_RESP - 10 NA 1 SYNC, FOLLOW_UP - 11 NA 0 SYNC, FOLLOW_UP, DELAY_REQ, DELAY_RESP, PDELAY_REQ, PDELAY_RESP - 11 NA 1 SYNC, PDELAY_REQ, PDELAY_RESP - */ - GmacTSOrdClk = 0x00000000, /* 00=> Ordinary clock*/ - GmacTSBouClk = 0x00010000, /* 01=> Boundary clock*/ - GmacTSEtoEClk = 0x00020000, /* 10=> End-to-End transparent clock*/ - GmacTSPtoPClk = 0x00030000, /* 11=> P-to-P transparent clock*/ - - GmacTSMSTRENA = 0x00008000, /* Ena TS Snapshot for Master Messages 15 RW 0 */ - GmacTSEVNTENA = 0x00004000, /* Ena TS Snapshot for Event Messages 14 RW 0 */ - GmacTSIPV4ENA = 0x00002000, /* Ena TS snapshot for IPv4 13 RW 1 */ - GmacTSIPV6ENA = 0x00001000, /* Ena TS snapshot for IPv6 12 RW 0 */ - GmacTSIPENA = 0x00000800, /* Ena TS snapshot for PTP over E'net 11 RW 0 */ - GmacTSVER2ENA = 0x00000400, /* Ena PTP snooping for version 2 10 RW 0 */ - - GmacTSCTRLSSR = 0x00000200, /* Digital or Binary Rollover 9 RW 0 */ - - GmacTSENALL = 0x00000100, /* Enable TS fro all frames (Ver2 only) 8 RW 0 */ - - GmacTSADDREG = 0x00000020, /* Addend Register Update 5 RW_SC 0 */ - GmacTSUPDT = 0x00000008, /* Time Stamp Update 3 RW_SC 0 */ - GmacTSINT = 0x00000004, /* Time Atamp Initialize 2 RW_SC 0 */ - - GmacTSTRIG = 0x00000010, /* Time stamp interrupt Trigger Enable 4 RW_SC 0 */ - - GmacTSCFUPDT = 0x00000002, /* Time Stamp Fine/Coarse 1 RW 0 */ - GmacTSCUPDTCoarse = 0x00000000, /* 0=> Time Stamp update method is coarse */ - GmacTSCUPDTFine = 0x00000002, /* 1=> Time Stamp update method is fine */ - - GmacTSENA = 0x00000001, /* Time Stamp Enable 0 RW 0 */ -}; - - -/* GmacTSSubSecIncr = 0x0704, 8 bit value by which sub second register is incremented : only when IEEE 1588 time stamping without external timestamp input */ -enum GmacTSSubSecIncrReg -{ - GmacSSINCMsk = 0x000000FF, /* Only Lower 8 bits are valid bits 7:0 RW 00 */ -}; - -/* GmacTSLow = 0x070C, Indicates whether the timestamp low count is positive or negative; for Adv timestamp it is always zero */ -enum GmacTSSign -{ - GmacTSSign = 0x80000000, /* PSNT 31 RW 0 */ - GmacTSPositive = 0x00000000, - GmacTSNegative = 0x80000000, -}; - -/*GmacTargetTimeLow = 0x0718, 32 bit nano seconds(MS) to be compared with system time : only when IEEE 1588 time stamping without external timestamp input */ -enum GmacTSLowReg -{ - GmacTSDecThr = 0x3B9AC9FF, /*when TSCTRLSSR is set the max value for GmacTargetTimeLowReg and GmacTimeStampLow register is 0x3B9AC9FF at 1ns precision */ -}; - -/* GmacTSHighWord = 0x0724, Time Stamp Higher Word Register (Version 2 only); only lower 16 bits are valid */ -enum GmacTSHighWordReg -{ - GmacTSHighWordMask = 0x0000FFFF, /* Time Stamp Higher work register has only lower 16 bits valid */ -}; -/*GmacTSStatus = 0x0728, Time Stamp Status Register */ -enum GmacTSStatusReg -{ - GmacTSTargTimeReached = 0x00000002, /* Time Stamp Target Time Reached 1 RO 0 */ - GmacTSSecondsOverflow = 0x00000001, /* Time Stamp Seconds Overflow 0 RO 0 */ -}; - -/********************************************************** - * Time stamp related functions - **********************************************************/ -void synopGMAC_TS_enable(synopGMACdevice *gmacdev); -void synopGMAC_TS_disable(synopGMACdevice *gmacdev); - -void synopGMAC_TS_int_enable(synopGMACdevice *gmacdev); -void synopGMAC_TS_int_disable(synopGMACdevice *gmacdev); - -void synopGMAC_TS_mac_addr_filt_enable(synopGMACdevice *gmacdev); -void synopGMAC_TS_mac_addr_filt_disable(synopGMACdevice *gmacdev); -void synopGMAC_TS_set_clk_type(synopGMACdevice *gmacdev, u32 clk_type); -void synopGMAC_TS_master_enable(synopGMACdevice *gmacdev); // Only for Ordinary clock and Boundary clock and "Advanced Time Stamp" -void synopGMAC_TS_master_disable(synopGMACdevice *gmacdev); // Only for Ordinary clock and Boundary clock and "Advanced Time Stamp" -void synopGMAC_TS_event_enable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" -void synopGMAC_TS_event_disable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" -void synopGMAC_TS_IPV4_enable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" -void synopGMAC_TS_IPV4_disable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" -void synopGMAC_TS_IPV6_enable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" -void synopGMAC_TS_IPV6_disable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" -void synopGMAC_TS_ptp_over_ethernet_enable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" -void synopGMAC_TS_ptp_over_ethernet_disable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" -void synopGMAC_TS_pkt_snoop_ver2(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" -void synopGMAC_TS_pkt_snoop_ver1(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" - -void synopGMAC_TS_digital_rollover_enable(synopGMACdevice *gmacdev); -void synopGMAC_TS_binary_rollover_enable(synopGMACdevice *gmacdev); -void synopGMAC_TS_all_frames_enable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" -void synopGMAC_TS_all_frames_disable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" - -s32 synopGMAC_TS_addend_update(synopGMACdevice *gmacdev, u32 addend_value); -s32 synopGMAC_TS_timestamp_update(synopGMACdevice *gmacdev, u32 high_value, u32 low_value); -s32 synopGMAC_TS_timestamp_init(synopGMACdevice *gmacdev, u32 high_value, u32 low_value); - -void synopGMAC_TS_coarse_update(synopGMACdevice *gmacdev); // Only if "fine correction" enabled -void synopGMAC_TS_fine_update(synopGMACdevice *gmacdev); // Only if "fine correction" enabled - -void synopGMAC_TS_subsecond_init(synopGMACdevice *gmacdev, u32 sub_sec_inc_val); // Update should happen making use of subsecond mask -void synopGMAC_TS_read_timestamp(synopGMACdevice *gmacdev, u16 * higher_sec_val, - u32 * sec_val, u32 * sub_sec_val); // Reads the timestamp low,high and higher(Ver2) registers in the the struct pointer; readonly contents -void synopGMAC_TS_load_target_timestamp(synopGMACdevice *gmacdev, u32 sec_val, u32 sub_sec_val); //Loads the timestamp target register with the values provided - -void synopGMAC_TS_load_timestamp_higher_val(synopGMACdevice *gmacdev, u32 higher_sec_val); -void synopGMAC_TS_read_timestamp_higher_val(synopGMACdevice *gmacdev, u16 * higher_sec_val); -void synopGMAC_TS_read_target_timestamp(synopGMACdevice *gmacdev, u32 * sec_val, u32 * sub_sec_val); //Read the target time stamp register contents - -/*******************Ip checksum offloading APIs***************************************/ -void synopGMAC_enable_rx_chksum_offload(synopGMACdevice *gmacdev); -void synopGMAC_disable_rx_Ipchecksum_offload(synopGMACdevice *gmacdev); -void synopGMAC_rx_tcpip_chksum_drop_enable(synopGMACdevice *gmacdev); -void synopGMAC_rx_tcpip_chksum_drop_disable(synopGMACdevice *gmacdev); - -/* - * Decodes the Rx Descriptor status to various checksum error conditions. - * @param[in] pointer to synopGMACdevice. - * @param[in] u32 status field of the corresponding descriptor. - * \return returns decoded enum (u32) indicating the status. - */ -static inline u32 synopGMAC_is_rx_checksum_error(synopGMACdevice *gmacdev, u32 status) -{ - return (status & (DescRxChkBit7 | DescRxChkBit5 | DescRxChkBit0)); -} - -/* - * Checks if any Ipv4 header checksum error in the frame just transmitted. - * This serves as indication that error occureed in the IPv4 header checksum insertion. - * The sent out frame doesnot carry any ipv4 header checksum inserted by the hardware. - * @param[in] pointer to synopGMACdevice. - * @param[in] u32 status field of the corresponding descriptor. - * \return returns true if error in ipv4 header checksum, else returns false. - */ -static inline bool synopGMAC_is_tx_ipv4header_checksum_error(synopGMACdevice *gmacdev, u32 status) -{ - return((status & DescTxIpv4ChkError) == DescTxIpv4ChkError); -} - -/* - * Checks if any payload checksum error in the frame just transmitted. - * This serves as indication that error occureed in the payload checksum insertion. - * The sent out frame doesnot carry any payload checksum inserted by the hardware. - * @param[in] pointer to synopGMACdevice. - * @param[in] u32 status field of the corresponding descriptor. - * \return returns true if error in ipv4 header checksum, else returns false. - */ -static inline bool synopGMAC_is_tx_payload_checksum_error(synopGMACdevice *gmacdev, u32 status) -{ - return((status & DescTxPayChkError) == DescTxPayChkError); -} - -/* - * The check summ offload engine is bypassed in the tx path. - * Checksum is not computed in the Hardware. - * @param[in] pointer to synopGMACdevice. - * @param[in] Pointer to tx descriptor for which ointer to synopGMACdevice. - * \return returns void. - */ -static inline void synopGMAC_tx_checksum_offload_bypass(synopGMACdevice *gmacdev, DmaDesc *desc) -{ - #ifdef ENH_DESC - desc->status = (desc->length & (~DescTxCisMask));//ENH_DESC - #else - desc->length = (desc->length & (~DescTxCisMask)); - #endif - -} - -/* - * The check summ offload engine is enabled to do only IPV4 header checksum. - * IPV4 header Checksum is computed in the Hardware. - * @param[in] pointer to synopGMACdevice. - * @param[in] Pointer to tx descriptor for which ointer to synopGMACdevice. - * \return returns void. - */ -static inline void synopGMAC_tx_checksum_offload_ipv4hdr(synopGMACdevice *gmacdev, DmaDesc *desc) -{ - #ifdef ENH_DESC - desc->status = ((desc->status & (~DescTxCisMask)) | DescTxCisIpv4HdrCs);//ENH_DESC - #else - desc->length = ((desc->length & (~DescTxCisMask)) | DescTxCisIpv4HdrCs); - #endif - -} - -/* - * The check summ offload engine is enabled to do TCPIP checsum assuming Pseudo header is available. - * Hardware computes the tcp ip checksum assuming pseudo header checksum is computed in software. - * Ipv4 header checksum is also inserted. - * @param[in] pointer to synopGMACdevice. - * @param[in] Pointer to tx descriptor for which ointer to synopGMACdevice. - * \return returns void. - */ -static inline void synopGMAC_tx_checksum_offload_tcponly(synopGMACdevice *gmacdev, DmaDesc *desc) -{ - #ifdef ENH_DESC - desc->status = ((desc->status & (~DescTxCisMask)) | DescTxCisTcpOnlyCs);//ENH_DESC - #else - desc->length = ((desc->length & (~DescTxCisMask)) | DescTxCisTcpOnlyCs); - #endif - -} - -/* - * The check summ offload engine is enabled to do complete checksum computation. - * Hardware computes the tcp ip checksum including the pseudo header checksum. - * Here the tcp payload checksum field should be set to 0000. - * Ipv4 header checksum is also inserted. - * @param[in] pointer to synopGMACdevice. - * @param[in] Pointer to tx descriptor for which ointer to synopGMACdevice. - * \return returns void. - */ -static inline void synopGMAC_tx_checksum_offload_tcp_pseudo(synopGMACdevice *gmacdev, DmaDesc *desc) -{ - #ifdef ENH_DESC - desc->status = ((desc->length & (~DescTxCisMask)) | DescTxCisTcpPseudoCs); - #else - desc->length = ((desc->length & (~DescTxCisMask)) | DescTxCisTcpPseudoCs); - #endif - -} - -/********************************************************** - * Common functions - **********************************************************/ -s32 synopGMAC_set_mdc_clk_div(synopGMACdevice *gmacdev,u32 clk_div_val); -u32 synopGMAC_get_mdc_clk_div(synopGMACdevice *gmacdev); -s32 synopGMAC_read_phy_reg(u32 *RegBase,u32 PhyBase, u32 RegOffset, u16 * data); -s32 synopGMAC_write_phy_reg(u32 *RegBase, u32 PhyBase, u32 RegOffset, u16 data); -s32 synopGMAC_read_version (synopGMACdevice * gmacdev) ; -void synopGMAC_reset (synopGMACdevice * gmacdev ); -s32 synopGMAC_dma_bus_mode_init(synopGMACdevice * gmacdev, u32 init_value ); -s32 synopGMAC_dma_control_init(synopGMACdevice * gmacdev, u32 init_value); -void synopGMAC_wd_enable(synopGMACdevice * gmacdev); -void synopGMAC_wd_disable(synopGMACdevice * gmacdev); -void synopGMAC_jab_enable(synopGMACdevice * gmacdev); -void synopGMAC_jab_disable(synopGMACdevice * gmacdev); -void synopGMAC_frame_burst_enable(synopGMACdevice * gmacdev); -void synopGMAC_frame_burst_disable(synopGMACdevice * gmacdev); -void synopGMAC_select_gmii(synopGMACdevice * gmacdev); -void synopGMAC_select_mii(synopGMACdevice * gmacdev); -void synopGMAC_rx_own_enable(synopGMACdevice * gmacdev); -void synopGMAC_rx_own_disable(synopGMACdevice * gmacdev); -void synopGMAC_loopback_on(synopGMACdevice * gmacdev); -void synopGMAC_loopback_off(synopGMACdevice * gmacdev); -void synopGMAC_set_full_duplex(synopGMACdevice * gmacdev); -void synopGMAC_set_half_duplex(synopGMACdevice * gmacdev); -void synopGMAC_retry_enable(synopGMACdevice * gmacdev); -void synopGMAC_retry_disable(synopGMACdevice * gmacdev); -void synopGMAC_pad_crc_strip_enable(synopGMACdevice * gmacdev); -void synopGMAC_pad_crc_strip_disable(synopGMACdevice * gmacdev); -void synopGMAC_back_off_limit(synopGMACdevice * gmacdev, u32 value); -void synopGMAC_deferral_check_enable(synopGMACdevice * gmacdev); -void synopGMAC_deferral_check_disable(synopGMACdevice * gmacdev); -void synopGMAC_rx_enable(synopGMACdevice * gmacdev); -void synopGMAC_rx_disable(synopGMACdevice * gmacdev); -void synopGMAC_tx_enable(synopGMACdevice * gmacdev); -void synopGMAC_tx_disable(synopGMACdevice * gmacdev); -void synopGMAC_frame_filter_enable(synopGMACdevice * gmacdev); -void synopGMAC_frame_filter_disable(synopGMACdevice * gmacdev); -void synopGMAC_write_hash_table_high(synopGMACdevice * gmacdev, u32 data); -void synopGMAC_write_hash_table_low(synopGMACdevice * gmacdev, u32 data); -void synopGMAC_hash_perfect_filter_enable(synopGMACdevice * gmacdev); -void synopGMAC_Hash_filter_only_enable(synopGMACdevice * gmacdev); -void synopGMAC_src_addr_filter_enable(synopGMACdevice * gmacdev); -void synopGMAC_src_addr_filter_disable(synopGMACdevice * gmacdev); -void synopGMAC_dst_addr_filter_inverse(synopGMACdevice * gmacdev); -void synopGMAC_dst_addr_filter_normal(synopGMACdevice * gmacdev); -void synopGMAC_set_pass_control(synopGMACdevice * gmacdev,u32 passcontrol); -void synopGMAC_broadcast_enable(synopGMACdevice * gmacdev); -void synopGMAC_broadcast_disable(synopGMACdevice * gmacdev); -void synopGMAC_multicast_enable(synopGMACdevice * gmacdev); -void synopGMAC_multicast_disable(synopGMACdevice * gmacdev); -void synopGMAC_multicast_hash_filter_enable(synopGMACdevice * gmacdev); -void synopGMAC_multicast_hash_filter_disable(synopGMACdevice * gmacdev); -void synopGMAC_promisc_enable(synopGMACdevice * gmacdev); -void synopGMAC_promisc_disable(synopGMACdevice * gmacdev); -void synopGMAC_unicast_hash_filter_enable(synopGMACdevice * gmacdev); -void synopGMAC_unicast_hash_filter_disable(synopGMACdevice * gmacdev); -void synopGMAC_unicast_pause_frame_detect_enable(synopGMACdevice * gmacdev); -void synopGMAC_unicast_pause_frame_detect_disable(synopGMACdevice * gmacdev); -void synopGMAC_rx_flow_control_enable(synopGMACdevice * gmacdev); -void synopGMAC_rx_flow_control_disable(synopGMACdevice * gmacdev); -void synopGMAC_tx_flow_control_enable(synopGMACdevice * gmacdev); -void synopGMAC_tx_flow_control_disable(synopGMACdevice * gmacdev); -void synopGMAC_tx_activate_flow_control(synopGMACdevice * gmacdev); -void synopGMAC_tx_deactivate_flow_control(synopGMACdevice * gmacdev); -void synopGMAC_pause_control(synopGMACdevice *gmacdev); -s32 synopGMAC_mac_init(synopGMACdevice * gmacdev); -s32 synopGMAC_check_phy_init (synopGMACdevice * gmacdev); -s32 synopGMAC_set_mac_addr(synopGMACdevice *gmacdev, u32 MacHigh, u32 MacLow, u8 *MacAddr); -s32 synopGMAC_get_mac_addr(synopGMACdevice *gmacdev, u32 MacHigh, u32 MacLow, u8 *MacAddr); -s32 synopGMAC_attach (synopGMACdevice * gmacdev, u32 regBase); - -/* - * Initialize the rx descriptors for ring or chain mode operation. - * - Status field is initialized to 0. - * - EndOfRing set for the last descriptor. - * - buffer1 and buffer2 set to 0 for ring mode of operation. (note) - * - data1 and data2 set to 0. (note) - * @param[in] pointer to DmaDesc structure. - * @param[in] whether end of ring - * \return void. - * \note Initialization of the buffer1, buffer2, data1,data2 and status are not done here. This only initializes whether one wants to use this descriptor - * in chain mode or ring mode. For chain mode of operation the buffer2 and data2 are programmed before calling this function. - */ -static inline void synopGMAC_rx_desc_init_ring(DmaDesc *desc, bool last_ring_desc) -{ - desc->status = 0; - desc->length = last_ring_desc ? RxDescEndOfRing : 0; - desc->buffer1 = 0; - desc->data1 = 0; - return; -} - -/* - * Initialize the tx descriptors for ring or chain mode operation. - * - Status field is initialized to 0. - * - EndOfRing set for the last descriptor. - * - buffer1 and buffer2 set to 0 for ring mode of operation. (note) - * - data1 and data2 set to 0. (note) - * @param[in] pointer to DmaDesc structure. - * @param[in] whether end of ring - * \return void. - * \note Initialization of the buffer1, buffer2, data1,data2 and status are not done here. This only initializes whether one wants to use this descriptor - * in chain mode or ring mode. For chain mode of operation the buffer2 and data2 are programmed before calling this function. - */ -static inline void synopGMAC_tx_desc_init_ring(DmaDesc *desc, bool last_ring_desc) -{ - #ifdef ENH_DESC - desc->status = last_ring_desc? TxDescEndOfRing : 0; - desc->length = 0; - #else - desc->length = last_ring_desc? TxDescEndOfRing : 0; - #endif - desc->buffer1 = 0; - desc->data1 = 0; - return; -} - -/* - * Initialize the rx descriptors for chain mode of operation. - * - Status field is initialized to 0. - * - EndOfRing set for the last descriptor. - * - buffer1 and buffer2 set to 0. - * - data1 and data2 set to 0. - * @param[in] pointer to DmaDesc structure. - * @param[in] whether end of ring - * \return void. - -static inline void synopGMAC_rx_desc_init_chain(DmaDesc * desc) -{ - desc->status = 0; - desc->length = RxDescChain; - desc->buffer1 = 0; - desc->data1 = 0; - return; -} - */ - -/* - * Initialize the rx descriptors for chain mode of operation. - * - Status field is initialized to 0. - * - EndOfRing set for the last descriptor. - * - buffer1 and buffer2 set to 0. - * - data1 and data2 set to 0. - * @param[in] pointer to DmaDesc structure. - * @param[in] whether end of ring - * \return void. -static inline void synopGMAC_tx_desc_init_chain(DmaDesc * desc) -{ - #ifdef ENH_DESC - desc->status = TxDescChain; - desc->length = 0; - #else - desc->length = TxDescChain; - #endif - desc->buffer1 = 0; - desc->data1 = 0; - return; -} - */ - -s32 synopGMAC_init_tx_rx_desc_queue(synopGMACdevice *gmacdev); -void synopGMAC_init_rx_desc_base(synopGMACdevice *gmacdev); -void synopGMAC_init_tx_desc_base(synopGMACdevice *gmacdev); -void synopGMAC_set_owner_dma(DmaDesc *desc); -void synopGMAC_set_desc_sof(DmaDesc *desc); -void synopGMAC_set_desc_eof(DmaDesc *desc); -bool synopGMAC_is_sof_in_rx_desc(DmaDesc *desc); -bool synopGMAC_is_eof_in_rx_desc(DmaDesc *desc); -bool synopGMAC_is_da_filter_failed(DmaDesc *desc); -bool synopGMAC_is_sa_filter_failed(DmaDesc *desc); - -/* - * Checks whether the descriptor is owned by DMA. - * If descriptor is owned by DMA then the OWN bit is set to 1. This API is same for both ring and chain mode. - * @param[in] pointer to DmaDesc structure. - * \return returns true if Dma owns descriptor and false if not. - */ -static inline bool synopGMAC_is_desc_owned_by_dma(DmaDesc *desc) -{ -return ((desc->status & DescOwnByDma) == DescOwnByDma ); -} - -/* - * returns the byte length of received frame including CRC. - * This returns the no of bytes received in the received ethernet frame including CRC(FCS). - * @param[in] pointer to DmaDesc structure. - * \return returns the length of received frame lengths in bytes. - */ -static inline u32 synopGMAC_get_rx_desc_frame_length(u32 status) -{ - return ((status & DescFrameLengthMask) >> DescFrameLengthShift); -} - -/* - * Checks whether the descriptor is valid - * if no errors such as CRC/Receive Error/Watchdog Timeout/Late collision/Giant Frame/Overflow/Descriptor - * error the descritpor is said to be a valid descriptor. - * @param[in] pointer to DmaDesc structure. - * \return True if desc valid. false if error. - */ -static inline bool synopGMAC_is_desc_valid(u32 status) -{ - return ((status & DescError) == 0); -} - -/* - * Checks whether the descriptor is empty. - * If the buffer1 and buffer2 lengths are zero in ring mode descriptor is empty. - * In chain mode buffer2 length is 0 but buffer2 itself contains the next descriptor address. - * @param[in] pointer to DmaDesc structure. - * \return returns true if descriptor is empty, false if not empty. - */ -static inline bool synopGMAC_is_desc_empty(DmaDesc *desc) -{ - //if both the buffer1 length and buffer2 length are zero desc is empty - return ((desc->length & DescSize1Mask) == 0); -} - -/* - * Checks whether the rx descriptor is valid. - * if rx descripor is not in error and complete frame is available in the same descriptor - * @param[in] pointer to DmaDesc structure. - * \return returns true if no error and first and last desc bits are set, otherwise it returns false. - */ -static inline bool synopGMAC_is_rx_desc_valid(u32 status) -{ - return ((status & (DescError|DescRxFirst|DescRxLast)) == (DescRxFirst|DescRxLast)); -} - -bool synopGMAC_is_tx_aborted(u32 status); -bool synopGMAC_is_tx_carrier_error(u32 status); - -/* - * Gives the transmission collision count. - * returns the transmission collision count indicating number of collisions occured before the frame was transmitted. - * Make sure to check excessive collision didnot happen to ensure the count is valid. - * @param[in] pointer to DmaDesc structure. - * \return returns the count value of collision. - */ -static inline u32 synopGMAC_get_tx_collision_count(u32 status) -{ - return ((status & DescTxCollMask) >> DescTxCollShift); -} - -static inline u32 synopGMAC_is_exc_tx_collisions(u32 status) -{ - return ((status & DescTxExcCollisions) == DescTxExcCollisions); -} - -bool synopGMAC_is_rx_frame_damaged(u32 status); -bool synopGMAC_is_rx_frame_collision(u32 status); -bool synopGMAC_is_rx_crc(u32 status); -bool synopGMAC_is_frame_dribbling_errors(u32 status); -bool synopGMAC_is_rx_frame_length_errors(u32 status); - -/* - * Checks whether this rx descriptor is last rx descriptor. - * This returns true if it is last descriptor either in ring mode or in chain mode. - * @param[in] pointer to devic structure. - * @param[in] pointer to DmaDesc structure. - * \return returns true if it is last descriptor, false if not. - * \note This function should not be called before initializing the descriptor using synopGMAC_desc_init(). - */ -static inline bool synopGMAC_is_last_rx_desc(synopGMACdevice * gmacdev,DmaDesc *desc) -{ - return (unlikely((desc->length & RxDescEndOfRing) != 0)); -} - -/* - * Checks whether this tx descriptor is last tx descriptor. - * This returns true if it is last descriptor either in ring mode or in chain mode. - * @param[in] pointer to devic structure. - * @param[in] pointer to DmaDesc structure. - * \return returns true if it is last descriptor, false if not. - * \note This function should not be called before initializing the descriptor using synopGMAC_desc_init(). - */ -static inline bool synopGMAC_is_last_tx_desc(synopGMACdevice * gmacdev,DmaDesc *desc) -{ -#ifdef ENH_DESC - return (unlikely((desc->status & TxDescEndOfRing) != 0)); -#else - return (unlikely((desc->length & TxDescEndOfRing) != 0)); -#endif -} - -/* - * Checks whether this rx descriptor is in chain mode. - * This returns true if it is this descriptor is in chain mode. - * @param[in] pointer to DmaDesc structure. - * \return returns true if chain mode is set, false if not. - */ -static inline bool synopGMAC_is_rx_desc_chained(DmaDesc * desc) -{ - /* - * This is also the only way to support jumbo in the futrue. - */ - return 0; //((desc->length & RxDescChain) == RxDescChain); -} - -/* - * Checks whether this tx descriptor is in chain mode. - * This returns true if it is this descriptor is in chain mode. - * @param[in] pointer to DmaDesc structure. - * \return returns true if chain mode is set, false if not. - */ -static inline bool synopGMAC_is_tx_desc_chained(DmaDesc * desc) -{ - /* - * This is also the only way to support jumbo in the futrue. - */ - return 0; -#ifdef ENH_DESC - //return((desc->status & TxDescChain) == TxDescChain); -#else - //return((desc->length & TxDescChain) == TxDescChain); -#endif -} - -void synopGMAC_get_desc_data(DmaDesc * desc, u32 * Status, u32 * Buffer1, u32 * Length1, u32 * Data1); - -/* - * This function is defined two times. Once when the code is compiled for ENHANCED DESCRIPTOR SUPPORT and Once for Normal descriptor - * Get the index and address of Tx desc. - * This api is same for both ring mode and chain mode. - * This function tracks the tx descriptor the DMA just closed after the transmission of data from this descriptor is - * over. This returns the descriptor fields to the caller. - * @param[in] pointer to synopGMACdevice. - * @param[out] status field of the descriptor. - * @param[out] Dma-able buffer1 pointer. - * @param[out] length of buffer1 (Max is 2048). - * @param[out] virtual pointer for buffer1. - * @param[out] Dma-able buffer2 pointer. - * @param[out] length of buffer2 (Max is 2048). - * @param[out] virtual pointer for buffer2. - * @param[out] u32 data indicating whether the descriptor is in ring mode or chain mode. - * \return returns present tx descriptor index on success. Negative value if error. - */ -static inline DmaDesc *synopGMAC_get_tx_qptr(synopGMACdevice * gmacdev) -{ - DmaDesc * txdesc = gmacdev->TxBusyDesc; - - if (unlikely(gmacdev->BusyTxDesc == 0)) { - return NULL; - } - - if(synopGMAC_is_desc_owned_by_dma(txdesc)) { - return NULL; - } - BUG_ON(synopGMAC_is_desc_empty(txdesc)); - - return txdesc; -} - -static inline void synopGMAC_reset_tx_qptr(synopGMACdevice * gmacdev) -{ - u32 txover = gmacdev->TxBusy; - DmaDesc * txdesc = gmacdev->TxBusyDesc; - - BUG_ON(txdesc != (gmacdev->TxDesc + txover)); - gmacdev->TxBusy = (txover + 1) & (gmacdev->TxDescCount -1); - gmacdev->TxBusyDesc = gmacdev->TxDesc + gmacdev->TxBusy; - - #ifdef ENH_DESC - txdesc->status &= TxDescEndOfRing; - txdesc->length = 0; - #else - txdesc->length &= TxDescEndOfRing; - #endif - txdesc->buffer1 = 0; - txdesc->data1 = 0; - - (gmacdev->BusyTxDesc)--; //busy tx descriptor is reduced by one as it will be handed over to Processor now //Akronite -// asm volatile ("sub.4 %0, %0, %1" : : "U4"(gmacdev->BusyTxDesc), "d"(1) : "cc", "memory"); //Akronite -} - -/* - * Populate the tx desc structure with the buffer address. - * Once the driver has a packet ready to be transmitted, this function is called with the - * valid dma-able buffer addresses and their lengths. This function populates the descriptor - * and make the DMA the owner for the descriptor. This function also controls whetther Checksum - * offloading to be done in hardware or not. - * This api is same for both ring mode and chain mode. - * @param[in] pointer to synopGMACdevice. - * @param[in] Dma-able buffer1 pointer. - * @param[in] length of buffer1 (Max is 2048). - * @param[in] virtual pointer for buffer1. - * @param[in] Dma-able buffer2 pointer. - * @param[in] length of buffer2 (Max is 2048). - * @param[in] virtual pointer for buffer2. - * @param[in] u32 data indicating whether the descriptor is in ring mode or chain mode. - * @param[in] u32 indicating whether the checksum offloading in HW/SW. - * \return returns present tx descriptor index on success. Negative value if error. - */ -static inline s32 synopGMAC_set_tx_qptr(synopGMACdevice * gmacdev, u32 Buffer1, u32 Length1, u32 Data1,u32 offload_needed) -{ - u32 txnext = gmacdev->TxNext; - DmaDesc * txdesc = gmacdev->TxNextDesc; - - BUG_ON(gmacdev->BusyTxDesc > gmacdev->TxDescCount); - BUG_ON(txdesc != (gmacdev->TxDesc + txnext)); - BUG_ON(!synopGMAC_is_desc_empty(txdesc)); - BUG_ON(synopGMAC_is_desc_owned_by_dma(txdesc)); - - txdesc->length |= ((Length1 <status |= (DescTxFirst | DescTxLast | DescTxIntEnable); //ENH_DESC - #else - txdesc->length |= (DescTxFirst | DescTxLast | DescTxIntEnable); //Its always assumed that complete data will fit in to one descriptor - #endif - - txdesc->buffer1 = Buffer1; - txdesc->data1 = Data1; - - if (likely(offload_needed)) { - /* - Make sure that the OS you are running supports the IP and TCP checkusm offloaidng, - before calling any of the functions given below. - */ - //synopGMAC_tx_checksum_offload_ipv4hdr(gmacdev, txdesc); - synopGMAC_tx_checksum_offload_tcponly(gmacdev, txdesc); - //synopGMAC_tx_checksum_offload_tcp_pseudo(gmacdev, txdesc); - } - - #ifdef ENH_DESC - txdesc->status |= DescOwnByDma;//ENH_DESC - #else - txdesc->status = DescOwnByDma; - #endif - TR("%02d %08x %08x %08x %08x %08x\n", txnext, (u32)txdesc, - txdesc->status, txdesc->length, txdesc->buffer1, txdesc->data1); - - gmacdev->TxNext = (txnext + 1) & (gmacdev->TxDescCount - 1); - gmacdev->TxNextDesc = gmacdev->TxDesc + gmacdev->TxNext; - - (gmacdev->BusyTxDesc)++; //busy tx descriptor is reduced by one as it will be handed over to Processor now - - return txnext; -} - -/* - * Prepares the descriptor to receive packets. - * The descriptor is allocated with the valid buffer addresses (sk_buff address) and the length fields - * and handed over to DMA by setting the ownership. After successful return from this function the - * descriptor is added to the receive descriptor pool/queue. - * This api is same for both ring mode and chain mode. - * @param[in] pointer to synopGMACdevice. - * @param[in] Dma-able buffer1 pointer. - * @param[in] length of buffer1 (Max is 2048). - * @param[in] Dma-able buffer2 pointer. - * @param[in] length of buffer2 (Max is 2048). - * @param[in] u32 data indicating whether the descriptor is in ring mode or chain mode. - * \return returns present rx descriptor index on success. Negative value if error. - */ -static inline s32 synopGMAC_set_rx_qptr(synopGMACdevice * gmacdev, u32 Buffer1, u32 Length1, u32 Data1) -{ - u32 rxnext = gmacdev->RxNext; - DmaDesc * rxdesc = gmacdev->RxNextDesc; - - BUG_ON(gmacdev->BusyRxDesc >= gmacdev->RxDescCount); - BUG_ON(rxdesc != (gmacdev->RxDesc + rxnext)); - BUG_ON(!synopGMAC_is_desc_empty(rxdesc)); - BUG_ON(synopGMAC_is_desc_owned_by_dma(rxdesc)); - - rxdesc->length |= ((Length1 <buffer1 = Buffer1; - rxdesc->data1 = Data1; - -#ifdef ENH_DESC_8W - rxdesc->extstatus = 0; - rxdesc->reserved1 = 0; - rxdesc->timestamplow = 0; - rxdesc->timestamphigh = 0; -#endif - - rxdesc->status = DescOwnByDma; - TR("%02d %08x %08x %08x %08x %08x\n", rxnext, (u32)rxdesc, - rxdesc->status, rxdesc->length, rxdesc->buffer1, rxdesc->data1); - - gmacdev->RxNext = (rxnext + 1) & (gmacdev->RxDescCount - 1); - gmacdev->RxNextDesc = gmacdev->RxDesc + gmacdev->RxNext; - - (gmacdev->BusyRxDesc)++; //One descriptor will be given to Hardware. So busy count incremented by one - return rxnext; -} - -/* - * This function is defined two times. Once when the code is compiled for ENHANCED DESCRIPTOR SUPPORT and Once for Normal descriptor - * Get back the descriptor from DMA after data has been received. - * When the DMA indicates that the data is received (interrupt is generated), this function should be - * called to get the descriptor and hence the data buffers received. With successful return from this - * function caller gets the descriptor fields for processing. check the parameters to understand the - * fields returned.` - * @param[in] pointer to synopGMACdevice. - * @param[out] pointer to hold the status of DMA. - * @param[out] Dma-able buffer1 pointer. - * @param[out] pointer to hold length of buffer1 (Max is 2048). - * @param[out] virtual pointer for buffer1. - * @param[out] Dma-able buffer2 pointer. - * @param[out] pointer to hold length of buffer2 (Max is 2048). - * @param[out] virtual pointer for buffer2. - * \return returns present rx descriptor index on success. Negative value if error. - */ -static inline DmaDesc *synopGMAC_get_rx_qptr(synopGMACdevice * gmacdev) -{ - DmaDesc * rxdesc = gmacdev->RxBusyDesc; - - if (unlikely(gmacdev->BusyRxDesc == 0)) { - return NULL; - } - - if((gmacdev->state == ETH_STATE_PASSIVE) || synopGMAC_is_desc_owned_by_dma(rxdesc)) { - return NULL; - } - BUG_ON(synopGMAC_is_desc_empty(rxdesc)); - - return rxdesc; -} - -static inline void synopGMAC_reset_rx_qptr(synopGMACdevice * gmacdev) -{ - u32 rxnext = gmacdev->RxBusy; // index of descriptor the DMA just completed. May be useful when data - //is spread over multiple buffers/descriptors - DmaDesc * rxdesc = gmacdev->RxBusyDesc; - - BUG_ON(rxdesc != (gmacdev->RxDesc + rxnext)); - gmacdev->RxBusy = (rxnext + 1) & (gmacdev->RxDescCount - 1); - gmacdev->RxBusyDesc = gmacdev->RxDesc + gmacdev->RxBusy; - - rxdesc->status = 0; - rxdesc->length &= RxDescEndOfRing; - rxdesc->buffer1 = 0; - rxdesc->data1 = 0; - - (gmacdev->BusyRxDesc)--; //This returns one descriptor to processor. So busy count will be decremented by one //Akronite - -// asm volatile ("sub.4 %0, %0, %1" : : "U4"(gmacdev->BusyRxDesc), "d"(1) : "cc", "memory"); //Akronite -} - -/* - * Clears all the pending interrupts. - * If the Dma status register is read then all the interrupts gets cleared - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -static inline void synopGMAC_clear_interrupt(synopGMACdevice *gmacdev) -{ - u32 data; - data = synopGMACReadReg((u32 *)gmacdev->DmaBase, DmaStatus); - synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaStatus ,data); -} - -/* - * Returns the all unmasked interrupt status after reading the DmaStatus register. - * @param[in] pointer to synopGMACdevice. - * \return 0 upon success. Error code upon failure. - */ -static inline u32 synopGMAC_get_interrupt_type(synopGMACdevice *gmacdev) -{ - u32 interrupts = 0; - interrupts = synopGMACReadReg((u32 *)gmacdev->DmaBase, DmaStatus); - synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaStatus ,interrupts); // Clear interrupt here - - return interrupts; -} - -/* - * Returns the interrupt mask. - * @param[in] pointer to synopGMACdevice. - * \return 0 upon success. Error code upon failure. - */ -static inline u32 synopGMAC_get_interrupt_mask(synopGMACdevice *gmacdev) -{ - return(synopGMACReadReg((u32 *)gmacdev->DmaBase, DmaInterrupt)); -} - -/* - * Enable all the interrupts. - * Enables the DMA interrupt as specified by the bit mask. - * @param[in] pointer to synopGMACdevice. - * @param[in] bit mask of interrupts to be enabled. - * \return returns void. - */ -static inline void synopGMAC_enable_interrupt(synopGMACdevice *gmacdev, u32 interrupts) -{ - synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaInterrupt, interrupts); -} - -/* - * Disable all the interrupts. - * Disables all DMA interrupts. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - * \note This function disabled all the interrupts, if you want to disable a particular interrupt then - * use synopGMAC_disable_interrupt(). - */ -static inline void synopGMAC_disable_interrupt_all(synopGMACdevice *gmacdev) -{ - synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaInterrupt, DmaIntDisable); -} - -/* - * Disable interrupt according to the bitfield supplied. - * Disables only those interrupts specified in the bit mask in second argument. - * @param[in] pointer to synopGMACdevice. - * @param[in] bit mask for interrupts to be disabled. - * \return returns void. - */ -static inline void synopGMAC_disable_interrupt(synopGMACdevice *gmacdev, u32 interrupts) -{ - synopGMACClearBits((u32 *)gmacdev->DmaBase, DmaInterrupt, interrupts); -} - -void synopGMAC_enable_dma_rx(synopGMACdevice * gmacdev); -void synopGMAC_enable_dma_tx(synopGMACdevice * gmacdev); - -/* - * Resumes the DMA Transmission. - * the DmaTxPollDemand is written. (the data writeen could be anything). - * This forces the DMA to resume transmission. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -static inline void synopGMAC_resume_dma_tx(synopGMACdevice * gmacdev) -{ - synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaTxPollDemand, 0); - -} - -/* - * Resumes the DMA Reception. - * the DmaRxPollDemand is written. (the data writeen could be anything). - * This forces the DMA to resume reception. - * @param[in] pointer to synopGMACdevice. - * \return returns void. - */ -static inline void synopGMAC_resume_dma_rx(synopGMACdevice * gmacdev) -{ - synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaRxPollDemand, 0); - -} - -void synopGMAC_take_desc_ownership(DmaDesc * desc); -void synopGMAC_take_desc_ownership_rx(synopGMACdevice * gmacdev); -void synopGMAC_take_desc_ownership_tx(synopGMACdevice * gmacdev); -void synopGMAC_disable_dma_tx(synopGMACdevice * gmacdev); -void synopGMAC_disable_dma_rx(synopGMACdevice * gmacdev); - -/******Following APIs are valid only for Enhanced Descriptor from 3.50a release onwards*******/ -/* - * When the Enhanced Descriptor is enabled then the bit 0 of RDES0 indicates whether the - * Extended Status is available (RDES4). Time Stamp feature and the Checksum Offload Engine2 - * makes use of this extended status to provide the status of the received packet. - * @param[in] pointer to synopGMACdevice - * \return returns TRUE or FALSE - */ - -#ifdef ENH_DESC_8W -/* - * This function indicates whether extended status is available in the RDES0. - * Any function which accesses the fields of extended status register must ensure a check on this has been made - * This is valid only for Enhanced Descriptor. - * @param[in] pointer to synopGMACdevice. - * @param[in] u32 status field of the corresponding descriptor. - * \return returns TRUE or FALSE. - */ -static inline bool synopGMAC_is_ext_status(synopGMACdevice *gmacdev,u32 status) // extended status present indicates that the RDES4 need to be probed -{ - return((status & DescRxEXTsts ) != 0 ); // if extstatus set then it returns 1 -} - -/* - * This function returns true if the IP header checksum bit is set in the extended status. - * Valid only when enhaced status available is set in RDES0 bit 0. - * This is valid only for Enhanced Descriptor. - * @param[in] pointer to synopGMACdevice. - * @param[in] u32 status field of the corresponding descriptor. - * \return returns TRUE or FALSE. - */ -static inline bool synopGMAC_ES_is_IP_header_error(synopGMACdevice *gmacdev, u32 ext_status) // IP header (IPV4) checksum error -{ - return((ext_status & DescRxIpHeaderError) != 0 ); // if IPV4 header error return 1 -} - -/* - * This function returns true if the Checksum is bypassed in the hardware. - * Valid only when enhaced status available is set in RDES0 bit 0. - * This is valid only for Enhanced Descriptor. - * @param[in] pointer to synopGMACdevice. - * @param[in] u32 status field of the corresponding descriptor. - * \return returns TRUE or FALSE. - */ -static inline bool synopGMAC_ES_is_rx_checksum_bypassed(synopGMACdevice *gmacdev, u32 ext_status) // Hardware engine bypassed the checksum computation/checking -{ - return((ext_status & DescRxChkSumBypass ) != 0 ); // if checksum offloading bypassed return 1 -} - -/* - * This function returns true if payload checksum error is set in the extended status. - * Valid only when enhaced status available is set in RDES0 bit 0. - * This is valid only for Enhanced Descriptor. - * @param[in] pointer to synopGMACdevice. - * @param[in] u32 status field of the corresponding descriptor. - * \return returns TRUE or FALSE. - */ -static inline bool synopGMAC_ES_is_IP_payload_error(synopGMACdevice *gmacdev, u32 ext_status) // IP payload checksum is in error (UDP/TCP/ICMP checksum error) -{ - return((ext_status & DescRxIpPayloadError) != 0 ); // if IP payload error return 1 -} -#endif - -/*******************PMT APIs***************************************/ -void synopGMAC_pmt_int_enable(synopGMACdevice *gmacdev); -void synopGMAC_pmt_int_disable(synopGMACdevice *gmacdev); -void synopGMAC_power_down_enable(synopGMACdevice *gmacdev); -void synopGMAC_power_down_disable(synopGMACdevice *gmacdev); -void synopGMAC_magic_packet_enable(synopGMACdevice *gmacdev); -void synopGMAC_wakeup_frame_enable(synopGMACdevice *gmacdev); -void synopGMAC_pmt_unicast_enable(synopGMACdevice *gmacdev); -bool synopGMAC_is_magic_packet_received(synopGMACdevice *gmacdev); -bool synopGMAC_is_wakeup_frame_received(synopGMACdevice *gmacdev); -void synopGMAC_write_wakeup_frame_register(synopGMACdevice *gmacdev, u32 * filter_contents); -/*******************MMC APIs***************************************/ -void synopGMAC_mmc_counters_stop(synopGMACdevice *gmacdev); -void synopGMAC_mmc_counters_resume(synopGMACdevice *gmacdev); -void synopGMAC_mmc_counters_set_selfclear(synopGMACdevice *gmacdev); -void synopGMAC_mmc_counters_reset_selfclear(synopGMACdevice *gmacdev); -void synopGMAC_mmc_counters_disable_rollover(synopGMACdevice *gmacdev); -void synopGMAC_mmc_counters_enable_rollover(synopGMACdevice *gmacdev); -u32 synopGMAC_read_mmc_counter(synopGMACdevice *gmacdev, u32 counter); -u32 synopGMAC_read_mmc_rx_int_status(synopGMACdevice *gmacdev); -u32 synopGMAC_read_mmc_tx_int_status(synopGMACdevice *gmacdev); -void synopGMAC_disable_mmc_tx_interrupt(synopGMACdevice *gmacdev, u32 mask); -void synopGMAC_enable_mmc_tx_interrupt(synopGMACdevice *gmacdev, u32 mask); -void synopGMAC_disable_mmc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask); -void synopGMAC_enable_mmc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask); -void synopGMAC_enable_mmc_ipc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask); -void synopGMAC_disable_mmc_ipc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask); -void nss_gmac_qsgmii_dev_init(synopGMACdevice *gmacdev); -void ipq806x_dev_board_init(synopGMACdevice *gmacdev); -int32_t nss_gmac_common_init(void); -extern board_ipq806x_params_t *gboard_param ; -void nss_gmac_reset_phy( uint32_t phyid); -int32_t ipq806x_get_link_speed(uint32_t phyid); -int32_t ipq806x_get_duplex(uint32_t phyid); -int32_t nss_gmac_dev_set_speed(synopGMACdevice *gmacdev); -#endif /* End of file */ diff --git a/root/package/utils/sysupgrade-helper/src/drivers/net/nss/synopGMAC_network_interface.c b/root/package/utils/sysupgrade-helper/src/drivers/net/nss/synopGMAC_network_interface.c deleted file mode 100644 index edd0f9bd..00000000 --- a/root/package/utils/sysupgrade-helper/src/drivers/net/nss/synopGMAC_network_interface.c +++ /dev/null @@ -1,1526 +0,0 @@ -/* * Copyright (c) 2012 - 2013 The Linux Foundation. All rights reserved.* */ - -/* - * This is the network dependent layer to handle network related functionality. - * This file is tightly coupled to neworking frame work of linux 2.6.xx kernel. - * The functionality carried out in this file should be treated as an example only - * if the underlying operating system is not Linux. - * - * \note Many of the functions other than the device specific functions - * changes for operating system other than Linux 2.6.xx - * \internal - *-----------------------------REVISION HISTORY----------------------------------- - * Ubicom 01/Mar/2010 Modified for Ubicom32 - * Synopsys 01/Aug/2007 Created - */ - -#include "synopGMAC_plat.h" -#include "synopGMAC_Dev.h" -#include -#include -#include -#include -#include -#include -#include - - -#define CONFIG_ARCH_IPQ806X -/* - * u-boot API - */ -extern int eth_rx(void); -extern void eth_halt(void); -extern int eth_init(bd_t *bd); -extern void cleanup_skb(void); - -extern int synop_phy_link_status(int speed); -void synop_phy_outofreset(void); -extern s32 synopGMAC_check_link(synopGMACdevice *gmacdev); -extern uint16_t mii_read_reg(synopGMACdevice *gmacdev, uint32_t phy, uint32_t reg); -int eth_init_done; -u32 nss_base; -u32 gmac_base; -u32 qsgmii_base; -uint16_t ipq_mii_read_reg(uint32_t phy, uint32_t reg); -void ipq_mii_write_reg(uint32_t phy, uint32_t reg, uint16_t data); - -#define GMAC_PORT 1 /* after bringup will be moved to board specific params */ -#define TX_TOTAL_BUFSIZE 1700 - -u8 txbuffs[TX_TOTAL_BUFSIZE]; -u8 TxSkbuf[sizeof(struct sk_buff)]; - -/* - * These are the global pointers for their respecive structures - */ -static synopGMACdevice *synopGMACDev[1] = {NULL}; - -synopGMACdevice *netdev_priv(struct eth_device *dev) { - return (synopGMACdevice *)(dev->priv); -} - -static s32 gmac_plat_init(void) -{ - - /*XXX: needs cleanup. need better way to share registers between different modules. */ - nss_base = NSS_REG_BASE ; - gmac_base = gboard_param->gmac_base; - qsgmii_base = QSGMII_REG_BASE; - - TR("%s: ipq806x: NSS base done. \n",__FUNCTION__); - - return 0; -} - - -static s32 gmac_dev_init(u32 id) -{ - u32 val; - - /* Set GMACn Ctl */ - val = GMAC_PHY_RGMII | GMAC_IFG_CTL(GMAC_IFG) - | GMAC_IFG_LIMIT(GMAC_IFG); - synopGMACSetBits((u32 *)nss_base, NSS_GMACn_CTL(id), val); - - val = synopGMACReadReg((u32 *)nss_base, NSS_GMACn_CTL(id)); - TR("%s: IPQ806X_GMAC%d_CTL(0x%x) - 0x%x\n", __FUNCTION__, id , - NSS_GMACn_CTL(id), val); - - /* Enable clk for GMACn */ - val = GMACn_RGMII_RX_CLK(id) | GMACn_RGMII_TX_CLK(id) - | GMACn_PTP_CLK(id); - synopGMACSetBits((u32 *)nss_base, NSS_ETH_CLK_GATE_CTL, val); - - val = synopGMACReadReg((u32 *)nss_base, NSS_ETH_CLK_GATE_CTL); - TR("%s:NSS_ETHERNET_CLK_GATE_CTL(0x%x) - 0x%x \n", __FUNCTION__ , - NSS_ETH_CLK_GATE_CTL, val); - - /* Select GMACn clk source. - * TODO: support for SGMII/QSGMII\ - */ - - val = synopGMACReadReg((u32 *)nss_base, NSS_ETH_CLK_SRC_CTL); - TR("%s:NSS_ETHERNET_CLK_SRC_CTL(0x%x)- 0x%x\n", __FUNCTION__, - NSS_ETH_CLK_SRC_CTL, val); - - /* Read status registers */ - val = synopGMACReadReg((u32 *)nss_base, NSS_ETH_CLK_ROOT_STAT ); - TR("%s:CLK_ROOT_STAT - 0x%x \n", __FUNCTION__, val); - - val = synopGMACReadReg((u32 *)nss_base, NSS_QSGMII_CLK_CTL); - TR("%s:QSGMII_CLK_CTL - 0x%x \n", __FUNCTION__, val); - - synopGMACSetBits((u32 *)nss_base, NSS_ETH_CLK_SRC_CTL, (0x1 << id)); - - return 0; -} - - -static s32 gmac_spare_ctl(synopGMACdevice *gmacdev) -{ - u32 val; - u32 count; - u32 id = 0; - - val = 1 << id; - synopGMACSetBits((u32 *)nss_base, NSS_ETH_SPARE_CTL , val); - - val = synopGMACReadReg((u32 *)nss_base, NSS_ETH_SPARE_CTL ); - TR("NSS_ETHERNET_SPARE_CTL - 0x%x\n",val); - - val = 1 << id; - synopGMACClearBits((u32 *)nss_base, NSS_ETH_SPARE_CTL , val); - - val = synopGMACReadReg((u32 *)nss_base, NSS_ETH_SPARE_CTL); - TR("NSS_ETHERNET_SPARE_CTL - 0x%x after clear for gmac %d\n",val,id); - - val = synopGMACReadReg((u32 *)nss_base, NSS_ETH_SPARE_STAT) ; - TR("NSS_ETHERNET_SPARE_STAT - 0x%x; gmac %d spare ctl reset...\n",val,id); - count =0; - while((val & (1 << id)) != (1 << id)) { - __udelay(1000); - val = synopGMACReadReg((u32 *)nss_base, NSS_ETH_SPARE_STAT) ; - if(count++ > 20) { - TR0("!!!!!!!!!!! Timeout waiting for ETH_SPARE_STAT bit to set. Moving on...\n"); - break; - } - } - - return 0; -} - -static void synopGMAC_linux_powerup_mac(synopGMACdevice *gmacdev) -{ - gmacdev->GMAC_Power_down = 0; // Let ISR know that MAC is out of power down now - if (synopGMAC_is_magic_packet_received(gmacdev)) - TR("GMAC wokeup due to Magic Pkt Received\n"); - if (synopGMAC_is_wakeup_frame_received(gmacdev)) - TR("GMAC wokeup due to Wakeup Frame Received\n"); - /*Disable the assertion of PMT interrupt*/ - synopGMAC_pmt_int_disable(gmacdev); - /*Enable the mac and Dma rx and tx paths*/ - synopGMAC_rx_enable(gmacdev); - synopGMAC_enable_dma_rx(gmacdev); - - synopGMAC_tx_enable(gmacdev); - synopGMAC_enable_dma_tx(gmacdev); -} - -/* - * This sets up the transmit Descriptor queue in ring or chain mode. - * This function is tightly coupled to the platform and operating system - * Device is interested only after the descriptors are setup. Therefore this function - * is not included in the device driver API. This function should be treated as an - * example code to design the descriptor structures for ring mode or chain mode. - * This function depends on the device structure for allocation consistent dma-able memory in case of linux. - * - Allocates the memory for the descriptors. - * - Initialize the Busy and Next descriptors indices to 0(Indicating first descriptor). - * - Initialize the Busy and Next descriptors to first descriptor address. - * - Initialize the last descriptor with the endof ring in case of ring mode. - * - Initialize the descriptors in chain mode. - * @param[in] pointer to synopGMACdevice. - * @param[in] pointer to device structure. - * @param[in] number of descriptor expected in tx descriptor queue. - * @param[in] whether descriptors to be created in RING mode or CHAIN mode. - * \return 0 upon success. Error code upon failure. - * \note This function fails if allocation fails for required number of descriptors in Ring mode, but in chain mode - * function returns -ESYNOPGMACNOMEM in the process of descriptor chain creation. once returned from this function - * user should for gmacdev->TxDescCount to see how many descriptors are there in the chain. Should continue further - * only if the number of descriptors in the chain meets the requirements - */ -static s32 synopGMAC_setup_tx_desc_queue(synopGMACdevice * gmacdev, void * dev,u32 no_of_desc, u32 desc_mode) -{ - s32 i; - DmaDesc *first_desc = NULL; - dma_addr_t dma_addr; - gmacdev->TxDescCount = 0; - - BUG_ON(desc_mode != RINGMODE); - BUG_ON((no_of_desc & (no_of_desc - 1)) != 0); /* Must be power-of-2 */ - - TR("Total size of memory required for Tx Descriptors in Ring Mode = 0x%08x\n", - (u32)((sizeof(DmaDesc) * no_of_desc))); - first_desc = plat_alloc_consistent_dmaable_memory(dev, sizeof(DmaDesc) * no_of_desc,&dma_addr); - if (first_desc == NULL) { - TR("Error in Tx Descriptors memory allocation\n"); - return -ESYNOPGMACNOMEM; - } - - BUG_ON((int)first_desc & (CACHE_LINE_SIZE - 1)); - gmacdev->TxDescCount = no_of_desc; - gmacdev->TxDesc = first_desc; - gmacdev->TxDescDma = dma_addr; - TR("Tx Descriptors in Ring Mode: No. of descriptors = %d base = 0x%08x dma = 0x%08x\n", - no_of_desc, (u32)first_desc, dma_addr); - - for (i =0; i < gmacdev -> TxDescCount; i++) { - synopGMAC_tx_desc_init_ring(gmacdev->TxDesc + i, i == (gmacdev->TxDescCount - 1)); - TR("%02d %08x \n",i, (unsigned int)(gmacdev->TxDesc + i) ); - } - - gmacdev->TxNext = 0; - gmacdev->TxBusy = 0; - gmacdev->TxNextDesc = gmacdev->TxDesc; - gmacdev->TxBusyDesc = gmacdev->TxDesc; - gmacdev->BusyTxDesc = 0; - - return -ESYNOPGMACNOERR; -} - -/* - * This sets up the receive Descriptor queue in ring or chain mode. - * This function is tightly coupled to the platform and operating system - * Device is interested only after the descriptors are setup. Therefore this function - * is not included in the device driver API. This function should be treated as an - * example code to design the descriptor structures in ring mode or chain mode. - * This function depends on the device structure for allocation of consistent dma-able memory in case of linux. - * - Allocates the memory for the descriptors. - * - Initialize the Busy and Next descriptors indices to 0(Indicating first descriptor). - * - Initialize the Busy and Next descriptors to first descriptor address. - * - Initialize the last descriptor with the endof ring in case of ring mode. - * - Initialize the descriptors in chain mode. - * @param[in] pointer to synopGMACdevice. - * @param[in] pointer to device structure. - * @param[in] number of descriptor expected in rx descriptor queue. - * @param[in] whether descriptors to be created in RING mode or CHAIN mode. - * \return 0 upon success. Error code upon failure. - * \note This function fails if allocation fails for required number of descriptors in Ring mode, but in chain mode - * function returns -ESYNOPGMACNOMEM in the process of descriptor chain creation. once returned from this function - * user should for gmacdev->RxDescCount to see how many descriptors are there in the chain. Should continue further - * only if the number of descriptors in the chain meets the requirements - */ -static s32 synopGMAC_setup_rx_desc_queue(synopGMACdevice * gmacdev,void * dev,u32 no_of_desc, u32 desc_mode) -{ - s32 i; - DmaDesc *first_desc = NULL; - dma_addr_t dma_addr; - gmacdev->RxDescCount = 0; - - BUG_ON(desc_mode != RINGMODE); - BUG_ON((no_of_desc & (no_of_desc - 1)) != 0); /* Must be power-of-2 */ - - TR("total size of memory required for Rx Descriptors in Ring Mode = 0x%08x\n", - (u32)((sizeof(DmaDesc) * no_of_desc))); - first_desc = plat_alloc_consistent_dmaable_memory (dev, sizeof(DmaDesc) * no_of_desc, &dma_addr); - if (first_desc == NULL) { - TR("Error in Rx Descriptor Memory allocation in Ring mode\n"); - return -ESYNOPGMACNOMEM; - } - BUG_ON((int)first_desc & (CACHE_LINE_SIZE - 1)); - gmacdev->RxDescCount = no_of_desc; - gmacdev->RxDesc = first_desc; - gmacdev->RxDescDma = dma_addr; - TR("Rx Descriptors in Ring Mode: No. of descriptors = %d base = 0x%08x dma = 0x%08x\n", - no_of_desc, (u32)first_desc, dma_addr); - - for (i =0; i < gmacdev -> RxDescCount; i++) { - synopGMAC_rx_desc_init_ring(gmacdev->RxDesc + i, i == (gmacdev->RxDescCount - 1)); - TR("%02d %08x \n",i, (unsigned int)(gmacdev->RxDesc + i)); - } - - gmacdev->RxNext = 0; - gmacdev->RxBusy = 0; - gmacdev->RxNextDesc = gmacdev->RxDesc; - gmacdev->RxBusyDesc = gmacdev->RxDesc; - gmacdev->BusyRxDesc = 0; - - return -ESYNOPGMACNOERR; -} - -/* - * This gives up the receive Descriptor queue in ring or chain mode. - * This function is tightly coupled to the platform and operating system - * Once device's Dma is stopped the memory descriptor memory and the buffer memory deallocation, - * is completely handled by the operating system, this call is kept outside the device driver Api. - * This function should be treated as an example code to de-allocate the descriptor structures in ring mode or chain mode - * and network buffer deallocation. - * This function depends on the device structure for dma-able memory deallocation for both descriptor memory and the - * network buffer memory under linux. - * The responsibility of this function is to - * - Free the network buffer memory if any. - * - Fee the memory allocated for the descriptors. - * @param[in] pointer to synopGMACdevice. - * @param[in] pointer to device structure. - * @param[in] number of descriptor expected in rx descriptor queue. - * @param[in] whether descriptors to be created in RING mode or CHAIN mode. - * \return 0 upon success. Error code upon failure. - * \note No referece should be made to descriptors once this function is called. This function is invoked when the device is closed. - */ -static void synopGMAC_giveup_rx_desc_queue(synopGMACdevice * gmacdev, void *dev, u32 desc_mode) -{ - s32 i; - u32 status; - dma_addr_t dma_addr1; - u32 length1; - u32 data1; - - for (i = 0; i < gmacdev->RxDescCount; i++) { - synopGMAC_get_desc_data(gmacdev->RxDesc + i, &status, &dma_addr1, &length1, &data1); - if ((length1 != 0) && (data1 != 0)) { - dev_kfree_skb_any((struct sk_buff *) data1); - TR("(Ring mode) rx buffer1 %08x of size %d from %d rx descriptor is given back\n", data1, length1, i); - } - } - free(gmacdev->RxDesc); - TR("Memory allocated %08x for Rx Desriptors (ring) is given back\n", (u32)gmacdev->RxDesc); - TR("rx-------------------------------------------------------------------rx\n"); - - gmacdev->RxDesc = NULL; - gmacdev->RxDescDma = 0; -} - -/* - * This gives up the transmit Descriptor queue in ring or chain mode. - * This function is tightly coupled to the platform and operating system - * Once device's Dma is stopped the memory descriptor memory and the buffer memory deallocation, - * is completely handled by the operating system, this call is kept outside the device driver Api. - * This function should be treated as an example code to de-allocate the descriptor structures in ring mode or chain mode - * and network buffer deallocation. - * This function depends on the device structure for dma-able memory deallocation for both descriptor memory and the - * network buffer memory under linux. - * The responsibility of this function is to - * - Free the network buffer memory if any. - * - Fee the memory allocated for the descriptors. - * @param[in] pointer to synopGMACdevice. - * @param[in] pointer to device structure. - * @param[in] number of descriptor expected in tx descriptor queue. - * @param[in] whether descriptors to be created in RING mode or CHAIN mode. - * \return 0 upon success. Error code upon failure. - * \note No reference should be made to descriptors once this function is called. This function is invoked when the device is closed. - */ -static void synopGMAC_giveup_tx_desc_queue(synopGMACdevice * gmacdev,void * dev, u32 desc_mode) -{ - s32 i; - u32 status; - dma_addr_t dma_addr1; - u32 length1; - u32 data1; - - for (i = 0; i < gmacdev->TxDescCount; i++) { - synopGMAC_get_desc_data(gmacdev->TxDesc + i, &status, &dma_addr1, &length1, &data1); - if((length1 != 0) && (data1 != 0)){ - dev_kfree_skb_any((struct sk_buff *) data1); - TR("(Ring mode) tx buffer1 %08x of size %d from %d rx descriptor is given back\n", data1, length1, i); - } - } - free(gmacdev->TxDesc); - TR("Memory allocated %08x for Tx Desriptors (ring) is given back\n", (u32)gmacdev->TxDesc); - TR("tx-------------------------------------------------------------------tx\n"); - - gmacdev->TxDesc = NULL; - gmacdev->TxDescDma = 0; -} - -/* - * Function to handle housekeeping after a packet is transmitted over the wire. - * After the transmission of a packet DMA generates corresponding interrupt - * (if it is enabled). It takes care of returning the sk_buff to the linux - * kernel, updating the networking statistics and tracking the descriptors. - * @param[in] pointer to net_device structure. - * \return void. - * \note This function runs in interrupt context - */ -static void synopGMAC_handle_transmit_over(struct eth_device *netdev) -{ - synopGMACdevice *gmacdev = netdev_priv(netdev); - DmaDesc *txdesc; - u32 status; - - /* - * Handle the transmit Descriptors - */ - while (1) { - txdesc = synopGMAC_get_tx_qptr(gmacdev); - if (unlikely(txdesc == NULL)) { - break; - } - - status = txdesc->status; - synopGMAC_reset_tx_qptr(gmacdev); - - if (unlikely(synopGMAC_is_tx_ipv4header_checksum_error(gmacdev, status))) { - TR0("Harware Failed to Insert IPV4 Header Checksum\n"); - } - - if (unlikely(synopGMAC_is_tx_payload_checksum_error(gmacdev, status))) { - TR0("Harware Failed to Insert Payload Checksum\n"); - } - - if (likely(synopGMAC_is_desc_valid(status))) { - } - else { - TR0("Error in Status %08x\n",status); - } - } - netif_wake_queue(netdev); -} - - -/* - * Function to Receive a packet from the interface. - * After Receiving a packet, DMA transfers the received packet to the system memory - * and generates corresponding interrupt (if it is enabled). This function prepares - * the sk_buff for received packet after removing the ethernet CRC, and hands it over - * to linux networking stack. - * - Updataes the networking interface statistics - * - Keeps track of the rx descriptors - * @param[in] pointer to net_device structure. - * \return void. - * \note This function runs in interrupt context. - */ -static u32 synopGMAC_handle_received_data(struct eth_device *netdev, u32 quota) -{ - synopGMACdevice *gmacdev = netdev_priv(netdev); - DmaDesc *rxdesc; - u32 status; - u32 len; - u32 data1; - u32 dma_addr1; - struct sk_buff *skb; - u32 count = 0, refill_count = 0, reserve_len; - - /* - * Handle the Receive Descriptors - */ - while (count < quota) { - rxdesc = synopGMAC_get_rx_qptr(gmacdev); - - if (unlikely(rxdesc == NULL)) { - - break; - } - - status = rxdesc->status; - dma_addr1 = rxdesc->buffer1; - data1 = rxdesc->data1; - synopGMAC_reset_rx_qptr(gmacdev); - - BUG_ON(data1 == 0); - - /* - * Perform prefetch on skbuff structure data - */ - skb = (struct sk_buff *)data1; - - /* - * Validate RX frame: - * The max frame size check is implied by buffer's limited length - * and the presence of both first and last descritpor flags. - */ - len = synopGMAC_get_rx_desc_frame_length(status); - - if (unlikely(!synopGMAC_is_rx_desc_valid(status)) || - unlikely(len < (ETH_ZLEN + ETH_FCS_LEN))) { - /* - * At first step unmapped the dma address - */ - //dma_unmap_single_buf(dma_addr1, 0); - - /* - * Now the present skb should be set free - */ - dev_kfree_skb_any(skb); - TR0("%s: Invalid RX status = %08x\n", __FUNCTION__, status); - - count++; - - continue; - } - - /* - * At first step unmapped the dma address - */ - len -= ETH_FCS_LEN; //Not interested in Ethernet CRC bytes - skb_put(skb, len); - count++; - NetReceive(skb->data, skb->len); - dev_kfree_skb_any(skb); - } - - /* U-Boot could invoke eth_halt and halt our operations. */ - if (gmacdev->state == ETH_STATE_PASSIVE) - return count; - - /* - * Now allocate more RX buffer and let GMAC DMA engine know about them. - */ - reserve_len = ETHERNET_EXTRA; - while (gmacdev->BusyRxDesc < gmacdev->RxDescCount) { - - skb = alloc_skb(ETHERNET_EXTRA + ETH_MAX_FRAME_LEN + - CACHE_LINE_SIZE, 0); - if(skb == NULL){ - TR("SKB memory allocation failed \n"); - break; - } - - skb_reserve(skb, reserve_len); - dma_addr1 = virt_to_phys(skb->data); - synopGMAC_set_rx_qptr(gmacdev, dma_addr1, ETH_MAX_FRAME_LEN, - (u32)skb); - refill_count++; - } - - if (refill_count > 0) { - synopGMAC_resume_dma_rx(gmacdev); - } - - return count; -} - - -/* - * Tasklet poll callback - * This is the Tasklet callback function - * @param[in] tasklet structure. - * - */ -static void synopGMAC_task_poll(unsigned long arg) -{ - struct eth_device *netdev; - synopGMACdevice *gmacdev; - u32 interrupt; - u32 budget = GMAC_POLL_BUDGET; - - gmacdev = (synopGMACdevice *)arg; - BUG_ON(gmacdev == NULL); - - netdev = gmacdev->synopGMACnetdev; - BUG_ON(netdev == NULL); - - /* - * Now lets handle the DMA interrupts - */ - interrupt = synopGMAC_get_interrupt_type(gmacdev); - TR("%s:Interrupts to be handled: 0x%08x\n", __FUNCTION__, interrupt); - - if (unlikely(interrupt & GmacPmtIntr)) { - TR("%s:: Interrupt due to PMT module\n",__FUNCTION__); - synopGMAC_linux_powerup_mac(gmacdev); - } - - if (unlikely(interrupt & GmacMmcIntr)) { - TR("%s:: Interrupt due to MMC module\n",__FUNCTION__); - TR("%s:: synopGMAC_rx_int_status = %08x\n",__FUNCTION__,synopGMAC_read_mmc_rx_int_status(gmacdev)); - TR("%s:: synopGMAC_tx_int_status = %08x\n",__FUNCTION__,synopGMAC_read_mmc_tx_int_status(gmacdev)); - } - - if (unlikely(interrupt & GmacLineIntfIntr)) { - TR("%s:: Interrupt due to GMAC LINE module\n",__FUNCTION__); - TR("GMAC status reg is %08x mask is %08x\n", - synopGMACReadReg((u32 *)gmacdev->MacBase, GmacInterruptStatus), - synopGMACReadReg((u32 *)gmacdev->MacBase, GmacInterruptMask)); - if (synopGMACReadReg((u32 *)gmacdev->MacBase, GmacInterruptStatus) & GmacRgmiiIntSts) { - TR("GMAC RGMII status is %08x\n", synopGMACReadReg((u32 *)gmacdev->MacBase, 0x00D8)); - synopGMACReadReg((u32 *)gmacdev->MacBase, 0x00D8); - } - } - if (interrupt && DmaIntRxCompleted) { - synopGMAC_handle_received_data(netdev, budget); - } - - if (gmacdev->BusyTxDesc > 0) { - synopGMAC_handle_transmit_over(netdev); - } - - if (unlikely(interrupt & (DmaIntErrorMask - | DmaIntRxAbnMask | DmaIntRxStoppedMask - | DmaIntTxAbnMask | DmaIntTxStoppedMask))) { - - if (interrupt & DmaIntErrorMask) { - TR0("%s::Fatal Bus Error Inetrrupt Seen (DMA status = 0x%08x)\n",__FUNCTION__,interrupt); - BUG(); - - } - - if (interrupt & DmaIntRxAbnMask) { - TR0("%s::Abnormal Rx Interrupt Seen (DMA status = 0x%08x)\n", __FUNCTION__, interrupt); - if (gmacdev->GMAC_Power_down == 0) { - /* - * Just issue a poll demand to resume DMA operation - * (May happen when too few RX desciptors are in use) - */ - synopGMAC_handle_received_data(netdev, 0); - synopGMAC_resume_dma_rx(gmacdev); - } - } - - if (interrupt & DmaIntRxStoppedMask) { - if (gmacdev->GMAC_Power_down == 0) { - TR0("%s::Receiver stopped (DMA status = 0x%08x)\n", __FUNCTION__, interrupt); - BUG(); - synopGMAC_handle_received_data(netdev, 0); - synopGMAC_enable_dma_rx(gmacdev); - } - } - - if (interrupt & DmaIntTxAbnMask) { - TR0("%s::Abnormal Tx Interrupt Seen (DMA status = 0x%08x)\n", __FUNCTION__, interrupt); - if (gmacdev->GMAC_Power_down == 0) { - synopGMAC_handle_transmit_over(netdev); - } - } - - if (interrupt & DmaIntTxStoppedMask) { - if (gmacdev->GMAC_Power_down == 0) { - TR0("%s::Transmitter stopped (DMA status = 0x%08x)\n", __FUNCTION__, interrupt); - BUG(); - - synopGMAC_disable_dma_tx(gmacdev); - synopGMAC_take_desc_ownership_tx(gmacdev); - synopGMAC_enable_dma_tx(gmacdev); - netif_wake_queue(netdev); - } - } - } -} - -/* - * Function used when the interface is opened for use. - * We register synopGMAC_linux_open function to linux open(). Basically this - * function prepares the the device for operation . This function is called whenever ifconfig (in Linux) - * activates the device (for example "ifconfig eth0 up"). This function registers - * system resources needed - * - Attaches device to device specific structure - * - Programs the MDC clock for PHY configuration - * - Check and initialize the PHY interface - * - ISR registration - * - Setup and initialize Tx and Rx descriptors - * - Initialize MAC and DMA - * - Allocate Memory for RX descriptors (The should be DMAable) - * - Initialize one second timer to detect cable plug/unplug - * - Configure and Enable Interrupts - * - Enable Tx and Rx - * - start the Linux network queue interface - * @param[in] pointer to net_device structure. - * \return Returns 0 on success and error status upon failure. - * - */ -static s32 synopGMAC_linux_open(struct eth_device *netdev, - struct eth_device *device) -{ - void *dev = NULL;; - synopGMACdevice *gmacdev = (synopGMACdevice *) netdev_priv(netdev); - - TR("%s called \n",__FUNCTION__); - TR("gmacdev = %08x netdev = %08x dev= %08x\n", (u32)gmacdev, (u32)netdev, (u32)dev); - BUG_ON(gmacdev->synopGMACnetdev != netdev); - - /* - * Now platform dependent initialization. - */ - synopGMAC_disable_interrupt_all(gmacdev); - - /* - * Lets reset the IP - */ - synopGMAC_reset(gmacdev); - - /* - * Lets read the version of ip in to device structure - */ - synopGMAC_read_version(gmacdev); - synopGMAC_set_mac_addr(gmacdev, GmacAddr0High, GmacAddr0Low, device->enetaddr); - - - /* - * Set up the tx and rx descriptor queue/ring - */ - if (synopGMAC_setup_tx_desc_queue(gmacdev, dev, TRANSMIT_DESC_SIZE, RINGMODE) < 0) { - TR0("Error in setup TX descriptor\n"); - return -ESYNOPGMACNOMEM; - } - synopGMAC_init_tx_desc_base(gmacdev); //Program the transmit descriptor base address in to DmaTxBase addr - - if (synopGMAC_setup_rx_desc_queue(gmacdev, dev, RECEIVE_DESC_SIZE, RINGMODE) < 0) { - TR0("Error in setup RX descriptor\n"); - synopGMAC_giveup_tx_desc_queue(gmacdev, dev, RINGMODE); - return -ESYNOPGMACNOMEM; - } - synopGMAC_init_rx_desc_base(gmacdev); /*Program the receive descriptor base address in to DmaTxBase addr*/ - - synopGMAC_dma_bus_mode_init(gmacdev, DmaFixedBurstEnable | DmaBurstLength16 | DmaDescriptorSkip0 | DmaDescriptor8Words | DmaArbitPr); /*pbl32 incr with rxthreshold 128 and Desc is 8 Words */ - synopGMAC_dma_control_init(gmacdev, DmaStoreAndForward | DmaRxThreshCtrl128 | DmaTxSecondFrame); - - /* - * Initialize the mac interface - */ - synopGMAC_mac_init(gmacdev); - synopGMAC_pause_control(gmacdev); // This enables the pause control in Full duplex mode of operation - /* - * IPC Checksum offloading is enabled for this driver. Should only be used if Full Ip checksumm offload engine is configured in the hardware - */ - synopGMAC_enable_rx_chksum_offload(gmacdev); //Enable the offload engine in the receive path - synopGMAC_rx_tcpip_chksum_drop_enable(gmacdev); // This is default configuration, DMA drops the packets if error in encapsulated ethernet payload - // The FEF bit in DMA control register is configured to 0 indicating DMA to drop the errored frames. - - synopGMAC_handle_received_data(netdev, 0); - - synopGMAC_clear_interrupt(gmacdev); - - /* - * Disable the interrupts generated by MMC and IPC counters. - * If these are not disabled ISR should be modified accordingly to handle these interrupts. - */ - synopGMAC_disable_mmc_tx_interrupt(gmacdev, 0xFFFFFFFF); - synopGMAC_disable_mmc_rx_interrupt(gmacdev, 0xFFFFFFFF); - synopGMAC_disable_mmc_ipc_rx_interrupt(gmacdev, 0xFFFFFFFF); - - synopGMAC_enable_dma_rx(gmacdev); - synopGMAC_enable_dma_tx(gmacdev); - - netif_start_queue(netdev); - synopGMAC_enable_interrupt(gmacdev, DmaIntEnable); - - return 0; -} - -/* - * Function used when the interface is closed. - * - * This function is registered to linux stop() function. This function is - * called whenever ifconfig (in Linux) closes the device (for example "ifconfig eth0 down"). - * This releases all the system resources allocated during open call. - * system resources int needs - * - Disable the device interrupts - * - Stop the receiver and get back all the rx descriptors from the DMA - * - Stop the transmitter and get back all the tx descriptors from the DMA - * - Stop the Linux network queue interface - * - Free the irq (ISR registered is removed from the kernel) - * - Release the TX and RX descripor memory - * - De-initialize one second timer rgistered for cable plug/unplug tracking - * @param[in] pointer to net_device structure. - * \return Returns 0 on success and error status upon failure. - * \callgraph - */ -static s32 synopGMAC_linux_close(struct eth_device *netdev) -{ - synopGMACdevice *gmacdev = (synopGMACdevice *) netdev_priv(netdev); - void *dev = NULL; - - TR("%s\n",__FUNCTION__); - BUG_ON(gmacdev->synopGMACnetdev != netdev); - - /* - * Disable all the interrupts - */ - synopGMAC_disable_interrupt_all(gmacdev); - TR("the synopGMAC interrupt has been disabled\n"); - - /* - * Disable the reception - */ - synopGMAC_rx_disable(gmacdev); - /*Allow any pending buffer to be read by host */ - __udelay(10000); - synopGMAC_disable_dma_rx(gmacdev); - synopGMAC_take_desc_ownership_rx(gmacdev); - TR("the synopGMAC Reception has been disabled\n"); - - /* - * Disable the transmission - */ - synopGMAC_disable_dma_tx(gmacdev); - /* allow any pending transmission to complete */ - __udelay(10000); - synopGMAC_tx_disable(gmacdev); - synopGMAC_take_desc_ownership_tx(gmacdev); - TR("the synopGMAC Transmission has been disabled\n"); - netif_stop_queue(netdev); - - /* - * Free the Rx Descriptor contents - */ - TR("Now calling synopGMAC_giveup_rx_desc_queue \n"); - synopGMAC_giveup_rx_desc_queue(gmacdev, dev, RINGMODE); - TR("Now calling synopGMAC_giveup_tx_desc_queue \n"); - synopGMAC_giveup_tx_desc_queue(gmacdev, dev, RINGMODE); - - return -ESYNOPGMACNOERR; -} - -/* - * Function to transmit a given packet on the wire. - * Whenever Linux Kernel has a packet ready to be transmitted, this function is called. - * The function prepares a packet and prepares the descriptor and - * enables/resumes the transmission. - * @param[in] pointer to sk_buff structure. - * @param[in] pointer to net_device structure. - * \return Returns 0 on success and Error code on failure. - * \note structure sk_buff is used to hold packet in Linux networking stacks. - */ -static s32 synopGMAC_linux_xmit_frames(struct sk_buff *skb, struct eth_device *netdev) -{ - u32 dma_addr; - synopGMACdevice *gmacdev; - - TR("%s called \n",__FUNCTION__); - BUG_ON(skb == NULL); - BUG_ON((skb->len < ETH_HLEN) || (skb->len > ETH_MAX_FRAME_LEN)); - if ((skb->len < ETH_HLEN) || (skb->len > ETH_MAX_FRAME_LEN)) - goto drop; - - gmacdev = (synopGMACdevice *) netdev_priv(netdev); - if (gmacdev == NULL) - goto drop; - BUG_ON(gmacdev->synopGMACnetdev != netdev); - - if (gmacdev->BusyTxDesc == gmacdev->TxDescCount) { - /* - * Return busy here. The TX will be re-tried - */ - TR0("%s No More Free Tx Descriptors\n",__FUNCTION__); - netif_stop_queue(netdev); - return NETDEV_TX_BUSY; - } - - /* - * Now we have skb ready and OS invoked this function. Lets make our DMA know about this - */ - dma_addr = virt_to_phys(skb->data); - synopGMAC_set_tx_qptr(gmacdev, dma_addr, skb->len, (u32)skb, 0); - - /* - * Now force the DMA to start transmission - */ - synopGMAC_resume_dma_tx(gmacdev); - TR("%s called \n",__FUNCTION__); - BUG_ON(skb == NULL); - return NETDEV_TX_OK; - -drop: - /* - * Now drop it - */ - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; -} - -/* - * Function to initialize the Linux network interface. - * - * Linux dependent Network interface is setup here. This provides - * an example to handle the network dependent functionality. - * - * \return Returns 0 on success and Error code on failure. - */ -s32 synopGMAC_init_network_interface(void) -{ - u32 i; - u32 id; - s32 err = 0; - struct eth_device *netdev; - synopGMACdevice *gmacdev; - const char *eth_name[2] = {"eth_lan", "eth_wan"};; - - cleanup_skb(); - - for (i = 0; i < 1; i++) { - - /* - * Lets allocate and set up an ethernet device, it takes the sizeof the private structure. - * This is mandatory as a 32 byte allignment is required for the private data structure. - */ - netdev = malloc(sizeof(struct eth_device)); - if(!netdev){ - TR0("Problem in alloc_etherdev()..Take Necessary action\n"); - err = -ESYNOPGMACNOMEM; - break; - } - memcpy(netdev->name, eth_name[i], sizeof(netdev->name) - 1); - - /* - * Allocate Memory for the the GMACip structure - */ - gmacdev = malloc(sizeof(synopGMACdevice)); - if(!gmacdev){ - TR0("Error in Memory Allocataion \n"); - free(netdev); - err = -ESYNOPGMACNOMEM; - break; - } - netdev->priv = gmacdev; - gmac_plat_init(); - gmacdev->phyid = gboard_param->phy_id; /* 6 or 4 */ - gmacdev->synopGMACMappedAddr = gmac_base; - TR("Initializing synopsys GMAC interface at port = 0x%x\n", - gmacdev->synopGMACMappedAddr) ; - - id = ((gmac_base - NSS_GMAC0_BASE) / NSS_GMAC_REG_LEN); - if (id > 3) - return -EINVAL; - - gmac_dev_init(id); - - /* - * Attach the device to MAC struct This will configure all the required base addresses - * such as Mac base, configuration base, phy base address (out of 32 possible phys) - */ - synopGMAC_attach(gmacdev, gmacdev->synopGMACMappedAddr); - gmacdev->synopGMACnetdev = netdev; - - /* - * This just fill in some default MAC address - */ - eth_getenv_enetaddr("ethaddr", netdev->dev_addr); - synopGMACDev[i] = gmacdev; - } - - if (synopGMACDev[0] == NULL) { - TR0("no native Ethernet interface found\n"); - return err; - } - - return 0; -} - -/* - * Function to initialize the Linux network interface. - * Linux dependent Network interface is setup here. This provides - * an example to handle the network dependent functionality. - * \return Returns 0 on success and Error code on failure. - */ -void synopGMAC_exit_network_interface(void) -{ - u32 i; - synopGMACdevice *gmacdev; - - TR0("Now Calling network_unregister\n"); - for (i = 0; i < 1; i++) { - gmacdev = synopGMACDev[i]; - if (gmacdev) { - free(gmacdev->synopGMACnetdev); - free(gmacdev); - synopGMACDev[i] = NULL; - } - } - - cleanup_skb(); -} - -/***************************************************/ - -void ubi32_eth_cleanup(void) -{ - TR("ubi32_eth_cleanup\n"); - - eth_init_done = 0; - synopGMAC_exit_network_interface(); -} - -int ipq_gmac_eth_send(struct eth_device *dev, void *packet, int len) -{ - synopGMACdevice *gmacdev = synopGMACDev[0]; - - struct sk_buff *skb = (struct sk_buff *)TxSkbuf; - - skb->data = (u8*)txbuffs; - - if (!gmacdev) { - goto dropped; - } - if (!skb) { - printf("ipq_gmac_eth_send: alloc_skb return NULL \n"); - goto dropped; - } - - skb->len=len; - memcpy(skb->data, (void *)packet, len); - synopGMAC_linux_xmit_frames(skb, gmacdev->synopGMACnetdev); - return NETDEV_TX_OK; - -dropped: -printf("dropped\n"); - return 1; -} - -int ipq_gmac_eth_rx(struct eth_device *dev) -{ - synopGMACdevice *gmacdev = synopGMACDev[0]; - - if (!gmacdev) { - return 0; - } - - synopGMAC_task_poll((unsigned long)gmacdev); - - return 1; -} - -void ipq_gmac_eth_halt(struct eth_device *dev) -{ - TR("eth_halt\n"); - - /* - * We are not initialized yet, so nothing to stop - */ - if (!eth_init_done) { - return; - } - - synopGMAC_linux_close(synopGMACDev[0]->synopGMACnetdev); - synopGMACDev[0]->state = ETH_STATE_PASSIVE; -} - -int ipq_gmac_eth_init(struct eth_device *dev,bd_t *bd) -{ - TR("eth_init\n"); - - if (!eth_init_done) { - TR("eth_init: init GMAC\n"); - synopGMAC_init_network_interface(); - athrs17_reg_init(); - synopGMACDev[0]->state = ETH_STATE_INIT; - eth_init_done = 1; - } - - synopGMAC_linux_open(synopGMACDev[0]->synopGMACnetdev, dev); - synopGMACDev[0]->state = ETH_STATE_ACTIVE; - - return 0; -} - -uint16_t mii_read_reg(synopGMACdevice *gmacdev, uint32_t phy, uint32_t reg) -{ - u16 data = 0; - - synopGMAC_read_phy_reg((u32 *)gmacdev->MacBase , phy, reg, &data); - return (uint16_t)data; -} - -/* - * mii_write_reg() - * Write a register of an external PHY/Switch - */ -void mii_write_reg(synopGMACdevice *gmacdev, uint32_t phy, uint32_t reg, uint16_t data) -{ - synopGMAC_write_phy_reg((u32 *)gmacdev->MacBase, phy, reg, (uint16_t)data); -} - - -#define MII_BMCR 0x00 -#define BMCR_RESET 0x8000 -#define BMCR_ANENABLE 0x1000 - -void synopGMAC_reset_phy(synopGMACdevice *gmacdev, u32 phyid) -{ - mii_write_reg(gmacdev, phyid , MII_BMCR, BMCR_RESET); - mii_write_reg(gmacdev, phyid , MII_BMCR, mii_read_reg(gmacdev, phyid, MII_BMCR) | BMCR_ANENABLE); - - TR("Reset Phy %u successful\n",phyid); -} - - -int ipq_gmac_eth_initialize(const char *ethaddr) -{ - struct eth_device *dev; - unsigned int m = 5, not_n = 0xF4, not_2d = 0xF5; - int i; - gpio_func_data_t *gpio_func = gboard_param->gmac_gpio; - - gmac_clock_config(m, not_n, not_2d); - - TR("\r\n ***** ipqg_mac_eth_initialize ***** \r\n"); - dev = malloc(sizeof(*dev)); - if (dev == NULL) - return -1; - memset(dev, 0, sizeof(*dev)); - dev->iobase = gboard_param->gmac_base; - dev->init = ipq_gmac_eth_init; - dev->halt = ipq_gmac_eth_halt; - dev->send = ipq_gmac_eth_send; - dev->recv = ipq_gmac_eth_rx; - memcpy(dev->enetaddr, ethaddr, 6); - strcpy(dev->name, "ipq_gmac"); - eth_register(dev); - - for (i = 0; i < gboard_param->gmac_gpio_count; i++) { - gpio_tlmm_config(gpio_func->gpio, gpio_func->func, gpio_func->dir, - gpio_func->pull, gpio_func->drvstr, gpio_func->enable); - gpio_func++; - } - - return 0; -} - -#include "nss_gmac_clocks.h" - - -/** - * @brief Return clock divider value for RGMII PHY. - * @param[in] nss_gmac_dev * - * @return returns RGMII clock divider value. - */ -static uint32_t clk_div_rgmii(synopGMACdevice *gmacdev) -{ - uint32_t div; - - switch (gmacdev->Speed) { - case SPEED1000: - div = RGMII_CLK_DIV_1000; - break; - - case SPEED100: - div = RGMII_CLK_DIV_100; - break; - - case SPEED10: - div = RGMII_CLK_DIV_10; - break; - - default: - div = RGMII_CLK_DIV_1000; - break; - } - - return div; -} - -/** - * @brief Return clock divider value for SGMII PHY. - * @param[in] nss_gmac_dev * - * @return returns SGMII clock divider value. - */ -static uint32_t clk_div_sgmii(synopGMACdevice *gmacdev) -{ - uint32_t div; - - switch (gmacdev->Speed) { - case SPEED1000: - div = SGMII_CLK_DIV_1000; - break; - - case SPEED100: - div = SGMII_CLK_DIV_100; - break; - - case SPEED10: - div = SGMII_CLK_DIV_10; - break; - - default: - div = SGMII_CLK_DIV_1000; - break; - } - - return div; -} - - -/* - * @brief Return clock divider value for QSGMII PHY. - * @param[in] nss_gmac_dev * - * @return returns QSGMII clock divider value. - */ -static uint32_t clk_div_qsgmii(synopGMACdevice *gmacdev) -{ - uint32_t div; - - switch (gmacdev->Speed) { - case SPEED1000: - div = QSGMII_CLK_DIV_1000; - break; - - case SPEED100: - div = QSGMII_CLK_DIV_100; - break; - - case SPEED10: - div = QSGMII_CLK_DIV_10; - break; - - default: - div = QSGMII_CLK_DIV_1000; - break; - } - - return div; -} - - -void nss_gmac_dev_init(synopGMACdevice *gmacdev) -{ - uint32_t val = 0; - uint32_t id = 0, div; - - val = GMAC_IFG_CTL(GMAC_IFG) | GMAC_IFG_LIMIT(GMAC_IFG) | GMAC_CSYS_REQ; - if (gmacdev->phy_mii_type == GMAC_INTF_RGMII) { - val |= GMAC_PHY_RGMII; - } else { - val &= ~GMAC_PHY_RGMII; - } - - synopGMACSetBits((u32 *)nss_base, NSS_GMACn_CTL(id), val); - - synopGMACClearBits((u32 *)MSM_CLK_CTL_BASE, GMAC_COREn_RESET(id), 0x1); - - /* Configure clock dividers for 1000Mbps default */ - gmacdev->Speed = SPEED1000; - switch (gmacdev->phy_mii_type) { - case GMAC_INTF_RGMII: - div = clk_div_rgmii(gmacdev); - break; - - case GMAC_INTF_SGMII: - div = clk_div_sgmii(gmacdev); - break; - - case GMAC_INTF_QSGMII: - div = clk_div_qsgmii(gmacdev); - break; - } - - val = synopGMACReadReg((u32 *)nss_base, NSS_ETH_CLK_DIV0); - - val &= ~GMACn_CLK_DIV(id, GMACn_CLK_DIV_SIZE); - val |= GMACn_CLK_DIV(id, div); - synopGMACWriteReg((u32 *)nss_base, NSS_ETH_CLK_DIV0, val); - - /* Select Tx/Rx CLK source */ - val = 0; - if (id == 0 || id == 1) { - if (gmacdev->phy_mii_type == GMAC_INTF_RGMII) { - val |= (1 << id); - } - } else { - if (gmacdev->phy_mii_type == GMAC_INTF_SGMII) { - val |= (1 << id); - } - } - - synopGMACSetBits((u32 *)nss_base, NSS_ETH_CLK_SRC_CTL, val); - - synopGMACSetBits((u32 *)nss_base, NSS_QSGMII_CLK_CTL, 0x1); - - /* Enable xGMII clk for GMACn */ - val = 0; - if (gmacdev->phy_mii_type == GMAC_INTF_RGMII) { - val |= GMACn_RGMII_RX_CLK(id) | GMACn_RGMII_TX_CLK(id); - } else { - val |= GMACn_GMII_RX_CLK(id) | GMACn_GMII_TX_CLK(id); - } - - /* Optionally configure RGMII CDC delay */ - - /* Enable PTP clock */ - val |= GMACn_PTP_CLK(id); - - synopGMACSetBits((u32 *)nss_base, NSS_ETH_CLK_GATE_CTL, val); -} - -/** - * @brief QSGMII dev init - * - * @param[in] nss_gmac_dev * - * @return void - */ -void nss_gmac_qsgmii_dev_init(synopGMACdevice *gmacdev) -{ - uint32_t val; - uint32_t id = gmacdev->macid; - -#ifdef CONFIG_MACH_IPQ806X_RUMI3 - nss_gmac_rumi_qsgmii_init(gmacdev); -#endif - /* Enable clk for GMACn */ - val = 0; - if ((gmacdev->phy_mii_type == GMAC_INTF_SGMII) || (gmacdev->phy_mii_type == GMAC_INTF_QSGMII)) { - val |= GMACn_QSGMII_RX_CLK(id) | GMACn_QSGMII_TX_CLK(id); - } - - synopGMACSetBits((uint32_t *)nss_base, NSS_QSGMII_CLK_CTL, val); - - val = synopGMACReadReg((uint32_t *)nss_base, NSS_QSGMII_CLK_CTL); - TR("%s: NSS_QSGMII_CLK_CTL(0x%x) - 0x%x", - __FUNCTION__, NSS_QSGMII_CLK_CTL, val); -} - - - -/** - * @brief Clear all NSS GMAC interface registers. - * @return returns 0 on success. - */ -static void nss_gmac_clear_all_regs(void) -{ - synopGMACClearBits((uint32_t *)nss_base, - NSS_ETH_CLK_GATE_CTL, 0xFFFFFFFF); - synopGMACClearBits((uint32_t *)nss_base, - NSS_ETH_CLK_DIV0, 0xFFFFFFFF); - synopGMACClearBits((uint32_t *)nss_base, - NSS_ETH_CLK_DIV1, 0xFFFFFFFF); - synopGMACClearBits((uint32_t *)nss_base, - NSS_ETH_CLK_SRC_CTL, 0xFFFFFFFF); - synopGMACClearBits((uint32_t *)nss_base, - NSS_ETH_CLK_INV_CTL, 0xFFFFFFFF); - synopGMACClearBits((uint32_t *)nss_base, - NSS_GMAC0_CTL, 0xFFFFFFFF); - synopGMACClearBits((uint32_t *)nss_base, - NSS_GMAC1_CTL, 0xFFFFFFFF); - synopGMACClearBits((uint32_t *)nss_base, - NSS_GMAC2_CTL, 0xFFFFFFFF); - synopGMACClearBits((uint32_t *)nss_base, - NSS_GMAC3_CTL, 0xFFFFFFFF); - synopGMACClearBits((uint32_t *)nss_base, - NSS_QSGMII_CLK_CTL, 0xFFFFFFFF); -} - - -static void nss_gmac_qsgmii_common_init(uint32_t *qsgmii_base) -{ -#if defined(CONFIG_IPQ_GMAC_PHY_PROFILE_QS) - /* Configure QSGMII Block for QSGMII mode */ - - /* Put PHY in QSGMII Mode */ - synopGMACWriteReg(qsgmii_base, QSGMII_PHY_MODE_CTL, QSGMII_PHY_MODE_QSGMII); - - /* Put PCS in QSGMII Mode */ - synopGMACWriteReg(qsgmii_base, PCS_QSGMII_SGMII_MODE, PCS_QSGMII_MODE_QSGMII); -#else - /* Configure QSGMII Block for 3xSGMII mode */ - - /* Put PHY in SGMII Mode */ - synopGMACWriteReg(qsgmii_base, QSGMII_PHY_MODE_CTL, QSGMII_PHY_MODE_SGMII); - - /* Put PCS in SGMII Mode */ - synopGMACWriteReg(qsgmii_base, PCS_QSGMII_SGMII_MODE, PCS_QSGMII_MODE_SGMII); -#endif -} - - -/** - * @brief Set GMAC speed. - * @param[in] nss_gmac_dev * - * @return returns 0 on success. - */ -int32_t nss_gmac_dev_set_speed(synopGMACdevice *gmacdev) -{ - uint32_t val; - uint32_t id = gmacdev->macid; - uint32_t div; - uint32_t clk; - - gmacdev->phy_mii_type = GMAC_INTF_RGMII; - switch (gmacdev->phy_mii_type) { - case GMAC_INTF_RGMII: - div = clk_div_rgmii(gmacdev); - break; - - case GMAC_INTF_SGMII: - div = clk_div_sgmii(gmacdev); - break; - - case GMAC_INTF_QSGMII: - div = clk_div_qsgmii(gmacdev); - break; - - default: - return -EINVAL; - TR0("%s: Invalid MII type", __FUNCTION__); - break; - } - - clk = 0; - /* Disable GMACn Tx/Rx clk */ - if (gmacdev->phy_mii_type == GMAC_INTF_RGMII) { - clk |= GMACn_RGMII_RX_CLK(id) | GMACn_RGMII_TX_CLK(id); - } else { - clk |= GMACn_GMII_RX_CLK(id) | GMACn_GMII_TX_CLK(id); - } - synopGMACClearBits((u32*)nss_base, NSS_ETH_CLK_GATE_CTL, clk); - - /* set clock divider */ - val = synopGMACReadReg((u32*)nss_base, NSS_ETH_CLK_DIV0); - val &= ~GMACn_CLK_DIV(id, GMACn_CLK_DIV_SIZE); - val |= GMACn_CLK_DIV(id, div); - synopGMACWriteReg((u32*)nss_base, NSS_ETH_CLK_DIV0, val); - - /* Enable GMACn Tx/Rx clk */ - synopGMACSetBits((u32*)nss_base, NSS_ETH_CLK_GATE_CTL, clk); - - val = synopGMACReadReg((u32*)nss_base, NSS_ETH_CLK_DIV0); - TR0("%s:NSS_ETH_CLK_DIV0(0x%x) - 0x%x", - __FUNCTION__, NSS_ETH_CLK_DIV0, val); - - return 0; -} - - -void ipq806x_dev_board_init(synopGMACdevice *gmacdev) -{ - nss_gmac_common_init(); - switch (gmacdev->macid) { - case 0: - gmacdev->phy_mii_type = NSS_GMAC0_MII_MODE; - break; - - case 1: - gmacdev->phy_mii_type = NSS_GMAC1_MII_MODE; - break; - - case 2: - gmacdev->phy_mii_type = NSS_GMAC2_MII_MODE; - break; - - case 3: - gmacdev->phy_mii_type = NSS_GMAC3_MII_MODE; - break; - - default: - TR0("%s: Invalid MII type", __FUNCTION__); - return ; - break; - } - - nss_gmac_dev_init(gmacdev); -} - -/* - * @brief Initialization commom to all GMACs. - * @return returns 0 on success. - */ -int32_t nss_gmac_common_init(void) -{ - volatile uint32_t val; - - nss_gmac_clear_all_regs(); - - synopGMACWriteReg(qsgmii_base, NSS_QSGMII_PHY_SERDES_CTL, - PLL_PUMP_CURRENT_600uA | PLL_TANK_CURRENT_7mA | - PCIE_MAX_POWER_MODE | PLL_LOOP_FILTER_RESISTOR_DEFAULT | - PLL_ENABLE | SERDES_ENABLE_LCKDT); - - synopGMACWriteReg(qsgmii_base, NSS_PCS_CAL_LCKDT_CTL, LCKDT_RST_n); - - synopGMACWriteReg(qsgmii_base, NSS_QSGMII_PHY_QSGMII_CTL, - QSGMII_TX_AMPLITUDE_600mV | QSGMII_TX_SLC_10 | - QSGMII_THRESHOLD_DEFAULT | QSGMII_SLEW_RATE_DEFAULT | - QSGMII_RX_EQUALIZER_DEFAULT | QSGMII_RX_DC_BIAS_DEFAULT | - QSGMII_PHASE_LOOP_GAIN_DEFAULT | QSGMII_TX_DE_EMPHASIS_DEFAULT | - QSGMII_ENABLE | QSGMII_ENABLE_TX | - QSGMII_ENABLE_SD | QSGMII_ENABLE_RX | - QSGMII_ENABLE_CDR); - - synopGMACWriteReg(qsgmii_base, NSS_PCS_QSGMII_BERT_THLD_CTL, 0x0); - - /* - * Deaassert GMAC AHB reset - */ - synopGMACClearBits((uint32_t *)(MSM_CLK_CTL_BASE), GMAC_AHB_RESET, 0x1); - - /* Bypass MACSEC */ - synopGMACSetBits((uint32_t *)nss_base, NSS_MACSEC_CTL, 0x7); - - val = synopGMACReadReg((uint32_t *)nss_base, NSS_MACSEC_CTL); - TR("%s:NSS_MACSEC_CTL(0x%x) - 0x%x", - __FUNCTION__, NSS_MACSEC_CTL, val); - - /* - * Initialize ACC_GMAC_CUST field of NSS_ACC_REG register - * for GMAC and MACSEC memories. - */ - synopGMACClearBits((uint32_t *)(MSM_CLK_CTL_BASE), NSS_ACC_REG, GMAC_ACC_CUST_MASK); - - return 0; -} - - -void nss_gmac_reset_phy( uint32_t phyid) -{ - ipq_mii_write_reg( phyid, MII_BMCR, BMCR_RESET); - ipq_mii_write_reg( phyid, MII_BMCR, - ipq_mii_read_reg( phyid, MII_BMCR) - | BMCR_ANENABLE); -} - -int32_t ipq806x_get_link_speed(uint32_t phyid) -{ - int32_t lpa = 0, media, adv; - lpa = ipq_mii_read_reg(phyid, MII_LPA); - TR(" get_link_speed LPA %x \r\n ", lpa); - adv = ipq_mii_read_reg(phyid, MII_ADVERTISE); - TR(" get_link_speed LPA %x ADV %x \r\n ", lpa, adv); - media = mii_nway_result(lpa & adv); - if((media & ADVERTISE_1000XFULL)) - return SPEED1000; - else if (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)) - return SPEED100; - else if (media & (ADVERTISE_10FULL | ADVERTISE_10HALF)) - return SPEED10; - else return SPEED1000; /* fix to 1000 for bringup */ -} - -int32_t ipq806x_get_duplex(uint32_t phyid) -{ - int32_t lpa = 0, media, duplex, adv; - lpa = ipq_mii_read_reg(phyid, MII_LPA); - TR(" get_link_speed LPA %x \r\n ", lpa); - adv = ipq_mii_read_reg(phyid, MII_ADVERTISE); - TR(" get_link_speed LPA %x ADV %x \r\n ", lpa, adv); - media = mii_nway_result(lpa & adv); - duplex = (media & (ADVERTISE_FULL | ADVERTISE_1000XFULL)) ? FULLDUPLEX : HALFDUPLEX; - - return duplex; -} - diff --git a/root/package/utils/sysupgrade-helper/src/drivers/net/nss/synopGMAC_plat.h b/root/package/utils/sysupgrade-helper/src/drivers/net/nss/synopGMAC_plat.h deleted file mode 100644 index 2130668a..00000000 --- a/root/package/utils/sysupgrade-helper/src/drivers/net/nss/synopGMAC_plat.h +++ /dev/null @@ -1,149 +0,0 @@ - -/* * Copyright (c) 2012 The Linux Foundation. All rights reserved.* */ - -/**\file - * This file serves as the wrapper for the platform/OS dependent functions - * It is needed to modify these functions accordingly based on the platform and the - * OS. Whenever the synopsys GMAC driver ported on to different platform, this file - * should be handled at most care. - * The corresponding function definitions for non-inline functions are available in - * synopGMAC_plat.c file. - * \internal - * -------------------------------------REVISION HISTORY--------------------------- - * Ubicom 01/Mar/2010 Modified for Ubicom32 - * Synopsys 01/Aug/2007 Created - */ - -#ifndef SYNOP_GMAC_PLAT_H -#define SYNOP_GMAC_PLAT_H 1 - -#include -#include -#include -#include "uboot_skb.h" -#include - -#define CACHE_LINE_SHIFT 5 -#define CACHE_LINE_SIZE (1 << CACHE_LINE_SHIFT) /* in bytes */ - -#define TR0(fmt, args...) printf("SynopGMAC: " fmt, ##args) -# define TR(fmt, args...) /* not debugging: nothing */ - -typedef int bool; - -#define virt_to_phys(x) ((unsigned long)(x)) - -#ifdef __GNUC__ -#define likely(x) __builtin_expect(!!(x), 1) -#define unlikely(x) __builtin_expect(!!(x), 0) -#else -#define likely(x) (x) -#define unlikely(x) (x) -#endif - -#define NETDEV_TX_OK 0 -#define NETDEV_TX_BUSY 1 /* driver tx path was busy*/ - -#define DEFAULT_DELAY_VARIABLE 10 -#define DEFAULT_LOOP_VARIABLE 10/*000*/ - -/* There are platform related endian conversions - * - */ - -/* Error Codes */ -#define ESYNOPGMACNOERR 0 -#define ESYNOPGMACNOMEM ENOMEM -#define ESYNOPGMACPHYERR EIO - -static void __inline__ *plat_alloc_consistent_dmaable_memory(void *dev, size_t size, dma_addr_t *dma_addr) -{ - void *buf = memalign(CACHE_LINE_SIZE, size); - *dma_addr = (dma_addr_t)(virt_to_phys(buf)); - return buf; -} - -/** - * The Low level function to read register contents from Hardware. - * - * @param[in] pointer to the base of register map - * @param[in] Offset from the base - * \return Returns the register contents - */ -static u32 __inline__ synopGMACReadReg(u32 *RegBase, u32 RegOffset) -{ - u32 addr = (u32)RegBase + RegOffset; - u32 data; - - data = readl(addr); - TR("%s RegBase = 0x%08x RegOffset = 0x%08x RegData = 0x%08x\n", __FUNCTION__, (u32)RegBase, RegOffset, data ); - return data; -} - -/** - * The Low level function to write to a register in Hardware. - * - * @param[in] pointer to the base of register map - * @param[in] Offset from the base - * @param[in] Data to be written - * \return void - */ -static void __inline__ synopGMACWriteReg(u32 *RegBase, u32 RegOffset, u32 RegData) -{ - u32 addr = (u32)RegBase + RegOffset; - - writel(RegData, addr); - TR("%s RegBase = 0x%08x RegOffset = 0x%08x RegData = 0x%08x\n", __FUNCTION__,(u32) RegBase, RegOffset, RegData ); -} - -/** - * The Low level function to set bits of a register in Hardware. - * - * @param[in] pointer to the base of register map - * @param[in] Offset from the base - * @param[in] Bit mask to set bits to logical 1 - * \return void - */ -static void __inline__ synopGMACSetBits(u32 *RegBase, u32 RegOffset, u32 BitPos) -{ - u32 addr = (u32)RegBase + RegOffset; - - setbits_le32(addr,BitPos); - TR("%s !!!!!!!!!!!!! RegOffset = 0x%08x RegData = 0x%08x (| 0x%08x)\n", __FUNCTION__, RegOffset, data, BitPos); -} - -/** - * The Low level function to clear bits of a register in Hardware. - * - * @param[in] pointer to the base of register map - * @param[in] Offset from the base - * @param[in] Bit mask to clear bits to logical 0 - * \return void - */ -static void __inline__ synopGMACClearBits(u32 *RegBase, u32 RegOffset, u32 BitPos) -{ - u32 addr = (u32)RegBase + RegOffset; - - clrbits_le32( addr, BitPos); - TR("%s !!!!!!!!!!! RegOffset = 0x%08x RegData = 0x%08x (& ~0x%08x)\n", __FUNCTION__, RegOffset, data, BitPos); -} - -/** - * The Low level function to Check the setting of the bits. - * - * @param[in] pointer to the base of register map - * @param[in] Offset from the base - * @param[in] Bit mask to set bits to logical 1 - * \return returns TRUE if set to '1' returns FALSE if set to '0'. Result undefined there are no bit set in the BitPos argument. - * - */ -static bool __inline__ synopGMACCheckBits(u32 *RegBase, u32 RegOffset, u32 BitPos) -{ - u32 addr = (u32)RegBase + RegOffset; - u32 data; - - data = readl(addr) & BitPos ; - return (data != 0); -} - -#endif diff --git a/root/package/utils/sysupgrade-helper/src/drivers/net/nss/uboot_skb.c b/root/package/utils/sysupgrade-helper/src/drivers/net/nss/uboot_skb.c deleted file mode 100644 index 655bed2e..00000000 --- a/root/package/utils/sysupgrade-helper/src/drivers/net/nss/uboot_skb.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Definitions for the 'struct sk_buff' memory handlers in U-Boot. - * - n (C) Copyright 2003 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include -#include -#include "uboot_skb.h" - -#define MAX_SKB 1024 - -static struct sk_buff *sk_table[MAX_SKB]; - -struct sk_buff * alloc_skb(u32 size, int dummy) -{ - int i; - struct sk_buff * ret = NULL; - - for (i = 0; i < MAX_SKB; i++) - { - if (sk_table[i]) - { - /* Already allocated. - */ - continue; - } - - sk_table[i] = malloc(sizeof(struct sk_buff)); - if (! sk_table[i]) - { - printf("alloc_skb: malloc failed\n"); - break; - } - - memset(sk_table[i], 0, sizeof(struct sk_buff)); - sk_table[i]->data = sk_table[i]->data_unaligned = - malloc(size + 48); - if (! sk_table[i]->data) - { - printf("alloc_skb: malloc failed\n"); - free(sk_table[i]); - sk_table[i] = NULL; - break; - } - - sk_table[i]->data += 48 - ((u32)sk_table[i]->data & 31); - sk_table[i]->len = size; - - break; - } - - if (i < MAX_SKB) - { - ret = sk_table[i]; - } - - if (! ret) - { - printf("Unable to allocate skb!\n"); - } - - return ret; -} - -void dev_kfree_skb_any(struct sk_buff *skb) -{ - int i; - - for (i = 0; i < MAX_SKB; i++) - { - if (sk_table[i] != skb) - { - continue; - } - - free(skb->data_unaligned); - free(skb); - sk_table[i] = NULL; - break; - } - -} - -void skb_reserve(struct sk_buff *skb, unsigned int len) -{ - skb->data+=len; -} - -void skb_put(struct sk_buff *skb, unsigned int len) -{ - skb->len+=len; -} - -void cleanup_skb(void) -{ - int i; - for (i = 0; i < MAX_SKB; i++) - { - if (sk_table[i]) - { - /* Already allocated. - */ - free(sk_table[i]->data_unaligned); - free(sk_table[i]); - sk_table[i] = NULL; - } - } -} diff --git a/root/package/utils/sysupgrade-helper/src/drivers/net/nss/uboot_skb.h b/root/package/utils/sysupgrade-helper/src/drivers/net/nss/uboot_skb.h deleted file mode 100644 index b40a30a8..00000000 --- a/root/package/utils/sysupgrade-helper/src/drivers/net/nss/uboot_skb.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * (C) Copyright 2003 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#ifndef _UBOOT_COMPAT_H__ -#define _UBOOT_COMPAT_H__ - -#include -#include -#include - -#define netif_start_queue(x) -#define netif_stop_queue(x) -#define netif_wake_queue(x) - -#define dev_addr enetaddr -struct sk_buff -{ - u8 * data; - u32 len; - u8 * data_unaligned; - u32 padding; - char cb[16]; -}; - -struct sk_buff * alloc_skb(u32 size, int dummy); -void dev_kfree_skb_any(struct sk_buff *skb); -void skb_reserve(struct sk_buff *skb, unsigned int len); -void skb_put(struct sk_buff *skb, unsigned int len); - -#define dev_kfree_skb dev_kfree_skb_any -#define dev_kfree_skb_irq dev_kfree_skb_any - -#endif /* _UBOOT_COMPAT_H__ */ diff --git a/root/package/utils/sysupgrade-helper/src/mkconfig b/root/package/utils/sysupgrade-helper/src/mkconfig deleted file mode 100644 index 801f9212..00000000 --- a/root/package/utils/sysupgrade-helper/src/mkconfig +++ /dev/null @@ -1,181 +0,0 @@ -#!/bin/sh -e - -# Script to create header files and links to configure -# U-Boot for a specific board. -# -# Parameters: Target Architecture CPU Board [VENDOR] [SOC] -# -# (C) 2002-2010 DENX Software Engineering, Wolfgang Denk -# - -APPEND=no # Default: Create new config file -BOARD_NAME="" # Name to print in make output -TARGETS="" - -arch="" -cpu="" -board="" -vendor="" -soc="" -options="" - -if [ \( $# -eq 2 \) -a \( "$1" = "-A" \) ] ; then - # Automatic mode - line=`egrep -i "^[[:space:]]*${2}[[:space:]]" boards.cfg` || { - echo "make: *** No rule to make target \`$2_config'. Stop." >&2 - exit 1 - } - - set ${line} - # add default board name if needed - [ $# = 3 ] && set ${line} ${1} -elif [ "${MAKEFLAGS+set}${MAKELEVEL+set}" = "setset" ] ; then - # only warn when using a config target in the Makefile - cat <<-EOF - - warning: Please migrate to boards.cfg. Failure to do so will - mean removal of your board in the next release. - - EOF - sleep 5 -fi - -while [ $# -gt 0 ] ; do - case "$1" in - --) shift ; break ;; - -a) shift ; APPEND=yes ;; - -n) shift ; BOARD_NAME="${1%_config}" ; shift ;; - -t) shift ; TARGETS="`echo $1 | sed 's:_: :g'` ${TARGETS}" ; shift ;; - *) break ;; - esac -done - -[ $# -lt 4 ] && exit 1 -[ $# -gt 7 ] && exit 1 - -# Strip all options and/or _config suffixes -CONFIG_NAME="${1%_config}" - -[ "${BOARD_NAME}" ] || BOARD_NAME="${1%_config}" - -arch="$2" -cpu="$3" -if [ "$4" = "-" ] ; then - board=${BOARD_NAME} -else - board="$4" -fi -[ $# -gt 4 ] && [ "$5" != "-" ] && vendor="$5" -[ $# -gt 5 ] && [ "$6" != "-" ] && soc="$6" -[ $# -gt 6 ] && [ "$7" != "-" ] && { - # check if we have a board config name in the options field - # the options field mave have a board config name and a list - # of options, both separated by a colon (':'); the options are - # separated by commas (','). - # - # Check for board name - tmp="${7%:*}" - if [ "$tmp" ] ; then - CONFIG_NAME="$tmp" - fi - # Check if we only have a colon... - if [ "${tmp}" != "$7" ] ; then - options=${7#*:} - TARGETS="`echo ${options} | sed 's:,: :g'` ${TARGETS}" - fi -} - -if [ "${ARCH}" -a "${ARCH}" != "${arch}" ]; then - echo "Failed: \$ARCH=${ARCH}, should be '${arch}' for ${BOARD_NAME}" 1>&2 - exit 1 -fi - -if [ "$options" ] ; then - echo "Configuring for ${BOARD_NAME} - Board: ${CONFIG_NAME}, Options: ${options}" -else - echo "Configuring for ${BOARD_NAME} board..." -fi - -# -# Create link to architecture specific headers -# -if [ "$SRCTREE" != "$OBJTREE" ] ; then - mkdir -p ${OBJTREE}/include - mkdir -p ${OBJTREE}/include2 - cd ${OBJTREE}/include2 - rm -f asm - ln -s ${SRCTREE}/arch/${arch}/include/asm asm - LNPREFIX=${SRCTREE}/arch/${arch}/include/asm/ - cd ../include - mkdir -p asm -else - cd ./include - rm -f asm - ln -s ../arch/${arch}/include/asm asm -fi - -rm -f asm/arch - -if [ -z "${soc}" ] ; then - ln -s ${LNPREFIX}arch-${cpu} asm/arch -else - ln -s ${LNPREFIX}arch-${soc} asm/arch -fi - -if [ "${arch}" = "arm" ] ; then - rm -f asm/proc - ln -s ${LNPREFIX}proc-armv asm/proc -fi - -# -# Create include file for Make -# -echo "ARCH = ${arch}" > config.mk -echo "CPU = ${cpu}" >> config.mk -echo "BOARD = ${board}" >> config.mk - -[ "${vendor}" ] && echo "VENDOR = ${vendor}" >> config.mk - -[ "${soc}" ] && echo "SOC = ${soc}" >> config.mk - -# Assign board directory to BOARDIR variable -if [ -z "${vendor}" ] ; then - BOARDDIR=${board} -else - BOARDDIR=${vendor}/${board} -fi - -# -# Create board specific header file -# -if [ "$APPEND" = "yes" ] # Append to existing config file -then - echo >> config.h -else - > config.h # Create new config file -fi -echo "/* Automatically generated - do not edit */" >>config.h - -for i in ${TARGETS} ; do - i="`echo ${i} | sed '/=/ {s/=/ /;q; } ; { s/$/ 1/; }'`" - echo "#define CONFIG_${i}" >>config.h ; -done - -echo "#define CONFIG_SYS_ARCH \"${arch}\"" >> config.h -echo "#define CONFIG_SYS_CPU \"${cpu}\"" >> config.h -echo "#define CONFIG_SYS_BOARD \"${board}\"" >> config.h - -[ "${vendor}" ] && echo "#define CONFIG_SYS_VENDOR \"${vendor}\"" >> config.h - -[ "${soc}" ] && echo "#define CONFIG_SYS_SOC \"${soc}\"" >> config.h - -cat << EOF >> config.h -#define CONFIG_BOARDDIR board/$BOARDDIR -#include -#include -#include -#include -#include -EOF - -exit 0 diff --git a/root/package/utils/sysupgrade-helper/src/tools/checkpatch.pl b/root/package/utils/sysupgrade-helper/src/tools/checkpatch.pl deleted file mode 100644 index c7475f9e..00000000 --- a/root/package/utils/sysupgrade-helper/src/tools/checkpatch.pl +++ /dev/null @@ -1,3343 +0,0 @@ -#!/usr/bin/perl -w -# (c) 2001, Dave Jones. (the file handling bit) -# (c) 2005, Joel Schopp (the ugly bit) -# (c) 2007,2008, Andy Whitcroft (new conditions, test suite) -# (c) 2008-2010 Andy Whitcroft -# Licensed under the terms of the GNU GPL License version 2 - -use strict; - -my $P = $0; -$P =~ s@.*/@@g; - -my $V = '0.32'; - -use Getopt::Long qw(:config no_auto_abbrev); - -my $quiet = 0; -my $tree = 1; -my $chk_signoff = 1; -my $chk_patch = 1; -my $tst_only; -my $emacs = 0; -my $terse = 0; -my $file = 0; -my $check = 0; -my $summary = 1; -my $mailback = 0; -my $summary_file = 0; -my $show_types = 0; -my $root; -my %debug; -my %ignore_type = (); -my @ignore = (); -my $help = 0; -my $configuration_file = ".checkpatch.conf"; - -sub help { - my ($exitcode) = @_; - - print << "EOM"; -Usage: $P [OPTION]... [FILE]... -Version: $V - -Options: - -q, --quiet quiet - --no-tree run without a kernel tree - --no-signoff do not check for 'Signed-off-by' line - --patch treat FILE as patchfile (default) - --emacs emacs compile window format - --terse one line per report - -f, --file treat FILE as regular source file - --subjective, --strict enable more subjective tests - --ignore TYPE(,TYPE2...) ignore various comma separated message types - --show-types show the message "types" in the output - --root=PATH PATH to the kernel tree root - --no-summary suppress the per-file summary - --mailback only produce a report in case of warnings/errors - --summary-file include the filename in summary - --debug KEY=[0|1] turn on/off debugging of KEY, where KEY is one of - 'values', 'possible', 'type', and 'attr' (default - is all off) - --test-only=WORD report only warnings/errors containing WORD - literally - -h, --help, --version display this help and exit - -When FILE is - read standard input. -EOM - - exit($exitcode); -} - -my $conf = which_conf($configuration_file); -if (-f $conf) { - my @conf_args; - open(my $conffile, '<', "$conf") - or warn "$P: Can't find a readable $configuration_file file $!\n"; - - while (<$conffile>) { - my $line = $_; - - $line =~ s/\s*\n?$//g; - $line =~ s/^\s*//g; - $line =~ s/\s+/ /g; - - next if ($line =~ m/^\s*#/); - next if ($line =~ m/^\s*$/); - - my @words = split(" ", $line); - foreach my $word (@words) { - last if ($word =~ m/^#/); - push (@conf_args, $word); - } - } - close($conffile); - unshift(@ARGV, @conf_args) if @conf_args; -} - -GetOptions( - 'q|quiet+' => \$quiet, - 'tree!' => \$tree, - 'signoff!' => \$chk_signoff, - 'patch!' => \$chk_patch, - 'emacs!' => \$emacs, - 'terse!' => \$terse, - 'f|file!' => \$file, - 'subjective!' => \$check, - 'strict!' => \$check, - 'ignore=s' => \@ignore, - 'show-types!' => \$show_types, - 'root=s' => \$root, - 'summary!' => \$summary, - 'mailback!' => \$mailback, - 'summary-file!' => \$summary_file, - - 'debug=s' => \%debug, - 'test-only=s' => \$tst_only, - 'h|help' => \$help, - 'version' => \$help -) or help(1); - -help(0) if ($help); - -my $exit = 0; - -if ($#ARGV < 0) { - print "$P: no input files\n"; - exit(1); -} - -@ignore = split(/,/, join(',',@ignore)); -foreach my $word (@ignore) { - $word =~ s/\s*\n?$//g; - $word =~ s/^\s*//g; - $word =~ s/\s+/ /g; - $word =~ tr/[a-z]/[A-Z]/; - - next if ($word =~ m/^\s*#/); - next if ($word =~ m/^\s*$/); - - $ignore_type{$word}++; -} - -my $dbg_values = 0; -my $dbg_possible = 0; -my $dbg_type = 0; -my $dbg_attr = 0; -for my $key (keys %debug) { - ## no critic - eval "\${dbg_$key} = '$debug{$key}';"; - die "$@" if ($@); -} - -my $rpt_cleaners = 0; - -if ($terse) { - $emacs = 1; - $quiet++; -} - -if ($tree) { - if (defined $root) { - if (!top_of_kernel_tree($root)) { - die "$P: $root: --root does not point at a valid tree\n"; - } - } else { - if (top_of_kernel_tree('.')) { - $root = '.'; - } elsif ($0 =~ m@(.*)/scripts/[^/]*$@ && - top_of_kernel_tree($1)) { - $root = $1; - } - } - - if (!defined $root) { - print "Must be run from the top-level dir. of a kernel tree\n"; - exit(2); - } -} - -my $emitted_corrupt = 0; - -our $Ident = qr{ - [A-Za-z_][A-Za-z\d_]* - (?:\s*\#\#\s*[A-Za-z_][A-Za-z\d_]*)* - }x; -our $Storage = qr{extern|static|asmlinkage}; -our $Sparse = qr{ - __user| - __kernel| - __force| - __iomem| - __must_check| - __init_refok| - __kprobes| - __ref| - __rcu - }x; - -# Notes to $Attribute: -# We need \b after 'init' otherwise 'initconst' will cause a false positive in a check -our $Attribute = qr{ - const| - __percpu| - __nocast| - __safe| - __bitwise__| - __packed__| - __packed2__| - __naked| - __maybe_unused| - __always_unused| - __noreturn| - __used| - __cold| - __noclone| - __deprecated| - __read_mostly| - __kprobes| - __(?:mem|cpu|dev|)(?:initdata|initconst|init\b)| - ____cacheline_aligned| - ____cacheline_aligned_in_smp| - ____cacheline_internodealigned_in_smp| - __weak - }x; -our $Modifier; -our $Inline = qr{inline|__always_inline|noinline}; -our $Member = qr{->$Ident|\.$Ident|\[[^]]*\]}; -our $Lval = qr{$Ident(?:$Member)*}; - -our $Constant = qr{(?:[0-9]+|0x[0-9a-fA-F]+)[UL]*}; -our $Assignment = qr{(?:\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=)}; -our $Compare = qr{<=|>=|==|!=|<|>}; -our $Operators = qr{ - <=|>=|==|!=| - =>|->|<<|>>|<|>|!|~| - &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|% - }x; - -our $NonptrType; -our $Type; -our $Declare; - -our $UTF8 = qr { - [\x09\x0A\x0D\x20-\x7E] # ASCII - | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte - | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs - | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte - | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates - | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 - | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 - | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 -}x; - -our $typeTypedefs = qr{(?x: - (?:__)?(?:u|s|be|le)(?:8|16|32|64)| - atomic_t -)}; - -our $logFunctions = qr{(?x: - printk(?:_ratelimited|_once|)| - [a-z0-9]+_(?:printk|emerg|alert|crit|err|warning|warn|notice|info|debug|dbg|vdbg|devel|cont|WARN)(?:_ratelimited|_once|)| - WARN(?:_RATELIMIT|_ONCE|)| - panic| - MODULE_[A-Z_]+ -)}; - -our $signature_tags = qr{(?xi: - Signed-off-by:| - Acked-by:| - Tested-by:| - Reviewed-by:| - Reported-by:| - To:| - Cc: -)}; - -our @typeList = ( - qr{void}, - qr{(?:unsigned\s+)?char}, - qr{(?:unsigned\s+)?short}, - qr{(?:unsigned\s+)?int}, - qr{(?:unsigned\s+)?long}, - qr{(?:unsigned\s+)?long\s+int}, - qr{(?:unsigned\s+)?long\s+long}, - qr{(?:unsigned\s+)?long\s+long\s+int}, - qr{unsigned}, - qr{float}, - qr{double}, - qr{bool}, - qr{struct\s+$Ident}, - qr{union\s+$Ident}, - qr{enum\s+$Ident}, - qr{${Ident}_t}, - qr{${Ident}_handler}, - qr{${Ident}_handler_fn}, -); -our @modifierList = ( - qr{fastcall}, -); - -our $allowed_asm_includes = qr{(?x: - irq| - memory -)}; -# memory.h: ARM has a custom one - -sub build_types { - my $mods = "(?x: \n" . join("|\n ", @modifierList) . "\n)"; - my $all = "(?x: \n" . join("|\n ", @typeList) . "\n)"; - $Modifier = qr{(?:$Attribute|$Sparse|$mods)}; - $NonptrType = qr{ - (?:$Modifier\s+|const\s+)* - (?: - (?:typeof|__typeof__)\s*\(\s*\**\s*$Ident\s*\)| - (?:$typeTypedefs\b)| - (?:${all}\b) - ) - (?:\s+$Modifier|\s+const)* - }x; - $Type = qr{ - $NonptrType - (?:[\s\*]+\s*const|[\s\*]+|(?:\s*\[\s*\])+)? - (?:\s+$Inline|\s+$Modifier)* - }x; - $Declare = qr{(?:$Storage\s+)?$Type}; -} -build_types(); - -our $match_balanced_parentheses = qr/(\((?:[^\(\)]+|(-1))*\))/; - -our $Typecast = qr{\s*(\(\s*$NonptrType\s*\)){0,1}\s*}; -our $LvalOrFunc = qr{($Lval)\s*($match_balanced_parentheses{0,1})\s*}; - -sub deparenthesize { - my ($string) = @_; - return "" if (!defined($string)); - $string =~ s@^\s*\(\s*@@g; - $string =~ s@\s*\)\s*$@@g; - $string =~ s@\s+@ @g; - return $string; -} - -$chk_signoff = 0 if ($file); - -my @dep_includes = (); -my @dep_functions = (); -my $removal = "Documentation/feature-removal-schedule.txt"; -if ($tree && -f "$root/$removal") { - open(my $REMOVE, '<', "$root/$removal") || - die "$P: $removal: open failed - $!\n"; - while (<$REMOVE>) { - if (/^Check:\s+(.*\S)/) { - for my $entry (split(/[, ]+/, $1)) { - if ($entry =~ m@include/(.*)@) { - push(@dep_includes, $1); - - } elsif ($entry !~ m@/@) { - push(@dep_functions, $entry); - } - } - } - } - close($REMOVE); -} - -my @rawlines = (); -my @lines = (); -my $vname; -for my $filename (@ARGV) { - my $FILE; - if ($file) { - open($FILE, '-|', "diff -u /dev/null $filename") || - die "$P: $filename: diff failed - $!\n"; - } elsif ($filename eq '-') { - open($FILE, '<&STDIN'); - } else { - open($FILE, '<', "$filename") || - die "$P: $filename: open failed - $!\n"; - } - if ($filename eq '-') { - $vname = 'Your patch'; - } else { - $vname = $filename; - } - while (<$FILE>) { - chomp; - push(@rawlines, $_); - } - close($FILE); - if (!process($filename)) { - $exit = 1; - } - @rawlines = (); - @lines = (); -} - -exit($exit); - -sub top_of_kernel_tree { - my ($root) = @_; - - my @tree_check = ( - "COPYING", "CREDITS", "Kbuild", "MAINTAINERS", "Makefile", - "README", "Documentation", "arch", "include", "drivers", - "fs", "init", "ipc", "kernel", "lib", "scripts", - ); - - foreach my $check (@tree_check) { - if (! -e $root . '/' . $check) { - return 0; - } - } - return 1; - } - -sub parse_email { - my ($formatted_email) = @_; - - my $name = ""; - my $address = ""; - my $comment = ""; - - if ($formatted_email =~ /^(.*)<(\S+\@\S+)>(.*)$/) { - $name = $1; - $address = $2; - $comment = $3 if defined $3; - } elsif ($formatted_email =~ /^\s*<(\S+\@\S+)>(.*)$/) { - $address = $1; - $comment = $2 if defined $2; - } elsif ($formatted_email =~ /(\S+\@\S+)(.*)$/) { - $address = $1; - $comment = $2 if defined $2; - $formatted_email =~ s/$address.*$//; - $name = $formatted_email; - $name =~ s/^\s+|\s+$//g; - $name =~ s/^\"|\"$//g; - # If there's a name left after stripping spaces and - # leading quotes, and the address doesn't have both - # leading and trailing angle brackets, the address - # is invalid. ie: - # "joe smith joe@smith.com" bad - # "joe smith ]+>$/) { - $name = ""; - $address = ""; - $comment = ""; - } - } - - $name =~ s/^\s+|\s+$//g; - $name =~ s/^\"|\"$//g; - $address =~ s/^\s+|\s+$//g; - $address =~ s/^\<|\>$//g; - - if ($name =~ /[^\w \-]/i) { ##has "must quote" chars - $name =~ s/(?"; - } - - return $formatted_email; -} - -sub which_conf { - my ($conf) = @_; - - foreach my $path (split(/:/, ".:$ENV{HOME}:.scripts")) { - if (-e "$path/$conf") { - return "$path/$conf"; - } - } - - return ""; -} - -sub expand_tabs { - my ($str) = @_; - - my $res = ''; - my $n = 0; - for my $c (split(//, $str)) { - if ($c eq "\t") { - $res .= ' '; - $n++; - for (; ($n % 8) != 0; $n++) { - $res .= ' '; - } - next; - } - $res .= $c; - $n++; - } - - return $res; -} -sub copy_spacing { - (my $res = shift) =~ tr/\t/ /c; - return $res; -} - -sub line_stats { - my ($line) = @_; - - # Drop the diff line leader and expand tabs - $line =~ s/^.//; - $line = expand_tabs($line); - - # Pick the indent from the front of the line. - my ($white) = ($line =~ /^(\s*)/); - - return (length($line), length($white)); -} - -my $sanitise_quote = ''; - -sub sanitise_line_reset { - my ($in_comment) = @_; - - if ($in_comment) { - $sanitise_quote = '*/'; - } else { - $sanitise_quote = ''; - } -} -sub sanitise_line { - my ($line) = @_; - - my $res = ''; - my $l = ''; - - my $qlen = 0; - my $off = 0; - my $c; - - # Always copy over the diff marker. - $res = substr($line, 0, 1); - - for ($off = 1; $off < length($line); $off++) { - $c = substr($line, $off, 1); - - # Comments we are wacking completly including the begin - # and end, all to $;. - if ($sanitise_quote eq '' && substr($line, $off, 2) eq '/*') { - $sanitise_quote = '*/'; - - substr($res, $off, 2, "$;$;"); - $off++; - next; - } - if ($sanitise_quote eq '*/' && substr($line, $off, 2) eq '*/') { - $sanitise_quote = ''; - substr($res, $off, 2, "$;$;"); - $off++; - next; - } - if ($sanitise_quote eq '' && substr($line, $off, 2) eq '//') { - $sanitise_quote = '//'; - - substr($res, $off, 2, $sanitise_quote); - $off++; - next; - } - - # A \ in a string means ignore the next character. - if (($sanitise_quote eq "'" || $sanitise_quote eq '"') && - $c eq "\\") { - substr($res, $off, 2, 'XX'); - $off++; - next; - } - # Regular quotes. - if ($c eq "'" || $c eq '"') { - if ($sanitise_quote eq '') { - $sanitise_quote = $c; - - substr($res, $off, 1, $c); - next; - } elsif ($sanitise_quote eq $c) { - $sanitise_quote = ''; - } - } - - #print "c<$c> SQ<$sanitise_quote>\n"; - if ($off != 0 && $sanitise_quote eq '*/' && $c ne "\t") { - substr($res, $off, 1, $;); - } elsif ($off != 0 && $sanitise_quote eq '//' && $c ne "\t") { - substr($res, $off, 1, $;); - } elsif ($off != 0 && $sanitise_quote && $c ne "\t") { - substr($res, $off, 1, 'X'); - } else { - substr($res, $off, 1, $c); - } - } - - if ($sanitise_quote eq '//') { - $sanitise_quote = ''; - } - - # The pathname on a #include may be surrounded by '<' and '>'. - if ($res =~ /^.\s*\#\s*include\s+\<(.*)\>/) { - my $clean = 'X' x length($1); - $res =~ s@\<.*\>@<$clean>@; - - # The whole of a #error is a string. - } elsif ($res =~ /^.\s*\#\s*(?:error|warning)\s+(.*)\b/) { - my $clean = 'X' x length($1); - $res =~ s@(\#\s*(?:error|warning)\s+).*@$1$clean@; - } - - return $res; -} - -sub ctx_statement_block { - my ($linenr, $remain, $off) = @_; - my $line = $linenr - 1; - my $blk = ''; - my $soff = $off; - my $coff = $off - 1; - my $coff_set = 0; - - my $loff = 0; - - my $type = ''; - my $level = 0; - my @stack = (); - my $p; - my $c; - my $len = 0; - - my $remainder; - while (1) { - @stack = (['', 0]) if ($#stack == -1); - - #warn "CSB: blk<$blk> remain<$remain>\n"; - # If we are about to drop off the end, pull in more - # context. - if ($off >= $len) { - for (; $remain > 0; $line++) { - last if (!defined $lines[$line]); - next if ($lines[$line] =~ /^-/); - $remain--; - $loff = $len; - $blk .= $lines[$line] . "\n"; - $len = length($blk); - $line++; - last; - } - # Bail if there is no further context. - #warn "CSB: blk<$blk> off<$off> len<$len>\n"; - if ($off >= $len) { - last; - } - } - $p = $c; - $c = substr($blk, $off, 1); - $remainder = substr($blk, $off); - - #warn "CSB: c<$c> type<$type> level<$level> remainder<$remainder> coff_set<$coff_set>\n"; - - # Handle nested #if/#else. - if ($remainder =~ /^#\s*(?:ifndef|ifdef|if)\s/) { - push(@stack, [ $type, $level ]); - } elsif ($remainder =~ /^#\s*(?:else|elif)\b/) { - ($type, $level) = @{$stack[$#stack - 1]}; - } elsif ($remainder =~ /^#\s*endif\b/) { - ($type, $level) = @{pop(@stack)}; - } - - # Statement ends at the ';' or a close '}' at the - # outermost level. - if ($level == 0 && $c eq ';') { - last; - } - - # An else is really a conditional as long as its not else if - if ($level == 0 && $coff_set == 0 && - (!defined($p) || $p =~ /(?:\s|\}|\+)/) && - $remainder =~ /^(else)(?:\s|{)/ && - $remainder !~ /^else\s+if\b/) { - $coff = $off + length($1) - 1; - $coff_set = 1; - #warn "CSB: mark coff<$coff> soff<$soff> 1<$1>\n"; - #warn "[" . substr($blk, $soff, $coff - $soff + 1) . "]\n"; - } - - if (($type eq '' || $type eq '(') && $c eq '(') { - $level++; - $type = '('; - } - if ($type eq '(' && $c eq ')') { - $level--; - $type = ($level != 0)? '(' : ''; - - if ($level == 0 && $coff < $soff) { - $coff = $off; - $coff_set = 1; - #warn "CSB: mark coff<$coff>\n"; - } - } - if (($type eq '' || $type eq '{') && $c eq '{') { - $level++; - $type = '{'; - } - if ($type eq '{' && $c eq '}') { - $level--; - $type = ($level != 0)? '{' : ''; - - if ($level == 0) { - if (substr($blk, $off + 1, 1) eq ';') { - $off++; - } - last; - } - } - $off++; - } - # We are truly at the end, so shuffle to the next line. - if ($off == $len) { - $loff = $len + 1; - $line++; - $remain--; - } - - my $statement = substr($blk, $soff, $off - $soff + 1); - my $condition = substr($blk, $soff, $coff - $soff + 1); - - #warn "STATEMENT<$statement>\n"; - #warn "CONDITION<$condition>\n"; - - #print "coff<$coff> soff<$off> loff<$loff>\n"; - - return ($statement, $condition, - $line, $remain + 1, $off - $loff + 1, $level); -} - -sub statement_lines { - my ($stmt) = @_; - - # Strip the diff line prefixes and rip blank lines at start and end. - $stmt =~ s/(^|\n)./$1/g; - $stmt =~ s/^\s*//; - $stmt =~ s/\s*$//; - - my @stmt_lines = ($stmt =~ /\n/g); - - return $#stmt_lines + 2; -} - -sub statement_rawlines { - my ($stmt) = @_; - - my @stmt_lines = ($stmt =~ /\n/g); - - return $#stmt_lines + 2; -} - -sub statement_block_size { - my ($stmt) = @_; - - $stmt =~ s/(^|\n)./$1/g; - $stmt =~ s/^\s*{//; - $stmt =~ s/}\s*$//; - $stmt =~ s/^\s*//; - $stmt =~ s/\s*$//; - - my @stmt_lines = ($stmt =~ /\n/g); - my @stmt_statements = ($stmt =~ /;/g); - - my $stmt_lines = $#stmt_lines + 2; - my $stmt_statements = $#stmt_statements + 1; - - if ($stmt_lines > $stmt_statements) { - return $stmt_lines; - } else { - return $stmt_statements; - } -} - -sub ctx_statement_full { - my ($linenr, $remain, $off) = @_; - my ($statement, $condition, $level); - - my (@chunks); - - # Grab the first conditional/block pair. - ($statement, $condition, $linenr, $remain, $off, $level) = - ctx_statement_block($linenr, $remain, $off); - #print "F: c<$condition> s<$statement> remain<$remain>\n"; - push(@chunks, [ $condition, $statement ]); - if (!($remain > 0 && $condition =~ /^\s*(?:\n[+-])?\s*(?:if|else|do)\b/s)) { - return ($level, $linenr, @chunks); - } - - # Pull in the following conditional/block pairs and see if they - # could continue the statement. - for (;;) { - ($statement, $condition, $linenr, $remain, $off, $level) = - ctx_statement_block($linenr, $remain, $off); - #print "C: c<$condition> s<$statement> remain<$remain>\n"; - last if (!($remain > 0 && $condition =~ /^(?:\s*\n[+-])*\s*(?:else|do)\b/s)); - #print "C: push\n"; - push(@chunks, [ $condition, $statement ]); - } - - return ($level, $linenr, @chunks); -} - -sub ctx_block_get { - my ($linenr, $remain, $outer, $open, $close, $off) = @_; - my $line; - my $start = $linenr - 1; - my $blk = ''; - my @o; - my @c; - my @res = (); - - my $level = 0; - my @stack = ($level); - for ($line = $start; $remain > 0; $line++) { - next if ($rawlines[$line] =~ /^-/); - $remain--; - - $blk .= $rawlines[$line]; - - # Handle nested #if/#else. - if ($lines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) { - push(@stack, $level); - } elsif ($lines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) { - $level = $stack[$#stack - 1]; - } elsif ($lines[$line] =~ /^.\s*#\s*endif\b/) { - $level = pop(@stack); - } - - foreach my $c (split(//, $lines[$line])) { - ##print "C<$c>L<$level><$open$close>O<$off>\n"; - if ($off > 0) { - $off--; - next; - } - - if ($c eq $close && $level > 0) { - $level--; - last if ($level == 0); - } elsif ($c eq $open) { - $level++; - } - } - - if (!$outer || $level <= 1) { - push(@res, $rawlines[$line]); - } - - last if ($level == 0); - } - - return ($level, @res); -} -sub ctx_block_outer { - my ($linenr, $remain) = @_; - - my ($level, @r) = ctx_block_get($linenr, $remain, 1, '{', '}', 0); - return @r; -} -sub ctx_block { - my ($linenr, $remain) = @_; - - my ($level, @r) = ctx_block_get($linenr, $remain, 0, '{', '}', 0); - return @r; -} -sub ctx_statement { - my ($linenr, $remain, $off) = @_; - - my ($level, @r) = ctx_block_get($linenr, $remain, 0, '(', ')', $off); - return @r; -} -sub ctx_block_level { - my ($linenr, $remain) = @_; - - return ctx_block_get($linenr, $remain, 0, '{', '}', 0); -} -sub ctx_statement_level { - my ($linenr, $remain, $off) = @_; - - return ctx_block_get($linenr, $remain, 0, '(', ')', $off); -} - -sub ctx_locate_comment { - my ($first_line, $end_line) = @_; - - # Catch a comment on the end of the line itself. - my ($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*(?:\\\s*)?$@); - return $current_comment if (defined $current_comment); - - # Look through the context and try and figure out if there is a - # comment. - my $in_comment = 0; - $current_comment = ''; - for (my $linenr = $first_line; $linenr < $end_line; $linenr++) { - my $line = $rawlines[$linenr - 1]; - #warn " $line\n"; - if ($linenr == $first_line and $line =~ m@^.\s*\*@) { - $in_comment = 1; - } - if ($line =~ m@/\*@) { - $in_comment = 1; - } - if (!$in_comment && $current_comment ne '') { - $current_comment = ''; - } - $current_comment .= $line . "\n" if ($in_comment); - if ($line =~ m@\*/@) { - $in_comment = 0; - } - } - - chomp($current_comment); - return($current_comment); -} -sub ctx_has_comment { - my ($first_line, $end_line) = @_; - my $cmt = ctx_locate_comment($first_line, $end_line); - - ##print "LINE: $rawlines[$end_line - 1 ]\n"; - ##print "CMMT: $cmt\n"; - - return ($cmt ne ''); -} - -sub raw_line { - my ($linenr, $cnt) = @_; - - my $offset = $linenr - 1; - $cnt++; - - my $line; - while ($cnt) { - $line = $rawlines[$offset++]; - next if (defined($line) && $line =~ /^-/); - $cnt--; - } - - return $line; -} - -sub cat_vet { - my ($vet) = @_; - my ($res, $coded); - - $res = ''; - while ($vet =~ /([^[:cntrl:]]*)([[:cntrl:]]|$)/g) { - $res .= $1; - if ($2 ne '') { - $coded = sprintf("^%c", unpack('C', $2) + 64); - $res .= $coded; - } - } - $res =~ s/$/\$/; - - return $res; -} - -my $av_preprocessor = 0; -my $av_pending; -my @av_paren_type; -my $av_pend_colon; - -sub annotate_reset { - $av_preprocessor = 0; - $av_pending = '_'; - @av_paren_type = ('E'); - $av_pend_colon = 'O'; -} - -sub annotate_values { - my ($stream, $type) = @_; - - my $res; - my $var = '_' x length($stream); - my $cur = $stream; - - print "$stream\n" if ($dbg_values > 1); - - while (length($cur)) { - @av_paren_type = ('E') if ($#av_paren_type < 0); - print " <" . join('', @av_paren_type) . - "> <$type> <$av_pending>" if ($dbg_values > 1); - if ($cur =~ /^(\s+)/o) { - print "WS($1)\n" if ($dbg_values > 1); - if ($1 =~ /\n/ && $av_preprocessor) { - $type = pop(@av_paren_type); - $av_preprocessor = 0; - } - - } elsif ($cur =~ /^(\(\s*$Type\s*)\)/ && $av_pending eq '_') { - print "CAST($1)\n" if ($dbg_values > 1); - push(@av_paren_type, $type); - $type = 'C'; - - } elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\(|\s*$)/) { - print "DECLARE($1)\n" if ($dbg_values > 1); - $type = 'T'; - - } elsif ($cur =~ /^($Modifier)\s*/) { - print "MODIFIER($1)\n" if ($dbg_values > 1); - $type = 'T'; - - } elsif ($cur =~ /^(\#\s*define\s*$Ident)(\(?)/o) { - print "DEFINE($1,$2)\n" if ($dbg_values > 1); - $av_preprocessor = 1; - push(@av_paren_type, $type); - if ($2 ne '') { - $av_pending = 'N'; - } - $type = 'E'; - - } elsif ($cur =~ /^(\#\s*(?:undef\s*$Ident|include\b))/o) { - print "UNDEF($1)\n" if ($dbg_values > 1); - $av_preprocessor = 1; - push(@av_paren_type, $type); - - } elsif ($cur =~ /^(\#\s*(?:ifdef|ifndef|if))/o) { - print "PRE_START($1)\n" if ($dbg_values > 1); - $av_preprocessor = 1; - - push(@av_paren_type, $type); - push(@av_paren_type, $type); - $type = 'E'; - - } elsif ($cur =~ /^(\#\s*(?:else|elif))/o) { - print "PRE_RESTART($1)\n" if ($dbg_values > 1); - $av_preprocessor = 1; - - push(@av_paren_type, $av_paren_type[$#av_paren_type]); - - $type = 'E'; - - } elsif ($cur =~ /^(\#\s*(?:endif))/o) { - print "PRE_END($1)\n" if ($dbg_values > 1); - - $av_preprocessor = 1; - - # Assume all arms of the conditional end as this - # one does, and continue as if the #endif was not here. - pop(@av_paren_type); - push(@av_paren_type, $type); - $type = 'E'; - - } elsif ($cur =~ /^(\\\n)/o) { - print "PRECONT($1)\n" if ($dbg_values > 1); - - } elsif ($cur =~ /^(__attribute__)\s*\(?/o) { - print "ATTR($1)\n" if ($dbg_values > 1); - $av_pending = $type; - $type = 'N'; - - } elsif ($cur =~ /^(sizeof)\s*(\()?/o) { - print "SIZEOF($1)\n" if ($dbg_values > 1); - if (defined $2) { - $av_pending = 'V'; - } - $type = 'N'; - - } elsif ($cur =~ /^(if|while|for)\b/o) { - print "COND($1)\n" if ($dbg_values > 1); - $av_pending = 'E'; - $type = 'N'; - - } elsif ($cur =~/^(case)/o) { - print "CASE($1)\n" if ($dbg_values > 1); - $av_pend_colon = 'C'; - $type = 'N'; - - } elsif ($cur =~/^(return|else|goto|typeof|__typeof__)\b/o) { - print "KEYWORD($1)\n" if ($dbg_values > 1); - $type = 'N'; - - } elsif ($cur =~ /^(\()/o) { - print "PAREN('$1')\n" if ($dbg_values > 1); - push(@av_paren_type, $av_pending); - $av_pending = '_'; - $type = 'N'; - - } elsif ($cur =~ /^(\))/o) { - my $new_type = pop(@av_paren_type); - if ($new_type ne '_') { - $type = $new_type; - print "PAREN('$1') -> $type\n" - if ($dbg_values > 1); - } else { - print "PAREN('$1')\n" if ($dbg_values > 1); - } - - } elsif ($cur =~ /^($Ident)\s*\(/o) { - print "FUNC($1)\n" if ($dbg_values > 1); - $type = 'V'; - $av_pending = 'V'; - - } elsif ($cur =~ /^($Ident\s*):(?:\s*\d+\s*(,|=|;))?/) { - if (defined $2 && $type eq 'C' || $type eq 'T') { - $av_pend_colon = 'B'; - } elsif ($type eq 'E') { - $av_pend_colon = 'L'; - } - print "IDENT_COLON($1,$type>$av_pend_colon)\n" if ($dbg_values > 1); - $type = 'V'; - - } elsif ($cur =~ /^($Ident|$Constant)/o) { - print "IDENT($1)\n" if ($dbg_values > 1); - $type = 'V'; - - } elsif ($cur =~ /^($Assignment)/o) { - print "ASSIGN($1)\n" if ($dbg_values > 1); - $type = 'N'; - - } elsif ($cur =~/^(;|{|})/) { - print "END($1)\n" if ($dbg_values > 1); - $type = 'E'; - $av_pend_colon = 'O'; - - } elsif ($cur =~/^(,)/) { - print "COMMA($1)\n" if ($dbg_values > 1); - $type = 'C'; - - } elsif ($cur =~ /^(\?)/o) { - print "QUESTION($1)\n" if ($dbg_values > 1); - $type = 'N'; - - } elsif ($cur =~ /^(:)/o) { - print "COLON($1,$av_pend_colon)\n" if ($dbg_values > 1); - - substr($var, length($res), 1, $av_pend_colon); - if ($av_pend_colon eq 'C' || $av_pend_colon eq 'L') { - $type = 'E'; - } else { - $type = 'N'; - } - $av_pend_colon = 'O'; - - } elsif ($cur =~ /^(\[)/o) { - print "CLOSE($1)\n" if ($dbg_values > 1); - $type = 'N'; - - } elsif ($cur =~ /^(-(?![->])|\+(?!\+)|\*|\&\&|\&)/o) { - my $variant; - - print "OPV($1)\n" if ($dbg_values > 1); - if ($type eq 'V') { - $variant = 'B'; - } else { - $variant = 'U'; - } - - substr($var, length($res), 1, $variant); - $type = 'N'; - - } elsif ($cur =~ /^($Operators)/o) { - print "OP($1)\n" if ($dbg_values > 1); - if ($1 ne '++' && $1 ne '--') { - $type = 'N'; - } - - } elsif ($cur =~ /(^.)/o) { - print "C($1)\n" if ($dbg_values > 1); - } - if (defined $1) { - $cur = substr($cur, length($1)); - $res .= $type x length($1); - } - } - - return ($res, $var); -} - -sub possible { - my ($possible, $line) = @_; - my $notPermitted = qr{(?: - ^(?: - $Modifier| - $Storage| - $Type| - DEFINE_\S+ - )$| - ^(?: - goto| - return| - case| - else| - asm|__asm__| - do - )(?:\s|$)| - ^(?:typedef|struct|enum)\b - )}x; - warn "CHECK<$possible> ($line)\n" if ($dbg_possible > 2); - if ($possible !~ $notPermitted) { - # Check for modifiers. - $possible =~ s/\s*$Storage\s*//g; - $possible =~ s/\s*$Sparse\s*//g; - if ($possible =~ /^\s*$/) { - - } elsif ($possible =~ /\s/) { - $possible =~ s/\s*$Type\s*//g; - for my $modifier (split(' ', $possible)) { - if ($modifier !~ $notPermitted) { - warn "MODIFIER: $modifier ($possible) ($line)\n" if ($dbg_possible); - push(@modifierList, $modifier); - } - } - - } else { - warn "POSSIBLE: $possible ($line)\n" if ($dbg_possible); - push(@typeList, $possible); - } - build_types(); - } else { - warn "NOTPOSS: $possible ($line)\n" if ($dbg_possible > 1); - } -} - -my $prefix = ''; - -sub show_type { - return !defined $ignore_type{$_[0]}; -} - -sub report { - if (!show_type($_[1]) || - (defined $tst_only && $_[2] !~ /\Q$tst_only\E/)) { - return 0; - } - my $line; - if ($show_types) { - $line = "$prefix$_[0]:$_[1]: $_[2]\n"; - } else { - $line = "$prefix$_[0]: $_[2]\n"; - } - $line = (split('\n', $line))[0] . "\n" if ($terse); - - push(our @report, $line); - - return 1; -} -sub report_dump { - our @report; -} - -sub ERROR { - if (report("ERROR", $_[0], $_[1])) { - our $clean = 0; - our $cnt_error++; - } -} -sub WARN { - if (report("WARNING", $_[0], $_[1])) { - our $clean = 0; - our $cnt_warn++; - } -} -sub CHK { - if ($check && report("CHECK", $_[0], $_[1])) { - our $clean = 0; - our $cnt_chk++; - } -} - -sub check_absolute_file { - my ($absolute, $herecurr) = @_; - my $file = $absolute; - - ##print "absolute<$absolute>\n"; - - # See if any suffix of this path is a path within the tree. - while ($file =~ s@^[^/]*/@@) { - if (-f "$root/$file") { - ##print "file<$file>\n"; - last; - } - } - if (! -f _) { - return 0; - } - - # It is, so see if the prefix is acceptable. - my $prefix = $absolute; - substr($prefix, -length($file)) = ''; - - ##print "prefix<$prefix>\n"; - if ($prefix ne ".../") { - WARN("USE_RELATIVE_PATH", - "use relative pathname instead of absolute in changelog text\n" . $herecurr); - } -} - -sub process { - my $filename = shift; - - my $linenr=0; - my $prevline=""; - my $prevrawline=""; - my $stashline=""; - my $stashrawline=""; - - my $length; - my $indent; - my $previndent=0; - my $stashindent=0; - - our $clean = 1; - my $signoff = 0; - my $is_patch = 0; - - our @report = (); - our $cnt_lines = 0; - our $cnt_error = 0; - our $cnt_warn = 0; - our $cnt_chk = 0; - - # Trace the real file/line as we go. - my $realfile = ''; - my $realline = 0; - my $realcnt = 0; - my $here = ''; - my $in_comment = 0; - my $comment_edge = 0; - my $first_line = 0; - my $p1_prefix = ''; - - my $prev_values = 'E'; - - # suppression flags - my %suppress_ifbraces; - my %suppress_whiletrailers; - my %suppress_export; - - # Pre-scan the patch sanitizing the lines. - # Pre-scan the patch looking for any __setup documentation. - # - my @setup_docs = (); - my $setup_docs = 0; - - sanitise_line_reset(); - my $line; - foreach my $rawline (@rawlines) { - $linenr++; - $line = $rawline; - - if ($rawline=~/^\+\+\+\s+(\S+)/) { - $setup_docs = 0; - if ($1 =~ m@Documentation/kernel-parameters.txt$@) { - $setup_docs = 1; - } - #next; - } - if ($rawline=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) { - $realline=$1-1; - if (defined $2) { - $realcnt=$3+1; - } else { - $realcnt=1+1; - } - $in_comment = 0; - - # Guestimate if this is a continuing comment. Run - # the context looking for a comment "edge". If this - # edge is a close comment then we must be in a comment - # at context start. - my $edge; - my $cnt = $realcnt; - for (my $ln = $linenr + 1; $cnt > 0; $ln++) { - next if (defined $rawlines[$ln - 1] && - $rawlines[$ln - 1] =~ /^-/); - $cnt--; - #print "RAW<$rawlines[$ln - 1]>\n"; - last if (!defined $rawlines[$ln - 1]); - if ($rawlines[$ln - 1] =~ m@(/\*|\*/)@ && - $rawlines[$ln - 1] !~ m@"[^"]*(?:/\*|\*/)[^"]*"@) { - ($edge) = $1; - last; - } - } - if (defined $edge && $edge eq '*/') { - $in_comment = 1; - } - - # Guestimate if this is a continuing comment. If this - # is the start of a diff block and this line starts - # ' *' then it is very likely a comment. - if (!defined $edge && - $rawlines[$linenr] =~ m@^.\s*(?:\*\*+| \*)(?:\s|$)@) - { - $in_comment = 1; - } - - ##print "COMMENT:$in_comment edge<$edge> $rawline\n"; - sanitise_line_reset($in_comment); - - } elsif ($realcnt && $rawline =~ /^(?:\+| |$)/) { - # Standardise the strings and chars within the input to - # simplify matching -- only bother with positive lines. - $line = sanitise_line($rawline); - } - push(@lines, $line); - - if ($realcnt > 1) { - $realcnt-- if ($line =~ /^(?:\+| |$)/); - } else { - $realcnt = 0; - } - - #print "==>$rawline\n"; - #print "-->$line\n"; - - if ($setup_docs && $line =~ /^\+/) { - push(@setup_docs, $line); - } - } - - $prefix = ''; - - $realcnt = 0; - $linenr = 0; - foreach my $line (@lines) { - $linenr++; - - my $rawline = $rawlines[$linenr - 1]; - -#extract the line range in the file after the patch is applied - if ($line=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) { - $is_patch = 1; - $first_line = $linenr + 1; - $realline=$1-1; - if (defined $2) { - $realcnt=$3+1; - } else { - $realcnt=1+1; - } - annotate_reset(); - $prev_values = 'E'; - - %suppress_ifbraces = (); - %suppress_whiletrailers = (); - %suppress_export = (); - next; - -# track the line number as we move through the hunk, note that -# new versions of GNU diff omit the leading space on completely -# blank context lines so we need to count that too. - } elsif ($line =~ /^( |\+|$)/) { - $realline++; - $realcnt-- if ($realcnt != 0); - - # Measure the line length and indent. - ($length, $indent) = line_stats($rawline); - - # Track the previous line. - ($prevline, $stashline) = ($stashline, $line); - ($previndent, $stashindent) = ($stashindent, $indent); - ($prevrawline, $stashrawline) = ($stashrawline, $rawline); - - #warn "line<$line>\n"; - - } elsif ($realcnt == 1) { - $realcnt--; - } - - my $hunk_line = ($realcnt != 0); - -#make up the handle for any error we report on this line - $prefix = "$filename:$realline: " if ($emacs && $file); - $prefix = "$filename:$linenr: " if ($emacs && !$file); - - $here = "#$linenr: " if (!$file); - $here = "#$realline: " if ($file); - - # extract the filename as it passes - if ($line =~ /^diff --git.*?(\S+)$/) { - $realfile = $1; - $realfile =~ s@^([^/]*)/@@; - - } elsif ($line =~ /^\+\+\+\s+(\S+)/) { - $realfile = $1; - $realfile =~ s@^([^/]*)/@@; - - $p1_prefix = $1; - if (!$file && $tree && $p1_prefix ne '' && - -e "$root/$p1_prefix") { - WARN("PATCH_PREFIX", - "patch prefix '$p1_prefix' exists, appears to be a -p0 patch\n"); - } - - if ($realfile =~ m@^include/asm/@) { - ERROR("MODIFIED_INCLUDE_ASM", - "do not modify files in include/asm, change architecture specific files in include/asm-\n" . "$here$rawline\n"); - } - next; - } - - $here .= "FILE: $realfile:$realline:" if ($realcnt != 0); - - my $hereline = "$here\n$rawline\n"; - my $herecurr = "$here\n$rawline\n"; - my $hereprev = "$here\n$prevrawline\n$rawline\n"; - - $cnt_lines++ if ($realcnt != 0); - -# Check for incorrect file permissions - if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) { - my $permhere = $here . "FILE: $realfile\n"; - if ($realfile =~ /(Makefile|Kconfig|\.c|\.h|\.S|\.tmpl)$/) { - ERROR("EXECUTE_PERMISSIONS", - "do not set execute permissions for source files\n" . $permhere); - } - } - -# Check the patch for a signoff: - if ($line =~ /^\s*signed-off-by:/i) { - $signoff++; - } - -# Check signature styles - if ($line =~ /^(\s*)($signature_tags)(\s*)(.*)/) { - my $space_before = $1; - my $sign_off = $2; - my $space_after = $3; - my $email = $4; - my $ucfirst_sign_off = ucfirst(lc($sign_off)); - - if (defined $space_before && $space_before ne "") { - WARN("BAD_SIGN_OFF", - "Do not use whitespace before $ucfirst_sign_off\n" . $herecurr); - } - if ($sign_off =~ /-by:$/i && $sign_off ne $ucfirst_sign_off) { - WARN("BAD_SIGN_OFF", - "'$ucfirst_sign_off' is the preferred signature form\n" . $herecurr); - } - if (!defined $space_after || $space_after ne " ") { - WARN("BAD_SIGN_OFF", - "Use a single space after $ucfirst_sign_off\n" . $herecurr); - } - - my ($email_name, $email_address, $comment) = parse_email($email); - my $suggested_email = format_email(($email_name, $email_address)); - if ($suggested_email eq "") { - ERROR("BAD_SIGN_OFF", - "Unrecognized email address: '$email'\n" . $herecurr); - } else { - my $dequoted = $suggested_email; - $dequoted =~ s/^"//; - $dequoted =~ s/" $comment" ne $email && - "$suggested_email$comment" ne $email) { - WARN("BAD_SIGN_OFF", - "email address '$email' might be better as '$suggested_email$comment'\n" . $herecurr); - } - } - } - -# Check for wrappage within a valid hunk of the file - if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) { - ERROR("CORRUPTED_PATCH", - "patch seems to be corrupt (line wrapped?)\n" . - $herecurr) if (!$emitted_corrupt++); - } - -# Check for absolute kernel paths. - if ($tree) { - while ($line =~ m{(?:^|\s)(/\S*)}g) { - my $file = $1; - - if ($file =~ m{^(.*?)(?::\d+)+:?$} && - check_absolute_file($1, $herecurr)) { - # - } else { - check_absolute_file($file, $herecurr); - } - } - } - -# UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php - if (($realfile =~ /^$/ || $line =~ /^\+/) && - $rawline !~ m/^$UTF8*$/) { - my ($utf8_prefix) = ($rawline =~ /^($UTF8*)/); - - my $blank = copy_spacing($rawline); - my $ptr = substr($blank, 0, length($utf8_prefix)) . "^"; - my $hereptr = "$hereline$ptr\n"; - - CHK("INVALID_UTF8", - "Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $hereptr); - } - -# ignore non-hunk lines and lines being removed - next if (!$hunk_line || $line =~ /^-/); - -#trailing whitespace - if ($line =~ /^\+.*\015/) { - my $herevet = "$here\n" . cat_vet($rawline) . "\n"; - ERROR("DOS_LINE_ENDINGS", - "DOS line endings\n" . $herevet); - - } elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) { - my $herevet = "$here\n" . cat_vet($rawline) . "\n"; - ERROR("TRAILING_WHITESPACE", - "trailing whitespace\n" . $herevet); - $rpt_cleaners = 1; - } - -# check for Kconfig help text having a real description -# Only applies when adding the entry originally, after that we do not have -# sufficient context to determine whether it is indeed long enough. - if ($realfile =~ /Kconfig/ && - $line =~ /\+\s*(?:---)?help(?:---)?$/) { - my $length = 0; - my $cnt = $realcnt; - my $ln = $linenr + 1; - my $f; - my $is_end = 0; - while ($cnt > 0 && defined $lines[$ln - 1]) { - $f = $lines[$ln - 1]; - $cnt-- if ($lines[$ln - 1] !~ /^-/); - $is_end = $lines[$ln - 1] =~ /^\+/; - $ln++; - - next if ($f =~ /^-/); - $f =~ s/^.//; - $f =~ s/#.*//; - $f =~ s/^\s+//; - next if ($f =~ /^$/); - if ($f =~ /^\s*config\s/) { - $is_end = 1; - last; - } - $length++; - } - WARN("CONFIG_DESCRIPTION", - "please write a paragraph that describes the config symbol fully\n" . $herecurr) if ($is_end && $length < 4); - #print "is_end<$is_end> length<$length>\n"; - } - -# check we are in a valid source file if not then ignore this hunk - next if ($realfile !~ /\.(h|c|s|S|pl|sh)$/); - -#80 column limit - if ($line =~ /^\+/ && $prevrawline !~ /\/\*\*/ && - $rawline !~ /^.\s*\*\s*\@$Ident\s/ && - !($line =~ /^\+\s*$logFunctions\s*\(\s*(?:(KERN_\S+\s*|[^"]*))?"[X\t]*"\s*(?:|,|\)\s*;)\s*$/ || - $line =~ /^\+\s*"[^"]*"\s*(?:\s*|,|\)\s*;)\s*$/) && - $length > 80) - { - WARN("LONG_LINE", - "line over 80 characters\n" . $herecurr); - } - -# check for spaces before a quoted newline - if ($rawline =~ /^.*\".*\s\\n/) { - WARN("QUOTED_WHITESPACE_BEFORE_NEWLINE", - "unnecessary whitespace before a quoted newline\n" . $herecurr); - } - -# check for adding lines without a newline. - if ($line =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ No newline at end of file/) { - WARN("MISSING_EOF_NEWLINE", - "adding a line without newline at end of file\n" . $herecurr); - } - -# Blackfin: use hi/lo macros - if ($realfile =~ m@arch/blackfin/.*\.S$@) { - if ($line =~ /\.[lL][[:space:]]*=.*&[[:space:]]*0x[fF][fF][fF][fF]/) { - my $herevet = "$here\n" . cat_vet($line) . "\n"; - ERROR("LO_MACRO", - "use the LO() macro, not (... & 0xFFFF)\n" . $herevet); - } - if ($line =~ /\.[hH][[:space:]]*=.*>>[[:space:]]*16/) { - my $herevet = "$here\n" . cat_vet($line) . "\n"; - ERROR("HI_MACRO", - "use the HI() macro, not (... >> 16)\n" . $herevet); - } - } - -# check we are in a valid source file C or perl if not then ignore this hunk - next if ($realfile !~ /\.(h|c|pl)$/); - -# at the beginning of a line any tabs must come first and anything -# more than 8 must use tabs. - if ($rawline =~ /^\+\s* \t\s*\S/ || - $rawline =~ /^\+\s* \s*/) { - my $herevet = "$here\n" . cat_vet($rawline) . "\n"; - ERROR("CODE_INDENT", - "code indent should use tabs where possible\n" . $herevet); - $rpt_cleaners = 1; - } - -# check for space before tabs. - if ($rawline =~ /^\+/ && $rawline =~ / \t/) { - my $herevet = "$here\n" . cat_vet($rawline) . "\n"; - WARN("SPACE_BEFORE_TAB", - "please, no space before tabs\n" . $herevet); - } - -# check for spaces at the beginning of a line. -# Exceptions: -# 1) within comments -# 2) indented preprocessor commands -# 3) hanging labels - if ($rawline =~ /^\+ / && $line !~ /\+ *(?:$;|#|$Ident:)/) { - my $herevet = "$here\n" . cat_vet($rawline) . "\n"; - WARN("LEADING_SPACE", - "please, no spaces at the start of a line\n" . $herevet); - } - -# check we are in a valid C source file if not then ignore this hunk - next if ($realfile !~ /\.(h|c)$/); - -# check for RCS/CVS revision markers - if ($rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|)/) { - WARN("CVS_KEYWORD", - "CVS style keyword markers, these will _not_ be updated\n". $herecurr); - } - -# Blackfin: don't use __builtin_bfin_[cs]sync - if ($line =~ /__builtin_bfin_csync/) { - my $herevet = "$here\n" . cat_vet($line) . "\n"; - ERROR("CSYNC", - "use the CSYNC() macro in asm/blackfin.h\n" . $herevet); - } - if ($line =~ /__builtin_bfin_ssync/) { - my $herevet = "$here\n" . cat_vet($line) . "\n"; - ERROR("SSYNC", - "use the SSYNC() macro in asm/blackfin.h\n" . $herevet); - } - -# Check for potential 'bare' types - my ($stat, $cond, $line_nr_next, $remain_next, $off_next, - $realline_next); - if ($realcnt && $line =~ /.\s*\S/) { - ($stat, $cond, $line_nr_next, $remain_next, $off_next) = - ctx_statement_block($linenr, $realcnt, 0); - $stat =~ s/\n./\n /g; - $cond =~ s/\n./\n /g; - - # Find the real next line. - $realline_next = $line_nr_next; - if (defined $realline_next && - (!defined $lines[$realline_next - 1] || - substr($lines[$realline_next - 1], $off_next) =~ /^\s*$/)) { - $realline_next++; - } - - my $s = $stat; - $s =~ s/{.*$//s; - - # Ignore goto labels. - if ($s =~ /$Ident:\*$/s) { - - # Ignore functions being called - } elsif ($s =~ /^.\s*$Ident\s*\(/s) { - - } elsif ($s =~ /^.\s*else\b/s) { - - # declarations always start with types - } elsif ($prev_values eq 'E' && $s =~ /^.\s*(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?((?:\s*$Ident)+?)\b(?:\s+$Sparse)?\s*\**\s*(?:$Ident|\(\*[^\)]*\))(?:\s*$Modifier)?\s*(?:;|=|,|\()/s) { - my $type = $1; - $type =~ s/\s+/ /g; - possible($type, "A:" . $s); - - # definitions in global scope can only start with types - } elsif ($s =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b\s*(?!:)/s) { - possible($1, "B:" . $s); - } - - # any (foo ... *) is a pointer cast, and foo is a type - while ($s =~ /\(($Ident)(?:\s+$Sparse)*[\s\*]+\s*\)/sg) { - possible($1, "C:" . $s); - } - - # Check for any sort of function declaration. - # int foo(something bar, other baz); - # void (*store_gdt)(x86_descr_ptr *); - if ($prev_values eq 'E' && $s =~ /^(.(?:typedef\s*)?(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*(?:\b$Ident|\(\*\s*$Ident\))\s*)\(/s) { - my ($name_len) = length($1); - - my $ctx = $s; - substr($ctx, 0, $name_len + 1, ''); - $ctx =~ s/\)[^\)]*$//; - - for my $arg (split(/\s*,\s*/, $ctx)) { - if ($arg =~ /^(?:const\s+)?($Ident)(?:\s+$Sparse)*\s*\**\s*(:?\b$Ident)?$/s || $arg =~ /^($Ident)$/s) { - - possible($1, "D:" . $s); - } - } - } - - } - -# -# Checks which may be anchored in the context. -# - -# Check for switch () and associated case and default -# statements should be at the same indent. - if ($line=~/\bswitch\s*\(.*\)/) { - my $err = ''; - my $sep = ''; - my @ctx = ctx_block_outer($linenr, $realcnt); - shift(@ctx); - for my $ctx (@ctx) { - my ($clen, $cindent) = line_stats($ctx); - if ($ctx =~ /^\+\s*(case\s+|default:)/ && - $indent != $cindent) { - $err .= "$sep$ctx\n"; - $sep = ''; - } else { - $sep = "[...]\n"; - } - } - if ($err ne '') { - ERROR("SWITCH_CASE_INDENT_LEVEL", - "switch and case should be at the same indent\n$hereline$err"); - } - } - -# if/while/etc brace do not go on next line, unless defining a do while loop, -# or if that brace on the next line is for something else - if ($line =~ /(.*)\b((?:if|while|for|switch)\s*\(|do\b|else\b)/ && $line !~ /^.\s*\#/) { - my $pre_ctx = "$1$2"; - - my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0); - my $ctx_cnt = $realcnt - $#ctx - 1; - my $ctx = join("\n", @ctx); - - my $ctx_ln = $linenr; - my $ctx_skip = $realcnt; - - while ($ctx_skip > $ctx_cnt || ($ctx_skip == $ctx_cnt && - defined $lines[$ctx_ln - 1] && - $lines[$ctx_ln - 1] =~ /^-/)) { - ##print "SKIP<$ctx_skip> CNT<$ctx_cnt>\n"; - $ctx_skip-- if (!defined $lines[$ctx_ln - 1] || $lines[$ctx_ln - 1] !~ /^-/); - $ctx_ln++; - } - - #print "realcnt<$realcnt> ctx_cnt<$ctx_cnt>\n"; - #print "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n"; - - if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln -1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) { - ERROR("OPEN_BRACE", - "that open brace { should be on the previous line\n" . - "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n"); - } - if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ && - $ctx =~ /\)\s*\;\s*$/ && - defined $lines[$ctx_ln - 1]) - { - my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]); - if ($nindent > $indent) { - WARN("TRAILING_SEMICOLON", - "trailing semicolon indicates no statements, indent implies otherwise\n" . - "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n"); - } - } - } - -# Check relative indent for conditionals and blocks. - if ($line =~ /\b(?:(?:if|while|for)\s*\(|do\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) { - my ($s, $c) = ($stat, $cond); - - substr($s, 0, length($c), ''); - - # Make sure we remove the line prefixes as we have - # none on the first line, and are going to readd them - # where necessary. - $s =~ s/\n./\n/gs; - - # Find out how long the conditional actually is. - my @newlines = ($c =~ /\n/gs); - my $cond_lines = 1 + $#newlines; - - # We want to check the first line inside the block - # starting at the end of the conditional, so remove: - # 1) any blank line termination - # 2) any opening brace { on end of the line - # 3) any do (...) { - my $continuation = 0; - my $check = 0; - $s =~ s/^.*\bdo\b//; - $s =~ s/^\s*{//; - if ($s =~ s/^\s*\\//) { - $continuation = 1; - } - if ($s =~ s/^\s*?\n//) { - $check = 1; - $cond_lines++; - } - - # Also ignore a loop construct at the end of a - # preprocessor statement. - if (($prevline =~ /^.\s*#\s*define\s/ || - $prevline =~ /\\\s*$/) && $continuation == 0) { - $check = 0; - } - - my $cond_ptr = -1; - $continuation = 0; - while ($cond_ptr != $cond_lines) { - $cond_ptr = $cond_lines; - - # If we see an #else/#elif then the code - # is not linear. - if ($s =~ /^\s*\#\s*(?:else|elif)/) { - $check = 0; - } - - # Ignore: - # 1) blank lines, they should be at 0, - # 2) preprocessor lines, and - # 3) labels. - if ($continuation || - $s =~ /^\s*?\n/ || - $s =~ /^\s*#\s*?/ || - $s =~ /^\s*$Ident\s*:/) { - $continuation = ($s =~ /^.*?\\\n/) ? 1 : 0; - if ($s =~ s/^.*?\n//) { - $cond_lines++; - } - } - } - - my (undef, $sindent) = line_stats("+" . $s); - my $stat_real = raw_line($linenr, $cond_lines); - - # Check if either of these lines are modified, else - # this is not this patch's fault. - if (!defined($stat_real) || - $stat !~ /^\+/ && $stat_real !~ /^\+/) { - $check = 0; - } - if (defined($stat_real) && $cond_lines > 1) { - $stat_real = "[...]\n$stat_real"; - } - - #print "line<$line> prevline<$prevline> indent<$indent> sindent<$sindent> check<$check> continuation<$continuation> s<$s> cond_lines<$cond_lines> stat_real<$stat_real> stat<$stat>\n"; - - if ($check && (($sindent % 8) != 0 || - ($sindent <= $indent && $s ne ''))) { - WARN("SUSPECT_CODE_INDENT", - "suspect code indent for conditional statements ($indent, $sindent)\n" . $herecurr . "$stat_real\n"); - } - } - - # Track the 'values' across context and added lines. - my $opline = $line; $opline =~ s/^./ /; - my ($curr_values, $curr_vars) = - annotate_values($opline . "\n", $prev_values); - $curr_values = $prev_values . $curr_values; - if ($dbg_values) { - my $outline = $opline; $outline =~ s/\t/ /g; - print "$linenr > .$outline\n"; - print "$linenr > $curr_values\n"; - print "$linenr > $curr_vars\n"; - } - $prev_values = substr($curr_values, -1); - -#ignore lines not being added - if ($line=~/^[^\+]/) {next;} - -# TEST: allow direct testing of the type matcher. - if ($dbg_type) { - if ($line =~ /^.\s*$Declare\s*$/) { - ERROR("TEST_TYPE", - "TEST: is type\n" . $herecurr); - } elsif ($dbg_type > 1 && $line =~ /^.+($Declare)/) { - ERROR("TEST_NOT_TYPE", - "TEST: is not type ($1 is)\n". $herecurr); - } - next; - } -# TEST: allow direct testing of the attribute matcher. - if ($dbg_attr) { - if ($line =~ /^.\s*$Modifier\s*$/) { - ERROR("TEST_ATTR", - "TEST: is attr\n" . $herecurr); - } elsif ($dbg_attr > 1 && $line =~ /^.+($Modifier)/) { - ERROR("TEST_NOT_ATTR", - "TEST: is not attr ($1 is)\n". $herecurr); - } - next; - } - -# check for initialisation to aggregates open brace on the next line - if ($line =~ /^.\s*{/ && - $prevline =~ /(?:^|[^=])=\s*$/) { - ERROR("OPEN_BRACE", - "that open brace { should be on the previous line\n" . $hereprev); - } - -# -# Checks which are anchored on the added line. -# - -# check for malformed paths in #include statements (uses RAW line) - if ($rawline =~ m{^.\s*\#\s*include\s+[<"](.*)[">]}) { - my $path = $1; - if ($path =~ m{//}) { - ERROR("MALFORMED_INCLUDE", - "malformed #include filename\n" . - $herecurr); - } - } - -# no C99 // comments - if ($line =~ m{//}) { - ERROR("C99_COMMENTS", - "do not use C99 // comments\n" . $herecurr); - } - # Remove C99 comments. - $line =~ s@//.*@@; - $opline =~ s@//.*@@; - -# EXPORT_SYMBOL should immediately follow the thing it is exporting, consider -# the whole statement. -#print "APW <$lines[$realline_next - 1]>\n"; - if (defined $realline_next && - exists $lines[$realline_next - 1] && - !defined $suppress_export{$realline_next} && - ($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/ || - $lines[$realline_next - 1] =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) { - # Handle definitions which produce identifiers with - # a prefix: - # XXX(foo); - # EXPORT_SYMBOL(something_foo); - my $name = $1; - if ($stat =~ /^.([A-Z_]+)\s*\(\s*($Ident)/ && - $name =~ /^${Ident}_$2/) { -#print "FOO C name<$name>\n"; - $suppress_export{$realline_next} = 1; - - } elsif ($stat !~ /(?: - \n.}\s*$| - ^.DEFINE_$Ident\(\Q$name\E\)| - ^.DECLARE_$Ident\(\Q$name\E\)| - ^.LIST_HEAD\(\Q$name\E\)| - ^.(?:$Storage\s+)?$Type\s*\(\s*\*\s*\Q$name\E\s*\)\s*\(| - \b\Q$name\E(?:\s+$Attribute)*\s*(?:;|=|\[|\() - )/x) { -#print "FOO A<$lines[$realline_next - 1]> stat<$stat> name<$name>\n"; - $suppress_export{$realline_next} = 2; - } else { - $suppress_export{$realline_next} = 1; - } - } - if (!defined $suppress_export{$linenr} && - $prevline =~ /^.\s*$/ && - ($line =~ /EXPORT_SYMBOL.*\((.*)\)/ || - $line =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) { -#print "FOO B <$lines[$linenr - 1]>\n"; - $suppress_export{$linenr} = 2; - } - if (defined $suppress_export{$linenr} && - $suppress_export{$linenr} == 2) { - WARN("EXPORT_SYMBOL", - "EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr); - } - -# check for global initialisers. - if ($line =~ /^.$Type\s*$Ident\s*(?:\s+$Modifier)*\s*=\s*(0|NULL|false)\s*;/) { - ERROR("GLOBAL_INITIALISERS", - "do not initialise globals to 0 or NULL\n" . - $herecurr); - } -# check for static initialisers. - if ($line =~ /\bstatic\s.*=\s*(0|NULL|false)\s*;/) { - ERROR("INITIALISED_STATIC", - "do not initialise statics to 0 or NULL\n" . - $herecurr); - } - -# check for static const char * arrays. - if ($line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/) { - WARN("STATIC_CONST_CHAR_ARRAY", - "static const char * array should probably be static const char * const\n" . - $herecurr); - } - -# check for static char foo[] = "bar" declarations. - if ($line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/) { - WARN("STATIC_CONST_CHAR_ARRAY", - "static char array declaration should probably be static const char\n" . - $herecurr); - } - -# check for declarations of struct pci_device_id - if ($line =~ /\bstruct\s+pci_device_id\s+\w+\s*\[\s*\]\s*\=\s*\{/) { - WARN("DEFINE_PCI_DEVICE_TABLE", - "Use DEFINE_PCI_DEVICE_TABLE for struct pci_device_id\n" . $herecurr); - } - -# check for new typedefs, only function parameters and sparse annotations -# make sense. - if ($line =~ /\btypedef\s/ && - $line !~ /\btypedef\s+$Type\s*\(\s*\*?$Ident\s*\)\s*\(/ && - $line !~ /\btypedef\s+$Type\s+$Ident\s*\(/ && - $line !~ /\b$typeTypedefs\b/ && - $line !~ /\b__bitwise(?:__|)\b/) { - WARN("NEW_TYPEDEFS", - "do not add new typedefs\n" . $herecurr); - } - -# * goes on variable not on type - # (char*[ const]) - if ($line =~ m{\($NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)\)}) { - my ($from, $to) = ($1, $1); - - # Should start with a space. - $to =~ s/^(\S)/ $1/; - # Should not end with a space. - $to =~ s/\s+$//; - # '*'s should not have spaces between. - while ($to =~ s/\*\s+\*/\*\*/) { - } - - #print "from<$from> to<$to>\n"; - if ($from ne $to) { - ERROR("POINTER_LOCATION", - "\"(foo$from)\" should be \"(foo$to)\"\n" . $herecurr); - } - } elsif ($line =~ m{\b$NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)($Ident)}) { - my ($from, $to, $ident) = ($1, $1, $2); - - # Should start with a space. - $to =~ s/^(\S)/ $1/; - # Should not end with a space. - $to =~ s/\s+$//; - # '*'s should not have spaces between. - while ($to =~ s/\*\s+\*/\*\*/) { - } - # Modifiers should have spaces. - $to =~ s/(\b$Modifier$)/$1 /; - - #print "from<$from> to<$to> ident<$ident>\n"; - if ($from ne $to && $ident !~ /^$Modifier$/) { - ERROR("POINTER_LOCATION", - "\"foo${from}bar\" should be \"foo${to}bar\"\n" . $herecurr); - } - } - -# # no BUG() or BUG_ON() -# if ($line =~ /\b(BUG|BUG_ON)\b/) { -# print "Try to use WARN_ON & Recovery code rather than BUG() or BUG_ON()\n"; -# print "$herecurr"; -# $clean = 0; -# } - - if ($line =~ /\bLINUX_VERSION_CODE\b/) { - WARN("LINUX_VERSION_CODE", - "LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged\n" . $herecurr); - } - -# check for uses of printk_ratelimit - if ($line =~ /\bprintk_ratelimit\s*\(/) { - WARN("PRINTK_RATELIMITED", -"Prefer printk_ratelimited or pr__ratelimited to printk_ratelimit\n" . $herecurr); - } - -# printk should use KERN_* levels. Note that follow on printk's on the -# same line do not need a level, so we use the current block context -# to try and find and validate the current printk. In summary the current -# printk includes all preceding printk's which have no newline on the end. -# we assume the first bad printk is the one to report. - if ($line =~ /\bprintk\((?!KERN_)\s*"/) { - my $ok = 0; - for (my $ln = $linenr - 1; $ln >= $first_line; $ln--) { - #print "CHECK<$lines[$ln - 1]\n"; - # we have a preceding printk if it ends - # with "\n" ignore it, else it is to blame - if ($lines[$ln - 1] =~ m{\bprintk\(}) { - if ($rawlines[$ln - 1] !~ m{\\n"}) { - $ok = 1; - } - last; - } - } - if ($ok == 0) { - WARN("PRINTK_WITHOUT_KERN_LEVEL", - "printk() should include KERN_ facility level\n" . $herecurr); - } - } - -# function brace can't be on same line, except for #defines of do while, -# or if closed on same line - if (($line=~/$Type\s*$Ident\(.*\).*\s{/) and - !($line=~/\#\s*define.*do\s{/) and !($line=~/}/)) { - ERROR("OPEN_BRACE", - "open brace '{' following function declarations go on the next line\n" . $herecurr); - } - -# open braces for enum, union and struct go on the same line. - if ($line =~ /^.\s*{/ && - $prevline =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?\s*$/) { - ERROR("OPEN_BRACE", - "open brace '{' following $1 go on the same line\n" . $hereprev); - } - -# missing space after union, struct or enum definition - if ($line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?(?:\s+$Ident)?[=\{]/) { - WARN("SPACING", - "missing space after $1 definition\n" . $herecurr); - } - -# check for spacing round square brackets; allowed: -# 1. with a type on the left -- int [] a; -# 2. at the beginning of a line for slice initialisers -- [0...10] = 5, -# 3. inside a curly brace -- = { [0...10] = 5 } - while ($line =~ /(.*?\s)\[/g) { - my ($where, $prefix) = ($-[1], $1); - if ($prefix !~ /$Type\s+$/ && - ($where != 0 || $prefix !~ /^.\s+$/) && - $prefix !~ /{\s+$/) { - ERROR("BRACKET_SPACE", - "space prohibited before open square bracket '['\n" . $herecurr); - } - } - -# check for spaces between functions and their parentheses. - while ($line =~ /($Ident)\s+\(/g) { - my $name = $1; - my $ctx_before = substr($line, 0, $-[1]); - my $ctx = "$ctx_before$name"; - - # Ignore those directives where spaces _are_ permitted. - if ($name =~ /^(?: - if|for|while|switch|return|case| - volatile|__volatile__| - __attribute__|format|__extension__| - asm|__asm__)$/x) - { - - # cpp #define statements have non-optional spaces, ie - # if there is a space between the name and the open - # parenthesis it is simply not a parameter group. - } elsif ($ctx_before =~ /^.\s*\#\s*define\s*$/) { - - # cpp #elif statement condition may start with a ( - } elsif ($ctx =~ /^.\s*\#\s*elif\s*$/) { - - # If this whole things ends with a type its most - # likely a typedef for a function. - } elsif ($ctx =~ /$Type$/) { - - } else { - WARN("SPACING", - "space prohibited between function name and open parenthesis '('\n" . $herecurr); - } - } -# Check operator spacing. - if (!($line=~/\#\s*include/)) { - my $ops = qr{ - <<=|>>=|<=|>=|==|!=| - \+=|-=|\*=|\/=|%=|\^=|\|=|&=| - =>|->|<<|>>|<|>|=|!|~| - &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%| - \?|: - }x; - my @elements = split(/($ops|;)/, $opline); - my $off = 0; - - my $blank = copy_spacing($opline); - - for (my $n = 0; $n < $#elements; $n += 2) { - $off += length($elements[$n]); - - # Pick up the preceding and succeeding characters. - my $ca = substr($opline, 0, $off); - my $cc = ''; - if (length($opline) >= ($off + length($elements[$n + 1]))) { - $cc = substr($opline, $off + length($elements[$n + 1])); - } - my $cb = "$ca$;$cc"; - - my $a = ''; - $a = 'V' if ($elements[$n] ne ''); - $a = 'W' if ($elements[$n] =~ /\s$/); - $a = 'C' if ($elements[$n] =~ /$;$/); - $a = 'B' if ($elements[$n] =~ /(\[|\()$/); - $a = 'O' if ($elements[$n] eq ''); - $a = 'E' if ($ca =~ /^\s*$/); - - my $op = $elements[$n + 1]; - - my $c = ''; - if (defined $elements[$n + 2]) { - $c = 'V' if ($elements[$n + 2] ne ''); - $c = 'W' if ($elements[$n + 2] =~ /^\s/); - $c = 'C' if ($elements[$n + 2] =~ /^$;/); - $c = 'B' if ($elements[$n + 2] =~ /^(\)|\]|;)/); - $c = 'O' if ($elements[$n + 2] eq ''); - $c = 'E' if ($elements[$n + 2] =~ /^\s*\\$/); - } else { - $c = 'E'; - } - - my $ctx = "${a}x${c}"; - - my $at = "(ctx:$ctx)"; - - my $ptr = substr($blank, 0, $off) . "^"; - my $hereptr = "$hereline$ptr\n"; - - # Pull out the value of this operator. - my $op_type = substr($curr_values, $off + 1, 1); - - # Get the full operator variant. - my $opv = $op . substr($curr_vars, $off, 1); - - # Ignore operators passed as parameters. - if ($op_type ne 'V' && - $ca =~ /\s$/ && $cc =~ /^\s*,/) { - -# # Ignore comments -# } elsif ($op =~ /^$;+$/) { - - # ; should have either the end of line or a space or \ after it - } elsif ($op eq ';') { - if ($ctx !~ /.x[WEBC]/ && - $cc !~ /^\\/ && $cc !~ /^;/) { - ERROR("SPACING", - "space required after that '$op' $at\n" . $hereptr); - } - - # // is a comment - } elsif ($op eq '//') { - - # No spaces for: - # -> - # : when part of a bitfield - } elsif ($op eq '->' || $opv eq ':B') { - if ($ctx =~ /Wx.|.xW/) { - ERROR("SPACING", - "spaces prohibited around that '$op' $at\n" . $hereptr); - } - - # , must have a space on the right. - } elsif ($op eq ',') { - if ($ctx !~ /.x[WEC]/ && $cc !~ /^}/) { - ERROR("SPACING", - "space required after that '$op' $at\n" . $hereptr); - } - - # '*' as part of a type definition -- reported already. - } elsif ($opv eq '*_') { - #warn "'*' is part of type\n"; - - # unary operators should have a space before and - # none after. May be left adjacent to another - # unary operator, or a cast - } elsif ($op eq '!' || $op eq '~' || - $opv eq '*U' || $opv eq '-U' || - $opv eq '&U' || $opv eq '&&U') { - if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) { - ERROR("SPACING", - "space required before that '$op' $at\n" . $hereptr); - } - if ($op eq '*' && $cc =~/\s*$Modifier\b/) { - # A unary '*' may be const - - } elsif ($ctx =~ /.xW/) { - ERROR("SPACING", - "space prohibited after that '$op' $at\n" . $hereptr); - } - - # unary ++ and unary -- are allowed no space on one side. - } elsif ($op eq '++' or $op eq '--') { - if ($ctx !~ /[WEOBC]x[^W]/ && $ctx !~ /[^W]x[WOBEC]/) { - ERROR("SPACING", - "space required one side of that '$op' $at\n" . $hereptr); - } - if ($ctx =~ /Wx[BE]/ || - ($ctx =~ /Wx./ && $cc =~ /^;/)) { - ERROR("SPACING", - "space prohibited before that '$op' $at\n" . $hereptr); - } - if ($ctx =~ /ExW/) { - ERROR("SPACING", - "space prohibited after that '$op' $at\n" . $hereptr); - } - - - # << and >> may either have or not have spaces both sides - } elsif ($op eq '<<' or $op eq '>>' or - $op eq '&' or $op eq '^' or $op eq '|' or - $op eq '+' or $op eq '-' or - $op eq '*' or $op eq '/' or - $op eq '%') - { - if ($ctx =~ /Wx[^WCE]|[^WCE]xW/) { - ERROR("SPACING", - "need consistent spacing around '$op' $at\n" . - $hereptr); - } - - # A colon needs no spaces before when it is - # terminating a case value or a label. - } elsif ($opv eq ':C' || $opv eq ':L') { - if ($ctx =~ /Wx./) { - ERROR("SPACING", - "space prohibited before that '$op' $at\n" . $hereptr); - } - - # All the others need spaces both sides. - } elsif ($ctx !~ /[EWC]x[CWE]/) { - my $ok = 0; - - # Ignore email addresses - if (($op eq '<' && - $cc =~ /^\S+\@\S+>/) || - ($op eq '>' && - $ca =~ /<\S+\@\S+$/)) - { - $ok = 1; - } - - # Ignore ?: - if (($opv eq ':O' && $ca =~ /\?$/) || - ($op eq '?' && $cc =~ /^:/)) { - $ok = 1; - } - - if ($ok == 0) { - ERROR("SPACING", - "spaces required around that '$op' $at\n" . $hereptr); - } - } - $off += length($elements[$n + 1]); - } - } - -# check for multiple assignments - if ($line =~ /^.\s*$Lval\s*=\s*$Lval\s*=(?!=)/) { - CHK("MULTIPLE_ASSIGNMENTS", - "multiple assignments should be avoided\n" . $herecurr); - } - -## # check for multiple declarations, allowing for a function declaration -## # continuation. -## if ($line =~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Ident.*/ && -## $line !~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Type\s*$Ident.*/) { -## -## # Remove any bracketed sections to ensure we do not -## # falsly report the parameters of functions. -## my $ln = $line; -## while ($ln =~ s/\([^\(\)]*\)//g) { -## } -## if ($ln =~ /,/) { -## WARN("MULTIPLE_DECLARATION", -## "declaring multiple variables together should be avoided\n" . $herecurr); -## } -## } - -#need space before brace following if, while, etc - if (($line =~ /\(.*\){/ && $line !~ /\($Type\){/) || - $line =~ /do{/) { - ERROR("SPACING", - "space required before the open brace '{'\n" . $herecurr); - } - -# closing brace should have a space following it when it has anything -# on the line - if ($line =~ /}(?!(?:,|;|\)))\S/) { - ERROR("SPACING", - "space required after that close brace '}'\n" . $herecurr); - } - -# check spacing on square brackets - if ($line =~ /\[\s/ && $line !~ /\[\s*$/) { - ERROR("SPACING", - "space prohibited after that open square bracket '['\n" . $herecurr); - } - if ($line =~ /\s\]/) { - ERROR("SPACING", - "space prohibited before that close square bracket ']'\n" . $herecurr); - } - -# check spacing on parentheses - if ($line =~ /\(\s/ && $line !~ /\(\s*(?:\\)?$/ && - $line !~ /for\s*\(\s+;/) { - ERROR("SPACING", - "space prohibited after that open parenthesis '('\n" . $herecurr); - } - if ($line =~ /(\s+)\)/ && $line !~ /^.\s*\)/ && - $line !~ /for\s*\(.*;\s+\)/ && - $line !~ /:\s+\)/) { - ERROR("SPACING", - "space prohibited before that close parenthesis ')'\n" . $herecurr); - } - -#goto labels aren't indented, allow a single space however - if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and - !($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) { - WARN("INDENTED_LABEL", - "labels should not be indented\n" . $herecurr); - } - -# Return is not a function. - if (defined($stat) && $stat =~ /^.\s*return(\s*)(\(.*);/s) { - my $spacing = $1; - my $value = $2; - - # Flatten any parentheses - $value =~ s/\(/ \(/g; - $value =~ s/\)/\) /g; - while ($value =~ s/\[[^\{\}]*\]/1/ || - $value !~ /(?:$Ident|-?$Constant)\s* - $Compare\s* - (?:$Ident|-?$Constant)/x && - $value =~ s/\([^\(\)]*\)/1/) { - } -#print "value<$value>\n"; - if ($value =~ /^\s*(?:$Ident|-?$Constant)\s*$/) { - ERROR("RETURN_PARENTHESES", - "return is not a function, parentheses are not required\n" . $herecurr); - - } elsif ($spacing !~ /\s+/) { - ERROR("SPACING", - "space required before the open parenthesis '('\n" . $herecurr); - } - } -# Return of what appears to be an errno should normally be -'ve - if ($line =~ /^.\s*return\s*(E[A-Z]*)\s*;/) { - my $name = $1; - if ($name ne 'EOF' && $name ne 'ERROR') { - WARN("USE_NEGATIVE_ERRNO", - "return of an errno should typically be -ve (return -$1)\n" . $herecurr); - } - } - -# typecasts on min/max could be min_t/max_t - if ($line =~ /^\+(?:.*?)\b(min|max)\s*\($Typecast{0,1}($LvalOrFunc)\s*,\s*$Typecast{0,1}($LvalOrFunc)\s*\)/) { - if (defined $2 || defined $8) { - my $call = $1; - my $cast1 = deparenthesize($2); - my $arg1 = $3; - my $cast2 = deparenthesize($8); - my $arg2 = $9; - my $cast; - - if ($cast1 ne "" && $cast2 ne "") { - $cast = "$cast1 or $cast2"; - } elsif ($cast1 ne "") { - $cast = $cast1; - } else { - $cast = $cast2; - } - WARN("MINMAX", - "$call() should probably be ${call}_t($cast, $arg1, $arg2)\n" . $herecurr); - } - } - -# Need a space before open parenthesis after if, while etc - if ($line=~/\b(if|while|for|switch)\(/) { - ERROR("SPACING", "space required before the open parenthesis '('\n" . $herecurr); - } - -# Check for illegal assignment in if conditional -- and check for trailing -# statements after the conditional. - if ($line =~ /do\s*(?!{)/) { - my ($stat_next) = ctx_statement_block($line_nr_next, - $remain_next, $off_next); - $stat_next =~ s/\n./\n /g; - ##print "stat<$stat> stat_next<$stat_next>\n"; - - if ($stat_next =~ /^\s*while\b/) { - # If the statement carries leading newlines, - # then count those as offsets. - my ($whitespace) = - ($stat_next =~ /^((?:\s*\n[+-])*\s*)/s); - my $offset = - statement_rawlines($whitespace) - 1; - - $suppress_whiletrailers{$line_nr_next + - $offset} = 1; - } - } - if (!defined $suppress_whiletrailers{$linenr} && - $line =~ /\b(?:if|while|for)\s*\(/ && $line !~ /^.\s*#/) { - my ($s, $c) = ($stat, $cond); - - if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/s) { - ERROR("ASSIGN_IN_IF", - "do not use assignment in if condition\n" . $herecurr); - } - - # Find out what is on the end of the line after the - # conditional. - substr($s, 0, length($c), ''); - $s =~ s/\n.*//g; - $s =~ s/$;//g; # Remove any comments - if (length($c) && $s !~ /^\s*{?\s*\\*\s*$/ && - $c !~ /}\s*while\s*/) - { - # Find out how long the conditional actually is. - my @newlines = ($c =~ /\n/gs); - my $cond_lines = 1 + $#newlines; - my $stat_real = ''; - - $stat_real = raw_line($linenr, $cond_lines) - . "\n" if ($cond_lines); - if (defined($stat_real) && $cond_lines > 1) { - $stat_real = "[...]\n$stat_real"; - } - - ERROR("TRAILING_STATEMENTS", - "trailing statements should be on next line\n" . $herecurr . $stat_real); - } - } - -# Check for bitwise tests written as boolean - if ($line =~ / - (?: - (?:\[|\(|\&\&|\|\|) - \s*0[xX][0-9]+\s* - (?:\&\&|\|\|) - | - (?:\&\&|\|\|) - \s*0[xX][0-9]+\s* - (?:\&\&|\|\||\)|\]) - )/x) - { - WARN("HEXADECIMAL_BOOLEAN_TEST", - "boolean test with hexadecimal, perhaps just 1 \& or \|?\n" . $herecurr); - } - -# if and else should not have general statements after it - if ($line =~ /^.\s*(?:}\s*)?else\b(.*)/) { - my $s = $1; - $s =~ s/$;//g; # Remove any comments - if ($s !~ /^\s*(?:\sif|(?:{|)\s*\\?\s*$)/) { - ERROR("TRAILING_STATEMENTS", - "trailing statements should be on next line\n" . $herecurr); - } - } -# if should not continue a brace - if ($line =~ /}\s*if\b/) { - ERROR("TRAILING_STATEMENTS", - "trailing statements should be on next line\n" . - $herecurr); - } -# case and default should not have general statements after them - if ($line =~ /^.\s*(?:case\s*.*|default\s*):/g && - $line !~ /\G(?: - (?:\s*$;*)(?:\s*{)?(?:\s*$;*)(?:\s*\\)?\s*$| - \s*return\s+ - )/xg) - { - ERROR("TRAILING_STATEMENTS", - "trailing statements should be on next line\n" . $herecurr); - } - - # Check for }else {, these must be at the same - # indent level to be relevant to each other. - if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ and - $previndent == $indent) { - ERROR("ELSE_AFTER_BRACE", - "else should follow close brace '}'\n" . $hereprev); - } - - if ($prevline=~/}\s*$/ and $line=~/^.\s*while\s*/ and - $previndent == $indent) { - my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0); - - # Find out what is on the end of the line after the - # conditional. - substr($s, 0, length($c), ''); - $s =~ s/\n.*//g; - - if ($s =~ /^\s*;/) { - ERROR("WHILE_AFTER_BRACE", - "while should follow close brace '}'\n" . $hereprev); - } - } - -#studly caps, commented out until figure out how to distinguish between use of existing and adding new -# if (($line=~/[\w_][a-z\d]+[A-Z]/) and !($line=~/print/)) { -# print "No studly caps, use _\n"; -# print "$herecurr"; -# $clean = 0; -# } - -#no spaces allowed after \ in define - if ($line=~/\#\s*define.*\\\s$/) { - WARN("WHITESPACE_AFTER_LINE_CONTINUATION", - "Whitepspace after \\ makes next lines useless\n" . $herecurr); - } - -#warn if is #included and is available (uses RAW line) - if ($tree && $rawline =~ m{^.\s*\#\s*include\s*\}) { - my $file = "$1.h"; - my $checkfile = "include/linux/$file"; - if (-f "$root/$checkfile" && - $realfile ne $checkfile && - $1 !~ /$allowed_asm_includes/) - { - if ($realfile =~ m{^arch/}) { - CHK("ARCH_INCLUDE_LINUX", - "Consider using #include instead of \n" . $herecurr); - } else { - WARN("INCLUDE_LINUX", - "Use #include instead of \n" . $herecurr); - } - } - } - -# multi-statement macros should be enclosed in a do while loop, grab the -# first statement and ensure its the whole macro if its not enclosed -# in a known good container - if ($realfile !~ m@/vmlinux.lds.h$@ && - $line =~ /^.\s*\#\s*define\s*$Ident(\()?/) { - my $ln = $linenr; - my $cnt = $realcnt; - my ($off, $dstat, $dcond, $rest); - my $ctx = ''; - - my $args = defined($1); - - # Find the end of the macro and limit our statement - # search to that. - while ($cnt > 0 && defined $lines[$ln - 1] && - $lines[$ln - 1] =~ /^(?:-|..*\\$)/) - { - $ctx .= $rawlines[$ln - 1] . "\n"; - $cnt-- if ($lines[$ln - 1] !~ /^-/); - $ln++; - } - $ctx .= $rawlines[$ln - 1]; - - ($dstat, $dcond, $ln, $cnt, $off) = - ctx_statement_block($linenr, $ln - $linenr + 1, 0); - #print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n"; - #print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n"; - - # Extract the remainder of the define (if any) and - # rip off surrounding spaces, and trailing \'s. - $rest = ''; - while ($off != 0 || ($cnt > 0 && $rest =~ /\\\s*$/)) { - #print "ADDING cnt<$cnt> $off <" . substr($lines[$ln - 1], $off) . "> rest<$rest>\n"; - if ($off != 0 || $lines[$ln - 1] !~ /^-/) { - $rest .= substr($lines[$ln - 1], $off) . "\n"; - $cnt--; - } - $ln++; - $off = 0; - } - $rest =~ s/\\\n.//g; - $rest =~ s/^\s*//s; - $rest =~ s/\s*$//s; - - # Clean up the original statement. - if ($args) { - substr($dstat, 0, length($dcond), ''); - } else { - $dstat =~ s/^.\s*\#\s*define\s+$Ident\s*//; - } - $dstat =~ s/$;//g; - $dstat =~ s/\\\n.//g; - $dstat =~ s/^\s*//s; - $dstat =~ s/\s*$//s; - - # Flatten any parentheses and braces - while ($dstat =~ s/\([^\(\)]*\)/1/ || - $dstat =~ s/\{[^\{\}]*\}/1/ || - $dstat =~ s/\[[^\{\}]*\]/1/) - { - } - - my $exceptions = qr{ - $Declare| - module_param_named| - MODULE_PARAM_DESC| - DECLARE_PER_CPU| - DEFINE_PER_CPU| - __typeof__\(| - union| - struct| - \.$Ident\s*=\s*| - ^\"|\"$ - }x; - #print "REST<$rest> dstat<$dstat> ctx<$ctx>\n"; - if ($rest ne '' && $rest ne ',') { - if ($rest !~ /while\s*\(/ && - $dstat !~ /$exceptions/) - { - ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE", - "Macros with multiple statements should be enclosed in a do - while loop\n" . "$here\n$ctx\n"); - } - - } elsif ($ctx !~ /;/) { - if ($dstat ne '' && - $dstat !~ /^(?:$Ident|-?$Constant)$/ && - $dstat !~ /$exceptions/ && - $dstat !~ /^\.$Ident\s*=/ && - $dstat =~ /$Operators/) - { - ERROR("COMPLEX_MACRO", - "Macros with complex values should be enclosed in parenthesis\n" . "$here\n$ctx\n"); - } - } - } - -# make sure symbols are always wrapped with VMLINUX_SYMBOL() ... -# all assignments may have only one of the following with an assignment: -# . -# ALIGN(...) -# VMLINUX_SYMBOL(...) - if ($realfile eq 'vmlinux.lds.h' && $line =~ /(?:(?:^|\s)$Ident\s*=|=\s*$Ident(?:\s|$))/) { - WARN("MISSING_VMLINUX_SYMBOL", - "vmlinux.lds.h needs VMLINUX_SYMBOL() around C-visible symbols\n" . $herecurr); - } - -# check for redundant bracing round if etc - if ($line =~ /(^.*)\bif\b/ && $1 !~ /else\s*$/) { - my ($level, $endln, @chunks) = - ctx_statement_full($linenr, $realcnt, 1); - #print "chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n"; - #print "APW: <<$chunks[1][0]>><<$chunks[1][1]>>\n"; - if ($#chunks > 0 && $level == 0) { - my $allowed = 0; - my $seen = 0; - my $herectx = $here . "\n"; - my $ln = $linenr - 1; - for my $chunk (@chunks) { - my ($cond, $block) = @{$chunk}; - - # If the condition carries leading newlines, then count those as offsets. - my ($whitespace) = ($cond =~ /^((?:\s*\n[+-])*\s*)/s); - my $offset = statement_rawlines($whitespace) - 1; - - #print "COND<$cond> whitespace<$whitespace> offset<$offset>\n"; - - # We have looked at and allowed this specific line. - $suppress_ifbraces{$ln + $offset} = 1; - - $herectx .= "$rawlines[$ln + $offset]\n[...]\n"; - $ln += statement_rawlines($block) - 1; - - substr($block, 0, length($cond), ''); - - $seen++ if ($block =~ /^\s*{/); - - #print "cond<$cond> block<$block> allowed<$allowed>\n"; - if (statement_lines($cond) > 1) { - #print "APW: ALLOWED: cond<$cond>\n"; - $allowed = 1; - } - if ($block =~/\b(?:if|for|while)\b/) { - #print "APW: ALLOWED: block<$block>\n"; - $allowed = 1; - } - if (statement_block_size($block) > 1) { - #print "APW: ALLOWED: lines block<$block>\n"; - $allowed = 1; - } - } - if ($seen && !$allowed) { - WARN("BRACES", - "braces {} are not necessary for any arm of this statement\n" . $herectx); - } - } - } - if (!defined $suppress_ifbraces{$linenr - 1} && - $line =~ /\b(if|while|for|else)\b/) { - my $allowed = 0; - - # Check the pre-context. - if (substr($line, 0, $-[0]) =~ /(\}\s*)$/) { - #print "APW: ALLOWED: pre<$1>\n"; - $allowed = 1; - } - - my ($level, $endln, @chunks) = - ctx_statement_full($linenr, $realcnt, $-[0]); - - # Check the condition. - my ($cond, $block) = @{$chunks[0]}; - #print "CHECKING<$linenr> cond<$cond> block<$block>\n"; - if (defined $cond) { - substr($block, 0, length($cond), ''); - } - if (statement_lines($cond) > 1) { - #print "APW: ALLOWED: cond<$cond>\n"; - $allowed = 1; - } - if ($block =~/\b(?:if|for|while)\b/) { - #print "APW: ALLOWED: block<$block>\n"; - $allowed = 1; - } - if (statement_block_size($block) > 1) { - #print "APW: ALLOWED: lines block<$block>\n"; - $allowed = 1; - } - # Check the post-context. - if (defined $chunks[1]) { - my ($cond, $block) = @{$chunks[1]}; - if (defined $cond) { - substr($block, 0, length($cond), ''); - } - if ($block =~ /^\s*\{/) { - #print "APW: ALLOWED: chunk-1 block<$block>\n"; - $allowed = 1; - } - } - if ($level == 0 && $block =~ /^\s*\{/ && !$allowed) { - my $herectx = $here . "\n";; - my $cnt = statement_rawlines($block); - - for (my $n = 0; $n < $cnt; $n++) { - $herectx .= raw_line($linenr, $n) . "\n";; - } - - WARN("BRACES", - "braces {} are not necessary for single statement blocks\n" . $herectx); - } - } - -# don't include deprecated include files (uses RAW line) - for my $inc (@dep_includes) { - if ($rawline =~ m@^.\s*\#\s*include\s*\<$inc>@) { - ERROR("DEPRECATED_INCLUDE", - "Don't use <$inc>: see Documentation/feature-removal-schedule.txt\n" . $herecurr); - } - } - -# don't use deprecated functions - for my $func (@dep_functions) { - if ($line =~ /\b$func\b/) { - ERROR("DEPRECATED_FUNCTION", - "Don't use $func(): see Documentation/feature-removal-schedule.txt\n" . $herecurr); - } - } - -# no volatiles please - my $asm_volatile = qr{\b(__asm__|asm)\s+(__volatile__|volatile)\b}; - if ($line =~ /\bvolatile\b/ && $line !~ /$asm_volatile/) { - WARN("VOLATILE", - "Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $herecurr); - } - -# warn about #if 0 - if ($line =~ /^.\s*\#\s*if\s+0\b/) { - CHK("REDUNDANT_CODE", - "if this code is redundant consider removing it\n" . - $herecurr); - } - -# check for needless kfree() checks - if ($prevline =~ /\bif\s*\(([^\)]*)\)/) { - my $expr = $1; - if ($line =~ /\bkfree\(\Q$expr\E\);/) { - WARN("NEEDLESS_KFREE", - "kfree(NULL) is safe this check is probably not required\n" . $hereprev); - } - } -# check for needless usb_free_urb() checks - if ($prevline =~ /\bif\s*\(([^\)]*)\)/) { - my $expr = $1; - if ($line =~ /\busb_free_urb\(\Q$expr\E\);/) { - WARN("NEEDLESS_USB_FREE_URB", - "usb_free_urb(NULL) is safe this check is probably not required\n" . $hereprev); - } - } - -# prefer usleep_range over udelay - if ($line =~ /\budelay\s*\(\s*(\w+)\s*\)/) { - # ignore udelay's < 10, however - if (! (($1 =~ /(\d+)/) && ($1 < 10)) ) { - CHK("USLEEP_RANGE", - "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt\n" . $line); - } - } - -# warn about unexpectedly long msleep's - if ($line =~ /\bmsleep\s*\((\d+)\);/) { - if ($1 < 20) { - WARN("MSLEEP", - "msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt\n" . $line); - } - } - -# warn about #ifdefs in C files -# if ($line =~ /^.\s*\#\s*if(|n)def/ && ($realfile =~ /\.c$/)) { -# print "#ifdef in C files should be avoided\n"; -# print "$herecurr"; -# $clean = 0; -# } - -# warn about spacing in #ifdefs - if ($line =~ /^.\s*\#\s*(ifdef|ifndef|elif)\s\s+/) { - ERROR("SPACING", - "exactly one space required after that #$1\n" . $herecurr); - } - -# check for spinlock_t definitions without a comment. - if ($line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/ || - $line =~ /^.\s*(DEFINE_MUTEX)\s*\(/) { - my $which = $1; - if (!ctx_has_comment($first_line, $linenr)) { - CHK("UNCOMMENTED_DEFINITION", - "$1 definition without comment\n" . $herecurr); - } - } -# check for memory barriers without a comment. - if ($line =~ /\b(mb|rmb|wmb|read_barrier_depends|smp_mb|smp_rmb|smp_wmb|smp_read_barrier_depends)\(/) { - if (!ctx_has_comment($first_line, $linenr)) { - CHK("MEMORY_BARRIER", - "memory barrier without comment\n" . $herecurr); - } - } -# check of hardware specific defines - if ($line =~ m@^.\s*\#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@ && $realfile !~ m@include/asm-@) { - CHK("ARCH_DEFINES", - "architecture specific defines should be avoided\n" . $herecurr); - } - -# Check that the storage class is at the beginning of a declaration - if ($line =~ /\b$Storage\b/ && $line !~ /^.\s*$Storage\b/) { - WARN("STORAGE_CLASS", - "storage class should be at the beginning of the declaration\n" . $herecurr) - } - -# check the location of the inline attribute, that it is between -# storage class and type. - if ($line =~ /\b$Type\s+$Inline\b/ || - $line =~ /\b$Inline\s+$Storage\b/) { - ERROR("INLINE_LOCATION", - "inline keyword should sit between storage class and type\n" . $herecurr); - } - -# Check for __inline__ and __inline, prefer inline - if ($line =~ /\b(__inline__|__inline)\b/) { - WARN("INLINE", - "plain inline is preferred over $1\n" . $herecurr); - } - -# Check for __attribute__ packed, prefer __packed - if ($line =~ /\b__attribute__\s*\(\s*\(.*\bpacked\b/) { - WARN("PREFER_PACKED", - "__packed is preferred over __attribute__((packed))\n" . $herecurr); - } - -# Check for __attribute__ aligned, prefer __aligned - if ($line =~ /\b__attribute__\s*\(\s*\(.*aligned/) { - WARN("PREFER_ALIGNED", - "__aligned(size) is preferred over __attribute__((aligned(size)))\n" . $herecurr); - } - -# check for sizeof(&) - if ($line =~ /\bsizeof\s*\(\s*\&/) { - WARN("SIZEOF_ADDRESS", - "sizeof(& should be avoided\n" . $herecurr); - } - -# check for line continuations in quoted strings with odd counts of " - if ($rawline =~ /\\$/ && $rawline =~ tr/"/"/ % 2) { - WARN("LINE_CONTINUATIONS", - "Avoid line continuations in quoted strings\n" . $herecurr); - } - -# check for new externs in .c files. - if ($realfile =~ /\.c$/ && defined $stat && - $stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s) - { - my $function_name = $1; - my $paren_space = $2; - - my $s = $stat; - if (defined $cond) { - substr($s, 0, length($cond), ''); - } - if ($s =~ /^\s*;/ && - $function_name ne 'uninitialized_var') - { - WARN("AVOID_EXTERNS", - "externs should be avoided in .c files\n" . $herecurr); - } - - if ($paren_space =~ /\n/) { - WARN("FUNCTION_ARGUMENTS", - "arguments for function declarations should follow identifier\n" . $herecurr); - } - - } elsif ($realfile =~ /\.c$/ && defined $stat && - $stat =~ /^.\s*extern\s+/) - { - WARN("AVOID_EXTERNS", - "externs should be avoided in .c files\n" . $herecurr); - } - -# checks for new __setup's - if ($rawline =~ /\b__setup\("([^"]*)"/) { - my $name = $1; - - if (!grep(/$name/, @setup_docs)) { - CHK("UNDOCUMENTED_SETUP", - "__setup appears un-documented -- check Documentation/kernel-parameters.txt\n" . $herecurr); - } - } - -# check for pointless casting of kmalloc return - if ($line =~ /\*\s*\)\s*[kv][czm]alloc(_node){0,1}\b/) { - WARN("UNNECESSARY_CASTS", - "unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr); - } - -# check for multiple semicolons - if ($line =~ /;\s*;\s*$/) { - WARN("ONE_SEMICOLON", - "Statements terminations use 1 semicolon\n" . $herecurr); - } - -# check for whitespace before semicolon - not allowed at end-of-line - if ($line =~ /\s+;$/) { - WARN("SPACEBEFORE_SEMICOLON", - "Whitespace before semicolon\n" . $herecurr); - } - -# check for gcc specific __FUNCTION__ - if ($line =~ /__FUNCTION__/) { - WARN("USE_FUNC", - "__func__ should be used instead of gcc specific __FUNCTION__\n" . $herecurr); - } - -# check for semaphores initialized locked - if ($line =~ /^.\s*sema_init.+,\W?0\W?\)/) { - WARN("CONSIDER_COMPLETION", - "consider using a completion\n" . $herecurr); - - } -# recommend kstrto* over simple_strto* - if ($line =~ /\bsimple_(strto.*?)\s*\(/) { - WARN("CONSIDER_KSTRTO", - "consider using kstrto* in preference to simple_$1\n" . $herecurr); - } -# check for __initcall(), use device_initcall() explicitly please - if ($line =~ /^.\s*__initcall\s*\(/) { - WARN("USE_DEVICE_INITCALL", - "please use device_initcall() instead of __initcall()\n" . $herecurr); - } -# check for various ops structs, ensure they are const. - my $struct_ops = qr{acpi_dock_ops| - address_space_operations| - backlight_ops| - block_device_operations| - dentry_operations| - dev_pm_ops| - dma_map_ops| - extent_io_ops| - file_lock_operations| - file_operations| - hv_ops| - ide_dma_ops| - intel_dvo_dev_ops| - item_operations| - iwl_ops| - kgdb_arch| - kgdb_io| - kset_uevent_ops| - lock_manager_operations| - microcode_ops| - mtrr_ops| - neigh_ops| - nlmsvc_binding| - pci_raw_ops| - pipe_buf_operations| - platform_hibernation_ops| - platform_suspend_ops| - proto_ops| - rpc_pipe_ops| - seq_operations| - snd_ac97_build_ops| - soc_pcmcia_socket_ops| - stacktrace_ops| - sysfs_ops| - tty_operations| - usb_mon_operations| - wd_ops}x; - if ($line !~ /\bconst\b/ && - $line =~ /\bstruct\s+($struct_ops)\b/) { - WARN("CONST_STRUCT", - "struct $1 should normally be const\n" . - $herecurr); - } - -# use of NR_CPUS is usually wrong -# ignore definitions of NR_CPUS and usage to define arrays as likely right - if ($line =~ /\bNR_CPUS\b/ && - $line !~ /^.\s*\s*#\s*if\b.*\bNR_CPUS\b/ && - $line !~ /^.\s*\s*#\s*define\b.*\bNR_CPUS\b/ && - $line !~ /^.\s*$Declare\s.*\[[^\]]*NR_CPUS[^\]]*\]/ && - $line !~ /\[[^\]]*\.\.\.[^\]]*NR_CPUS[^\]]*\]/ && - $line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/) - { - WARN("NR_CPUS", - "usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc\n" . $herecurr); - } - -# check for %L{u,d,i} in strings - my $string; - while ($line =~ /(?:^|")([X\t]*)(?:"|$)/g) { - $string = substr($rawline, $-[1], $+[1] - $-[1]); - $string =~ s/%%/__/g; - if ($string =~ /(?mutex.\n" . $herecurr); - } - } - - if ($line =~ /debugfs_create_file.*S_IWUGO/ || - $line =~ /DEVICE_ATTR.*S_IWUGO/ ) { - WARN("EXPORTED_WORLD_WRITABLE", - "Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr); - } - - # Check for memset with swapped arguments - if ($line =~ /memset.*\,(\ |)(0x|)0(\ |0|)\);/) { - ERROR("MEMSET", - "memset size is 3rd argument, not the second.\n" . $herecurr); - } - } - - # If we have no input at all, then there is nothing to report on - # so just keep quiet. - if ($#rawlines == -1) { - exit(0); - } - - # In mailback mode only produce a report in the negative, for - # things that appear to be patches. - if ($mailback && ($clean == 1 || !$is_patch)) { - exit(0); - } - - # This is not a patch, and we are are in 'no-patch' mode so - # just keep quiet. - if (!$chk_patch && !$is_patch) { - exit(0); - } - - if (!$is_patch) { - ERROR("NOT_UNIFIED_DIFF", - "Does not appear to be a unified-diff format patch\n"); - } - if ($is_patch && $chk_signoff && $signoff == 0) { - ERROR("MISSING_SIGN_OFF", - "Missing Signed-off-by: line(s)\n"); - } - - print report_dump(); - if ($summary && !($clean == 1 && $quiet == 1)) { - print "$filename " if ($summary_file); - print "total: $cnt_error errors, $cnt_warn warnings, " . - (($check)? "$cnt_chk checks, " : "") . - "$cnt_lines lines checked\n"; - print "\n" if ($quiet == 0); - } - - if ($quiet == 0) { - # If there were whitespace errors which cleanpatch can fix - # then suggest that. - if ($rpt_cleaners) { - print "NOTE: whitespace errors detected, you may wish to use scripts/cleanpatch or\n"; - print " scripts/cleanfile\n\n"; - $rpt_cleaners = 0; - } - } - - if (keys %ignore_type) { - print "NOTE: Ignored message types:"; - foreach my $ignore (sort keys %ignore_type) { - print " $ignore"; - } - print "\n"; - print "\n" if ($quiet == 0); - } - - if ($clean == 1 && $quiet == 0) { - print "$vname has no obvious style problems and is ready for submission.\n" - } - if ($clean == 0 && $quiet == 0) { - print << "EOM"; -$vname has style problems, please review. - -If any of these errors are false positives, please report -them to the maintainer, see CHECKPATCH in MAINTAINERS. -EOM - } - - return $clean; -} diff --git a/root/package/utils/sysupgrade-helper/src/tools/checkstack.pl b/root/package/utils/sysupgrade-helper/src/tools/checkstack.pl deleted file mode 100644 index c1cdc0a9..00000000 --- a/root/package/utils/sysupgrade-helper/src/tools/checkstack.pl +++ /dev/null @@ -1,171 +0,0 @@ -#!/usr/bin/perl - -# Check the stack usage of functions -# -# Copyright Joern Engel -# Inspired by Linus Torvalds -# Original idea maybe from Keith Owens -# s390 port and big speedup by Arnd Bergmann -# Mips port by Juan Quintela -# IA64 port via Andreas Dilger -# Arm port by Holger Schurig -# sh64 port by Paul Mundt -# Random bits by Matt Mackall -# M68k port by Geert Uytterhoeven and Andreas Schwab -# AVR32 port by Haavard Skinnemoen (Atmel) -# PARISC port by Kyle McMartin -# sparc port by Martin Habets -# -# Usage: -# objdump -d vmlinux | scripts/checkstack.pl [arch] -# -# TODO : Port to all architectures (one regex per arch) - -use strict; - -# check for arch -# -# $re is used for two matches: -# $& (whole re) matches the complete objdump line with the stack growth -# $1 (first bracket) matches the size of the stack growth -# -# $dre is similar, but for dynamic stack redutions: -# $& (whole re) matches the complete objdump line with the stack growth -# $1 (first bracket) matches the dynamic amount of the stack growth -# -# use anything else and feel the pain ;) -my (@stack, $re, $dre, $x, $xs); -{ - my $arch = shift; - if ($arch eq "") { - $arch = `uname -m`; - chomp($arch); - } - - $x = "[0-9a-f]"; # hex character - $xs = "[0-9a-f ]"; # hex character or space - if ($arch eq 'arm') { - #c0008ffc: e24dd064 sub sp, sp, #100 ; 0x64 - $re = qr/.*sub.*sp, sp, #(([0-9]{2}|[3-9])[0-9]{2})/o; - } elsif ($arch eq 'avr32') { - #8000008a: 20 1d sub sp,4 - #80000ca8: fa cd 05 b0 sub sp,sp,1456 - $re = qr/^.*sub.*sp.*,([0-9]{1,8})/o; - } elsif ($arch =~ /^i[3456]86$/) { - #c0105234: 81 ec ac 05 00 00 sub $0x5ac,%esp - $re = qr/^.*[as][du][db] \$(0x$x{1,8}),\%esp$/o; - $dre = qr/^.*[as][du][db] (%.*),\%esp$/o; - } elsif ($arch eq 'x86_64') { - # 2f60: 48 81 ec e8 05 00 00 sub $0x5e8,%rsp - $re = qr/^.*[as][du][db] \$(0x$x{1,8}),\%rsp$/o; - $dre = qr/^.*[as][du][db] (\%.*),\%rsp$/o; - } elsif ($arch eq 'ia64') { - #e0000000044011fc: 01 0f fc 8c adds r12=-384,r12 - $re = qr/.*adds.*r12=-(([0-9]{2}|[3-9])[0-9]{2}),r12/o; - } elsif ($arch eq 'm68k') { - # 2b6c: 4e56 fb70 linkw %fp,#-1168 - # 1df770: defc ffe4 addaw #-28,%sp - $re = qr/.*(?:linkw %fp,|addaw )#-([0-9]{1,4})(?:,%sp)?$/o; - } elsif ($arch eq 'mips64') { - #8800402c: 67bdfff0 daddiu sp,sp,-16 - $re = qr/.*daddiu.*sp,sp,-(([0-9]{2}|[3-9])[0-9]{2})/o; - } elsif ($arch eq 'mips') { - #88003254: 27bdffe0 addiu sp,sp,-32 - $re = qr/.*addiu.*sp,sp,-(([0-9]{2}|[3-9])[0-9]{2})/o; - } elsif ($arch eq 'parisc' || $arch eq 'parisc64') { - $re = qr/.*ldo ($x{1,8})\(sp\),sp/o; - } elsif ($arch eq 'ppc') { - #c00029f4: 94 21 ff 30 stwu r1,-208(r1) - $re = qr/.*stwu.*r1,-($x{1,8})\(r1\)/o; - } elsif ($arch eq 'ppc64') { - #XXX - $re = qr/.*stdu.*r1,-($x{1,8})\(r1\)/o; - } elsif ($arch eq 'powerpc') { - $re = qr/.*st[dw]u.*r1,-($x{1,8})\(r1\)/o; - } elsif ($arch =~ /^s390x?$/) { - # 11160: a7 fb ff 60 aghi %r15,-160 - # or - # 100092: e3 f0 ff c8 ff 71 lay %r15,-56(%r15) - $re = qr/.*(?:lay|ag?hi).*\%r15,-(([0-9]{2}|[3-9])[0-9]{2}) - (?:\(\%r15\))?$/ox; - } elsif ($arch =~ /^sh64$/) { - #XXX: we only check for the immediate case presently, - # though we will want to check for the movi/sub - # pair for larger users. -- PFM. - #a00048e0: d4fc40f0 addi.l r15,-240,r15 - $re = qr/.*addi\.l.*r15,-(([0-9]{2}|[3-9])[0-9]{2}),r15/o; - } elsif ($arch =~ /^blackfin$/) { - # 0: 00 e8 38 01 LINK 0x4e0; - $re = qr/.*[[:space:]]LINK[[:space:]]*(0x$x{1,8})/o; - } elsif ($arch eq 'sparc' || $arch eq 'sparc64') { - # f0019d10: 9d e3 bf 90 save %sp, -112, %sp - $re = qr/.*save.*%sp, -(([0-9]{2}|[3-9])[0-9]{2}), %sp/o; - } else { - print("wrong or unknown architecture \"$arch\"\n"); - exit - } -} - -# -# main() -# -my $funcre = qr/^$x* <(.*)>:$/; -my ($func, $file, $lastslash); - -while (my $line = ) { - if ($line =~ m/$funcre/) { - $func = $1; - } - elsif ($line =~ m/(.*):\s*file format/) { - $file = $1; - $file =~ s/\.ko//; - $lastslash = rindex($file, "/"); - if ($lastslash != -1) { - $file = substr($file, $lastslash + 1); - } - } - elsif ($line =~ m/$re/) { - my $size = $1; - $size = hex($size) if ($size =~ /^0x/); - - if ($size > 0xf0000000) { - $size = - $size; - $size += 0x80000000; - $size += 0x80000000; - } - next if ($size > 0x10000000); - - next if $line !~ m/^($xs*)/; - my $addr = $1; - $addr =~ s/ /0/g; - $addr = "0x$addr"; - - my $intro = "$addr $func [$file]:"; - my $padlen = 56 - length($intro); - while ($padlen > 0) { - $intro .= ' '; - $padlen -= 8; - } - next if ($size < 100); - push @stack, "$intro$size\n"; - } - elsif (defined $dre && $line =~ m/$dre/) { - my $size = "Dynamic ($1)"; - - next if $line !~ m/^($xs*)/; - my $addr = $1; - $addr =~ s/ /0/g; - $addr = "0x$addr"; - - my $intro = "$addr $func [$file]:"; - my $padlen = 56 - length($intro); - while ($padlen > 0) { - $intro .= ' '; - $padlen -= 8; - } - push @stack, "$intro$size\n"; - } -} - -# Sort output by size (last field) -print sort { ($b =~ /:\t*(\d+)$/)[0] <=> ($a =~ /:\t*(\d+)$/)[0] } @stack; diff --git a/root/package/utils/sysupgrade-helper/src/tools/gcc-version.sh b/root/package/utils/sysupgrade-helper/src/tools/gcc-version.sh deleted file mode 100644 index debecb55..00000000 --- a/root/package/utils/sysupgrade-helper/src/tools/gcc-version.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh -# -# gcc-version [-p] gcc-command -# -# Prints the gcc version of `gcc-command' in a canonical 4-digit form -# such as `0295' for gcc-2.95, `0303' for gcc-3.3, etc. -# -# With the -p option, prints the patchlevel as well, for example `029503' for -# gcc-2.95.3, `030301' for gcc-3.3.1, etc. -# - -if [ "$1" = "-p" ] ; then - with_patchlevel=1; - shift; -fi - -compiler="$*" - -if [ ${#compiler} -eq 0 ]; then - echo "Error: No compiler specified." - printf "Usage:\n\t$0 \n" - exit 1 -fi - -MAJOR=$(echo __GNUC__ | $compiler -E -xc - | tail -n 1) -MINOR=$(echo __GNUC_MINOR__ | $compiler -E -xc - | tail -n 1) -if [ "x$with_patchlevel" != "x" ] ; then - PATCHLEVEL=$(echo __GNUC_PATCHLEVEL__ | $compiler -E -xc - | tail -n 1) - printf "%02d%02d%02d\\n" $MAJOR $MINOR $PATCHLEVEL -else - printf "%02d%02d\\n" $MAJOR $MINOR -fi diff --git a/root/package/utils/sysupgrade-helper/src/tools/img2brec.sh b/root/package/utils/sysupgrade-helper/src/tools/img2brec.sh deleted file mode 100644 index 0fcdba27..00000000 --- a/root/package/utils/sysupgrade-helper/src/tools/img2brec.sh +++ /dev/null @@ -1,388 +0,0 @@ -#!/bin/sh - -# This script converts binary files (u-boot.bin) into so called -# bootstrap records that are accepted by Motorola's MC9328MX1/L -# (a.k.a. DragaonBall i.MX) in "Bootstrap Mode" -# -# The code for the SynchFlash programming routines is taken from -# Bootloader\Bin\SyncFlash\programBoot_b.txt contained in -# Motorolas LINUX_BSP_0_3_8.tar.gz -# -# The script could easily extended for AMD flash routines. -# -# 2004-06-23 - steven.scholz@imc-berlin.de - -################################################################################# -# From the posting to the U-Boot-Users mailing list, 23 Jun 2004: -# =============================================================== -# I just hacked a simple script that converts u-boot.bin into a text file -# containg processor init code, SynchFlash programming code and U-Boot data in -# form of so called b-records. -# -# This can be used to programm U-Boot into (Synch)Flash using the Bootstrap -# Mode of the MC9328MX1/L -# -# 0AFE1F3410202E2E2E000000002073756363656564/ -# 0AFE1F44102E0A0000206661696C656420210A0000/ -# 0AFE100000 -# ... -# MX1ADS Sync-flash Programming Utility v0.5 2002/08/21 -# -# Source address (stored in 0x0AFE0000): 0x0A000000 -# Target address (stored in 0x0AFE0004): 0x0C000000 -# Size (stored in 0x0AFE0008): 0x0001A320 -# -# Press any key to start programming ... -# Erasing ... -# Blank checking ... -# Programming ... -# Verifying flash ... succeed. -# -# Programming finished. -# -# So no need for a BDI2000 anymore... ;-) -# -# This is working on my MX1ADS eval board. Hope this could be useful for -# someone. -################################################################################# - -if [ "$#" -lt 1 -o "$#" -gt 2 ] ; then - echo "Usage: $0 infile [outfile]" >&2 - echo " $0 u-boot.bin [u-boot.brec]" >&2 - exit 1 -fi - -if [ "$#" -ge 1 ] ; then - INFILE=$1 -fi - -if [ ! -f $INFILE ] ; then - echo "Error: file '$INFILE' does not exist." >&2 - exit 1 -fi - -FILESIZE=`filesize $INFILE` - -output_init() -{ -echo "\ -******************************************** -* Initialize I/O Pad Driving Strength * -******************************************** -0021B80CC4000003AB -******************************************** -* Initialize SDRAM * -******************************************** -00221000C492120200 ; pre-charge command -08200000E4 ; special read - -00221000C4A2120200 ; auto-refresh command -08000000E4 ; 8 special read -08000000E4 ; 8 special read -08000000E4 ; 8 special read -08000000E4 ; 8 special read -08000000E4 ; 8 special read -08000000E4 ; 8 special read -08000000E4 ; 8 special read -08000000E4 ; 8 special read - -00221000C4B2120200 ; set mode register -08111800E4 ; special read - -00221000C482124200 ; set normal mode - " -} - -output_uboot() -{ -echo "\ -******************************************** -* U-Boot image as bootstrap records * -* will be stored in SDRAM at 0x0A000000 * -******************************************** - " - -cat $INFILE | \ -hexdump -v -e "\"0A0%05.5_ax10\" 16/1 \"%02x\"\"\r\n\"" | \ -tr [:lower:] [:upper:] -} - -output_flashprog() -{ -echo "\ -******************************************** -* Address of arguments to flashProg * -* ---------------------------------------- * -* Source : 0x0A000000 * -* Destination : 0x0C000000 * " - -# get the real size of the U-Boot image -printf "* Size : 0x%08X *\r\n" $FILESIZE -printf "********************************************\r\n" -printf "0AFE0000CC0A0000000C000000%08X\r\n" $FILESIZE - -#;0AFE0000CC0A0000000C00000000006000 - -echo "\ -******************************************** -* Flash Program * -******************************************** -0AFE10001008D09FE5AC0000EA00F0A0E1A42DFE0A -0AFE1010100080FE0A0DC0A0E100D82DE904B04CE2 -0AFE1020109820A0E318309FE5003093E5033082E0 -0AFE103010003093E5013003E2FF3003E20300A0E1 -0AFE10401000A81BE9A01DFE0A0DC0A0E100D82DE9 -0AFE10501004B04CE204D04DE20030A0E10D304BE5 -0AFE1060109820A0E330309FE5003093E5033082E0 -0AFE107010003093E5013903E2000053E3F7FFFF0A -0AFE1080104020A0E310309FE5003093E5032082E0 -0AFE1090100D305BE5003082E500A81BE9A01DFE0A -0AFE10A0100DC0A0E100D82DE904B04CE20000A0E1 -0AFE10B010D7FFFFEB0030A0E1FF3003E2000053E3 -0AFE10C010FAFFFF0A10309FE5003093E5003093E5 -0AFE10D010FF3003E20300A0E100A81BE9A01DFE0A -0AFE10E0100DC0A0E100D82DE904B04CE204D04DE2 -0AFE10F0100030A0E10D304BE50D305BE52332A0E1 -0AFE1100100E304BE50E305BE5090053E30300009A -0AFE1110100E305BE5373083E20E304BE5020000EA -0AFE1120100E305BE5303083E20E304BE50E305BE5 -0AFE1130100300A0E1C3FFFFEB0D305BE50F3003E2 -0AFE1140100E304BE50E305BE5090053E30300009A -0AFE1150100E305BE5373083E20E304BE5020000EA -0AFE1160100E305BE5303083E20E304BE50E305BE5 -0AFE1170100300A0E1B3FFFFEB00A81BE90DC0A0E1 -0AFE11801000D82DE904B04CE21CD04DE210000BE5 -0AFE11901014100BE518200BE588009FE5E50200EB -0AFE11A01010301BE51C300BE514301BE520300BE5 -0AFE11B0100030A0E324300BE524201BE518301BE5 -0AFE11C010030052E10000003A120000EA1C004BE2 -0AFE11D010002090E520104BE2003091E500C093E5 -0AFE11E010043083E2003081E5003092E5042082E2 -0AFE11F010002080E50C0053E10200000A0030A0E3 -0AFE12001028300BE5050000EA24301BE5043083E2 -0AFE12101024300BE5E7FFFFEA0130A0E328300BE5 -0AFE12201028001BE500A81BE9E81EFE0A0DC0A0E1 -0AFE12301000D82DE904B04CE214D04DE210000BE5 -0AFE12401014100BE56C009FE5BA0200EB10301BE5 -0AFE12501018300BE50030A0E31C300BE51C201BE5 -0AFE12601014301BE5030052E10000003A0D0000EA -0AFE12701018304BE2002093E5001092E5042082E2 -0AFE128010002083E5010071E30200000A0030A0E3 -0AFE12901020300BE5050000EA1C301BE5043083E2 -0AFE12A0101C300BE5ECFFFFEA0130A0E320300BE5 -0AFE12B01020001BE500A81BE9001FFE0A0DC0A0E1 -0AFE12C01000D82DE904B04CE224D04DE20130A0E3 -0AFE12D01024300BE5A4229FE58139A0E3023A83E2 -0AFE12E010003082E59820A0E390329FE5003093E5 -0AFE12F010033082E0003093E5023903E2000053E3 -0AFE1300100300001A74229FE58139A0E3033A83E2 -0AFE131010003082E568029FE5860200EBAF36A0E3 -0AFE1320100E3883E2003093E510300BE554029FE5 -0AFE133010800200EB10301BE5233CA0E1FF3003E2 -0AFE1340100300A0E165FFFFEB10301BE52338A0E1 -0AFE135010FF3003E20300A0E160FFFFEB10301BE5 -0AFE1360102334A0E1FF3003E20300A0E15BFFFFEB -0AFE13701010305BE50300A0E158FFFFEB0A00A0E3 -0AFE13801030FFFFEB0D00A0E32EFFFFEBAF36A0E3 -0AFE1390100E3883E2043083E2003093E514300BE5 -0AFE13A010E4019FE5630200EB14301BE5233CA0E1 -0AFE13B010FF3003E20300A0E148FFFFEB14301BE5 -0AFE13C0102338A0E1FF3003E20300A0E143FFFFEB -0AFE13D01014301BE52334A0E1FF3003E20300A0E1 -0AFE13E0103EFFFFEB14305BE50300A0E13BFFFFEB -0AFE13F0100A00A0E313FFFFEB0D00A0E311FFFFEB -0AFE140010AF36A0E30E3883E2083083E2003093E5 -0AFE14101018300BE574019FE5460200EB18301BE5 -0AFE142010233CA0E1FF3003E20300A0E12BFFFFEB -0AFE14301018301BE52338A0E1FF3003E20300A0E1 -0AFE14401026FFFFEB18301BE52334A0E1FF3003E2 -0AFE1450100300A0E121FFFFEB18305BE50300A0E1 -0AFE1460101EFFFFEB0A00A0E3F6FEFFEB0D00A0E3 -0AFE147010F4FEFFEBE6FEFFEB0030A0E1FF3003E2 -0AFE148010000053E30000001A020000EA03FFFFEB -0AFE1490102D004BE5F6FFFFEAF4009FE5250200EB -0AFE14A010FEFEFFEB2D004BE5CD0000EBC00000EB -0AFE14B010E0009FE51F0200EB18301BE528300BE5 -0AFE14C01014301BE52C300BE52C001BE5100100EB -0AFE14D01028301BE5013643E228300BE52C301BE5 -0AFE14E010013683E22C300BE528301BE5000053E3 -0AFE14F010F4FFFFCAAE0000EB14001BE518101BE5 -0AFE15001049FFFFEB0030A0E1FF3003E2000053E3 -0AFE151010E6FFFF0A80009FE5060200EB10001BE5 -0AFE15201014101BE518201BE5D00000EB10001BE5 -0AFE15301014101BE518201BE50FFFFFEB0030A0E1 -0AFE154010FF3003E2000053E30200000A4C009FE5 -0AFE155010F80100EB010000EA44009FE5F50100EB -0AFE156010930000EB3C009FE5F20100EB0000A0E3 -0AFE157010A4FEFFEB0030A0E30300A0E100A81BE9 -0AFE158010A01DFE0AA41DFE0AE01DFE0A0C1EFE0A -0AFE159010381EFE0A641EFE0A181FFE0A281FFE0A -0AFE15A0103C1FFE0A481FFE0AB41EFE0A0DC0A0E1 -0AFE15B01000D82DE904B04CE204D04DE210000BE5 -0AFE15C01010301BE5013043E210300BE5010073E3 -0AFE15D010FAFFFF1A00A81BE90DC0A0E100D82DE9 -0AFE15E01004B04CE208D04DE210000BE510301BE5 -0AFE15F01014300BE514301BE50300A0E100A81BE9 -0AFE1600100DC0A0E100D82DE904B04CE204D04DE2 -0AFE1610102228A0E3012A82E2042082E2E134A0E3 -0AFE162010023883E2033C83E2003082E50333A0E3 -0AFE163010053983E2003093E510300BE500A81BE9 -0AFE1640100DC0A0E100D82DE904B04CE204D04DE2 -0AFE1650102228A0E3012A82E2042082E29134A0E3 -0AFE166010023883E2033C83E2003082E5C136A0E3 -0AFE167010003093E510300BE52228A0E3012A82E2 -0AFE168010042082E2E134A0E3023883E2033C83E2 -0AFE169010003082E50333A0E3073983E20020A0E3 -0AFE16A010002083E52228A0E3012A82E2042082E2 -0AFE16B0108134A0E3023883E2033C83E2003082E5 -0AFE16C0100333A0E3003093E510300BE5CBFFFFEB -0AFE16D01010301BE50300A0E100A81BE90DC0A0E1 -0AFE16E01000D82DE904B04CE208D04DE2D3FFFFEB -0AFE16F0100030A0E110300BE510301BE5023503E2 -0AFE170010000053E30500000A10301BE5073703E2 -0AFE171010000053E30100000A10001BE5ADFFFFEB -0AFE17201010301BE5803003E2000053E30500000A -0AFE17301010301BE51C3003E2000053E30100000A -0AFE17401010001BE5A3FFFFEB10201BE50235A0E3 -0AFE175010803083E2030052E10200001A0130A0E3 -0AFE17601014300BE5010000EA0030A0E314300BE5 -0AFE17701014001BE500A81BE90DC0A0E100D82DE9 -0AFE17801004B04CE204D04DE22228A0E3012A82E2 -0AFE179010042082E29134A0E3023883E2033C83E2 -0AFE17A010003082E5C136A0E3003093E510300BE5 -0AFE17B01000A81BE90DC0A0E100D82DE904B04CE2 -0AFE17C010ECFFFFEB2228A0E3012A82E2042082E2 -0AFE17D0108134A0E3023883E2033C83E2003082E5 -0AFE17E01000A81BE90DC0A0E100D82DE904B04CE2 -0AFE17F01004D04DE22228A0E3012A82E2042082E2 -0AFE1800102238A0E3013A83E2043083E2003093E5 -0AFE181010023183E3003082E52228A0E3012A82E2 -0AFE1820102238A0E3013A83E2003093E5023183E3 -0AFE183010003082E5FA0FA0E35BFFFFEB2228A0E3 -0AFE184010012A82E2042082E2B134A0E3023883E2 -0AFE185010033C83E2003082E50333A0E3233983E2 -0AFE186010033B83E2003093E510300BE500A81BE9 -0AFE1870100DC0A0E100D82DE904B04CE21CD04DE2 -0AFE18801010000BE514100BE518200BE50030A0E3 -0AFE1890101C300BE51C201BE518301BE5030052E1 -0AFE18A0100000003A190000EAB2FFFFEB2228A0E3 -0AFE18B010012A82E2042082E2F134A0E3023883E2 -0AFE18C010033C83E2003082E514201BE51C301BE5 -0AFE18D010031082E010201BE51C301BE5033082E0 -0AFE18E010003093E5003081E57BFFFFEB0030A0E1 -0AFE18F010FF3003E2000053E3FAFFFF0AACFFFFEB -0AFE1900101C301BE5043083E21C300BE5E0FFFFEA -0AFE19101000A81BE90DC0A0E100D82DE904B04CE2 -0AFE1920100CD04DE210000BE52228A0E3012A82E2 -0AFE193010042082E28134A0E3023883E2033C83E2 -0AFE194010003082E510301BE5003093E514300BE5 -0AFE1950102228A0E3012A82E2042082E29134A0E3 -0AFE196010023883E2033C83E2003082E510301BE5 -0AFE197010003093E518300BE52228A0E3012A82E2 -0AFE198010042082E2E134A0E3023883E2033C83E2 -0AFE199010003082E50229A0E310301BE5032082E0 -0AFE19A0100030A0E3003082E52228A0E3012A82E2 -0AFE19B010042082E28134A0E3023883E2033C83E2 -0AFE19C010003082E510201BE50D3AA0E3D03083E2 -0AFE19D010033883E1003082E53FFFFFEB0030A0E1 -0AFE19E010FF3003E2000053E3FAFFFF0A70FFFFEB -0AFE19F01000A81BE90DC0A0E100D82DE904B04CE2 -0AFE1A00105CFFFFEB2228A0E3012A82E2042082E2 -0AFE1A1010E134A0E3023883E2033C83E2003082E5 -0AFE1A20100333A0E3033983E20020A0E3002083E5 -0AFE1A30102228A0E3012A82E2042082E28134A0E3 -0AFE1A4010023883E2033C83E2003082E50323A0E3 -0AFE1A5010032982E20339A0E3C03083E2033883E1 -0AFE1A6010003082E500A81BE90DC0A0E100D82DE9 -0AFE1A701004B04CE23FFFFFEB2228A0E3012A82E2 -0AFE1A8010042082E2E134A0E3023883E2033C83E2 -0AFE1A9010003082E50333A0E30A3983E20020A0E3 -0AFE1AA010002083E52228A0E3012A82E2042082E2 -0AFE1AB0108134A0E3023883E2033C83E2003082E5 -0AFE1AC0100323A0E30A2982E20339A0E3C03083E2 -0AFE1AD010033883E1003082E500A81BE90DC0A0E1 -0AFE1AE01000D82DE904B04CE28729A0E3222E82E2 -0AFE1AF0108739A0E3223E83E2003093E51E3CC3E3 -0AFE1B0010003082E58729A0E38E2F82E28739A0E3 -0AFE1B10108E3F83E2003093E51E3CC3E3003082E5 -0AFE1B20108139A0E3823D83E20520A0E3002083E5 -0AFE1B30108129A0E3822D82E2042082E20139A0E3 -0AFE1B4010273083E2003082E58139A0E3823D83E2 -0AFE1B50100C3083E20120A0E3002083E58129A0E3 -0AFE1B6010822D82E2102082E22A3DA0E3013083E2 -0AFE1B7010003082E58139A0E3823D83E2243083E2 -0AFE1B80100F20A0E3002083E58139A0E3823D83E2 -0AFE1B9010283083E28A20A0E3002083E58139A0E3 -0AFE1BA010823D83E22C3083E20820A0E3002083E5 -0AFE1BB01000A81BE90DC0A0E100D82DE904B04CE2 -0AFE1BC0108139A0E3823D83E2183083E2003093E5 -0AFE1BD010013003E2FF3003E20300A0E100A81BE9 -0AFE1BE0100DC0A0E100D82DE904B04CE204D04DE2 -0AFE1BF0100030A0E10D304BE58139A0E3823D83E2 -0AFE1C0010183083E2003093E5013903E2000053E3 -0AFE1C1010F8FFFF0A8139A0E3813D83E20D205BE5 -0AFE1C2010002083E50D305BE50A0053E30A00001A -0AFE1C30108139A0E3823D83E2183083E2003093E5 -0AFE1C4010013903E2000053E3F8FFFF0A8139A0E3 -0AFE1C5010813D83E20D20A0E3002083E500A81BE9 -0AFE1C60100DC0A0E100D82DE904B04CE20000A0E1 -0AFE1C7010CFFFFFEB0030A0E1FF3003E2000053E3 -0AFE1C8010FAFFFF0A8139A0E3023A83E2003093E5 -0AFE1C9010FF3003E20300A0E100A81BE90DC0A0E1 -0AFE1CA01000D82DE904B04CE204D04DE20030A0E1 -0AFE1CB0100D304BE50D305BE52332A0E10E304BE5 -0AFE1CC0100E305BE5090053E30300009A0E305BE5 -0AFE1CD010373083E20E304BE5020000EA0E305BE5 -0AFE1CE010303083E20E304BE50E305BE50300A0E1 -0AFE1CF010BAFFFFEB0D305BE50F3003E20E304BE5 -0AFE1D00100E305BE5090053E30300009A0E305BE5 -0AFE1D1010373083E20E304BE5020000EA0E305BE5 -0AFE1D2010303083E20E304BE50E305BE50300A0E1 -0AFE1D3010AAFFFFEB00A81BE90DC0A0E100D82DE9 -0AFE1D401004B04CE204D04DE210000BE510301BE5 -0AFE1D50100030D3E5000053E30000001A080000EA -0AFE1D601010104BE2003091E50320A0E10020D2E5 -0AFE1D7010013083E2003081E50200A0E197FFFFEB -0AFE1D8008F1FFFFEA00A81BE9 -0AFE1DA4100A0D4D58314144532053796E632D666C -0AFE1DB4106173682050726F6772616D6D696E6720 -0AFE1DC4105574696C6974792076302E3520323030 -0AFE1DD410322F30382F32310A0D000000536F7572 -0AFE1DE41063652061646472657373202873746F72 -0AFE1DF410656420696E2030783041464530303030 -0AFE1E0410293A2030780000005461726765742061 -0AFE1E1410646472657373202873746F7265642069 -0AFE1E24106E2030783041464530303034293A2030 -0AFE1E34107800000053697A652020202020202020 -0AFE1E44102020202873746F72656420696E203078 -0AFE1E54103041464530303038293A203078000000 -0AFE1E6410507265737320616E79206B657920746F -0AFE1E74102073746172742070726F6772616D6D69 -0AFE1E84106E67202E2E2E00000A0D45726173696E -0AFE1E94106720666C617368202E2E2E000A0D5072 -0AFE1EA4106F6772616D6D696E67202E2E2E000000 -0AFE1EB4100A0D50726F6772616D6D696E67206669 -0AFE1EC4106E69736865642E0A0D50726573732027 -0AFE1ED410612720746F20636F6E74696E7565202E -0AFE1EE4102E2E2E000A0D566572696679696E6720 -0AFE1EF410666C617368202E2E2E0000000A0D426C -0AFE1F0410616E6B20636865636B696E67202E2E2E -0AFE1F1410000000000A45726173696E67202E2E2E -0AFE1F2410000000000A50726F6772616D6D696E67 -0AFE1F3410202E2E2E000000002073756363656564 -0AFE1F44102E0A0000206661696C656420210A0000 -0AFE100000 - " -} - -######################################################### - -if [ "$#" -eq 2 ] ; then - output_init > $2 - output_uboot >> $2 - output_flashprog >> $2 -else - output_init; - output_uboot; - output_flashprog; -fi diff --git a/root/package/utils/sysupgrade-helper/src/tools/jtagconsole b/root/package/utils/sysupgrade-helper/src/tools/jtagconsole deleted file mode 100644 index d404fac5..00000000 --- a/root/package/utils/sysupgrade-helper/src/tools/jtagconsole +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/sh - -usage() { - ( - echo "Usage: $0 [board IP] [board port]" - echo "" - echo "If IP is not specified, 'localhost' will be used" - echo "If port is not specified, '2001' will be used" - [ -z "$*" ] && exit 0 - echo "" - echo "ERROR: $*" - exit 1 - ) 1>&2 - exit $? -} - -while [ -n "$1" ] ; do - case $1 in - -h|--help) usage;; - --) break;; - -*) usage "Invalid option $1";; - *) break;; - esac - shift -done - -ip=${1:-localhost} -port=${2:-2001} - -if [ -z "${ip}" ] || [ -n "$3" ] ; then - usage "Invalid number of arguments" -fi - -trap "stty icanon echo opost intr ^C" 0 2 3 5 10 13 15 -echo "NOTE: the interrupt signal (normally ^C) has been remapped to ^T" - -stty -icanon -echo -opost intr ^T -nc ${ip} ${port} -exit 0 diff --git a/root/package/utils/sysupgrade-helper/src/tools/netconsole b/root/package/utils/sysupgrade-helper/src/tools/netconsole deleted file mode 100644 index c8109bb0..00000000 --- a/root/package/utils/sysupgrade-helper/src/tools/netconsole +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/sh - -usage() { - ( - echo "Usage: $0 [board port]" - echo "" - echo "If port is not specified, '6666' will be used" - [ -z "$*" ] && exit 0 - echo "" - echo "ERROR: $*" - exit 1 - ) 1>&2 - exit $? -} - -while [ -n "$1" ] ; do - case $1 in - -h|--help) usage;; - --) break;; - -*) usage "Invalid option $1";; - *) break;; - esac - shift -done - -ip=$1 -port=${2:-6666} - -if [ -z "${ip}" ] || [ -n "$3" ] ; then - usage "Invalid number of arguments" -fi - -for nc in netcat nc ; do - type ${nc} >/dev/null 2>&1 && break -done - -trap "stty icanon echo intr ^C" 0 2 3 5 10 13 15 -echo "NOTE: the interrupt signal (normally ^C) has been remapped to ^T" - -stty -icanon -echo intr ^T -( -if type ncb 2>/dev/null ; then - # see if ncb is in $PATH - exec ncb ${port} - -elif [ -x ${0%/*}/ncb ] ; then - # maybe it's in the same dir as the netconsole script - exec ${0%/*}/ncb ${port} - -else - # blah, just use regular netcat - while ${nc} -u -l -p ${port} < /dev/null ; do - : - done -fi -) & -pid=$! -${nc} -u ${ip} ${port} -kill ${pid} 2>/dev/null diff --git a/root/package/utils/sysupgrade-helper/src/tools/pack.py b/root/package/utils/sysupgrade-helper/src/tools/pack.py deleted file mode 100644 index ccb269aa..00000000 --- a/root/package/utils/sysupgrade-helper/src/tools/pack.py +++ /dev/null @@ -1,1854 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. -# -""" -Script to create a U-Boot flashable multi-image blob. - -This script creates a multi-image blob, from a bunch of images, and -adds a U-Boot shell script to the blob, that can flash the images from -within U-Boot. The procedure to use this script is listed below. - - 1. Create an images folder. Ex: my-pack - - 2. Copy all the images to be flashed into the folder. - - 3. Copy the partition MBN file into the folder. The file should be - named 'partition.mbn'. This is used to determine the offsets for - each of the named partitions. - - 4. Create a flash configuration file, specifying the images be - flashed, and the partition in which the images is to be - flashed. The flash configuration file can be specified using the - -f option, default is flash.conf. - - 5. Invoke 'pack' with the folder name as argument, pass flash - parameters as arguments if required. A single image file will - be created, out side the images folder, with .img suffix. Ex: - my-pack.img - - 6. Transfer the file into a valid SDRAM address and invoke the - following U-Boot command to flash the images. Replace 0x41000000, - with address location where the image has been loaded. The script - expects the variable 'imgaddr' to be set. - - u-boot> imgaddr=0x41000000 source $imgaddr:script - -Host-side Pre-req - - * Python >= 2.6 - * ordereddict >= 1.1 (for Python 2.6) - * mkimage >= 2012.07 - * dtc >= 1.2.0 - -Target-side Pre-req - -The following U-Boot config macros should be enabled, for the -generated flashing script to work. - - * CONFIG_FIT -- FIT image format support - * CONFIG_SYS_HUSH_PARSER -- bash style scripting support - * CONFIG_SYS_NULLDEV -- redirecting command output support - * CONFIG_CMD_XIMG -- extracting sub-images support - * CONFIG_CMD_NAND -- NAND Flash commands support - * CONFIG_CMD_NAND_YAFFS -- NAND YAFFS2 write support - * CONFIG_CMD_SF -- SPI Flash commands support -""" - -from ConfigParser import ConfigParser -from ConfigParser import Error as ConfigParserError -from os.path import getsize -from getopt import getopt -from getopt import GetoptError -from collections import namedtuple -from string import Template -from unittest import TestCase -from tempfile import mkdtemp -from shutil import rmtree - -import os -import sys -import os.path -import subprocess -import struct -import re -import hashlib - -version = "1.1" - -# -# Python 2.6 and earlier did not have OrderedDict use the backport -# from ordereddict package. If that is not available report error. -# -try: - from collections import OrderedDict -except ImportError: - try: - from ordereddict import OrderedDict - except ImportError: - print "error: this script requires the 'ordereddict' class." - print "Try 'pip install --user ordereddict'" - print "Or 'easy_install --user ordereddict'" - sys.exit(1) - -__all__ = [] - -KB = 1024 -MB = 1024 * KB - -def error(msg, ex=None): - """Print an error message and exit. - - msg -- string, the message to print - ex -- exception, the associate exception, if any - """ - - sys.stderr.write("pack: %s" % msg) - if ex != None: sys.stderr.write(": %s" % str(ex)) - sys.stderr.write("\n") - sys.exit(1) - -FlashInfo = namedtuple("FlashInfo", "type pagesize blocksize chipsize") -ImageInfo = namedtuple("ProgInfo", "name filename type") -PartInfo = namedtuple("PartInfo", "name offset length") - -def roundup(value, roundto): - """Return the next largest multiple of 'roundto'.""" - - return ((value + roundto - 1) // roundto) * roundto - -class GPT(object): - GPTheader = namedtuple("GPTheader", "signature revision header_size" - " crc32 current_lba backup_lba first_usable_lba" - " last_usable_lba disk_guid start_lba_part_entry" - " num_part_entry part_entry_size part_crc32") - GPT_SIGNATURE = 'EFI PART' - GPT_REVISION = '\x00\x00\x01\x00' - GPT_HEADER_SIZE = 0x5C - GPT_HEADER_FMT = "<8s4sLL4xQQQQ16sQLLL" - - GPTtable = namedtuple("GPTtable", "part_type unique_guid first_lba" - " last_lba attribute_flag part_name") - GPT_TABLE_FMT = "<16s16sQQQ72s" - - def __init__(self, filename, pagesize, blocksize, chipsize): - self.filename = filename - self.pagesize = pagesize - self.blocksize = blocksize - self.chipsize = chipsize - self.__partitions = OrderedDict() - - def __validate_and_read_parts(self, part_fp): - """Validate the GPT and read the partition""" - part_fp.seek(self.blocksize, os.SEEK_SET) - gptheader_str = part_fp.read(struct.calcsize(GPT.GPT_HEADER_FMT)) - gptheader = struct.unpack(GPT.GPT_HEADER_FMT, gptheader_str) - gptheader = GPT.GPTheader._make(gptheader) - - if gptheader.signature != GPT.GPT_SIGNATURE: - error("Invalid signature") - - if gptheader.revision != GPT.GPT_REVISION: - error("Unsupported GPT Revision") - - if gptheader.header_size != GPT.GPT_HEADER_SIZE: - error("Invalid Header size") - - # Adding GPT partition info. This has to be flashed first. - # GPT Header starts at LBA1 so (current_lba -1) will give the - # starting of primary GPT. - # blocksize will equal to gptheader.first_usuable_lba - current_lba + 1 - - name = "0:GPT" - block_start = gptheader.current_lba - 1 - block_count = gptheader.first_usable_lba - gptheader.current_lba + 1 - part_info = PartInfo(name, block_start, block_count) - self.__partitions[name] = part_info - - part_fp.seek(2 * self.blocksize, os.SEEK_SET) - - for i in range(gptheader.num_part_entry): - gpt_table_str = part_fp.read(struct.calcsize(GPT.GPT_TABLE_FMT)) - gpt_table = struct.unpack(GPT.GPT_TABLE_FMT, gpt_table_str) - gpt_table = GPT.GPTtable._make(gpt_table) - - block_start = gpt_table.first_lba - block_count = gpt_table.last_lba - gpt_table.first_lba + 1 - - part_name = gpt_table.part_name.strip(chr(0)) - name = part_name.replace('\0','') - part_info = PartInfo(name, block_start, block_count) - self.__partitions[name] = part_info - - # Adding the GPT Backup partition. - # GPT header backup_lba gives block number where the GPT backup header will be. - # GPT Backup header will start from offset of 32 blocks before - # the GPTheader.backup_lba. Backup GPT size is 33 blocks. - name = "0:GPTBACKUP" - block_start = gptheader.backup_lba - 32 - block_count = 33 - part_info = PartInfo(name, block_start, block_count) - self.__partitions[name] = part_info - - def get_parts(self): - """Returns a list of partitions present in the GPT.""" - - try: - with open(self.filename, "r") as part_fp: - self.__validate_and_read_parts(part_fp) - except IOError, e: - error("error opening %s" % self.filename, e) - - return self.__partitions - -class MIBIB(object): - Header = namedtuple("Header", "magic1 magic2 version age") - HEADER_FMT = " 0: - if yaffs: - self.append("nand write.yaffs $fileaddr 0x%08x 0x%08x" - % (offset, size)) - else: - size = roundup(size, self.pagesize) - self.append("nand write $fileaddr 0x%08x 0x%08x" % (offset, size)) - - def switch_layout(self, layout): - """Generate code, to switch between sbl/linux layouts.""" - - self.append("ipq_nand %s" % layout) - -class NorScript(FlashScript): - """Class for creating NAND flash scripts.""" - - def __init__(self, flinfo): - FlashScript.__init__(self, flinfo) - - def erase(self, offset, size): - """Generate code, to erase the specified partition.""" - - size = roundup(size, self.blocksize) - self.append("sf erase 0x%08x +0x%08x" % (offset, size)) - - def write(self, offset, size, yaffs): - """Generate code, to write to a partition.""" - - if size > 0: - self.append("sf write $fileaddr 0x%08x 0x%08x" % (offset, size)) - - def nand_write(self, offset, part_size, img_size): - """Handle the NOR + NAND case - All binaries upto HLOS will go to NOR and Root FS will go to NAND - Assumed all nand page sizes are less than are equal to 8KB - """ - self.append("nand device 0 && nand erase 0x%08x 0x%08x" % (offset, part_size)) - if img_size > 0: - self.append("nand write $fileaddr 0x%08x 0x%08x" % (offset, img_size)) - - def switch_layout(self, layout): - pass - -class EmmcScript(FlashScript): - """Class for creating EMMC scripts.""" - - def __init__(self, flinfo): - FlashScript.__init__(self, flinfo) - - def erase(self, offset, size): - """Generate code, to erase the specified partition.""" - - self.append("mmc erase 0x%08x %x" % (offset, size)) - - def write(self, offset, size, yaffs): - """Generate code, to write to a partition.""" - if size > 0: - size = roundup(size, self.blocksize) - blk_cnt = size / self.blocksize - self.append("mmc write $fileaddr 0x%08x %x" % (offset, blk_cnt)) - - def switch_layout(self, layout): - pass - -its_tmpl = Template(""" -/dts-v1/; - -/ { - description = "${desc}"; - images { -${images} - }; -}; -""") - -its_image_tmpl = Template(""" - ${name} { - description = "${desc}"; - data = /incbin/("./${fname}"); - type = "${imtype}"; - arch = "arm"; - compression = "none"; - hash@1 { algo = "crc32"; }; - }; -""") - - -def sha1(message): - """Returns SHA1 digest in hex format of the message.""" - - m = hashlib.sha1() - m.update(message) - return m.hexdigest() - - -class Pack(object): - """Class to create a flashable, multi-image blob. - - Combine multiple images present in a directory, and generate a - U-Boot script to flash the images. - """ - # The maximum rootfs size is 64MB - norplusnand_rootfs_img_size = (64 * 1024 * 1024) - - def __init__(self): - self.flinfo = None - self.images_dname = None - self.ipq_nand = None - self.partitions = {} - - self.fconf_fname = None - self.scr_fname = None - self.its_fname = None - self.img_fname = None - - def __get_yaffs(self, info, section): - """Get the yaffs flag for a section. - - info -- ConfigParser object, containing image flashing info - section -- section to check if yaffs flag is set - """ - try: - yaffs = info.get(section, "yaffs") - if yaffs.lower() in ["0", "no"]: - yaffs = False - elif yaffs.lower() in ["1", "yes"]: - yaffs = True - else: - error("invalid value for 'yaffs' in '%s'" % section) - except ConfigParserError, e: - yaffs = False - - if self.flinfo.type == "nor" and yaffs == True: - error("yaffs cannot be used with NOR flash type") - - return yaffs - - def __get_layout(self, info, section): - """Get the layout for a section. - - info -- ConfigParser object, containing image flashing info - section - section to retreive the layout from - """ - try: - layout = info.get(section, "layout") - except ConfigParserError, e: - layout = None - - if self.ipq_nand and layout == None: - error("layout not specified for IPQ device") - - if not self.ipq_nand and layout != None: - error("layout specified for a non IPQ device") - - if layout not in ("sbl", "linux", None): - error("invalid layout in '%s'" % section) - - return layout - - def __get_machid(self, info, section): - """Get the machid for a section. - - info -- ConfigParser object, containing image flashing info - section -- section to retreive the machid from - """ - try: - machid = info.get(section, "if_machid") - machid = int(machid, 0) - machid = "%x" % machid - except ConfigParserError, e: - machid = None - except ValueError, e: - error("invalid value for machid, should be integer") - - return machid - - def __get_img_size(self, filename): - """Get the size of the image to be flashed - - filaneme -- string, filename of the image to be flashed - """ - - if filename.lower() == "none": - return 0 - try: - return getsize(os.path.join(self.images_dname, filename)) - except OSError, e: - error("error getting image size '%s'" % filename, e) - - def __get_part_info(self, partition): - """Return partition info for the specified partition. - - partition -- string, partition name - """ - try: - return self.partitions[partition] - except KeyError, e: - return None - - def __gen_flash_script(self, info, script, flinfo): - """Generate the script to flash the images. - - info -- ConfigParser object, containing image flashing info - script -- Script object, to append commands to - """ - count = 0 - - for section in info.sections(): - try: - filename = info.get(section, "filename") - partition = info.get(section, "partition") - include = info.get(section, "include") - except ConfigParserError, e: - error("error getting image info in section '%s'" % section, e) - - if include.lower() in ["0", "no"]: - continue - - machid = self.__get_machid(info, section) - layout = self.__get_layout(info, section) - yaffs = self.__get_yaffs(info, section) - - img_size = self.__get_img_size(filename) - part_info = self.__get_part_info(partition) - - if self.flinfo.type == 'nand': - size = roundup(img_size, flinfo.pagesize) - tr = ' | tr \"\\000\" \"\\377\"' - - if self.flinfo.type == 'emmc': - size = roundup(img_size, flinfo.blocksize) - tr = '' - - if ((self.flinfo.type == 'nand' or self.flinfo.type == 'emmc') and (size != img_size)): - pad_size = size - img_size - filename_abs = os.path.join(self.images_dname, filename) - filename_abs_pad = filename_abs + ".padded" - cmd = 'cat %s > %s' % (filename_abs, filename_abs_pad) - ret = subprocess.call(cmd, shell=True) - if ret != 0: - error("failed to copy image") - cmd = 'dd if=/dev/zero count=1 bs=%s %s >> %s' % (pad_size, tr, filename_abs_pad) - cmd = '(' + cmd + ') 1>/dev/null 2>/dev/null' - ret = subprocess.call(cmd, shell=True) - if ret != 0: - error("failed to create padded image from script") - - if self.flinfo.type != "emmc": - if part_info == None: - if self.flinfo.type == 'norplusnand': - if count > 2: - error("More than 2 NAND images for NOR+NAND is not allowed") - elif img_size > part_info.length: - error("img size is larger than part. len in '%s'" % section) - else: - if part_info != None: - if (img_size > 0): - if img_size > (part_info.length * self.flinfo.blocksize): - error("img size is larger than part. len in '%s'" % section) - - if part_info == None and self.flinfo.type != 'norplusnand': - continue - - if machid: - script.start_if("machid", machid) - - script.start_activity("Flashing %s:" % section) - if self.ipq_nand: script.switch_layout(layout) - if img_size > 0: - if ((self.flinfo.type == 'nand' or self.flinfo.type == 'emmc') and (size != img_size)): - filename_pad = filename + ".padded" - script.imxtract(section + "-" + sha1(filename_pad)) - else: - script.imxtract(section + "-" + sha1(filename)) - - if part_info == None: - if self.flinfo.type == 'norplusnand': - offset = count * Pack.norplusnand_rootfs_img_size - part_size = Pack.norplusnand_rootfs_img_size - script.nand_write(offset, part_size, img_size) - count = count + 1 - else: - offset = part_info.offset - script.erase(offset, part_info.length) - script.write(offset, img_size, yaffs) - script.finish_activity() - - if machid: - script.end_if() - - if part_info == None and self.flinfo.type != 'norplusnand': - print "Flash type is norplusemmc" - else: - script.end() - - def __gen_script(self, script_fp, info_fp, script, images, flinfo): - """Generate the script to flash the multi-image blob. - - script_fp -- file object, to write script to - info_fp -- file object, to read flashing information from - script -- Script object, to append the commands to - images -- list of ImageInfo, appended to, based on images in config - """ - try: - info = ConfigParser({"include": "yes"}) - info.readfp(info_fp) - except ConfigParserError, e: - error("error parsing info file '%s'" % self.fconf_fname, e) - - self.__gen_flash_script(info, script, flinfo) - - for section in info.sections(): - if info.get(section, "include").lower() in ["0", "no"]: - continue - - partition = info.get(section, "partition") - part_info = self.__get_part_info(partition) - - if part_info == None and self.flinfo.type != 'norplusnand': - continue - - filename = info.get(section, "filename") - if self.flinfo.type == 'nand': - img_size = self.__get_img_size(filename) - size = roundup(img_size, flinfo.pagesize) - if ( size != img_size ): - filename = filename + ".padded" - if self.flinfo.type == 'emmc': - img_size = self.__get_img_size(filename) - size = roundup(img_size, flinfo.blocksize) - if ( size != img_size ): - filename = filename + ".padded" - image_info = ImageInfo(section + "-" + sha1(filename), - filename, "firmware") - if filename.lower() != "none": - if image_info not in images: - images.append(image_info) - - def __its_escape(self, string): - """Return string with ITS special characters escaped. - - string -- string to be escape. - - String in ITS files, consider 'slash' as special - character. Escape them by prefixing them with a slash. - """ - return string.replace("\\", "\\\\") - - def __mkimage(self, images): - """Create the multi-image blob. - - images -- list of ImageInfo, containing images to be part of the blob - """ - try: - its_fp = open(self.its_fname, "wb") - except IOError, e: - error("error opening its file '%s'" % self.its_fname, e) - - desc = "Flashing %s %x %x" - desc = desc % (self.flinfo.type, self.flinfo.pagesize, - self.flinfo.blocksize) - - image_data = [] - for (section, fname, imtype) in images: - fname = self.__its_escape(fname) - subs = dict(name=section, desc=fname, fname=fname, imtype=imtype) - image_data.append(its_image_tmpl.substitute(subs)) - - image_data = "".join(image_data) - its_data = its_tmpl.substitute(desc=desc, images=image_data) - - its_fp.write(its_data) - its_fp.close() - - try: - cmd = ["mkimage", "-f", self.its_fname, self.img_fname] - ret = subprocess.call(cmd) - if ret != 0: - error("failed to create u-boot image from script") - except OSError, e: - error("error executing mkimage", e) - - def __create_fnames(self): - """Populate the filenames.""" - - self.scr_fname = os.path.join(self.images_dname, "flash.scr") - self.its_fname = os.path.join(self.images_dname, "flash.its") - - def __gen_board_script(self, board_section, machid, flinfo, - part_fname, fconf_fname, images): - """Generate the flashing script for one board. - - board_section -- string, board section in board config file - machid -- string, board machine ID in hex format - flinfo -- FlashInfo object, contains board specific flash params - part_fname -- string, partition file specific to the board - fconf_fname -- string, flash config file specific to the board - images -- list of ImageInfo, append images used by the board here - """ - script_fp = open(self.scr_fname, "a") - - try: - fconf_fp = open(fconf_fname) - except IOError, e: - error("error opening flash config file '%s'" % fconf_fname, e) - - if flinfo.type != "emmc": - mibib = MIBIB(part_fname, flinfo.pagesize, flinfo.blocksize, - flinfo.chipsize) - self.partitions = mibib.get_parts() - else: - gpt = GPT(part_fname, flinfo.pagesize, flinfo.blocksize, flinfo.chipsize) - self.partitions = gpt.get_parts() - - self.flinfo = flinfo - if flinfo.type == "nand": - self.ipq_nand = True - script = NandScript(flinfo, self.ipq_nand) - elif flinfo.type == "nor" or flinfo.type == "norplusnand": - self.ipq_nand = False - script = NorScript(flinfo) - elif flinfo.type == "emmc": - self.ipq_nand = False - script = EmmcScript(flinfo) - else: - error("error, flash type unspecified.") - - script.start_if("machid", machid) - self.__gen_script(script_fp, fconf_fp, script, images, flinfo) - script.end_if() - - try: - script_fp.write(script.dumps()) - except IOError, e: - error("error writing to script '%s'" % script_fp.name, e) - - script_fp.close() - - def __process_board_flash_emmc(self, ftype, board_section, machid, images): - """Extract board info from config and generate the flash script. - - ftype -- string, flash type 'emmc' - board_section -- string, board section in config file - machid -- string, board machine ID in hex format - images -- list of ImageInfo, append images used by the board here - """ - - pagesize_param = "%s_pagesize" % ftype - blocksize_param = "%s_blocksize" % "emmc" - blocks_per_chip_param = "%s_total_blocks" % "emmc" - part_fname_param = "%s_partition_mbn" % ftype - fconf_fname_param = "%s_flash_conf" % ftype - - if ftype == "norplusemmc": - part_fname_param = "%s_gpt_bin" % ftype - - try: - pagesize = int(self.bconf.get(board_section, pagesize_param)) - blocksize = int(self.bconf.get(board_section, blocksize_param)) - chipsize = int(self.bconf.get(board_section, - blocks_per_chip_param)) - except ConfigParserError, e: - error("missing flash info in section '%s'" % board_section, e) - except ValueError, e: - error("invalid flash info in section '%s'" % board_section, e) - - if ftype == "norplusemmc": - ftype = "emmc" - - flinfo = FlashInfo(ftype, pagesize, blocksize, chipsize) - - try: - part_fname = self.bconf.get(board_section, part_fname_param) - if not os.path.isabs(part_fname): - part_fname = os.path.join(self.images_dname, part_fname) - except ConfigParserError, e: - error("missing partition file in section '%s'" % board_section, e) - - try: - fconf_fname = self.bconf.get(board_section, fconf_fname_param) - if not os.path.isabs(fconf_fname): - fconf_fname = os.path.join(self.images_dname, fconf_fname) - except ConfigParserError, e: - error("missing NAND config in section '%s'" % board_section, e) - - self.__gen_board_script(board_section, machid, flinfo, - part_fname, fconf_fname, images) - - def __process_board_flash(self, ftype, board_section, machid, images): - """Extract board info from config and generate the flash script. - - ftype -- string, flash type 'nand' or 'nor' or 'emmc' or 'norplusnand' - board_section -- string, board section in config file - machid -- string, board machine ID in hex format - images -- list of ImageInfo, append images used by the board here - """ - - pagesize_param = "%s_pagesize" % ftype - pages_per_block_param = "%s_pages_per_block" % ftype - blocks_per_chip_param = "%s_total_blocks" % ftype - part_fname_param = "%s_partition_mbn" % ftype - fconf_fname_param = "%s_flash_conf" % ftype - - if ftype == "norplusnand" or ftype == "norplusemmc": - pagesize_param = "%s_pagesize" % "nor" - pages_per_block_param = "%s_pages_per_block" % "nor" - blocks_per_chip_param = "%s_total_blocks" % "nor" - - try: - pagesize = int(self.bconf.get(board_section, pagesize_param)) - pages_per_block = int(self.bconf.get(board_section, - pages_per_block_param)) - blocks_per_chip = int(self.bconf.get(board_section, - blocks_per_chip_param)) - except ConfigParserError, e: - error("missing flash info in section '%s'" % board_section, e) - except ValueError, e: - error("invalid flash info in section '%s'" % board_section, e) - - blocksize = pages_per_block * pagesize - chipsize = blocks_per_chip * blocksize - if ftype == "norplusemmc": - ftype = "nor" - - flinfo = FlashInfo(ftype, pagesize, blocksize, chipsize) - - try: - part_fname = self.bconf.get(board_section, part_fname_param) - if not os.path.isabs(part_fname): - part_fname = os.path.join(self.images_dname, part_fname) - except ConfigParserError, e: - error("missing partition file in section '%s'" % board_section, e) - - try: - fconf_fname = self.bconf.get(board_section, fconf_fname_param) - if not os.path.isabs(fconf_fname): - fconf_fname = os.path.join(self.images_dname, fconf_fname) - except ConfigParserError, e: - error("missing NAND config in section '%s'" % board_section, e) - - self.__gen_board_script(board_section, machid, flinfo, - part_fname, fconf_fname, images) - - def __process_board(self, board_section, images): - try: - machid = int(self.bconf.get(board_section, "machid"), 0) - machid = "%x" % machid - except ConfigParserError, e: - error("missing machid in section '%s'" % board_section, e) - except ValueError, e: - error("invalid machid in section '%s'" % board_section, e) - - try: - available = self.bconf.get(board_section, "nand_available") - if available == "true" and self.flash_type == "nand": - self.__process_board_flash("nand", board_section, machid, images) - except ConfigParserError, e: - error("error getting board info in section '%s'" % board_section, e) - - try: - available = self.bconf.get(board_section, "nor_available") - if available == "true" and self.flash_type == "nor": - self.__process_board_flash("nor", board_section, machid, images) - except ConfigParserError, e: - error("error getting board info in section '%s'" % board_section, e) - - try: - available = self.bconf.get(board_section, "emmc_available") - if available == "true" and self.flash_type == "emmc": - self.__process_board_flash_emmc("emmc", board_section, machid, images) - except ConfigParserError, e: - error("error getting board info in section '%s'" % board_section, e) - - try: - available = self.bconf.get(board_section, "norplusnand_available") - if available == "true" and self.flash_type == "norplusnand": - self.__process_board_flash("norplusnand", board_section, machid, images) - except ConfigParserError, e: - error("error getting board info in section '%s'" % board_section, e) - - try: - available = self.bconf.get(board_section, "norplusemmc_available") - if available == "true" and self.flash_type == "norplusemmc": - self.__process_board_flash("norplusemmc", board_section, machid, images) - self.__process_board_flash_emmc("norplusemmc", board_section, machid, images) - except ConfigParserError, e: - error("error getting board info in section '%s'" % board_section, e) - - - - def main_bconf(self, flash_type, images_dname, out_fname, brdconfig): - """Start the packing process, using board config. - - flash_type -- string, indicates flash type, 'nand' or 'nor' or 'emmc' or 'norplusnand' - images_dname -- string, name of images directory - out_fname -- string, output file path - """ - self.flash_type = flash_type - self.images_dname = images_dname - self.img_fname = out_fname - - self.__create_fnames() - - try: - os.unlink(self.scr_fname) - except OSError, e: - pass - - try: - bconf_fname = os.path.join(images_dname, brdconfig) - bconf_fp = open(bconf_fname) - self.bconf = ConfigParser() - self.bconf.readfp(bconf_fp) - bconf_fp.close() - except IOError, e: - error("error reading board configuration file", e) - except ConfigParserError, e: - error("error parsing board configuration file", e) - - images = [] - for section in self.bconf.sections(): - self.__process_board(section, images) - - images.insert(0, ImageInfo("script", "flash.scr", "script")) - self.__mkimage(images) - - def main(self, flinfo, images_dname, out_fname, part_fname, fconf_fname, ipq_nand): - """Start the packing process. - - flinfo -- FlashInfo object, containing flash parameters - images_dname -- string, name of images directory - out_fname -- string, output file path - part_fname -- string, partition file path - fconf_fname -- string, flash confing file path - ipq_nand -- bool, indicates whether this is an IPQ device - """ - self.flinfo = flinfo - self.images_dname = images_dname - self.img_fname = out_fname - self.ipq_nand = ipq_nand - - self.__create_fnames() - - if self.flinfo.type == "nand": - script = NandScript(self.flinfo, self.ipq_nand) - elif self.flinfo.type == "nor" or self.flinfo.type == "norplusnand": - script = NorScript(self.flinfo) - elif self.flinfo.type == "emmc": - script = EmmcScript(self.flinfo) - else: - error("Invalid flash type specified. It should be 'nand' or 'nor' or 'norplusnand'") - - if not os.path.isabs(part_fname): - part_fname = os.path.join(self.images_dname, part_fname) - - if not os.path.isabs(fconf_fname): - self.fconf_fname = os.path.join(self.images_dname, fconf_fname) - - mibib = MIBIB(part_fname, self.flinfo.pagesize, self.flinfo.blocksize, - self.flinfo.chipsize) - self.partitions = mibib.get_parts() - - script.echo("", verbose=True) - - script.start_activity("Check environment:") - script.check_isset("imgaddr") - script.check_isset("machid") - script.finish_activity() - - try: - info_fp = open(self.fconf_fname) - except IOError, e: - error("error opening info file '%s'" % self.fconf_fname, e) - - try: - scr_fp = open(self.scr_fname, "wb") - except IOError, e: - error("error opening script file '%s'" % self.scr_fname, e) - - images = [] - self.__gen_script(scr_fp, info_fp, script, images) - try: - scr_fp.write(script.dumps()) - except IOError, e: - error("error writing to script '%s'" % script_fp.name, e) - scr_fp.close() # Flush out all written commands - - images.insert(0, ImageInfo("script", "flash.scr", "script")) - self.__mkimage(images) - -class UsageError(Exception): - """Indicates error in command arguments.""" - pass - -class ArgParser(object): - """Class to parse command-line arguments.""" - - DEFAULT_PAGESIZE = 4096 - DEFAULT_PAGES_PER_BLOCK = 64 - DEFAULT_BLOCKS_PER_CHIP = 1024 - DEFAULT_TYPE = "nand" - DEFAULT_PART_FNAME = "partition.mbn" - DEFAULT_FCONF_FNAME = "flash.conf" - - def __init__(self): - self.__pagesize = None - self.__pages_per_block = None - self.__blocksize = None - self.__chipsize = None - self.__flash_type = None - - self.flash_info = None - self.images_dname = None - self.ipq_nand = False - self.bconf = False - self.bconf_fname = "boardconfig" - self.part_fname = None - self.fconf_fname = None - self.genitb_fname = None - - def __init_pagesize(self, pagesize): - """Set the pagesize, from the command line argument. - - pagesize -- string, flash page size - - Raise UsageError, if pagesize is invalid - """ - if pagesize == None: - self.__pagesize = ArgParser.DEFAULT_PAGESIZE - else: - try: - self.__pagesize = int(pagesize) - except ValueError: - raise UsageError("invalid page size '%s'" % pagesize) - - def __init_blocksize(self, pages_per_block): - """Set the blocksize, from the command line argument. - - pages_per_block -- string, no. of pages in a flash block - - Raise UsageError, if pages_per_block is invalid - """ - if pages_per_block == None: - self.__blocksize = (self.__pagesize - * ArgParser.DEFAULT_PAGES_PER_BLOCK) - else: - try: - self.__blocksize = self.__pagesize * int(pages_per_block) - except ValueError: - raise UsageError("invalid block size '%s'" % self.__blocksize) - - def __init_chipsize(self, blocks_per_chip): - """Set the chipsize, from the command line argument. - - blocks_per_chip -- string, no. of blocks in a flash chip - - Raise UsageError, if chips_per_block is invalid - """ - if blocks_per_chip == None: - self.__chipsize = (self.__blocksize - * ArgParser.DEFAULT_BLOCKS_PER_CHIP) - else: - try: - self.__chipsize = self.__blocksize * int(blocks_per_chip) - except ValueError: - raise UsageError("invalid chip size '%s'" % self.__chipsize) - - def __init_flash_info(self): - """Set flash_info from the parsed flash paramaters.""" - - self.flash_info = FlashInfo(self.__flash_type, - self.__pagesize, - self.__blocksize, - self.__chipsize) - - def __init_flash_type(self, flash_type): - """Set the flash_type, from the command line argument. - - flash_type -- string, nand or nor - - Raise UsageError, if flash_type is invalid - """ - - if flash_type == None: - self.__flash_type = ArgParser.DEFAULT_TYPE - elif flash_type in [ "nand", "nor", "emmc", "norplusnand", "norplusemmc" ]: - self.__flash_type = flash_type - else: - raise UsageError("invalid flash type '%s'" % flash_type) - - def __init_part_fname(self, part_fname): - """Set the partition filename from command line argument - - part_fname -- string, the partition filename - """ - - if part_fname == None: - self.part_fname = ArgParser.DEFAULT_PART_FNAME - else: - self.part_fname = part_fname - - def __init_fconf_fname(self, fconf_fname): - """Set the flash configuration filename from command line argument - - fconf_fname -- string, the flash configuration filename - """ - - if fconf_fname == None: - self.fconf_fname = ArgParser.DEFAULT_FCONF_FNAME - else: - self.fconf_fname = fconf_fname - - def __init_out_fname(self, out_fname, images_dname, flash_type, - pagesize, pages_per_block, blocks_per_chip, - bconf): - """Set the out_fname from the command line argument. - - out_fname -- string, the output filename - images_dname -- string, the images dirname - flash_type -- string, the flash type - pagesize -- int, the flash page size in bytes - pages_per_block -- int, the flash pages per block - blocks_per_chip -- int, the flash blocks per chip - bconf -- bool, whether is board config mode - """ - - if out_fname == None: - images_dname_norm = os.path.abspath(images_dname) - if bconf: - fmt = "%s-%s%simg" - self.out_fname = fmt % (images_dname_norm, flash_type, - os.path.extsep) - else: - fmt = "%s-%s-%d-%d-%d%simg" - self.out_fname = fmt % (images_dname_norm, flash_type, - pagesize, pages_per_block, - blocks_per_chip, os.path.extsep) - else: - if os.path.isabs(out_fname): - self.out_fname = out_fname - else: - images_dname_parent = os.path.dirname(images_dname) - self.out_fname = os.path.join(images_dname_parent, out_fname) - - def __init_images_dname(self, args): - """Set the images_dname from the command line argument. - - args -- list of string, command line args after stripping options - """ - self.images_dname = args[0] - - def parse(self, argv): - """Start the parsing process, and populate members with parsed value. - - argv -- list of string, the command line arguments - """ - flash_type = None - pagesize = None - pages_per_block = None - blocks_per_chip = None - ipq_nand = False - out_fname = None - part_fname = None - fconf_fname = None - bconf = False - bconf_fname = None - genitb_fname = None - - try: - opts, args = getopt(argv[1:], "Bib:hp:t:o:c:m:f:F:M:") - except GetoptError, e: - raise UsageError(e.msg) - - for option, value in opts: - if option == "-t": - flash_type = value - elif option == "-i": - ipq_nand = True - elif option == "-p": - pagesize = value - elif option == "-b": - pages_per_block = value - elif option == '-c': - blocks_per_chip = value - elif option == "-o": - out_fname = value - elif option == "-m": - part_fname = value - elif option == "-f": - fconf_fname = value - elif option == "-B": - bconf = True - elif option == "-F": - bconf_fname = value - elif option == "-M": - genitb_fname= value - - if len(args) != 1: - raise UsageError("insufficient arguments") - - self.__init_flash_type(flash_type) - self.__init_pagesize(pagesize) - self.__init_blocksize(pages_per_block) - self.__init_chipsize(blocks_per_chip) - self.__init_flash_info() - self.__init_images_dname(args) - self.__init_out_fname(out_fname, self.images_dname, - self.__flash_type, self.__pagesize, - self.__blocksize / self.__pagesize, - self.__chipsize / self.__blocksize, - bconf) - self.__init_part_fname(part_fname) - self.__init_fconf_fname(fconf_fname) - - self.ipq_nand = ipq_nand - self.bconf = bconf - if bconf_fname != None: - self.bconf_fname = bconf_fname - - self.genitb_fname = genitb_fname - - def usage(self, msg): - """Print error message and command usage information. - - msg -- string, the error message - """ - print "pack: %s" % msg - print - print "Usage: pack [options] IDIR" - print - print "where IDIR is the path containing the images." - print - print " -t TYPE specifies partition type, 'nand' or 'nor'," - print " default is '%s'." % ArgParser.DEFAULT_TYPE - print " -p SIZE specifies the page size in bytes," - print " default is %d." % ArgParser.DEFAULT_PAGESIZE - print " -b COUNT specifies the pages per block," - print " default is %d." % ArgParser.DEFAULT_PAGES_PER_BLOCK - print " -c COUNT specifies the no. of blocks per chip" - print " default is %d." % ArgParser.DEFAULT_BLOCKS_PER_CHIP - print " -i specifies IPQ processor specific NAND layout" - print " switch, default disabled." - print " -m FILE specifies the partition filename" - print " default is '%s'." % ArgParser.DEFAULT_PART_FNAME - print " -f FILE specifies the flash configuration filename" - print " default is '%s'." % ArgParser.DEFAULT_FCONF_FNAME - print " -o FILE specifies the output filename" - print " default is IDIR-TYPE-SIZE-COUNT.img" - print " if the filename is relative, it is relative" - print " to the parent of IDIR." - print " -M specifies script name to build single ITB with multiple dtb's," - print " default disabled." - print - print "NOTE: The above invocation method of pack is deprecated." - print "The new pack invocation uses a board config file to retrieve" - print "the board specific parameters. The new invocation is provided" - print "below." - print - print "Usage: pack [options] IDIR" - print - print "where IDIR is the path containing the images." - print - print " -t TYPE specifies partition type, 'nand' or 'nor', or 'emmc'" - print " default is '%s'." % ArgParser.DEFAULT_TYPE - print " -B specifies board config should be used, for" - print " flash parameters." - print " -F specifies board config file name should be used, for" - print " flash parameters. Defaults to 'boardconfig'" - print " -o FILE specifies the output filename" - print " default is IDIR-TYPE.img" - print " if the filename is relative, it is relative" - print " to the parent of IDIR." - print - print "Pack Version: %s" % version - - -def main(): - """Main script entry point. - - Created to avoid polluting the global namespace. - """ - try: - parser = ArgParser() - parser.parse(sys.argv) - except UsageError, e: - parser.usage(e.args[0]) - sys.exit(1) - - if parser.genitb_fname: - prc = subprocess.Popen(['sh', parser.genitb_fname]) - prc.wait() - - if prc.returncode != 0: - print 'ERROR: unable to create ITB' - return prc.returncode - else: - print '...ITB binary created' - - - pack = Pack() - if parser.bconf: - pack.main_bconf(parser.flash_info.type, parser.images_dname, - parser.out_fname, parser.bconf_fname) - else: - pack.main(parser.flash_info, parser.images_dname, - parser.out_fname, parser.part_fname, - parser.fconf_fname, parser.ipq_nand) - -class ArgParserTestCase(TestCase): - def setUp(self): - self.parser = ArgParser() - - def test_defaults(self): - self.parser.parse(["pack.py", "itest"]) - self.assertEqual(self.parser.images_dname, "itest") - - fmt = "itest-%s-%d-%d-%d.img" - expected_fname = fmt % (ArgParser.DEFAULT_TYPE, - ArgParser.DEFAULT_PAGESIZE, - ArgParser.DEFAULT_PAGES_PER_BLOCK, - ArgParser.DEFAULT_BLOCKS_PER_CHIP) - self.assertEqual(self.parser.out_fname, expected_fname) - self.assertEqual(self.parser.ipq_nand, False) - self.assertEqual(self.parser.flash_info.type, - ArgParser.DEFAULT_TYPE) - self.assertEqual(self.parser.flash_info.pagesize, - ArgParser.DEFAULT_PAGESIZE) - self.assertEqual(self.parser.flash_info.blocksize, - ArgParser.DEFAULT_PAGES_PER_BLOCK - * ArgParser.DEFAULT_PAGESIZE) - self.assertEqual(self.parser.flash_info.chipsize, - ArgParser.DEFAULT_BLOCKS_PER_CHIP - * ArgParser.DEFAULT_PAGES_PER_BLOCK - * ArgParser.DEFAULT_PAGESIZE) - - def test_ipq_flag(self): - self.parser.parse(["pack.py", "-i", "itest"]) - self.assertEqual(self.parser.ipq_nand, True) - - def test_invalid_flag(self): - self.assertRaises(UsageError, self.parser.parse, - ["pack.py", "-x", "itest"]) - - def test_type_option(self): - self.parser.parse(["pack.py", "-t", "nor", "itest"]) - self.assertEqual(self.parser.flash_info.type, "nor") - - def test_invalid_type_option(self): - self.assertRaises(UsageError, self.parser.parse, - ["pack.py", "-t", "abcd", "itest"]) - - def test_pagesize_option(self): - self.parser.parse(["pack.py", "-p", "2048", "itest"]) - self.assertEqual(self.parser.flash_info.pagesize, 2048) - - def test_invalid_pagesize_option(self): - self.assertRaises(UsageError, self.parser.parse, - ["pack.py", "-p", "abcd", "itest"]) - - def test_pages_per_block_option(self): - self.parser.parse(["pack.py", "-b", "32", "itest"]) - self.assertEqual(self.parser.flash_info.blocksize, - ArgParser.DEFAULT_PAGESIZE * 32) - - def test_invalid_pages_per_block_option(self): - self.assertRaises(UsageError, self.parser.parse, - ["pack.py", "-b", "abcd", "itest"]) - - def test_blocks_per_chip_option(self): - self.parser.parse(["pack.py", "-c", "512", "itest"]) - self.assertEqual(self.parser.flash_info.chipsize, - ArgParser.DEFAULT_PAGESIZE - * ArgParser.DEFAULT_PAGES_PER_BLOCK - * 512) - - def test_out_fname_rel_option(self): - self.parser.parse(["pack.py", "-o", "abcd", "/tmp/test/itest"]) - self.assertEqual(self.parser.out_fname, "/tmp/test/abcd") - - def test_out_fname_abs_option(self): - self.parser.parse(["pack.py", "-o", "/tmp/abcd", "/tmp/test/itest"]) - self.assertEqual(self.parser.out_fname, "/tmp/abcd") - - def test_partition_option(self): - self.parser.parse(["pack.py", "-m", "abcd", "/tmp/test/itest"]) - self.assertEqual(self.parser.part_fname, "abcd") - - def test_flash_conf_option(self): - self.parser.parse(["pack.py", "-f", "abcd", "/tmp/test/itest"]) - self.assertEqual(self.parser.fconf_fname, "abcd") - -class PackTestCase(TestCase): - def setUp(self): - self.pack = Pack() - blocksize = (ArgParser.DEFAULT_PAGESIZE - * ArgParser.DEFAULT_PAGES_PER_BLOCK) - chipsize = blocksize * ArgParser.DEFAULT_BLOCKS_PER_CHIP - - self.flinfo = FlashInfo(ArgParser.DEFAULT_TYPE, - ArgParser.DEFAULT_PAGESIZE, - blocksize, chipsize) - self.img_dname = mkdtemp() - self.img_fname = self.img_dname + ".img" - self.part_fname = "partition.mbn" - self.fconf_fname = "flash.conf" - - sbl1_fp = open(os.path.join(self.img_dname, "sbl1.mbn"), "w") - sbl1_fp.write("#" * blocksize * 2) - sbl1_fp.close() - - self.__create_partition_mbn(blocksize, chipsize) - - def __create_partition_mbn(self, blocksize, chipsize): - part_fname = os.path.join(self.img_dname, self.part_fname) - - mibib = MIBIB(part_fname, ArgParser.DEFAULT_PAGESIZE, blocksize, - chipsize) - - offset = 0 - part_size = 2 * blocksize - mibib.add_part(PartInfo("0:SBL1", offset, part_size)) - - offset += part_size - part_size = 2 * blocksize - mibib.add_part(PartInfo("0:MIBIB", offset, part_size)) - - offset += part_size - part_size = 1 * blocksize - mibib.add_part(PartInfo("0:SBL2", offset, part_size)) - - offset += part_size - part_size = None - mibib.add_part(PartInfo("0:FS", offset, part_size)) - - mibib.write() - - def __mkconf(self, conf_str): - conf_fname = os.path.join(self.img_dname, self.fconf_fname) - conf_fp = open(conf_fname, "w") - conf_fp.write(conf_str) - conf_fp.close() - - def tearDown(self): - rmtree(self.img_dname) - try: - os.remove(self.img_fname) - except OSError: - pass - - def test_simple(self): - self.__mkconf(""" -[sbl1] -partition = 0:SBL1 -filename = sbl1.mbn -""") - - self.pack.main(self.flinfo, self.img_dname, self.img_fname, - self.part_fname, self.fconf_fname, ipq_nand=False) - self.assertEqual(os.path.exists(self.img_fname), True) - - def test_missing_conf(self): - self.assertRaises(SystemExit, - self.pack.main, - self.flinfo, - self.img_dname, - self.img_fname, - self.part_fname, - self.fconf_fname, - ipq_nand=False) - - def test_nand_layout(self): - self.__mkconf(""" -[sbl1] -partition = 0:SBL1 -filename = sbl1.mbn -layout = sbl -""") - self.pack.main(self.flinfo, self.img_dname, self.img_fname, - self.part_fname, self.fconf_fname, ipq_nand=True) - self.assertEqual(os.path.exists(self.img_fname), True) - - def test_invalid_layout(self): - self.__mkconf(""" -[sbl1] -partition = 0:SBL1 -filename = sbl1.mbn -layout = abcd -""") - self.assertRaises(SystemExit, - self.pack.main, - self.flinfo, - self.img_dname, - self.img_fname, - self.part_fname, - self.fconf_fname, - ipq_nand=True) - - def test_inconsistent_layout(self): - self.__mkconf(""" -[sbl1] -partition = 0:SBL1 -filename = sbl1.mbn -layout = sbl -""") - self.assertRaises(SystemExit, - self.pack.main, - self.flinfo, - self.img_dname, - self.img_fname, - self.part_fname, - self.fconf_fname, - ipq_nand=False) - - def test_invalid_filename(self): - self.__mkconf(""" -[sbl1] -partition = 0:SBL1 -filename = sbl10.mbn -""") - self.assertRaises(SystemExit, - self.pack.main, - self.flinfo, - self.img_dname, - self.img_fname, - self.part_fname, - self.fconf_fname, - ipq_nand=False) - - def test_special_chars_in_filename(self): - self.__mkconf(""" -[slash] -partition = 0:SBL1 -filename = sb\\l1.mbn -""") - - sbl1_fp = open(os.path.join(self.img_dname, "sb\\l1.mbn"), "w") - sbl1_fp.write("abcdef") - sbl1_fp.close() - - self.pack.main(self.flinfo, self.img_dname, self.img_fname, - self.part_fname, self.fconf_fname, ipq_nand=False) - self.assertEqual(os.path.exists(self.img_fname), True) - - def __get_images(self): - mkimage_output = subprocess.check_output(["mkimage", "-l", self.img_fname]) - return re.findall(r"Image \d+ \((.*)\)", mkimage_output) - - def test_multi_image(self): - self.__mkconf(""" -[sbl1] -partition = 0:SBL1 -filename = sbl1.mbn - -[sbl2] -partition = 0:MIBIB -filename = partition.mbn -""") - - self.pack.main(self.flinfo, self.img_dname, self.img_fname, - self.part_fname, self.fconf_fname, ipq_nand=False) - count = len(self.__get_images()) - self.assertEqual(count, 3) - - def test_include(self): - self.__mkconf(""" -[sbl1] -partition = 0:SBL1 -filename = sbl1.mbn -include = no - -[sbl2] -partition = 0:MIBIB -filename = partition.mbn -""") - - self.pack.main(self.flinfo, self.img_dname, self.img_fname, - self.part_fname, self.fconf_fname, ipq_nand=False) - images = self.__get_images() - print images - self.assertTrue("sbl2" in images) - self.assertTrue("sbl1" not in images) - - def test_yaffs_yes(self): - self.__mkconf(""" -[sbl1] -partition = 0:SBL1 -filename = sbl1.mbn -yaffs = yes -""") - self.pack.main(self.flinfo, self.img_dname, self.img_fname, - self.part_fname, self.fconf_fname, ipq_nand=False) - - def test_yaffs_no(self): - self.__mkconf(""" -[sbl1] -partition = 0:SBL1 -filename = sbl1.mbn -yaffs = no -""") - self.pack.main(self.flinfo, self.img_dname, self.img_fname, - self.part_fname, self.fconf_fname, ipq_nand=False) - - def test_yaffs_invalid(self): - self.__mkconf(""" -[sbl1] -partition = 0:SBL1 -filename = sbl1.mbn -yaffs = abcd -""") - self.assertRaises(SystemExit, - self.pack.main, - self.flinfo, - self.img_dname, - self.img_fname, - self.part_fname, - self.fconf_fname, - ipq_nand=False) - - def test_invalid_partition(self): - self.__mkconf(""" -[sbl1] -partition = 0:SBL5 -filename = sbl1.mbn -""") - self.assertRaises(SystemExit, - self.pack.main, - self.flinfo, - self.img_dname, - self.img_fname, - self.part_fname, - self.fconf_fname, - ipq_nand=False) - - def test_img_larger_than_partition(self): - self.__mkconf(""" -[sbl2] -partition = 0:SBL2 -filename = sbl1.mbn -""") - self.assertRaises(SystemExit, - self.pack.main, - self.flinfo, - self.img_dname, - self.img_fname, - self.part_fname, - self.fconf_fname, - ipq_nand=False) - - def test_machid_in_hex(self): - self.__mkconf(""" -[sbl1] -partition = 0:SBL1 -filename = sbl1.mbn -if_machid = 0x152 -""") - self.pack.main(self.flinfo, self.img_dname, self.img_fname, - self.part_fname, self.fconf_fname, ipq_nand=False) - self.assertEqual(os.path.exists(self.img_fname), True) - - def test_machid_in_dec(self): - self.__mkconf(""" -[sbl1] -partition = 0:SBL1 -filename = sbl1.mbn -if_machid = 256 -""") - self.pack.main(self.flinfo, self.img_dname, self.img_fname, - self.part_fname, self.fconf_fname, ipq_nand=False) - self.assertEqual(os.path.exists(self.img_fname), True) - - def test_machid_invalid(self): - self.__mkconf(""" -[sbl1] -partition = 0:SBL1 -filename = sbl1.mbn -if_machid = xyz -""") - self.assertRaises(SystemExit, - self.pack.main, - self.flinfo, - self.img_dname, - self.img_fname, - self.part_fname, - self.fconf_fname, - ipq_nand=False) - -if __name__ == "__main__": - main() diff --git a/root/package/utils/sysupgrade-helper/src/tools/patman/patman.py b/root/package/utils/sysupgrade-helper/src/tools/patman/patman.py deleted file mode 100644 index cfe06d08..00000000 --- a/root/package/utils/sysupgrade-helper/src/tools/patman/patman.py +++ /dev/null @@ -1,153 +0,0 @@ -#!/usr/bin/python -# -# Copyright (c) 2011 The Chromium OS Authors. -# -# See file CREDITS for list of people who contributed to this -# project. -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of -# the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, -# MA 02111-1307 USA -# - -"""See README for more information""" - -from optparse import OptionParser -import os -import re -import sys -import unittest - -# Our modules -import checkpatch -import command -import gitutil -import patchstream -import terminal -import test - - -parser = OptionParser() -parser.add_option('-H', '--full-help', action='store_true', dest='full_help', - default=False, help='Display the README file') -parser.add_option('-c', '--count', dest='count', type='int', - default=-1, help='Automatically create patches from top n commits') -parser.add_option('-i', '--ignore-errors', action='store_true', - dest='ignore_errors', default=False, - help='Send patches email even if patch errors are found') -parser.add_option('-n', '--dry-run', action='store_true', dest='dry_run', - default=False, help="Do a try run (create but don't email patches)") -parser.add_option('-s', '--start', dest='start', type='int', - default=0, help='Commit to start creating patches from (0 = HEAD)') -parser.add_option('-t', '--test', action='store_true', dest='test', - default=False, help='run tests') -parser.add_option('-v', '--verbose', action='store_true', dest='verbose', - default=False, help='Verbose output of errors and warnings') -parser.add_option('--cc-cmd', dest='cc_cmd', type='string', action='store', - default=None, help='Output cc list for patch file (used by git)') -parser.add_option('--no-tags', action='store_false', dest='process_tags', - default=True, help="Don't process subject tags as aliaes") - -parser.usage = """patman [options] - -Create patches from commits in a branch, check them and email them as -specified by tags you place in the commits. Use -n to """ - -(options, args) = parser.parse_args() - -# Run our meagre tests -if options.test: - import doctest - - sys.argv = [sys.argv[0]] - suite = unittest.TestLoader().loadTestsFromTestCase(test.TestPatch) - result = unittest.TestResult() - suite.run(result) - - suite = doctest.DocTestSuite('gitutil') - suite.run(result) - - # TODO: Surely we can just 'print' result? - print result - for test, err in result.errors: - print err - for test, err in result.failures: - print err - -# Called from git with a patch filename as argument -# Printout a list of additional CC recipients for this patch -elif options.cc_cmd: - fd = open(options.cc_cmd, 'r') - re_line = re.compile('(\S*) (.*)') - for line in fd.readlines(): - match = re_line.match(line) - if match and match.group(1) == args[0]: - for cc in match.group(2).split(', '): - cc = cc.strip() - if cc: - print cc - fd.close() - -elif options.full_help: - pager = os.getenv('PAGER') - if not pager: - pager = 'more' - fname = os.path.join(os.path.dirname(sys.argv[0]), 'README') - command.Run(pager, fname) - -# Process commits, produce patches files, check them, email them -else: - gitutil.Setup() - - if options.count == -1: - # Work out how many patches to send if we can - options.count = gitutil.CountCommitsToBranch() - options.start - - col = terminal.Color() - if not options.count: - str = 'No commits found to process - please use -c flag' - print col.Color(col.RED, str) - sys.exit(1) - - # Read the metadata from the commits - if options.count: - series = patchstream.GetMetaData(options.start, options.count) - cover_fname, args = gitutil.CreatePatches(options.start, options.count, - series) - - # Fix up the patch files to our liking, and insert the cover letter - series = patchstream.FixPatches(series, args) - if series and cover_fname and series.get('cover'): - patchstream.InsertCoverLetter(cover_fname, series, options.count) - - # Do a few checks on the series - series.DoChecks() - - # Check the patches, and run them through 'git am' just to be sure - ok = checkpatch.CheckPatches(options.verbose, args) - if not gitutil.ApplyPatches(options.verbose, args, - options.count + options.start): - ok = False - - # Email the patches out (giving the user time to check / cancel) - cmd = '' - if ok or options.ignore_errors: - cc_file = series.MakeCcFile(options.process_tags) - cmd = gitutil.EmailPatches(series, cover_fname, args, - options.dry_run, cc_file) - os.remove(cc_file) - - # For a dry run, just show our actions as a sanity check - if options.dry_run: - series.ShowActions(args, cmd, options.process_tags) diff --git a/root/package/utils/sysupgrade-helper/src/tools/scripts/make-asm-offsets b/root/package/utils/sysupgrade-helper/src/tools/scripts/make-asm-offsets deleted file mode 100644 index 4c33756d..00000000 --- a/root/package/utils/sysupgrade-helper/src/tools/scripts/make-asm-offsets +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/sh - -# Adapted from Linux kernel's "Kbuild": -# commit 1cdf25d704f7951d02a04064c97db547d6021872 -# Author: Christoph Lameter - -mkdir -p $(dirname $2) - -# Default sed regexp - multiline due to syntax constraints -SED_CMD="/^->/{s:->#\(.*\):/* \1 */:; \ - s:^->\([^ ]*\) [\$#]*\([-0-9]*\) \(.*\):#define \1 (\2) /* \3 */:; \ - s:^->\([^ ]*\) [\$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \ - s:->::; p;}" - -(set -e - echo "#ifndef __ASM_OFFSETS_H__" - echo "#define __ASM_OFFSETS_H__" - echo "/*" - echo " * DO NOT MODIFY." - echo " *" - echo " * This file was generated by $(basename $0)" - echo " *" - echo " */" - echo "" - sed -ne "${SED_CMD}" $1 - echo "" - echo "#endif" ) > $2 diff --git a/root/package/utils/sysupgrade-helper/src/tools/setlocalversion b/root/package/utils/sysupgrade-helper/src/tools/setlocalversion deleted file mode 100644 index e4758f5e..00000000 --- a/root/package/utils/sysupgrade-helper/src/tools/setlocalversion +++ /dev/null @@ -1,177 +0,0 @@ -#!/bin/sh -# -# This scripts adds local version information from the version -# control systems git, mercurial (hg) and subversion (svn). -# -# It was originally copied from the Linux kernel v3.2.0-rc4 and modified -# to support the U-Boot build-system. -# - -usage() { - echo "Usage: $0 [--save-scmversion] [srctree]" >&2 - exit 1 -} - -scm_only=false -srctree=. -if test "$1" = "--save-scmversion"; then - scm_only=true - shift -fi -if test $# -gt 0; then - srctree=$1 - shift -fi -if test $# -gt 0 -o ! -d "$srctree"; then - usage -fi - -scm_version() -{ - local short - short=false - - cd "$srctree" - if test -e .scmversion; then - cat .scmversion - return - fi - if test "$1" = "--short"; then - short=true - fi - - # Check for git and a git repo. - if test -e .git && head=`git rev-parse --verify --short HEAD 2>/dev/null`; then - - # If we are at a tagged commit (like "v2.6.30-rc6"), we ignore - # it, because this version is defined in the top level Makefile. - if [ -z "`git describe --exact-match 2>/dev/null`" ]; then - - # If only the short version is requested, don't bother - # running further git commands - if $short; then - echo "+" - return - fi - # If we are past a tagged commit (like - # "v2.6.30-rc5-302-g72357d5"), we pretty print it. - if atag="`git describe 2>/dev/null`"; then - echo "$atag" | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}' - - # If we don't have a tag at all we print -g{commitish}. - else - printf '%s%s' -g $head - fi - fi - - # Is this git on svn? - if git config --get svn-remote.svn.url >/dev/null; then - printf -- '-svn%s' "`git svn find-rev $head`" - fi - - # Update index only on r/w media - [ -w . ] && git update-index --refresh --unmerged > /dev/null - - # Check for uncommitted changes - if git diff-index --name-only HEAD | grep -v "^scripts/package" \ - | read dummy; then - printf '%s' -dirty - fi - - # All done with git - return - fi - - # Check for mercurial and a mercurial repo. - if test -d .hg && hgid=`hg id 2>/dev/null`; then - # Do we have an tagged version? If so, latesttagdistance == 1 - if [ "`hg log -r . --template '{latesttagdistance}'`" == "1" ]; then - id=`hg log -r . --template '{latesttag}'` - printf '%s%s' -hg "$id" - else - tag=`printf '%s' "$hgid" | cut -d' ' -f2` - if [ -z "$tag" -o "$tag" = tip ]; then - id=`printf '%s' "$hgid" | sed 's/[+ ].*//'` - printf '%s%s' -hg "$id" - fi - fi - - # Are there uncommitted changes? - # These are represented by + after the changeset id. - case "$hgid" in - *+|*+\ *) printf '%s' -dirty ;; - esac - - # All done with mercurial - return - fi - - # Check for svn and a svn repo. - if rev=`svn info 2>/dev/null | grep '^Last Changed Rev'`; then - rev=`echo $rev | awk '{print $NF}'` - printf -- '-svn%s' "$rev" - - # All done with svn - return - fi -} - -collect_files() -{ - local file res - - for file; do - case "$file" in - *\~*) - continue - ;; - esac - if test -e "$file"; then - res="$res$(cat "$file")" - fi - done - echo "$res" -} - -if $scm_only; then - if test ! -e .scmversion; then - res=$(scm_version) - echo "$res" >.scmversion - fi - exit -fi - -#if test -e include/config/auto.conf; then -# . include/config/auto.conf -#else -# echo "Error: kernelrelease not valid - run 'make prepare' to update it" -# exit 1 -#fi -CONFIG_LOCALVERSION= -CONFIG_LOCALVERSION_AUTO=y - -# localversion* files in the build and source directory -res="$(collect_files localversion*)" -if test ! "$srctree" -ef .; then - res="$res$(collect_files "$srctree"/localversion*)" -fi - -# CONFIG_LOCALVERSION and LOCALVERSION (if set) -res="${res}${CONFIG_LOCALVERSION}${LOCALVERSION}" - -# scm version string if not at a tagged commit -if test "$CONFIG_LOCALVERSION_AUTO" = "y"; then - # full scm version string - res="$res$(scm_version)" -else - # append a plus sign if the repository is not in a clean - # annotated or signed tagged state (as git describe only - # looks at signed or annotated tags - git tag -a/-s) and - # LOCALVERSION= is not specified - if test "${LOCALVERSION+set}" != "set"; then - scm=$(scm_version --short) - res="$res${scm:++}" - fi -fi - -echo "$res [${VERSION_CODE:-"local"},${REVISION:-"local"}]" diff --git a/root/target/linux/bcm27xx/patches-5.15/950-0785-ARM-dts-Add-bcm2711-rpi-cm4antrouter5g.dts.patch b/root/target/linux/bcm27xx/patches-5.15/950-0785-ARM-dts-Add-bcm2711-rpi-cm4antrouter5g.dts.patch deleted file mode 100644 index 6912d784..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/950-0785-ARM-dts-Add-bcm2711-rpi-cm4antrouter5g.dts.patch +++ /dev/null @@ -1,317 +0,0 @@ ---- a/arch/arm/boot/dts/bcm2711-rpi-cm4.dts 2022-01-04 02:51:16.000000000 +0800 -+++ b/arch/arm/boot/dts/bcm2711-rpi-cm4.dts 2022-01-04 03:10:34.000000000 +0800 -@@ -7,7 +7,7 @@ - - / { - compatible = "raspberrypi,4-compute-module", "brcm,bcm2711"; -- model = "Raspberry Pi Compute Module 4"; -+ model = "openmptcprouter_5G_CM4"; - - chosen { - /* 8250 auxiliary UART instead of pl011 */ -@@ -91,19 +91,12 @@ - gpio-line-names = "BT_ON", - "WL_ON", - "PWR_LED_OFF", -- "ANT1", - "VDD_SD_IO_SEL", - "CAM_GPIO", - "SD_PWR_ON", - "ANT2"; - status = "okay"; - -- ant1: ant1 { -- gpio-hog; -- gpios = <3 GPIO_ACTIVE_HIGH>; -- output-high; -- }; -- - ant2: ant2 { - gpio-hog; - gpios = <7 GPIO_ACTIVE_HIGH>; -@@ -138,23 +131,10 @@ - "SPI_MISO", - "SPI_MOSI", - "SPI_SCLK", -- "GPIO12", -- "GPIO13", - /* Serial port */ - "TXD1", - "RXD1", -- "GPIO16", -- "GPIO17", -- "GPIO18", -- "GPIO19", -- "GPIO20", -- "GPIO21", -- "GPIO22", -- "GPIO23", -- "GPIO24", - "GPIO25", -- "GPIO26", -- "GPIO27", - "RGMII_MDIO", - "RGMIO_MDC", - /* Used by BT module */ -@@ -368,14 +348,9 @@ - mmc2 = &sdhost; - i2c3 = &i2c3; - i2c4 = &i2c4; -- i2c5 = &i2c5; -- i2c6 = &i2c6; - i2c20 = &ddc0; - i2c21 = &ddc1; -- spi3 = &spi3; - spi4 = &spi4; -- spi5 = &spi5; -- spi6 = &spi6; - /delete-property/ intc; - }; - -@@ -398,49 +373,7 @@ - pinctrl-0 = <&uart1_pins>; - }; - --&spi0 { -- pinctrl-names = "default"; -- pinctrl-0 = <&spi0_pins &spi0_cs_pins>; -- cs-gpios = <&gpio 8 1>, <&gpio 7 1>; -- -- spidev0: spidev@0{ -- compatible = "spidev"; -- reg = <0>; /* CE0 */ -- #address-cells = <1>; -- #size-cells = <0>; -- spi-max-frequency = <125000000>; -- }; -- -- spidev1: spidev@1{ -- compatible = "spidev"; -- reg = <1>; /* CE1 */ -- #address-cells = <1>; -- #size-cells = <0>; -- spi-max-frequency = <125000000>; -- }; --}; -- - &gpio { -- spi0_pins: spi0_pins { -- brcm,pins = <9 10 11>; -- brcm,function = ; -- }; -- -- spi0_cs_pins: spi0_cs_pins { -- brcm,pins = <8 7>; -- brcm,function = ; -- }; -- -- spi3_pins: spi3_pins { -- brcm,pins = <1 2 3>; -- brcm,function = ; -- }; -- -- spi3_cs_pins: spi3_cs_pins { -- brcm,pins = <0 24>; -- brcm,function = ; -- }; -- - spi4_pins: spi4_pins { - brcm,pins = <5 6 7>; - brcm,function = ; -@@ -451,38 +384,12 @@ - brcm,function = ; - }; - -- spi5_pins: spi5_pins { -- brcm,pins = <13 14 15>; -- brcm,function = ; -- }; -- -- spi5_cs_pins: spi5_cs_pins { -- brcm,pins = <12 26>; -- brcm,function = ; -- }; -- -- spi6_pins: spi6_pins { -- brcm,pins = <19 20 21>; -- brcm,function = ; -- }; -- -- spi6_cs_pins: spi6_cs_pins { -- brcm,pins = <18 27>; -- brcm,function = ; -- }; -- - i2c0_pins: i2c0 { - brcm,pins = <0 1>; - brcm,function = ; - brcm,pull = ; - }; - -- i2c1_pins: i2c1 { -- brcm,pins = <2 3>; -- brcm,function = ; -- brcm,pull = ; -- }; -- - i2c3_pins: i2c3 { - brcm,pins = <4 5>; - brcm,function = ; -@@ -495,23 +402,6 @@ - brcm,pull = ; - }; - -- i2c5_pins: i2c5 { -- brcm,pins = <12 13>; -- brcm,function = ; -- brcm,pull = ; -- }; -- -- i2c6_pins: i2c6 { -- brcm,pins = <22 23>; -- brcm,function = ; -- brcm,pull = ; -- }; -- -- i2s_pins: i2s { -- brcm,pins = <18 19 20 21>; -- brcm,function = ; -- }; -- - sdio_pins: sdio_pins { - brcm,pins = <34 35 36 37 38 39>; - brcm,function = ; // alt3 = SD1 -@@ -554,29 +444,12 @@ - brcm,function = ; - brcm,pull = <0 2>; - }; -- -- uart5_pins: uart5_pins { -- brcm,pins = <12 13>; -- brcm,function = ; -- brcm,pull = <0 2>; -- }; - }; - - &i2c0if { - clock-frequency = <100000>; - }; - --&i2c1 { -- pinctrl-names = "default"; -- pinctrl-0 = <&i2c1_pins>; -- clock-frequency = <100000>; --}; -- --&i2s { -- pinctrl-names = "default"; -- pinctrl-0 = <&i2s_pins>; --}; -- - // ============================================= - // Board specific stuff here - -@@ -611,6 +484,81 @@ - linux,default-trigger = "default-on"; - gpios = <&expgpio 2 GPIO_ACTIVE_LOW>; - }; -+ -+ wlan2g { -+ label = "wlan2g"; -+ gpios = <&gpio 17 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ wlan5g { -+ label = "wlan5g"; -+ gpios = <&gpio 3 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ wan { -+ label = "wan"; -+ gpios = <&gpio 27 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ 5g1 { -+ label = "5g1"; -+ gpios = <&gpio 21 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ 5g2 { -+ label = "5g2"; -+ gpios = <&gpio 20 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ 5g3 { -+ label = "5g3"; -+ gpios = <&gpio 16 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ 5g4 { -+ label = "5g4"; -+ gpios = <&gpio 12 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ 5g5 { -+ label = "5g5"; -+ gpios = <&gpio 10 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ 5g6 { -+ label = "5g6"; -+ gpios = <&gpio 22 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ 5gpwr1 { -+ label = "5gpwr1"; -+ gpios = <&gpio 26 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ 5gpwr2 { -+ label = "5gpwr2"; -+ gpios = <&gpio 19 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ 5gpwr3 { -+ label = "5gpwr3"; -+ gpios = <&gpio 13 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ 5gpwr4 { -+ label = "5gpwr4"; -+ gpios = <&gpio 24 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ 5gpwr5 { -+ label = "5gpwr5"; -+ gpios = <&gpio 23 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ 5gpwr6 { -+ label = "5gpwr6"; -+ gpios = <&gpio 18 GPIO_ACTIVE_HIGH>; -+ }; - }; - - &pwm1 { -@@ -640,21 +588,6 @@ - eth_led0 = <&phy1>,"led-modes:0"; - eth_led1 = <&phy1>,"led-modes:4"; - -- ant1 = <&ant1>,"output-high?=on", -- <&ant1>, "output-low?=off", -- <&ant2>, "output-high?=off", -- <&ant2>, "output-low?=on"; -- ant2 = <&ant1>,"output-high?=off", -- <&ant1>, "output-low?=on", -- <&ant2>, "output-high?=on", -- <&ant2>, "output-low?=off"; -- noant = <&ant1>,"output-high?=off", -- <&ant1>, "output-low?=on", -- <&ant2>, "output-high?=off", -- <&ant2>, "output-low?=on"; -- - sd_poll_once = <&emmc2>, "non-removable?"; -- spi_dma4 = <&spi0>, "dmas:0=", <&dma40>, -- <&spi0>, "dmas:8=", <&dma40>; - }; - }; diff --git a/root/target/linux/generic/pending-5.4/690-net-add-support-for-threaded-NAPI-polling.patch b/root/target/linux/generic/pending-5.4/690-net-add-support-for-threaded-NAPI-polling.patch deleted file mode 100644 index 88c995f2..00000000 --- a/root/target/linux/generic/pending-5.4/690-net-add-support-for-threaded-NAPI-polling.patch +++ /dev/null @@ -1,344 +0,0 @@ -From: Felix Fietkau -Date: Sun, 26 Jul 2020 14:03:21 +0200 -Subject: [PATCH] net: add support for threaded NAPI polling - -For some drivers (especially 802.11 drivers), doing a lot of work in the NAPI -poll function does not perform well. Since NAPI poll is bound to the CPU it -was scheduled from, we can easily end up with a few very busy CPUs spending -most of their time in softirq/ksoftirqd and some idle ones. - -Introduce threaded NAPI for such drivers based on a workqueue. The API is the -same except for using netif_threaded_napi_add instead of netif_napi_add. - -In my tests with mt76 on MT7621 using threaded NAPI + a thread for tx scheduling -improves LAN->WLAN bridging throughput by 10-50%. Throughput without threaded -NAPI is wildly inconsistent, depending on the CPU that runs the tx scheduling -thread. - -With threaded NAPI it seems stable and consistent (and higher than the best -results I got without it). - -Based on a patch by Hillf Danton - -Cc: Hillf Danton -Signed-off-by: Felix Fietkau ---- - ---- a/include/linux/netdevice.h -+++ b/include/linux/netdevice.h -@@ -340,6 +340,7 @@ struct napi_struct { - struct list_head dev_list; - struct hlist_node napi_hash_node; - unsigned int napi_id; -+ struct work_struct work; - }; - - enum { -@@ -350,6 +351,7 @@ enum { - NAPI_STATE_HASHED, /* In NAPI hash (busy polling possible) */ - NAPI_STATE_NO_BUSY_POLL,/* Do not add in napi_hash, no busy polling */ - NAPI_STATE_IN_BUSY_POLL,/* sk_busy_loop() owns this NAPI */ -+ NAPI_STATE_THREADED, /* Use threaded NAPI */ - }; - - enum { -@@ -360,6 +362,7 @@ enum { - NAPIF_STATE_HASHED = BIT(NAPI_STATE_HASHED), - NAPIF_STATE_NO_BUSY_POLL = BIT(NAPI_STATE_NO_BUSY_POLL), - NAPIF_STATE_IN_BUSY_POLL = BIT(NAPI_STATE_IN_BUSY_POLL), -+ NAPIF_STATE_THREADED = BIT(NAPI_STATE_THREADED), - }; - - enum gro_result { -@@ -2101,6 +2104,7 @@ struct net_device { - struct lock_class_key addr_list_lock_key; - bool proto_down; - unsigned wol_enabled:1; -+ unsigned threaded:1; - }; - #define to_net_dev(d) container_of(d, struct net_device, dev) - -@@ -2281,6 +2285,26 @@ void netif_napi_add(struct net_device *d - int (*poll)(struct napi_struct *, int), int weight); - - /** -+ * netif_threaded_napi_add - initialize a NAPI context -+ * @dev: network device -+ * @napi: NAPI context -+ * @poll: polling function -+ * @weight: default weight -+ * -+ * This variant of netif_napi_add() should be used from drivers using NAPI -+ * with CPU intensive poll functions. -+ * This will schedule polling from a high priority workqueue -+ */ -+static inline void netif_threaded_napi_add(struct net_device *dev, -+ struct napi_struct *napi, -+ int (*poll)(struct napi_struct *, int), -+ int weight) -+{ -+ set_bit(NAPI_STATE_THREADED, &napi->state); -+ netif_napi_add(dev, napi, poll, weight); -+} -+ -+/** - * netif_tx_napi_add - initialize a NAPI context - * @dev: network device - * @napi: NAPI context ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -156,6 +156,7 @@ static DEFINE_SPINLOCK(offload_lock); - struct list_head ptype_base[PTYPE_HASH_SIZE] __read_mostly; - struct list_head ptype_all __read_mostly; /* Taps */ - static struct list_head offload_base __read_mostly; -+static struct workqueue_struct *napi_workq __read_mostly; - - static int netif_rx_internal(struct sk_buff *skb); - static int call_netdevice_notifiers_info(unsigned long val, -@@ -5931,6 +5932,11 @@ void __napi_schedule(struct napi_struct - { - unsigned long flags; - -+ if (test_bit(NAPI_STATE_THREADED, &n->state)) { -+ queue_work(napi_workq, &n->work); -+ return; -+ } -+ - local_irq_save(flags); - ____napi_schedule(this_cpu_ptr(&softnet_data), n); - local_irq_restore(flags); -@@ -6246,9 +6256,89 @@ static void init_gro_hash(struct napi_st - napi->gro_bitmask = 0; - } - -+static int __napi_poll(struct napi_struct *n, bool *repoll) -+{ -+ int work, weight; -+ -+ weight = n->weight; -+ -+ /* This NAPI_STATE_SCHED test is for avoiding a race -+ * with netpoll's poll_napi(). Only the entity which -+ * obtains the lock and sees NAPI_STATE_SCHED set will -+ * actually make the ->poll() call. Therefore we avoid -+ * accidentally calling ->poll() when NAPI is not scheduled. -+ */ -+ work = 0; -+ if (test_bit(NAPI_STATE_SCHED, &n->state)) { -+ work = n->poll(n, weight); -+ trace_napi_poll(n, work, weight); -+ } -+ -+ WARN_ON_ONCE(work > weight); -+ -+ if (likely(work < weight)) -+ return work; -+ -+ /* Drivers must not modify the NAPI state if they -+ * consume the entire weight. In such cases this code -+ * still "owns" the NAPI instance and therefore can -+ * move the instance around on the list at-will. -+ */ -+ if (unlikely(napi_disable_pending(n))) { -+ napi_complete(n); -+ return work; -+ } -+ -+ if (n->gro_bitmask) { -+ /* flush too old packets -+ * If HZ < 1000, flush all packets. -+ */ -+ napi_gro_flush(n, HZ >= 1000); -+ } -+ -+ gro_normal_list(n); -+ -+ *repoll = true; -+ -+ return work; -+} -+ -+static void napi_workfn(struct work_struct *work) -+{ -+ struct napi_struct *n = container_of(work, struct napi_struct, work); -+ void *have; -+ -+ for (;;) { -+ bool repoll = false; -+ -+ local_bh_disable(); -+ -+ have = netpoll_poll_lock(n); -+ __napi_poll(n, &repoll); -+ netpoll_poll_unlock(have); -+ -+ local_bh_enable(); -+ -+ if (!repoll) -+ return; -+ -+ if (!need_resched()) -+ continue; -+ -+ /* -+ * have to pay for the latency of task switch even if -+ * napi is scheduled -+ */ -+ queue_work(napi_workq, work); -+ return; -+ } -+} -+ - void netif_napi_add(struct net_device *dev, struct napi_struct *napi, - int (*poll)(struct napi_struct *, int), int weight) - { -+ if (dev->threaded) -+ set_bit(NAPI_STATE_THREADED, &napi->state); - INIT_LIST_HEAD(&napi->poll_list); - hrtimer_init(&napi->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED); - napi->timer.function = napi_watchdog; -@@ -6265,6 +6355,7 @@ void netif_napi_add(struct net_device *d - #ifdef CONFIG_NETPOLL - napi->poll_owner = -1; - #endif -+ INIT_WORK(&napi->work, napi_workfn); - set_bit(NAPI_STATE_SCHED, &napi->state); - set_bit(NAPI_STATE_NPSVC, &napi->state); - list_add_rcu(&napi->dev_list, &dev->napi_list); -@@ -6305,6 +6396,7 @@ static void flush_gro_hash(struct napi_s - void netif_napi_del(struct napi_struct *napi) - { - might_sleep(); -+ cancel_work_sync(&napi->work); - if (napi_hash_del(napi)) - synchronize_net(); - list_del_init(&napi->dev_list); -@@ -6317,50 +6409,18 @@ EXPORT_SYMBOL(netif_napi_del); - - static int napi_poll(struct napi_struct *n, struct list_head *repoll) - { -+ bool do_repoll = false; - void *have; -- int work, weight; -+ int work; - - list_del_init(&n->poll_list); - - have = netpoll_poll_lock(n); - -- weight = n->weight; -- -- /* This NAPI_STATE_SCHED test is for avoiding a race -- * with netpoll's poll_napi(). Only the entity which -- * obtains the lock and sees NAPI_STATE_SCHED set will -- * actually make the ->poll() call. Therefore we avoid -- * accidentally calling ->poll() when NAPI is not scheduled. -- */ -- work = 0; -- if (test_bit(NAPI_STATE_SCHED, &n->state)) { -- work = n->poll(n, weight); -- trace_napi_poll(n, work, weight); -- } -- -- WARN_ON_ONCE(work > weight); -+ work = __napi_poll(n, &do_repoll); - -- if (likely(work < weight)) -- goto out_unlock; -- -- /* Drivers must not modify the NAPI state if they -- * consume the entire weight. In such cases this code -- * still "owns" the NAPI instance and therefore can -- * move the instance around on the list at-will. -- */ -- if (unlikely(napi_disable_pending(n))) { -- napi_complete(n); -+ if (!do_repoll) - goto out_unlock; -- } -- -- if (n->gro_bitmask) { -- /* flush too old packets -- * If HZ < 1000, flush all packets. -- */ -- napi_gro_flush(n, HZ >= 1000); -- } -- -- gro_normal_list(n); - - /* Some drivers may have called napi_schedule - * prior to exhausting their budget. -@@ -10340,6 +10400,10 @@ static int __init net_dev_init(void) - sd->backlog.weight = weight_p; - } - -+ napi_workq = alloc_workqueue("napi_workq", WQ_UNBOUND | WQ_HIGHPRI, -+ WQ_UNBOUND_MAX_ACTIVE | WQ_SYSFS); -+ BUG_ON(!napi_workq); -+ - dev_boot_phase = 0; - - /* The loopback device is special if any other network devices ---- a/net/core/net-sysfs.c -+++ b/net/core/net-sysfs.c -@@ -442,6 +442,52 @@ static ssize_t proto_down_store(struct d - } - NETDEVICE_SHOW_RW(proto_down, fmt_dec); - -+static int change_napi_threaded(struct net_device *dev, unsigned long val) -+{ -+ struct napi_struct *napi; -+ -+ if (list_empty(&dev->napi_list)) -+ return -EOPNOTSUPP; -+ -+ list_for_each_entry(napi, &dev->napi_list, dev_list) { -+ if (val) -+ set_bit(NAPI_STATE_THREADED, &napi->state); -+ else -+ clear_bit(NAPI_STATE_THREADED, &napi->state); -+ } -+ -+ return 0; -+} -+ -+static ssize_t napi_threaded_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t len) -+{ -+ return netdev_store(dev, attr, buf, len, change_napi_threaded); -+} -+ -+static ssize_t napi_threaded_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ struct net_device *netdev = to_net_dev(dev); -+ struct napi_struct *napi; -+ bool enabled = false; -+ -+ if (!rtnl_trylock()) -+ return restart_syscall(); -+ -+ list_for_each_entry(napi, &netdev->napi_list, dev_list) { -+ if (test_bit(NAPI_STATE_THREADED, &napi->state)) -+ enabled = true; -+ } -+ -+ rtnl_unlock(); -+ -+ return sprintf(buf, fmt_dec, enabled); -+} -+static DEVICE_ATTR_RW(napi_threaded); -+ - static ssize_t phys_port_id_show(struct device *dev, - struct device_attribute *attr, char *buf) - { -@@ -532,6 +578,7 @@ static struct attribute *net_class_attrs - &dev_attr_flags.attr, - &dev_attr_tx_queue_len.attr, - &dev_attr_gro_flush_timeout.attr, -+ &dev_attr_napi_threaded.attr, - &dev_attr_phys_port_id.attr, - &dev_attr_phys_port_name.attr, - &dev_attr_phys_switch_id.attr, diff --git a/root/target/linux/ipq40xx/base-files/bin/board_detect b/root/target/linux/ipq40xx/base-files/bin/board_detect deleted file mode 100644 index 840bd017..00000000 --- a/root/target/linux/ipq40xx/base-files/bin/board_detect +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -CFG=$1 - -[ -n "$CFG" ] || CFG=/etc/board.json - -[ -d "/etc/board.d/" -a ! -s "$CFG" ] && { - for a in $(ls /etc/board.d/*); do - [ -x $a ] || continue; - $(. $a) - done -} - -[ -s "$CFG" ] || return 1 diff --git a/root/target/linux/ipq40xx/base-files/bin/board_modem b/root/target/linux/ipq40xx/base-files/bin/board_modem deleted file mode 100644 index 7628fc86..00000000 --- a/root/target/linux/ipq40xx/base-files/bin/board_modem +++ /dev/null @@ -1,307 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2015 The Linux Foundation. All rights reserved. -# Copyright (c) 2011-2015 OpenWrt.org -# - -. /lib/functions/uci-defaults.sh -. /lib/functions/system.sh - -CFG=/etc/board.json - -# do not run on preinit/early init -[ "$EARLY_INIT" ] && return - -strstr() { - [ "${1#*$2*}" = "$1" ] && return 1 - return 0 -} - -print_array() { - json_add_array $1 - case "$1" in - 4G) - for element in $2 - do - json_add_string "" "$(echo $element)" - done - ;; - 3G) - for element in $2 - do - json_add_string "" "wcdma_$(echo $element)" - done - ;; - 2G) - for element in $2 - do - json_add_string "" "$(echo $element)" - done - ;; - esac - json_close_array -} - -gather_band_capabilities() { - # Same logic as unhandler.c - ###################### EG06 ######################### - if strstr $revision_from_unhandler "EG06E"; then #EG06E - lte_bands="1 3 5 7 8 20 28 32 38 40 41" #B - trysg_bands="850 900 1800 2100" #MHz - dug_bands="" - elif strstr $revision_from_unhandler "EG06A"; then #EG06A - lte_bands="2 4 5 7 12 13 25 26 29 30 66" - trysg_bands="850 1700 1900" - dug_bands="" - ###################### EC25 ######################### - elif strstr $revision_from_unhandler "EC25EF"; then #EC25E - lte_bands="1 3 5 7 8 20 38 40 41" - trysg_bands="850 900 2100" - dug_bands="900 1800" #MHz - elif strstr $revision_from_unhandler "EC25EC"; then #EC25EC - lte_bands="1 3 7 8 20 28" - trysg_bands="900 2100" - dug_bands="900 1800" - elif strstr $revision_from_unhandler "EC25AUX"; then #EC25AUX - lte_bands="1 2 3 4 5 7 8 28 40" - trysg_bands="850 900 1700 1900 2100" - dug_bands="850 900 1800 1900" - elif strstr $revision_from_unhandler "EC25AFA"; then #EC25A - lte_bands="2 4 12" - trysg_bands="850 1700 1900" - dug_bands="" - elif strstr $revision_from_unhandler "EC25V"; then #EC25V - lte_bands="4 13" - trysg_bands="" - dug_bands="" - elif strstr $revision_from_unhandler "EC25AFX"; then #EC25AFX - lte_bands="2 4 5 12 13 14 66 71" - trysg_bands="850 1700 1900" - dug_bands="" - elif strstr $revision_from_unhandler "EC25AFF"; then #EC25AF - lte_bands="2 4 5 12 13 14 66 71" - trysg_bands="850 1700 1900" - dug_bands="" - elif strstr $revision_from_unhandler "EC25AUTF"; then #EC25AUT - lte_bands="1 3 5 7 28" - trysg_bands="850 2100" - dug_bands="" - elif strstr $revision_from_unhandler "EC25AUTL"; then #EC25AUTL - lte_bands="3 7 28" - trysg_bands="" - dug_bands="" - elif strstr $revision_from_unhandler "EC25AUF"; then #EC25AU - lte_bands="1 2 3 4 5 7 8 28 40" - trysg_bands="850 900 1900 2100" - dug_bands="850 900 1800 1900" - elif strstr $revision_from_unhandler "EC25J"; then #EC25J - lte_bands="1 3 8 18 19 26 41" - trysg_bands="800 900 2100" - dug_bands="" - elif strstr $revision_from_unhandler "EC25EUX"; then #EC25EUX - lte_bands="1 3 7 8 20 28 38 40 41" - trysg_bands="900 2100" - dug_bands="900 1800" - elif strstr $revision_from_unhandler "EC25EUF"; then #EC25EU - lte_bands="1 3 7 8 20 28 38 40 41" - trysg_bands="900 2100" - dug_bands="900 1800" - elif strstr $revision_from_unhandler "EC25EUG"; then #EC25EU - lte_bands="1 3 7 8 20 28 38 40 41" - trysg_bands="900 2100" - dug_bands="900 1800" - elif strstr $revision_from_unhandler "EC25MX"; then #EC25MX - lte_bands="2 4 5 7 28 66" - trysg_bands="850 1700 1900" - dug_bands="" - ###################### EC21 ######################### - elif strstr $revision_from_unhandler "EC21EUX"; then #EC21EUX - lte_bands="1 3 7 8 20 28" - trysg_bands="900 2100" - dug_bands="900 1800" - elif strstr $revision_from_unhandler "EC21EU"; then #EC21EU - lte_bands="1 3 7 8 20 28" - trysg_bands="900 2100" - dug_bands="900 1800" - elif strstr $revision_from_unhandler "EC21EC"; then #EC21EC - lte_bands="1 3 7 8 20 28" - trysg_bands="900 2100" - dug_bands="900 1800" - elif strstr $revision_from_unhandler "EC21E"; then #EC21E - lte_bands="1 3 5 7 8 20" - trysg_bands="850 900 2100" - dug_bands="900 1800" - elif strstr $revision_from_unhandler "EC21V"; then #EC21V - lte_bands="4 13" - trysg_bands="" - dug_bands="" - elif strstr $revision_from_unhandler "EC21KL"; then #EC21KL - lte_bands="1 3 5 7 8" - trysg_bands="" - dug_bands="" - elif strstr $revision_from_unhandler "EC21J"; then #EC21J - lte_bands="1 3 8 18 19 26" - trysg_bands="" - dug_bands="" - elif strstr $revision_from_unhandler "EC21AUX"; then #EC21AUX - lte_bands="1 2 3 4 5 7 8 28 40" - trysg_bands="850 900 1700 1900 2100" - dug_bands="850 900 1800 1900" - elif strstr $revision_from_unhandler "EC21AUT"; then #EC21AUT - lte_bands="1 3 5 7 28" - trysg_bands="850 2100" - dug_bands="" - elif strstr $revision_from_unhandler "EC21AU"; then #EC21AU - lte_bands="1 2 3 4 5 7 8 28 40" - trysg_bands="850 900 1900 2100" - dug_bands="850 900 1800 1900" - elif strstr $revision_from_unhandler "EC21A"; then #EC21A - lte_bands="2 4 12" - trysg_bands="850 1700 1900" - dug_bands="" - ###################### EG25 ######################### - elif strstr $revision_from_unhandler "EG25G"; then #EG25G - lte_bands="1 2 3 4 5 7 8 12 13 18 19 20 25 26 28 38 39 40 41" - trysg_bands="800 850 900 1700 1900 2100" - dug_bands="850 900 1800 1900" - elif strstr $revision_from_unhandler "EG12EA"; then #EG12EA - lte_bands="1 3 5 7 8 20 28 38 40 41" - trysg_bands="850 900 1800 2100" - dug_bands="" - elif strstr $revision_from_unhandler "EG12NA"; then #EG12NA - lte_bands="2 4 5 7 12 13 14 17 25 26 29 30 41 66 71" - trysg_bands="850 1700 1900" - dug_bands="" - elif strstr $revision_from_unhandler "BG96"; then #BG96M - lte_bands="1 2 3 4 5 8 12 13 18 19 20 26 28 39" - trysg_bands="" - dug_bands="850 900 1800 1900" - ##################### SLM750 ######################## - elif strstr $revision_from_unhandler "750VE"; then #SLM750VE - lte_bands="1 3 5 7 8 20 40" - trysg_bands="850 900 2100" - dug_bands="900 1800" - elif strstr $revision_from_unhandler "750VAU"; then #SLM750VAU - lte_bands="1 3 5 7 8 28 40" - trysg_bands="850 900 2100" - dug_bands="850 900 1800" - elif strstr $revision_from_unhandler "750VA"; then #SLM750VA - lte_bands="2 4 5 12 13 17 18 25 26 41" - trysg_bands="850 1700 1900" - dug_bands="850 1900" - elif strstr $revision_from_unhandler "750VJ"; then #SLM750VJ - lte_bands="1 3 8 18 19 26 41" - trysg_bands="800 900 2100" - dug_bands="" - elif strstr $revision_from_unhandler "750VSA"; then #SLM750VSA - lte_bands="2 4 5 7 8 28 40" - trysg_bands="850 900 1900" - dug_bands="850 900 1900" - ###################### UC20 ######################### - elif strstr $revision_from_unhandler "UC20E"; then #UC20E - lte_bands="" - trysg_bands="900 2100" - dug_bands="850 900 1800 1900" - elif strstr $revision_from_unhandler "UC20G"; then #UC20G - lte_bands="" - trysg_bands="800 850 900 1900 2100" - dug_bands="850 900 1800 1900" - elif strstr $revision_from_unhandler "UC20A"; then #UC20A - lte_bands="" - trysg_bands="850 1900" - dug_bands="" - else - lte_bands="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28" - trysg_bands="700 800 850 900 1500 1700 2600" - dug_bands="1700 1800 1900 2100" - fi -} - -validate_service_modes() { - json_get_keys service_modes service_modes - - found_modes="$(printf "$service_modes" | awk '!seen[$0]++'| wc -l)" - [ "$found_modes" -eq 0 ] && { - return 0 - } - - return 1 -} - -#~ Get model name for RUTX products -setup_modem() { - local key="$1" - local object_num="$2" - local id gps boudrate type desc control product vendor stop_bits - - json_select "$object_num" - json_get_vars id product - - if [ "$id" = "$id_from_unhandler" ]; then - - [ -z "$product" ] || \ - { - [ -f "/sys/bus/usb/devices/$id/idVendor" ] && [ -f "/sys/bus/usb/devices/$id/idProduct" ] || { - json_select .. - return 1 - } - - validate_service_modes && { - gather_band_capabilities - json_select_object service_modes - [ -z "$lte_bands" ] || print_array "4G" "$lte_bands" - [ -z "$trysg_bands" ] || print_array "3G" "$trysg_bands" - [ -z "$dug_bands" ] || print_array "2G" "$dug_bands" - json_select .. - } - json_select .. - return 1 - } - - vendor="$(cat "/sys/bus/usb/devices/$id/idVendor")" - product="$(cat "/sys/bus/usb/devices/$id/idProduct")" - - [ -f "/lib/network/wwan/$vendor:$product" ] && { - devicename="$id" - - gather_band_capabilities - - json_set_namespace defaults old_cb - json_load "$(cat /lib/network/wwan/$vendor:$product)" - json_get_vars gps boudrate type desc control stop_bits - json_set_namespace "$old_cb" - - [ "${devicename%%:*}" = "$devicename" ] && { - json_add_string vendor "$vendor" - json_add_string product "$product" - json_add_string gps "$gps" - json_add_string stop_bits "$stop_bits" - json_add_string boudrate "$boudrate" - json_add_string type "$type" - json_add_string desc "$desc" - json_add_string control "$control" - json_add_object service_modes - [ -z "$lte_bands" ] || print_array "4G" "$lte_bands" - [ -z "$trysg_bands" ] || print_array "3G" "$trysg_bands" - [ -z "$dug_bands" ] || print_array "2G" "$dug_bands" - json_close_object - } - } - fi - json_select .. -} - -[ -s "${CFG}" ] || exit 1 - -id_from_unhandler="$1" -revision_from_unhandler="$2" - -lock /var/run/board_modem.lock - -board_config_update -json_for_each_item setup_modem modems -board_config_flush - -lock -u /var/run/board_modem.lock - -exit 0 diff --git a/root/target/linux/ipq40xx/base-files/bin/board_track b/root/target/linux/ipq40xx/base-files/bin/board_track deleted file mode 100644 index 563b8768..00000000 --- a/root/target/linux/ipq40xx/base-files/bin/board_track +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/sh - -. /lib/functions/uci-defaults.sh - -CFG=/etc/board.json -SLP=30 - -check_modem() { - json_select "$2" - json_get_vars id - - [ -z "$id" ] && { - json_select .. - return 0 - } - - #logger -t "board-track" "ls -d /sys/bus/usb/devices/$id/${id}*/tty?*" - ttys=$(ls -d /sys/bus/usb/devices/$id/${id}*/tty?*) - - [ -n "$ttys" ] || { #FAILED TO FIND MODEM - logger -t "board-track" "modem $id not detected" - for m in /sys/class/gpio/modem*_power; do - label="$(basename $m | awk -F_ '{print $1}')" - mctl -s -m ${label} - sleep 1 - mctl -p -m ${label} - done - sleep 5 - ip link set up dev wwan0 2>&1 >/dev/null - ip link set up dev wwan1 2>&1 >/dev/null - json_select .. - return 1 - } - - [ -n "$(ip link show dev wwan0 | grep DOWN)" ] && ip link set up dev wwan0 2>&1 >/dev/null - [ -n "$(ip link show dev wwan1 | grep DOWN)" ] && ip link set up dev wwan1 2>&1 >/dev/null - - #MODEM UP - json_select .. -} - -board_config_update -while true; do - json_for_each_item check_modem modems - sleep $SLP - [ $SLP -lt 300 ] && SLP=$((SLP+30)) -done diff --git a/root/target/linux/ipq40xx/base-files/bin/config_generate b/root/target/linux/ipq40xx/base-files/bin/config_generate deleted file mode 100644 index b2542b14..00000000 --- a/root/target/linux/ipq40xx/base-files/bin/config_generate +++ /dev/null @@ -1,665 +0,0 @@ -#!/bin/sh - -CFG=/etc/board.json - -. /usr/share/libubox/jshn.sh - -[ -s $CFG ] || /bin/board_detect || exit 1 - -[ -s /etc/config/network ] && \ -[ -s /etc/config/system ] && \ -[ -s /etc/config/hwinfo ] && \ -[ -s /etc/config/blesem ] && \ -exit 0 - -generate_static_network() { - uci -q batch <<-EOF - delete network.loopback - set network.loopback='interface' - set network.loopback.ifname='lo' - set network.loopback.proto='static' - set network.loopback.ipaddr='127.0.0.1' - set network.loopback.netmask='255.0.0.0' - EOF - [ -e /proc/sys/net/ipv6 ] && { - uci -q batch <<-EOF - delete network.globals - set network.globals='globals' - set network.globals.ula_prefix='auto' - EOF - } - - if json_is_a dsl object; then - json_select dsl - if json_is_a atmbridge object; then - json_select atmbridge - local vpi vci encaps payload nameprefix - json_get_vars vpi vci encaps payload nameprefix - uci -q batch <<-EOF - delete network.atm - set network.atm='atm-bridge' - set network.atm.vpi='$vpi' - set network.atm.vci='$vci' - set network.atm.encaps='$encaps' - set network.atm.payload='$payload' - set network.atm.nameprefix='$nameprefix' - EOF - json_select .. - fi - - if json_is_a modem object; then - json_select modem - local type annex firmware tone xfer_mode - json_get_vars type annex firmware tone xfer_mode - uci -q batch <<-EOF - delete network.dsl - set network.dsl='dsl' - set network.dsl.annex='$annex' - set network.dsl.firmware='$firmware' - set network.dsl.tone='$tone' - set network.dsl.xfer_mode='$xfer_mode' - EOF - json_select .. - fi - json_select .. - fi -} - -addr_offset=2 -generate_network() { - local keys var val ifname macaddr proto type ipaddr netmask - - uci -q batch <<-EOF - delete "network.$1" - set network.$1='interface' - EOF - - json_select network - json_select "$1" - json_get_keys keys - for var in $keys; do - json_get_var val "$var" - [ "${var#_*}" = "$var" ] && { - eval "$var=\"\$val\"" - uci -q set "network.$1.$var=$val" - } - done - json_select .. - json_select .. - - #~ [ -n "$ifname" ] || return - - # force bridge for multi-interface devices (and lan) - case "$1:$ifname" in - *\ * | lan:*) - type="bridge" - uci -q set "network.$1.type=$type" - ;; - esac - - if [ -n "$macaddr" ]; then - for name in $ifname; do - uci -q batch <<-EOF - delete network.$1_${name/./_}_dev - set network.$1_${name/./_}_dev='device' - set network.$1_${name/./_}_dev.name='$name' - set network.$1_${name/./_}_dev.macaddr='$macaddr' - EOF - done - fi - - case "$proto" in - static) - local ipad - case "$1" in - lan) - ipad=${ipaddr:-"192.168.100.1"} - ;; - *) ipad=${ipaddr:-"192.168.$((addr_offset++)).1"} ;; - esac - - netm=${netmask:-"255.255.255.0"} - - uci -q batch <<-EOF - set network.$1.proto='static' - set network.$1.ipaddr='$ipad' - set network.$1.netmask='$netm' - EOF - [ -e /proc/sys/net/ipv6 ] && uci set network.$1.ip6assign='60' - ;; - - dhcp) - # fixup IPv6 slave interface if parent is a bridge - [ "$type" = "bridge" ] && ifname="br-$1" - - uci set network.$1.proto='dhcp' - uci set network.$1.metric='1' - - #[ -e /proc/sys/net/ipv6 ] && { - # uci -q batch <<-EOF - # delete network.${1}6 - # set network.${1}6='interface' - # set network.${1}6.device='$ifname' - # set network.${1}6.proto='dhcpv6' - # set network.${1}6.metric='1' - # EOF - #} - ;; - - pppoe) - uci -q batch <<-EOF - set network.$1.proto='pppoe' - set network.$1.username='username' - set network.$1.password='password' - EOF - [ -e /proc/sys/net/ipv6 ] && { - uci -q batch <<-EOF - set network.$1.ipv6='1' - delete network.${1}6 - set network.${1}6='interface' - set network.${1}6.ifname='@${1}' - set network.${1}6.proto='dhcpv6' - EOF - } - ;; - esac -} - -add_modem_section() { - local id="$1" - local num="$2" - local simcount="$3" - local builtin="$4" - - for count in $(seq "$simcount"); do - interface="mob${num}s${count}a1" - local proto="wwan" - - # just like this for now - # probably we should merge connm with wwan - [ -e /dev/smd9 ] && { - proto="connm" - } - - uci -q batch <<-EOF - delete network.$interface - set network.$interface='interface' - set network.$interface.proto='$proto' - set network.$interface.modem='$id' - set network.$interface.metric='$((num+1))' - set network.$interface.sim='${count}' - set network.$interface.pdp='1' - EOF - - # just like this for now - # probably we should merge connm with wwan - [ -e /dev/smd9 ] && { - uci set network.$interface.ifname='rmnet0' - } - - update_firewall_zone "wan" "$interface" - create_multiwan_iface "$interface" "$num" - add_simcard_config "$id" "${count}" "${count}" "$builtin" - add_sim_switch_config "$id" "${count}" - add_quota_limit_config "$interface" - done - add_sms_storage_config "$id" -} - -generate_dynamic_lte() { -[ -f /lib/functions/modem.sh ] || return -. /lib/functions/modem.sh - - local interface num id simcount builtin - - #creating simcard sections from board.json file - if json_is_a modems array; then - json_get_keys modems modems - json_select modems - - num=1 - - for modem in $modems; do - json_select "$modem" - json_get_vars id simcount builtin - json_select .. - add_modem_section "$id" "$num" "$simcount" "$builtin" - num=$(( num + 1 )) - done - - json_select .. - else - ## because of RUTX8 have no default modem - # after this script runs out simcard config - # must not be empty due to external modems could appear to config - echo " " >> /etc/config/simcard - fi - - #creating simcard sections from conneted via USB - for a in `ls /sys/bus/usb/devices`; do - local vendor product - [ -f "/sys/bus/usb/devices/$a/idVendor" ] && [ -f "/sys/bus/usb/devices/$a/idProduct" ] || continue - vendor=$(cat "/sys/bus/usb/devices/$a/idVendor") - product=$(cat "/sys/bus/usb/devices/$a/idProduct") - [ -f "/lib/network/wwan/${vendor}:${product}" ] && { - add_simcard_config "$a" "1" "0" "" - } - done -} - -generate_switch_vlans_ports() { - local switch="$1" - local port ports role roles num attr val - - # - # autogenerate vlans - # - - if json_is_a roles array; then - json_get_keys roles roles - json_select roles - - for role in $roles; do - json_select "$role" - json_get_vars ports - json_select .. - - uci -q batch <<-EOF - add network switch_vlan - set network.@switch_vlan[-1].device='$switch' - set network.@switch_vlan[-1].vlan='$role' - set network.@switch_vlan[-1].ports='$ports' - EOF - done - - json_select .. - fi - - - # - # write port specific settings - # - - if json_is_a ports array; then - json_get_keys ports ports - json_select ports - - for port in $ports; do - json_select "$port" - json_get_vars num - - if json_is_a attr object; then - json_get_keys attr attr - json_select attr - uci -q batch <<-EOF - add network switch_port - set network.@switch_port[-1].device='$switch' - set network.@switch_port[-1].port=$num - EOF - - for attr in $attr; do - json_get_var val "$attr" - uci -q set network.@switch_port[-1].$attr="$val" - done - json_select .. - fi - json_select .. - done - - json_select .. - fi -} - -generate_switch() { - local key="$1" - local vlans - - json_select switch - json_select "$key" - json_get_vars enable reset blinkrate cpu_port \ - ar8xxx_mib_type ar8xxx_mib_poll_interval - - uci -q batch <<-EOF - add network switch - set network.@switch[-1].name='$key' - set network.@switch[-1].reset='$reset' - set network.@switch[-1].enable_vlan='$enable' - set network.@switch[-1].blinkrate='$blinkrate' - set network.@switch[-1].ar8xxx_mib_type='$ar8xxx_mib_type' - set network.@switch[-1].ar8xxx_mib_poll_interval='$ar8xxx_mib_poll_interval' - EOF - - generate_switch_vlans_ports "$1" - - json_select .. - json_select .. -} - - -generate_static_system() { - param=$(/sbin/mnf_info "--name") - hostname=${param:0:6} - uci -q batch <<-EOF - delete system.@system[0] - set system.system='system' - set system.@system[-1].hostname='OpenMPTCProuter' - set system.@system[-1].timezone='UTC' - set system.@system[-1].ttylogin='0' - set system.@system[-1].log_size='128' - set system.@system[-1].urandom_seed='0' - - delete system.ntp - set system.ntp='timeserver' - set system.ntp.enabled='0' - set system.ntp.enable_server='0' - add_list system.ntp.server='0.pool.ntp.org' - add_list system.ntp.server='1.pool.ntp.org' - add_list system.ntp.server='2.pool.ntp.org' - add_list system.ntp.server='3.pool.ntp.org' - - delete system.debug - set system.debug='debug' - set system.debug.sms_utils_debug_level='4' - EOF - - if json_is_a system object; then - json_select system - local hostname - #if json_get_var hostname hostname; then - # uci -q set "system.@system[-1].hostname=$hostname" - #fi - - if json_is_a ntpserver array; then - local keys key - json_get_keys keys ntpserver - json_select ntpserver - uci -q delete "system.ntp.server" - - for key in $keys; do - local server - if json_get_var server "$key"; then - uci -q add_list "system.ntp.server=$server" - fi - done - json_select .. - fi - json_select .. - fi -} - -generate_rssimon() { - local key="$1" - local cfg="rssid_$key" - local refresh threshold - - json_select rssimon - json_select "$key" - json_get_vars refresh threshold - json_select .. - json_select .. - - uci -q batch <<-EOF - delete system.$cfg - set system.$cfg='rssid' - set system.$cfg.dev='$key' - set system.$cfg.refresh='$refresh' - set system.$cfg.threshold='$threshold' - EOF -} - -generate_led() { - local key="$1" - local cfg="led_$key" - - json_select led - json_select "$key" - json_get_vars name sysfs type trigger default - - uci -q batch <<-EOF - delete system.$cfg - set system.$cfg='led' - set system.$cfg.name='$name' - set system.$cfg.sysfs='$sysfs' - set system.$cfg.trigger='$trigger' - set system.$cfg.default='$default' - EOF - - case "$type" in - gpio) - local gpio inverted - json_get_vars gpio inverted - uci -q batch <<-EOF - set system.$cfg.trigger='gpio' - set system.$cfg.gpio='$gpio' - set system.$cfg.inverted='$inverted' - EOF - ;; - - netdev) - local device mode - json_get_vars device mode - uci -q batch <<-EOF - set system.$cfg.trigger='netdev' - set system.$cfg.mode='$mode' - set system.$cfg.dev='$device' - EOF - ;; - - usb) - local device - json_get_vars device - uci -q batch <<-EOF - set system.$cfg.trigger='usbdev' - set system.$cfg.interval='50' - set system.$cfg.dev='$device' - EOF - ;; - - usbport) - local ports port - json_get_values ports ports - uci set system.$cfg.trigger='usbport' - for port in $ports; do - uci add_list system.$cfg.port=$port - done - ;; - - rssi) - local iface minq maxq offset factor - json_get_vars iface minq maxq offset factor - uci -q batch <<-EOF - set system.$cfg.trigger='rssi' - set system.$cfg.iface='rssid_$iface' - set system.$cfg.minq='$minq' - set system.$cfg.maxq='$maxq' - set system.$cfg.offset='$offset' - set system.$cfg.factor='$factor' - EOF - ;; - - switch) - local port_mask speed_mask mode - json_get_vars port_mask speed_mask mode - uci -q batch <<-EOF - set system.$cfg.port_mask='$port_mask' - set system.$cfg.speed_mask='$speed_mask' - set system.$cfg.mode='$mode' - EOF - ;; - - portstate) - local port_state - json_get_vars port_state - uci -q batch <<-EOF - set system.$cfg.port_state='$port_state' - EOF - ;; - - timer|oneshot) - local delayon delayoff - json_get_vars delayon delayoff - uci -q batch <<-EOF - set system.$cfg.trigger='$type' - set system.$cfg.delayon='$delayon' - set system.$cfg.delayoff='$delayoff' - EOF - ;; - esac - - json_select .. - json_select .. -} - -generate_gpioswitch() { - local cfg="$1" - - json_select gpioswitch - json_select "$cfg" - local name pin default - json_get_vars name pin default - uci -q batch <<-EOF - delete system.$cfg - set system.$cfg='gpio_switch' - set system.$cfg.name='$name' - set system.$cfg.gpio_pin='$pin' - set system.$cfg.value='$default' - EOF - json_select .. - json_select .. -} - -generate_hwinfo() { - local parameter="$1" - local temp - - json_select hwinfo - json_get_var temp "$parameter" - json_select .. - - uci -q batch <<-EOF - set hwinfo.hwinfo='hwinfo' - set hwinfo.hwinfo.$parameter='$temp' - EOF -} - -generate_bluetooth() { - uci -q batch <<-EOF - set blesem.general='section' - set blesem.general.enabled='0' - set blesem.settings='app' - set blesem.settings.refresh_time='30000' - EOF -} - -add_firewall_zone() { - local ifname - - json_select network - json_select "$1" - json_get_vars ifname - json_select .. - json_select .. - - fw3 -q network "$1" || fw3 -q device "$ifname" && return - - uci -q batch <<-EOF - add firewall zone - set firewall.@zone[-1].name='$1' - set firewall.@zone[-1].network='$1' - set firewall.@zone[-1].input='REJECT' - set firewall.@zone[-1].output='ACCEPT' - set firewall.@zone[-1].forward='REJECT' - - add firewall forwarding - set firewall.@forwarding[-1].src='$1' - set firewall.@forwarding[-1].dest='wan' - - add firewall rule - set firewall.@rule[-1].name='Allow-DNS-$1' - set firewall.@rule[-1].src='$1' - set firewall.@rule[-1].dest_port='53' - set firewall.@rule[-1].proto='tcp udp' - set firewall.@rule[-1].target='ACCEPT' - - add firewall rule - set firewall.@rule[-1].name='Allow-DHCP-$1' - set firewall.@rule[-1].src='$1' - set firewall.@rule[-1].dest_port='67' - set firewall.@rule[-1].proto='udp' - set firewall.@rule[-1].family='ipv4' - set firewall.@rule[-1].target='ACCEPT' - EOF -} - -add_dhcp() { - - json_select network - json_select "$1" - json_get_vars _dhcp - json_select .. - json_select .. - - [ "$_dhcp" = "1" ] || return - uci -q batch <<-EOF - set dhcp.$1='dhcp' - set dhcp.$1.interface='$1' - set dhcp.$1.start='100' - set dhcp.$1.limit='150' - set dhcp.$1.leasetime='1h' - EOF -} - -json_init -json_load "$(cat ${CFG})" - -umask 077 - -if [ ! -s /etc/config/network ]; then - touch /etc/config/network - generate_static_network - - json_get_keys keys network - for key in $keys; do - generate_network $key - add_firewall_zone "$key" - add_dhcp "$key" - done - - json_get_keys keys switch - for key in $keys; do generate_switch $key; done - - generate_dynamic_lte -fi - -if [ ! -s /etc/config/system ]; then - touch /etc/config/system - generate_static_system - - json_get_keys keys rssimon - for key in $keys; do generate_rssimon $key; done - - json_get_keys keys gpioswitch - for key in $keys; do generate_gpioswitch $key; done - - json_get_keys keys led - for key in $keys; do generate_led $key; done -fi - -if [ ! -s /etc/config/hwinfo ]; then - touch /etc/config/hwinfo - json_get_keys keys hwinfo - for key in $keys; do generate_hwinfo $key; done -fi - -if [ ! -s /etc/config/blesem ]; then - bluetooth="" - json_select hwinfo - json_get_vars bluetooth - [ "$bluetooth" -eq 1 ] && { - touch /etc/config/blesem - touch /etc/config/ble_devices - generate_bluetooth - } -fi - -uci commit diff --git a/root/target/linux/ipq40xx/base-files/bin/ipcalc.sh b/root/target/linux/ipq40xx/base-files/bin/ipcalc.sh deleted file mode 100644 index 5d5eac3e..00000000 --- a/root/target/linux/ipq40xx/base-files/bin/ipcalc.sh +++ /dev/null @@ -1,71 +0,0 @@ -#!/bin/sh - -awk -f - $* <limit) end=limit - - print "IP="int2ip(ipaddr) - print "NETMASK="int2ip(netmask) - print "BROADCAST="int2ip(broadcast) - print "NETWORK="int2ip(network) - print "PREFIX="32-bitcount(compl32(netmask)) - - # range calculations: - # ipcalc - - if (ARGC > 3) { - print "START="int2ip(start) - print "END="int2ip(end) - } -} -EOF diff --git a/root/target/linux/ipq40xx/base-files/etc/board.d/1-board_json b/root/target/linux/ipq40xx/base-files/etc/board.d/1-board_json deleted file mode 100644 index 619e0062..00000000 --- a/root/target/linux/ipq40xx/base-files/etc/board.d/1-board_json +++ /dev/null @@ -1,207 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2015 The Linux Foundation. All rights reserved. -# Copyright (c) 2011-2015 OpenWrt.org -# - -. /lib/functions/uci-defaults.sh -. /lib/functions/teltonika-defaults.sh -. /lib/functions/system.sh - -setup_json() { - local model="$1" - - case "$model" in - RUTX08*) - ucidef_set_interfaces_lan_wan "eth0" "eth1" - ucidef_add_switch "switch0" \ - "0u@eth0" "2:lan:1" "3:lan:2" "4:lan:3" "0u@eth1" "5:wan" - ucidef_set_hwinfo usb ethernet ios - ;; - RUTX09*) - ucidef_set_interfaces_lan_wan "eth0" "eth1" - ucidef_add_switch "switch0" \ - "0u@eth0" "2:lan:1" "3:lan:2" "4:lan:3" "0u@eth1" "5:wan" - ucidef_add_static_modem_info "$model" "3-1" "2" "gps_out" - ucidef_set_hwinfo dual_sim usb gps mobile ethernet ios - ;; - RUTX10*) - ucidef_set_interfaces_lan_wan "eth0" "eth1" - ucidef_add_switch "switch0" \ - "0u@eth0" "2:lan:1" "3:lan:2" "4:lan:3" "0u@eth1" "5:wan" - ucidef_set_hwinfo bluetooth usb wifi dual_band_ssid ethernet ios - ;; - RUTX11*) - ucidef_set_interfaces_lan_wan "eth0" "eth1" - ucidef_add_switch "switch0" \ - "0u@eth0" "2:lan:1" "3:lan:2" "4:lan:3" "0u@eth1" "5:wan" - ucidef_add_static_modem_info "$model" "3-1" "2" "gps_out" - ucidef_set_hwinfo dual_sim usb gps mobile wifi dual_band_ssid bluetooth ethernet ios - ;; - RUTXR1*) - ucidef_set_interfaces_lan_wan "eth0" "eth1" - ucidef_add_switch "switch0" \ - "0u@eth0" "1:lan" "2:lan" "3:lan" "4:lan" "0u@eth1" "5:wan" - ucidef_add_static_modem_info "$model" "3-1" "2" - ucidef_set_hwinfo dual_sim usb mobile wifi dual_band_ssid ethernet sfp_port - ucidef_set_release_version "2.3.1" - ;; - RUTX12*) - ucidef_set_interfaces_lan_wan "eth0" "eth1" - ucidef_add_switch "switch0" \ - "0u@eth0" "1:lan" "2:lan" "3:lan" "4:lan" "0u@eth1" "5:wan" - # builtin and primary should be first modem - ucidef_add_static_modem_info "$model" "3-1" "1" "primary" "gps_out" - ucidef_add_static_modem_info "$model" "1-1.2" "1" - ucidef_set_hwinfo usb gps mobile wifi dual_band_ssid bluetooth ethernet ios - ucidef_set_release_version "2.3.1" - ;; - RUTX14*) - ucidef_set_interfaces_lan_wan "eth0" "eth1" - ucidef_add_switch "switch0" \ - "0u@eth0" "1:lan" "2:lan" "3:lan" "4:lan" "0u@eth1" "5:wan" - ucidef_add_static_modem_info "$model" "1-1" "2" "gps_out" - ucidef_set_hwinfo usb gps dual_sim mobile wifi dual_band_ssid bluetooth ethernet ios at_sim - ucidef_set_release_version "2.6.1" - ;; - RUTX18*) - ucidef_set_interfaces_lan_wan "eth0" "eth1" - ucidef_add_switch "switch0" \ - "0u@eth0" "1:lan" "2:lan" "3:lan" "4:lan" "0u@eth1" "5:wan" - ucidef_add_static_modem_info "$model" "2-1" "2" "gps_out" - ucidef_set_hwinfo usb gps dual_sim mobile wifi dual_band_ssid bluetooth ethernet ios - ;; - TRB2*) - ucidef_set_led_switch "lan" "LAN" "eth_led" "switch0" "0x04" - ucidef_set_interface_lan "eth0" - ucidef_add_static_modem_info "$model" "1-1.4" "2" "gps_out" - ucidef_add_serial_capabilities "rs232 rs485" \ - "300 600 1200 2400 4800 9600 14400 19200 38400 56000 57600 115200 \ - 230400 460800 921600 1000000 3000000" \ - "7 8" - ucidef_set_hwinfo dual_sim mobile gps ethernet ios - ;; - RUT200* |\ - RUT241*) - ucidef_set_led_switch "lan" "LAN" "eth1_led" "switch0" "0x2" - ucidef_set_led_switch "wan" "WAN" "eth2_led" "switch0" "0x1" - ucidef_add_switch "switch0" "1:lan" "0:wan" "6@eth0" - ucidef_set_interface_macaddr "lan" "$(mtd_get_mac_binary config 0x0)" - ucidef_set_interface_macaddr "wan" "$(macaddr_add "$(mtd_get_mac_binary config 0x0)" 1)" - ucidef_add_static_modem_info "$model" "1-1" "1" - [ "${model:7:1}" = "1" ] && ucidef_set_hwinfo mobile wifi \ - ethernet || ucidef_set_hwinfo mobile wifi ethernet ios - ;; - RUT2*) - ucidef_set_led_switch "lan" "LAN" "lan_led" "switch0" "0x04" - ucidef_set_led_netdev "wan" "WAN" "wan_led" "eth1" - ucidef_set_interfaces_lan_wan "eth0" "eth1" - ucidef_add_static_modem_info "$model" "1-1" "1" - [ "${model:6:1}" = "1" ] && ucidef_set_hwinfo mobile wifi \ - ethernet || ucidef_set_hwinfo mobile wifi ethernet ios - ;; - RUT300*) - ucidef_set_led_switch "lan1" "LAN1" "eth1_led" "switch0" "0x02" - ucidef_set_led_switch "lan2" "LAN2" "eth2_led" "switch0" "0x10" - ucidef_set_led_switch "lan3" "LAN3" "eth3_led" "switch0" "0x08" - ucidef_set_led_switch "lan4" "LAN4" "eth4_led" "switch0" "0x04" - ucidef_set_led_netdev "wan" "WAN" "wan_led" "eth1" - ucidef_set_interface_wan "eth1" - ucidef_add_switch "switch0" \ - "0@eth0" "1:lan:1" "2:lan:4" "3:lan:3" "4:lan:2" - ucidef_set_hwinfo usb ethernet ios - ;; - RUT360*) - ucidef_set_led_switch "lan" "LAN" "eth1_led" "switch0" "0x10" - ucidef_set_led_netdev "wan" "WAN" "eth2_led" "eth1" - ucidef_set_interfaces_lan_wan "eth0" "eth1" - ucidef_add_static_modem_info "$model" "1-1" "1" - ucidef_set_hwinfo mobile wifi dual_band_ssid ethernet ios - ;; - RUT950*) - ucidef_set_led_switch "lan1" "LAN1" "eth1_led" "switch0" "0x10" - ucidef_set_led_switch "lan2" "LAN2" "eth2_led" "switch0" "0x08" - ucidef_set_led_switch "lan3" "LAN3" "eth3_led" "switch0" "0x04" - ucidef_set_led_netdev "wan" "WAN" "wan_led" "eth1" - ucidef_set_interface_wan "eth1" - ucidef_add_switch "switch0" "0@eth0" "2:lan:3" "3:lan:2" "4:lan:1" - ucidef_add_static_modem_info "$model" "1-1" "2" - [ "${model:7:2}" = "06" ] && ucidef_set_hwinfo dual_sim mobile \ - wifi ethernet || ucidef_set_hwinfo dual_sim mobile wifi ethernet ios - ;; - RUT955*) - ucidef_set_led_switch "lan1" "LAN1" "eth1_led" "switch0" "0x10" - ucidef_set_led_switch "lan2" "LAN2" "eth2_led" "switch0" "0x08" - ucidef_set_led_switch "lan3" "LAN3" "eth3_led" "switch0" "0x04" - ucidef_set_led_netdev "wan" "WAN" "wan_led" "eth1" - ucidef_set_interface_wan "eth1" - ucidef_add_switch "switch0" "0@eth0" "2:lan:3" "3:lan:2" "4:lan:1" - ucidef_add_static_modem_info "$model" "1-1.4" "2" "gps_out" - [ "${model:7:2}" = "06" ] && ucidef_set_hwinfo dual_sim usb gps \ - mobile wifi ethernet || ucidef_set_hwinfo dual_sim usb gps \ - mobile wifi ethernet ios - ucidef_add_serial_capabilities "rs232" \ - "200 300 600 1200 1800 2400 4800 9600 19200 38400 57600 115200 \ - 230400 460800 500000 576000" \ - "5 6 7 8" - ucidef_add_serial_capabilities "rs485" \ - "300 600 1200 1800 2400 4800 9600 19200 38400 57600 115200 230400 \ - 460800 500000 576000 921600 1000000 1152000 1500000 2000000 \ - 2500000 3000000" \ - "8" - ;; - TRB140*) - ucidef_set_interface_lan "eth0 rndis0" - ucidef_add_trb14x_lte_modem "$model" - ucidef_add_nand_info "$model" - [ "${model:7:1}" = "2" ] && ucidef_set_hwinfo mobile ethernet || \ - ucidef_set_hwinfo mobile ethernet ios - ;; - TRB141*) - ucidef_set_interface_lan "rndis0" - ucidef_add_trb14x_lte_modem "$model" - ucidef_add_nand_info "$model" - ucidef_set_hwinfo mobile ios - ;; - TRB142* |\ - TRB145*) - ucidef_set_interface_lan "rndis0" - ucidef_add_trb14x_lte_modem "$model" - ucidef_add_nand_info "$model" - [ "${model:7:1}" = "2" ] && ucidef_set_hwinfo mobile || \ - ucidef_set_hwinfo mobile ios - [ "${model:5:1}" = "2" ] && local rs="rs232" - ucidef_add_serial_capabilities "${rs:-rs485}" \ - "300 600 1200 2400 4800 9600 19200 38400 57600 115200 460800" \ - "5 6 7 8" - [ "${model:5:2}" = "23" -o "${model:5:2}" = "52" ] && \ - ucidef_set_release_version "7.1" - ;; - TCR100*) - ucidef_set_led_switch "lan" "LAN" "eth1_led" "switch0" "0x10" - ucidef_set_led_netdev "wan" "WAN" "eth2_led" "eth1" - ucidef_set_interfaces_lan_wan "eth0" "eth1" - ucidef_set_interface guest proto static type bridge \ - guest 1 _wireless true _dhcp true - ucidef_add_static_modem_info "$model" "1-1" "1" - ucidef_set_hwinfo mobile wifi dual_band_ssid wps ethernet - ;; - *) - echo "Unsupported hardware. Network interfaces not intialized" - ;; - esac -} - -#~ Get model name for RUTX products -model="$(mnf_info --name)" 2>/dev/null - -platform="$(cat /proc/device-tree/platform)" 2>/dev/null - -board_config_update -setup_json "$model" - -ucidef_set_board_platform "$platform" - -board_config_flush - -exit 0 diff --git a/root/target/linux/ipq40xx/base-files/etc/init.d/boot b/root/target/linux/ipq40xx/base-files/etc/init.d/boot deleted file mode 100644 index 85549882..00000000 --- a/root/target/linux/ipq40xx/base-files/etc/init.d/boot +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2006-2011 OpenWrt.org - -START=10 -STOP=90 - -uci_apply_defaults() { - . /lib/functions/system.sh - - cd /etc/uci-defaults || return 0 - files="$(find . -type f | sort)" - [ -z "$files" ] && return 0 - mkdir -p /tmp/.uci - for file in $files; do - ( . "./$file" ) && rm -f "$file" - done - uci commit -} - -boot() { - [ -f /proc/mounts ] || /sbin/mount_root - [ -f /proc/jffs2_bbc ] && echo "S" > /proc/jffs2_bbc - - mkdir -p /var/run - mkdir -p /var/log - mkdir -p /var/lock - mkdir -p /var/state - mkdir -p /var/tmp - mkdir -p /tmp/.uci - chmod 0700 /tmp/.uci - touch /var/log/wtmp - touch /var/log/lastlog - mkdir -p /tmp/resolv.conf.d - touch /tmp/resolv.conf.d/resolv.conf.auto - ln -sf /tmp/resolv.conf.d/resolv.conf.auto /tmp/resolv.conf - grep -q debugfs /proc/filesystems && /bin/mount -o noatime -t debugfs debugfs /sys/kernel/debug - grep -q bpf /proc/filesystems && /bin/mount -o nosuid,nodev,noexec,noatime,mode=0700 -t bpf bpffs /sys/fs/bpf - grep -q pstore /proc/filesystems && /bin/mount -o noatime -t pstore pstore /sys/fs/pstore - - # mount all entries in fstab - /bin/mount -a & - - # /log directory might be created on preinit - # symlink /storage to /log on TRB14X devices - [ -d /storage -a ! -h /log ] && { - rm -rf /log - ln -sf /storage /log - } - - # Wifi --- - param=$(/sbin/mnf_info "--name") - router_name=${param:0:6} - if [ $router_name == "RUTX08" ] || [ $router_name == "RUTX09" ]; then - rm /etc/modules.d/ath10k - fi - - /bin/board_detect - - /sbin/kmodloader - - /bin/config_generate - uci_apply_defaults - - [ -f "/etc/config/teltonika" ] && rm /etc/config/teltonika - - # temporary hack until configd exists - /sbin/reload_config - # leave finished boot script indication - touch /var/run/boot-done -} diff --git a/root/target/linux/ipq40xx/base-files/etc/init.d/done b/root/target/linux/ipq40xx/base-files/etc/init.d/done deleted file mode 100644 index b64e6e4d..00000000 --- a/root/target/linux/ipq40xx/base-files/etc/init.d/done +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2006 OpenWrt.org - -START=95 -boot() { - mount_root done - rm -f /sysupgrade.tgz && sync - - # process user commands - [ -f /etc/rc.local ] && { - sh /etc/rc.local - } -} diff --git a/root/target/linux/ipq40xx/base-files/etc/init.d/gpio_switch b/root/target/linux/ipq40xx/base-files/etc/init.d/gpio_switch deleted file mode 100644 index 24d790b0..00000000 --- a/root/target/linux/ipq40xx/base-files/etc/init.d/gpio_switch +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2015 OpenWrt.org - -START=94 -STOP=10 -USE_PROCD=1 - - -load_gpio_switch() -{ - local name - local gpio_pin - local value - - config_get gpio_pin "$1" gpio_pin - config_get name "$1" name - config_get value "$1" value 0 - - [ -z "$gpio_pin" ] && { - echo >&2 "Skipping gpio_switch '$name' due to missing gpio_pin" - return 1 - } - - local gpio_path - if [ -n "$(echo "$gpio_pin" | grep -E "^[0-9]+$")" ]; then - gpio_path="/sys/class/gpio/gpio${gpio_pin}" - - # export GPIO pin for access - [ -d "$gpio_path" ] || { - echo "$gpio_pin" >/sys/class/gpio/export - # we need to wait a bit until the GPIO appears - [ -d "$gpio_path" ] || sleep 1 - } - - # direction attribute only exists if the kernel supports changing the - # direction of a GPIO - if [ -e "${gpio_path}/direction" ]; then - # set the pin to output with high or low pin value - { [ "$value" = "0" ] && echo "low" || echo "high"; } \ - >"$gpio_path/direction" - else - { [ "$value" = "0" ] && echo "0" || echo "1"; } \ - >"$gpio_path/value" - fi - else - gpio_path="/sys/class/gpio/${gpio_pin}" - - [ -d "$gpio_path" ] && { - { [ "$value" = "0" ] && echo "0" || echo "1"; } \ - >"$gpio_path/value" - } - fi -} - -service_triggers() -{ - procd_add_reload_trigger "system" -} - -start_service() -{ - [ -e /sys/class/gpio/ ] && { - config_load system - config_foreach load_gpio_switch gpio_switch - } -} diff --git a/root/target/linux/ipq40xx/base-files/etc/init.d/led b/root/target/linux/ipq40xx/base-files/etc/init.d/led deleted file mode 100644 index 277fb4e7..00000000 --- a/root/target/linux/ipq40xx/base-files/etc/init.d/led +++ /dev/null @@ -1,140 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2008 OpenWrt.org - -START=96 - -load_led() { - local name - local sysfs - local trigger - local dev - local ports - local mode - local default - local delayon - local delayoff - local interval - - config_get sysfs $1 sysfs - config_get name $1 name "$sysfs" - config_get trigger $1 trigger "none" - config_get dev $1 dev - config_get ports $1 port - config_get mode $1 mode - config_get_bool default $1 default "0" - config_get delayon $1 delayon - config_get delayoff $1 delayoff - config_get interval $1 interval "50" - config_get port_state $1 port_state - config_get delay $1 delay "150" - config_get message $1 message "" - config_get gpio $1 gpio "0" - config_get inverted $1 inverted "0" - - if [ "$trigger" = "rssi" ]; then - # handled by rssileds userspace process - return - fi - - [ "$trigger" = "usbdev" ] && { - # Backward compatibility: translate to the new trigger - trigger="usbport" - # Translate port of root hub, e.g. 4-1 -> usb4-port1 - ports=$(echo "$dev" | sed -n 's/^\([0-9]*\)-\([0-9]*\)$/usb\1-port\2/p') - # Translate port of extra hub, e.g. 2-2.4 -> 2-2-port4 - [ -z "$ports" ] && ports=$(echo "$dev" | sed -n 's/\./-port/p') - } - - [ -e /sys/class/leds/${sysfs}/brightness ] && { - echo "setting up led ${name}" - - printf "%s %s %d\n" \ - "$sysfs" \ - "$(sed -ne 's/^.*\[\(.*\)\].*$/\1/p' /sys/class/leds/${sysfs}/trigger)" \ - "$(cat /sys/class/leds/${sysfs}/brightness)" \ - >> /var/run/led.state - - [ "$default" = 0 ] && - echo 0 >/sys/class/leds/${sysfs}/brightness - - echo $trigger > /sys/class/leds/${sysfs}/trigger 2> /dev/null - ret="$?" - - [ $default = 1 ] && - cat /sys/class/leds/${sysfs}/max_brightness > /sys/class/leds/${sysfs}/brightness - - [ $ret = 0 ] || { - echo >&2 "Skipping trigger '$trigger' for led '$name' due to missing kernel module" - return 1 - } - case "$trigger" in - "netdev") - [ -n "$dev" ] && { - echo $dev > /sys/class/leds/${sysfs}/device_name - for m in $mode; do - [ -e "/sys/class/leds/${sysfs}/$m" ] && \ - echo 1 > /sys/class/leds/${sysfs}/$m - done - echo $interval > /sys/class/leds/${sysfs}/interval - } - ;; - - "timer"|"oneshot") - [ -n "$delayon" ] && \ - echo $delayon > /sys/class/leds/${sysfs}/delay_on - [ -n "$delayoff" ] && \ - echo $delayoff > /sys/class/leds/${sysfs}/delay_off - ;; - - "usbport") - local p - - for p in $ports; do - echo 1 > /sys/class/leds/${sysfs}/ports/$p - done - ;; - - "port_state") - [ -n "$port_state" ] && \ - echo $port_state > /sys/class/leds/${sysfs}/port_state - ;; - - "gpio") - echo $gpio > /sys/class/leds/${sysfs}/gpio - echo $inverted > /sys/class/leds/${sysfs}/inverted - ;; - - switch[0-9]*) - local port_mask speed_mask - - config_get port_mask $1 port_mask - [ -n "$port_mask" ] && \ - echo $port_mask > /sys/class/leds/${sysfs}/port_mask - config_get speed_mask $1 speed_mask - [ -n "$speed_mask" ] && \ - echo $speed_mask > /sys/class/leds/${sysfs}/speed_mask - [ -n "$mode" ] && \ - echo "$mode" > /sys/class/leds/${sysfs}/mode - ;; - esac - } -} - -start() { - [ -e /sys/class/leds/ ] && { - [ -s /var/run/led.state ] && { - local led trigger brightness - while read led trigger brightness; do - [ -e "/sys/class/leds/$led/trigger" ] && \ - echo "$trigger" > "/sys/class/leds/$led/trigger" - - [ -e "/sys/class/leds/$led/brightness" ] && \ - echo "$brightness" > "/sys/class/leds/$led/brightness" - done < /var/run/led.state - rm /var/run/led.state - } - - config_load system - config_foreach load_led led - } -} diff --git a/root/target/linux/ipq40xx/base-files/etc/init.d/modem_tracker b/root/target/linux/ipq40xx/base-files/etc/init.d/modem_tracker deleted file mode 100644 index 46202b76..00000000 --- a/root/target/linux/ipq40xx/base-files/etc/init.d/modem_tracker +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2021 Teltonika Networks -# Copyright (C) 2022 Ycarus (Yannick Chabanois) - -START=2 - -USE_PROCD=1 - -PROG=/bin/board_track -NAME=board_track -PIDCOUNT=1 - -start_service() { - . /lib/functions - - [ "$(board_name)" != "teltonika,rutx" ] && return 0 - local pid_file="/var/run/${NAME}.${PIDCOUNT}.pid" - - procd_open_instance - procd_set_param command "$PROG" - procd_set_param file /etc/config/system - - procd_set_param respawn - - procd_set_param stdout 1 - procd_set_param pidfile $pid_file - procd_close_instance -} - -reload_service() { - stop - start -} - -service_triggers() { - procd_add_reload_trigger "system" -} diff --git a/root/target/linux/ipq40xx/base-files/etc/init.d/ntpserver b/root/target/linux/ipq40xx/base-files/etc/init.d/ntpserver deleted file mode 100644 index 78095bd4..00000000 --- a/root/target/linux/ipq40xx/base-files/etc/init.d/ntpserver +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh /etc/rc.common - -# Copyright (C) 2021 Teltonika - -START=50 -STOP=51 -USE_PROCD=1 - -service_triggers() -{ - procd_add_reload_trigger "ntpserver" -} - -start_service() { - . /lib/functions.sh - local enabled - - config_load ntpserver - config_get enabled general enabled "0" - - [ "$enabled" -gt 0 ] || return - - logger -t "ntpd" "Starting NTP server" - procd_open_instance - procd_set_param respawn 0 - procd_set_param command "ntpd" -ln - procd_close_instance -} diff --git a/root/target/linux/ipq40xx/base-files/etc/init.d/powerctl b/root/target/linux/ipq40xx/base-files/etc/init.d/powerctl deleted file mode 100644 index 7b346fc5..00000000 --- a/root/target/linux/ipq40xx/base-files/etc/init.d/powerctl +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh /etc/rc.common - -START=98 - -ipq40xx_power_auto() { - # change scaling governor as ondemand to enable clock scaling based on system load - echo "performance" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor - - # set scaling min freq as 200 MHz - echo "716000" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq - - # Change sampling rate for frequency scaling decisions to 1s, from 10 ms - #echo "1000000" > /sys/devices/system/cpu/cpufreq/ondemand/sampling_rate - - # Change sampling rate for frequency down scaling decision to 10s - #echo 10 > /sys/devices/system/cpu/cpufreq/ondemand/sampling_down_factor - - # Change the CPU load threshold above which frequency is up-scaled to - # turbo frequency,to 50% - #echo 50 > /sys/devices/system/cpu/cpufreq/ondemand/up_threshold -} - -start() { - . /lib/functions.sh - - local board=$(board_name) - case "$board" in - teltonika,rutx | ap-dk01.1-c1 | ap-dk01.1-c2 | ap-dk04.1-c1 | ap-dk04.1-c2 | ap-dk04.1-c3 | \ - ap-dk04.1-c4 | ap-dk04.1-c5 | ap-dk05.1-c1 | ap-dk06.1-c1 | ap-dk07.1-c1 | ap-dk07.1-c2 | ap-dk07.1-c3) - ipq40xx_power_auto ;; - esac -} diff --git a/root/target/linux/ipq40xx/base-files/etc/init.d/set-irq-affinity b/root/target/linux/ipq40xx/base-files/etc/init.d/set-irq-affinity deleted file mode 100644 index 910f661b..00000000 --- a/root/target/linux/ipq40xx/base-files/etc/init.d/set-irq-affinity +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh /etc/rc.common - -START=99 - -start() { - mask=4 - for rps in /sys/class/net/eth0/queues/rx-* - do - echo "$mask" > "$rps/rps_cpus" - done - for irq in $(grep -F "ath10k_ahb" /proc/interrupts | cut -d: -f1 | sed 's, *,,') - do - echo "$mask" > "/proc/irq/$irq/smp_affinity" - mask=8 - done - - mask=2 - for irq in $(grep -F "edma_eth_rx" /proc/interrupts | cut -d: -f1 | sed 's, *,,') - do - echo "$mask" > "/proc/irq/$irq/smp_affinity" - done -} \ No newline at end of file diff --git a/root/target/linux/ipq40xx/base-files/etc/init.d/sysctl b/root/target/linux/ipq40xx/base-files/etc/init.d/sysctl deleted file mode 100644 index 01416a5c..00000000 --- a/root/target/linux/ipq40xx/base-files/etc/init.d/sysctl +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2006 OpenWrt.org - -START=11 - -apply_defaults() { - local mem="$(awk '/^MemTotal:/ {print $2}' /proc/meminfo)" - local min_free frag_low_thresh frag_high_thresh - - if [ "$mem" -gt 65536 ]; then # 128M - min_free=16384 - elif [ "$mem" -gt 32768 ]; then # 64M - #Too high for RUT3 device, lets make 2048 - #min_free=8192 - min_free=2048 - else - min_free=1024 - frag_low_thresh=393216 - frag_high_thresh=524288 - fi - - sysctl -qw vm.min_free_kbytes="$min_free" - - [ "$frag_low_thresh" ] && sysctl -qw \ - net.ipv4.ipfrag_low_thresh="$frag_low_thresh" \ - net.ipv4.ipfrag_high_thresh="$frag_high_thresh" \ - net.ipv6.ip6frag_low_thresh="$frag_low_thresh" \ - net.ipv6.ip6frag_high_thresh="$frag_high_thresh" \ - net.netfilter.nf_conntrack_frag6_low_thresh="$frag_low_thresh" \ - net.netfilter.nf_conntrack_frag6_high_thresh="$frag_high_thresh" - - # first set default, then all interfaces to avoid races with appearing interfaces - if [ -d /proc/sys/net/ipv6/conf ]; then - echo 0 > /proc/sys/net/ipv6/conf/default/accept_ra - for iface in /proc/sys/net/ipv6/conf/*/accept_ra; do - echo 0 > "$iface" - done - fi -} - -start() { - apply_defaults - for CONF in /etc/sysctl.d/*.conf /etc/sysctl.conf; do - [ -f "$CONF" ] && sysctl -e -p "$CONF" >&- - done -} diff --git a/root/target/linux/ipq40xx/base-files/etc/init.d/sysfixtime b/root/target/linux/ipq40xx/base-files/etc/init.d/sysfixtime deleted file mode 100644 index 47d7af61..00000000 --- a/root/target/linux/ipq40xx/base-files/etc/init.d/sysfixtime +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2013-2014 OpenWrt.org - -START=00 -STOP=90 - -RTC_DEV=/dev/rtc0 -HWCLOCK=/sbin/hwclock - -boot() { -# start && exit 0 - - local maxtime="$(maxtime)" - local curtime="$(date +%s)" - [ $curtime -lt $maxtime ] && date -s @$maxtime -} - -start() { - boot -} - -stop() { - [ -e "$RTC_DEV" ] && [ -e "$HWCLOCK" ] && $HWCLOCK -w -u -f $RTC_DEV && \ - logger -t sysfixtime "saved '$(date)' to $RTC_DEV" -} - -maxtime() { - local file newest - - for file in $( find /etc -type f ) ; do - [ -z "$newest" -o "$newest" -ot "$file" ] && newest=$file - done - [ "$newest" ] && date -r "$newest" +%s -} diff --git a/root/target/linux/ipq40xx/base-files/etc/init.d/system b/root/target/linux/ipq40xx/base-files/etc/init.d/system deleted file mode 100644 index 0e467091..00000000 --- a/root/target/linux/ipq40xx/base-files/etc/init.d/system +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2014 OpenWrt.org - -START=10 -USE_PROCD=1 - -validate_system_section() { - uci_load_validate system system "$1" "$2" \ - 'hostname:string:%%NAME%%' \ - 'conloglevel:uinteger' \ - 'buffersize:uinteger' \ - 'timezone:string:UTC' \ - 'zonename:string' -} - -system_config() { - [ "$2" = 0 ] || { - echo "validation failed" - return 1 - } - - echo "$hostname" > /proc/sys/kernel/hostname - [ -z "$conloglevel" -a -z "$buffersize" ] || dmesg ${conloglevel:+-n $conloglevel} ${buffersize:+-s $buffersize} - echo "$timezone" > /tmp/TZ - [ -n "$zonename" ] && [ -f "/usr/share/zoneinfo/${zonename// /_}" ] \ - && ln -sf "/usr/share/zoneinfo/${zonename// /_}" /tmp/localtime \ - && rm -f /tmp/TZ - - # apply timezone to kernel - hwclock -u --systz -} - -reload_service() { - config_load system - config_foreach validate_system_section system system_config -} - -service_triggers() { - procd_add_reload_trigger "system" - procd_add_validation validate_system_section -} - -start_service() { - reload_service -} diff --git a/root/target/linux/ipq40xx/base-files/etc/init.d/umount b/root/target/linux/ipq40xx/base-files/etc/init.d/umount deleted file mode 100644 index b764ae15..00000000 --- a/root/target/linux/ipq40xx/base-files/etc/init.d/umount +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2006 OpenWrt.org - -STOP=90 - -restart() { - : -} - -stop() { - sync - /bin/umount -a -d -r -} diff --git a/root/target/linux/ipq40xx/base-files/lib/functions/teltonika-defaults.sh b/root/target/linux/ipq40xx/base-files/lib/functions/teltonika-defaults.sh deleted file mode 100644 index 5cb17a99..00000000 --- a/root/target/linux/ipq40xx/base-files/lib/functions/teltonika-defaults.sh +++ /dev/null @@ -1,284 +0,0 @@ -#!/bin/ash - -. /lib/functions.sh -. /usr/share/libubox/jshn.sh - -ucidef_add_nand_info() { - local model="$1" - - model=${model:0:7} - - json_select_object nand - - case "$model" in - TRB1412) - json_add_int blocksize 128 - json_add_int pagesize 2048 - json_add_int subpagesize 2048 - ;; - TRB1422 |\ - TRB1423 |\ - TRB1452) - json_add_int blocksize 256 - json_add_int pagesize 4096 - json_add_int subpagesize 4096 - ;; - TRB14*0) - json_add_int blocksize 128 - json_add_int pagesize 2048 - json_add_int subpagesize 2048 - ;; - TRB14*1) - json_add_int blocksize 256 - json_add_int pagesize 4096 - json_add_int subpagesize 4096 - ;; - esac - - json_select .. -} - -ucidef_add_static_modem_info() { - #Parameters: model usb_id sim_count other_params - local model usb_id count - local modem_counter=0 - local sim_count=1 - - model="$1" - usb_id="$2" - - [ -n "$3" ] && sim_count="$3" - - json_get_keys count modems - [ -n "$count" ] && modem_counter="$(echo "$count" | wc -w)" - - json_select_array "modems" - json_add_object - json_add_string id "$usb_id" - json_add_string num "$((modem_counter + 1))" - json_add_boolean builtin 1 - json_add_int simcount "$sim_count" - - for i in "$@"; do - case "$i" in - primary) - json_add_boolean primary 1 - ;; - gps_out) - json_add_boolean gps_out 1 - ;; - esac - done - - json_close_object - json_select .. -} - -ucidef_add_trb14x_lte_modem() { - print_array() { - json_add_array $1 - for element in $2 - do - json_add_string "" "$(echo $element)" - done - json_close_array - } - #Parameters: model primary - local model vendor product boudrate gps type desc control region modem_counter - modem_counter=1 - json_select_array "modems" - - model="$1" - - model=${model:0:7} - - case "$model" in - TRB1422) - vendor=05c6 - product=9215 - ;; - TRB1412 |\ - TRB1423 |\ - TRB1452 |\ - TRB140*) - vendor=2c7c - product=0125 - ;; - TRB14*) - vendor=2c7c - product=0121 - ;; - esac - - case "$model" in - TRB1412 |\ - TRB14*0) - region="EU" - [ "$product" = "0121" ] && { - lte_bands="1 3 7 8 20 28" - trysg_bands="wcdma_2100 wcdma_900" - dug_bands="gsm_1800 gsm_900" - } - [ "$product" = "0125" ] && { - lte_bands="1 3 7 8 20 28 38 40 41" - trysg_bands="wcdma_2100 wcdma_900" - dug_bands="gsm_1800 gsm_900" - } - ;; - TRB1422) - region="CE" - lte_bands="1 3 5 8 34 38 39 40 41" - trysg_bands="bc-0-a-system bc-0-b-system wcdma_2100 wcdma_900" - dug_bands="gsm_1800 gsm_900" - ;; - TRB1423 |\ - TRB1452 |\ - TRB14*1) - region="AU" - [ "$product" = "0121" ] && { - lte_bands="1 2 3 4 5 7 8 28 40" - trysg_bands="wcdma_2100 wcdma_1900 wcdma_900 wcdma_850" - dug_bands="gsm_1800 gsm_900 gsm_850 gsm_1900" - } - [ "$product" = "0125" ] && { - lte_bands="1 2 3 4 5 7 8 28 40" - trysg_bands="wcdma_2100 wcdma_1900 wcdma_900 wcdma_850" - dug_bands="gsm_1800 gsm_900 gsm_850 gsm_1900" - } - ;; - esac - - [ -f "/lib/network/wwan/$vendor:$product" ] && { - devicename="3-1" - json_set_namespace defaults old_cb - json_load "$(cat /lib/network/wwan/$vendor:$product)" - json_get_vars gps boudrate type desc control stop_bits - json_set_namespace $old_cb - - [ "${devicename%%:*}" = "$devicename" ] && { - json_add_object - json_add_string id "$devicename" - json_add_string num "$modem_counter" - json_add_string vendor "$vendor" - json_add_string product "$product" - json_add_string stop_bits "$stop_bits" - json_add_string gps "$gps" - json_add_string boudrate "$boudrate" - json_add_string type "$type" - json_add_string desc "$desc" - json_add_string region "$region" - json_add_string control "$control" - json_add_int simcount 1 - json_add_boolean builtin 1 - [ -n "$2" ] && json_add_boolean primary 1 - json_add_object service_modes - [ -z "$lte_bands" ] || print_array "4G" "$lte_bands" - [ -z "$trysg_bands" ] || print_array "3G" "$trysg_bands" - [ -z "$dug_bands" ] || print_array "2G" "$dug_bands" - json_close_object - json_close_object - } - } - json_select .. -} - -ucidef_add_serial_capabilities() { - json_select_array serial - json_add_object - [ -n "$1" ] && { - json_select_array devices - for d in $1; do - json_add_string "" $d - done - json_select .. - } - - json_select_array bauds - for b in $2; do - json_add_string "" $b - done - json_select .. - - json_select_array data_bits - for n in $3; do - json_add_string "" $n - done - json_select .. - json_close_object - json_select .. -} - -ucidef_set_hwinfo() { - local function - local dual_sim=0 - local wifi=0 - local dual_band_ssid=0 - local wps=0 - local mobile=0 - local gps=0 - local usb=0 - local bluetooth=0 - local ethernet=0 - local sfp_port=0 - local ios=0 - - for function in "$@"; do - case "$function" in - dual_sim) - dual_sim=1 - ;; - wifi) - wifi=1 - ;; - dual_band_ssid) - dual_band_ssid=1 - ;; - wps) - wps=1 - ;; - mobile) - mobile=1 - ;; - gps) - gps=1 - ;; - usb) - usb=1 - ;; - bluetooth) - bluetooth=1 - ;; - ethernet) - ethernet=1 - ;; - sfp_port) - sfp_port=1 - ;; - ios) - ios=1 - ;; - at_sim) - at_sim=1 - ;; - esac - done - - json_select_object hwinfo - json_add_boolean dual_sim "$dual_sim" - json_add_boolean usb "$usb" - json_add_boolean bluetooth "$bluetooth" - json_add_boolean wifi "$wifi" - json_add_boolean dual_band_ssid "$dual_band_ssid" - json_add_boolean wps "$wps" - json_add_boolean mobile "$mobile" - json_add_boolean gps "$gps" - json_add_boolean ethernet "$ethernet" - json_add_boolean sfp_port "$sfp_port" - json_add_boolean ios "$ios" - json_add_boolean at_sim "$at_sim" - json_select .. -} - -ucidef_set_release_version() { - json_add_string release_version "$1" -} diff --git a/root/target/linux/ipq40xx/base-files/lib/functions/teltonika-functions.sh b/root/target/linux/ipq40xx/base-files/lib/functions/teltonika-functions.sh deleted file mode 100644 index 5381f81f..00000000 --- a/root/target/linux/ipq40xx/base-files/lib/functions/teltonika-functions.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -. /usr/share/libubox/jshn.sh - -is_ios_enabled() { - local ios - json_load_file "/etc/board.json" && \ - json_select hwinfo && \ - json_get_var ios ios && [ "$ios" = "1" ] -} diff --git a/root/target/linux/ipq40xx/base-files/lib/upgrade/stage2 b/root/target/linux/ipq40xx/base-files/lib/upgrade/stage2 deleted file mode 100644 index 93792413..00000000 --- a/root/target/linux/ipq40xx/base-files/lib/upgrade/stage2 +++ /dev/null @@ -1,138 +0,0 @@ -#!/bin/sh - -. /lib/functions.sh -. /lib/functions/system.sh - -export IMAGE="$1" -COMMAND="$2" - -export INTERACTIVE=0 -export VERBOSE=1 -export CONFFILES=/tmp/sysupgrade.conffiles - -RAMFS_COPY_BIN= # extra programs for temporary ramfs root -RAMFS_COPY_DATA= # extra data files - -include /lib/upgrade - - -supivot() { # - /bin/mount | grep "on $1 type" 2>&- 1>&- || /bin/mount -o bind $1 $1 - mkdir -p $1$2 $1/proc $1/sys $1/dev $1/tmp $1/overlay && \ - /bin/mount -o noatime,move /proc $1/proc && \ - pivot_root $1 $1$2 || { - /bin/umount -l $1 $1 - return 1 - } - - /bin/mount -o noatime,move $2/sys /sys - /bin/mount -o noatime,move $2/dev /dev - /bin/mount -o noatime,move $2/tmp /tmp - /bin/mount -o noatime,move $2/overlay /overlay 2>&- - return 0 -} - -switch_to_ramfs() { - for binary in \ - /bin/busybox /bin/ash /bin/sh /bin/mount /bin/umount \ - pivot_root mount_root reboot sync kill sleep \ - md5sum hexdump cat zcat bzcat dd tar \ - ls basename find cp mv rm mkdir rmdir mknod touch chmod \ - '[' printf wc grep awk sed cut \ - mtd partx losetup mkfs.ext4 nandwrite flash_erase \ - ubiupdatevol ubiattach ubiblock ubiformat \ - ubidetach ubirsvol ubirmvol ubimkvol \ - snapshot snapshot_tool date \ - dumpimage $RAMFS_COPY_BIN - do - local file="$(command -v "$binary" 2>/dev/null)" - [ -n "$file" ] && install_bin "$file" - done - install_file /etc/resolv.conf /lib/*.sh /lib/functions/*.sh /lib/upgrade/*.sh /lib/upgrade/do_stage2 /usr/share/libubox/jshn.sh $RAMFS_COPY_DATA - - [ -L "/lib64" ] && ln -s /lib $RAM_ROOT/lib64 - - supivot $RAM_ROOT /mnt || { - v "Failed to switch over to ramfs. Please reboot." - exit 1 - } - - /bin/mount -o remount,ro /mnt - /bin/umount -l /mnt - - grep /overlay /proc/mounts > /dev/null && { - /bin/mount -o noatime,remount,ro /overlay - /bin/umount -l /overlay - } -} - -kill_remaining() { # [ [ ] ] - local loop_limit=10 - - local sig="${1:-TERM}" - local loop="${2:-0}" - local run=true - local stat - local proc_ppid=$(cut -d' ' -f4 /proc/$$/stat) - - vn "Sending $sig to remaining processes ..." - - while $run; do - run=false - for stat in /proc/[0-9]*/stat; do - [ -f "$stat" ] || continue - - local pid name state ppid rest - read pid name state ppid rest < $stat - name="${name#(}"; name="${name%)}" - - # Skip PID1, our parent, ourself and our children - [ $pid -ne 1 -a $pid -ne $proc_ppid -a $pid -ne $$ -a $ppid -ne $$ ] || continue - - local cmdline - read cmdline < /proc/$pid/cmdline - - # Skip kernel threads - [ -n "$cmdline" ] || continue - - _vn " $name" - kill -$sig $pid 2>/dev/null - - [ $loop -eq 1 ] && run=true - done - - let loop_limit-- - [ $loop_limit -eq 0 ] && { - _v - v "Failed to kill all processes." - exit 1 - } - done - _v -} - -indicate_upgrade - -killall -9 telnetd -killall -9 dropbear -killall -9 ash - -kill_remaining TERM -sleep 3 -kill_remaining KILL 1 - -sleep 1 - -echo 3 > /proc/sys/vm/drop_caches - -if [ -n "$IMAGE" ] && type 'platform_pre_upgrade' >/dev/null 2>/dev/null; then - platform_pre_upgrade "$IMAGE" -fi - -if [ -n "$(rootfs_type)" ]; then - v "Switching to ramdisk..." - switch_to_ramfs -fi - -# Exec new shell from ramfs -exec /bin/busybox ash -c "$COMMAND" diff --git a/root/target/linux/ipq40xx/base-files/sbin/mctl b/root/target/linux/ipq40xx/base-files/sbin/mctl deleted file mode 100644 index f501cc2e..00000000 --- a/root/target/linux/ipq40xx/base-files/sbin/mctl +++ /dev/null @@ -1,120 +0,0 @@ -#!/bin/sh - -. /usr/share/libubox/jshn.sh - -PS_ON=1 -PS_OFF=2 - -MPS=0 -MLBL="modem" - -modem_reset() { - local label="$1" - - [ -e "/sys/class/gpio/${label}_reset/value" ] || return - - echo 1 > "/sys/class/gpio/${label}_reset/value" - sleep 1 - echo 0 > "/sys/class/gpio/${label}_reset/value" -} - -modem_off() { - local label="$1" - - [ -e "/sys/class/gpio/${label}_reset/value" ] || return - - echo 1 > "/sys/class/gpio/${label}_reset/value" -} - -modem_power() { - local label="$1" - - [ -e "/sys/class/gpio/${label}_power/value" ] || return - - # simulate power press - echo 1 > "/sys/class/gpio/${label}_power/value" - sleep 1 - echo 0 > "/sys/class/gpio/${label}_power/value" -} - -modem_list() { - local list="modem" - local label - - [ "$(modem_fetch_primary)" -eq 0 ] && { - echo "${list}" - return - } - - for m in /sys/class/gpio/modem*_power; do - label="$(basename $m | awk -F_ '{print $1}')" - [ "${label}" != "modem" ] && list="${list},${label}" - done - - echo "${list}" -} - -modem_fetch_primary() { - local modem modems primary - - json_init - json_load_file "/etc/board.json" - - json_get_keys modems modems - json_select modems - - for modem in $modems; do - json_select "$modem" - json_get_vars primary - - [ -n "$primary" ] && { - echo 1 - return - } - - json_select .. - done - echo 0 -} - -modem_is_available() { - local label="$1" - [ -e "/sys/class/gpio/${label}_power/value" ] -} - -usage() { - cat < -Control modem power state. - -Options: - -p, --power-on power on modem - -s, --shutdown shutdown modem - -r, --reboot reboot modem - -m, --modem