From 65258f5d6093809c541050256646795bc0a460a9 Mon Sep 17 00:00:00 2001 From: Tiago Gaspar Date: Wed, 4 May 2022 10:36:07 +0100 Subject: [PATCH 01/24] firewall: config: remove restictions on DHCPv6 allow rule Remove restrictions on source and destination addresses, which aren't specified on RFC8415, and for some reason in openwrt are configured to allow both link-local and ULA addresses. As cleared out in issue #5066 there are some ISPs that use Gloabal Unicast addresses, so fix this rule to allow them. Fixes: #5066 Signed-off-by: Tiago Gaspar [rebase onto firewall3, clarify subject, bump PKG_RELEASE] Signed-off-by: Jo-Philipp Wich --- package/network/config/firewall/Makefile | 2 +- package/network/config/firewall/files/firewall.config | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/package/network/config/firewall/Makefile b/package/network/config/firewall/Makefile index 6296837563..9715e1f6bb 100644 --- a/package/network/config/firewall/Makefile +++ b/package/network/config/firewall/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=firewall -PKG_RELEASE:=2 +PKG_RELEASE:=3 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/firewall3.git diff --git a/package/network/config/firewall/files/firewall.config b/package/network/config/firewall/files/firewall.config index 5e22f984ce..61cfe665e4 100644 --- a/package/network/config/firewall/files/firewall.config +++ b/package/network/config/firewall/files/firewall.config @@ -54,13 +54,11 @@ config rule option target ACCEPT # Allow DHCPv6 replies -# see https://dev.openwrt.org/ticket/10381 +# see https://github.com/openwrt/openwrt/issues/5066 config rule option name Allow-DHCPv6 option src wan option proto udp - option src_ip fc00::/6 - option dest_ip fc00::/6 option dest_port 546 option family ipv6 option target ACCEPT From f4e219fd5e6cfa33d234dad134fb105cc1620f54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= Date: Wed, 4 May 2022 11:34:29 +0300 Subject: [PATCH 02/24] packages: nvram: add NVRAM quirks for bcm53xx target MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add NVRAM quirks script for the bcm53xx target. Split NVRAM quirks for the bcm47xx and bcm53xx targets. Move clear partialboot NVRAM quirk for Linksys EA9500 here. Add set wireless LED behaviour quirk for Asus RT-AC88U. Use boot() instead of start() as nvram commands are meant to be executed only once, at boot. Signed-off-by: Arınç ÜNAL --- package/utils/nvram/Makefile | 8 +++- .../files/{nvram.init => nvram-bcm47xx.init} | 4 +- package/utils/nvram/files/nvram-bcm53xx.init | 40 +++++++++++++++++++ .../base-files/etc/init.d/clear_partialboot | 13 ------ 4 files changed, 48 insertions(+), 17 deletions(-) rename package/utils/nvram/files/{nvram.init => nvram-bcm47xx.init} (97%) create mode 100755 package/utils/nvram/files/nvram-bcm53xx.init delete mode 100755 target/linux/bcm53xx/base-files/etc/init.d/clear_partialboot diff --git a/package/utils/nvram/Makefile b/package/utils/nvram/Makefile index 863b304d0d..b957211283 100644 --- a/package/utils/nvram/Makefile +++ b/package/utils/nvram/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=nvram -PKG_RELEASE:=10 +PKG_RELEASE:=11 PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) @@ -44,7 +44,11 @@ define Package/nvram/install $(INSTALL_BIN) $(PKG_BUILD_DIR)/nvram $(1)/usr/sbin/ ifneq ($(CONFIG_TARGET_bcm47xx),) $(INSTALL_DIR) $(1)/etc/init.d - $(INSTALL_BIN) ./files/nvram.init $(1)/etc/init.d/nvram + $(INSTALL_BIN) ./files/nvram-bcm47xx.init $(1)/etc/init.d/nvram +endif +ifneq ($(CONFIG_TARGET_bcm53xx),) + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/nvram-bcm53xx.init $(1)/etc/init.d/nvram endif endef diff --git a/package/utils/nvram/files/nvram.init b/package/utils/nvram/files/nvram-bcm47xx.init similarity index 97% rename from package/utils/nvram/files/nvram.init rename to package/utils/nvram/files/nvram-bcm47xx.init index 467ab28195..4a2bcd16fe 100755 --- a/package/utils/nvram/files/nvram.init +++ b/package/utils/nvram/files/nvram-bcm47xx.init @@ -1,7 +1,7 @@ #!/bin/sh /etc/rc.common # NVRAM setup # -# This file handles the NVRAM quirks of various hardware. +# This file handles the NVRAM quirks of various hardware of the bcm47xx target. START=02 alias debug=${DEBUG:-:} @@ -71,7 +71,7 @@ fixup_linksys() { esac } -start() { +boot() { # Don't do any fixups on the WGT634U [ "$(cat /proc/diag/model)" = "Netgear WGT634U" ] && return diff --git a/package/utils/nvram/files/nvram-bcm53xx.init b/package/utils/nvram/files/nvram-bcm53xx.init new file mode 100755 index 0000000000..0502cd28b6 --- /dev/null +++ b/package/utils/nvram/files/nvram-bcm53xx.init @@ -0,0 +1,40 @@ +#!/bin/sh /etc/rc.common +# NVRAM setup +# +# This file handles the NVRAM quirks of various hardware of the bcm53xx target. + +START=02 + +clear_partialboots() { + # clear partialboots + + case $(board_name) in + linksys,panamera) + COMMIT=1 + nvram set partialboots=0 + ;; + esac +} + +set_wireless_led_behaviour() { + # set Broadcom wireless LED behaviour for both radios + # 0:ledbh9 -> Behaviour of 2.4GHz LED + # 1:ledbh9 -> Behaviour of 5GHz LED + # 0x7 makes the wireless LEDs on, when radios are enabled, and blink when there's activity + + case $(board_name) in + asus,rt-ac88u) + COMMIT=1 + nvram set 0:ledbh9=0x7 set 1:ledbh9=0x7 + ;; + esac +} + +boot() { + . /lib/functions.sh + + clear_partialboots + set_wireless_led_behaviour + + [ "$COMMIT" = "1" ] && nvram commit +} diff --git a/target/linux/bcm53xx/base-files/etc/init.d/clear_partialboot b/target/linux/bcm53xx/base-files/etc/init.d/clear_partialboot deleted file mode 100755 index b3eddf4af0..0000000000 --- a/target/linux/bcm53xx/base-files/etc/init.d/clear_partialboot +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh /etc/rc.common - -START=97 -boot() { - . /lib/functions.sh - - case $(board_name) in - linksys,panamera) - # clear partialboots - nvram set partialboots=0 && nvram commit - ;; - esac -} From f8b0010dfb548469686049f85076fd6a3a6bca2e Mon Sep 17 00:00:00 2001 From: Rodrigo Balerdi Date: Thu, 7 Apr 2022 03:18:59 -0300 Subject: [PATCH 03/24] ipq806x: add support for Arris TR4400 v2 / RAC2V1A Hardware specs: SoC: Qualcomm IPQ8065 (dual core Cortex-A15) RAM: 512 MB DDR3 Flash: 256 MB NAND, 32 MB NOR WiFi: QCA9983 2.4 GHz, QCA9984 5 GHz Switch: QCA8337 Ethernet: 5x 10/100/1000 Mbit/s USB: 1x USB 3.0 Type-A Buttons: WPS, Reset Power: 12 VDC, 2.5 A Ethernet ports: 1x WAN: connected to eth2 4x LAN: connected via the switch to eth0 and eth1 (eth0 is disabled in OEM firmware) MAC addresses (OEM and OpenWrt): fw_env @ 0x00 d4:ab:82:??:??:?a LAN (eth1) fw_env @ 0x06 d4:ab:82:??:??:?b WAN (eth2) fw_env @ 0x0c d4:ab:82:??:??:?c WLAN 2.4 GHz (ath1) fw_env @ 0x12 d4:ab:82:??:??:?d WLAN 5 GHz (ath0) fw_env @ 0x18 d4:ab:82:??:??:?e OEM usage unknown (eth0 in OpenWrt) OID d4:ab:82 is registered to: ARRIS Group, Inc., 6450 Sequence Drive, San Diego CA 92121, US More info: https://openwrt.org/inbox/toh/arris/tr4400_v2 IMPORTANT: This port requires moving the 'fw_env' partition prior to first boot to consolidate 70% of the usable space in flash into a contiguous partition. 'fw_env' contains factory-programmed MAC addresses, SSIDs, and passwords. Its contents must be copied to 'rootfs_1' prior to booting via initramfs. Note that the stock 'fw_env' partition will be wiped during sysupgrade. A writable 'stock_fw_env' partition pointing to the old, stock location is included in the port to help rolling back this change if desired. Installation: - Requires serial access and a TFTP server. - Fully boot stock, press ENTER, type in: mtd erase /dev/mtd21 dd if=/dev/mtd22 bs=128K count=1 | mtd write - /dev/mtd21 umount /config && ubidetach -m 23 && mtd erase /dev/mtd23 - Reboot and interrupt U-Boot by pressing a key, type in: set mtdids 'nand0=nand0' set mtdparts 'mtdparts=nand0:155M@0x6500000(mtd_ubi)' set bootcmd 'ubi part mtd_ubi && ubi read 0x44000000 kernel && bootm' env save - Setup TFTP server serving initramfs image as 'recovery.bin', type in: set ipaddr 192.168.1.1 set serverip 192.168.1.2 tftpboot recovery.bin && bootm - Use sysupgrade to install squashfs image. This port is based on work done by AmadeusGhost . Signed-off-by: Rodrigo Balerdi [add 5.15 changes for 0069-arm-boot-add-dts-files.patch] Signed-off-by: Sungbo Eo --- package/boot/uboot-envtools/files/ipq806x | 1 + .../ipq806x/base-files/etc/board.d/02_network | 5 + .../base-files/lib/upgrade/platform.sh | 1 + .../arm/boot/dts/qcom-ipq8065-tr4400-v2.dts | 425 ++++++++++++++++++ target/linux/ipq806x/image/generic.mk | 13 + .../0069-arm-boot-add-dts-files.patch | 3 +- .../0069-arm-boot-add-dts-files.patch | 5 +- 7 files changed, 450 insertions(+), 3 deletions(-) create mode 100644 target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8065-tr4400-v2.dts diff --git a/package/boot/uboot-envtools/files/ipq806x b/package/boot/uboot-envtools/files/ipq806x index 7e1d71a7e9..a8285d1452 100644 --- a/package/boot/uboot-envtools/files/ipq806x +++ b/package/boot/uboot-envtools/files/ipq806x @@ -30,6 +30,7 @@ ubootenv_mtdinfo () { } case "$board" in +arris,tr4400-v2|\ askey,rt4230w-rev6) ubootenv_add_uci_config "/dev/mtd9" "0x0" "0x40000" "0x20000" ;; diff --git a/target/linux/ipq806x/base-files/etc/board.d/02_network b/target/linux/ipq806x/base-files/etc/board.d/02_network index 4cb691f32e..dc9c11e4ba 100644 --- a/target/linux/ipq806x/base-files/etc/board.d/02_network +++ b/target/linux/ipq806x/base-files/etc/board.d/02_network @@ -11,6 +11,11 @@ board_config_update board=$(board_name) case "$board" in +arris,tr4400-v2) + ucidef_set_interfaces_lan_wan "eth1" "eth2" + ucidef_add_switch "switch0" \ + "1:lan" "2:lan" "3:lan" "4:lan" "6u@eth1" "0u@eth0" + ;; askey,rt4230w-rev6 |\ asrock,g10 |\ nec,wg2600hp) diff --git a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh index 84ffcd8a15..f9e592f4bd 100644 --- a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh +++ b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh @@ -10,6 +10,7 @@ platform_check_image() { platform_do_upgrade() { case "$(board_name)" in + arris,tr4400-v2 |\ askey,rt4230w-rev6 |\ compex,wpq864|\ netgear,d7800 |\ diff --git a/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8065-tr4400-v2.dts b/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8065-tr4400-v2.dts new file mode 100644 index 0000000000..871cc09502 --- /dev/null +++ b/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8065-tr4400-v2.dts @@ -0,0 +1,425 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "qcom-ipq8065.dtsi" +#include + +/ { + model = "Arris TR4400 v2"; + compatible = "arris,tr4400-v2", "qcom,ipq8065", "qcom,ipq8064"; + + memory@0 { + reg = <0x42000000 0x1e000000>; + device_type = "memory"; + }; + + aliases { + led-boot = &led_status_blue; + led-failsafe = &led_status_red; + led-running = &led_status_blue; + led-upgrade = &led_status_red; + }; + + chosen { + bootargs = "rootfstype=squashfs noinitrd"; + }; + + keys { + compatible = "gpio-keys"; + pinctrl-0 = <&button_pins>; + pinctrl-names = "default"; + + reset { + label = "reset"; + gpios = <&qcom_pinmux 6 GPIO_ACTIVE_LOW>; + linux,code = ; + debounce-interval = <60>; + wakeup-source; + }; + + wps { + label = "wps"; + gpios = <&qcom_pinmux 54 GPIO_ACTIVE_LOW>; + linux,code = ; + debounce-interval = <60>; + wakeup-source; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-0 = <&led_pins>; + pinctrl-names = "default"; + + led_status_red: status_red { + label = "red:status"; + gpios = <&qcom_pinmux 7 GPIO_ACTIVE_HIGH>; + }; + + led_status_blue: status_blue { + label = "blue:status"; + gpios = <&qcom_pinmux 8 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&qcom_pinmux { + button_pins: button_pins { + mux { + pins = "gpio6", "gpio54"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + led_pins: led_pins { + mux { + pins = "gpio7", "gpio8"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + rgmii2_pins: rgmii2_pins { + tx { + pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32"; + input-disable; + }; + }; + + spi_pins: spi_pins { + cs { + pins = "gpio20"; + drive-strength = <12>; + }; + }; +}; + +&gsbi5 { + qcom,mode = ; + status = "okay"; + + spi@1a280000 { + status = "okay"; + + pinctrl-0 = <&spi_pins>; + pinctrl-names = "default"; + + cs-gpios = <&qcom_pinmux 20 GPIO_ACTIVE_HIGH>; + + flash@0 { + compatible = "everspin,mr25h256"; + spi-max-frequency = <40000000>; + reg = <0>; + }; + }; +}; + +&nand { + status = "okay"; + + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; + + nand@0 { + reg = <0>; + compatible = "qcom,nandcs"; + + nand-ecc-strength = <4>; + nand-bus-width = <8>; + nand-ecc-step-size = <512>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "0:SBL1"; + reg = <0x0000000 0x0040000>; + read-only; + }; + partition@40000 { + label = "0:MIBIB"; + reg = <0x0040000 0x0140000>; + read-only; + }; + partition@180000 { + label = "0:SBL2"; + reg = <0x0180000 0x0140000>; + read-only; + }; + partition@2c0000 { + label = "0:SBL3"; + reg = <0x02c0000 0x0280000>; + read-only; + }; + partition@540000 { + label = "0:DDRCONFIG"; + reg = <0x0540000 0x0120000>; + read-only; + }; + partition@660000 { + label = "0:SSD"; + reg = <0x0660000 0x0120000>; + read-only; + }; + partition@780000 { + label = "0:TZ"; + reg = <0x0780000 0x0280000>; + read-only; + }; + partition@a00000 { + label = "0:RPM"; + reg = <0x0a00000 0x0280000>; + read-only; + }; + partition@c80000 { + label = "0:APPSBL"; + reg = <0x0c80000 0x0500000>; + read-only; + }; + partition@1180000 { + label = "0:APPSBLENV"; + reg = <0x1180000 0x0080000>; + }; + partition@1200000 { + label = "0:ART"; + reg = <0x1200000 0x0140000>; + read-only; + + compatible = "nvmem-cells"; + #address-cells = <1>; + #size-cells = <1>; + + precal_ART_1000: precal@1000 { + reg = <0x1000 0x2f20>; + }; + precal_ART_5000: precal@5000 { + reg = <0x5000 0x2f20>; + }; + }; + stock_partition@1340000 { + label = "stock_rootfs"; + reg = <0x1340000 0x4000000>; + }; + partition@5340000 { + label = "0:BOOTCONFIG"; + reg = <0x5340000 0x0060000>; + read-only; + }; + partition@53a0000 { + label = "0:SBL2_1"; + reg = <0x53a0000 0x0140000>; + read-only; + }; + partition@54e0000 { + label = "0:SBL3_1"; + reg = <0x54e0000 0x0280000>; + read-only; + }; + partition@5760000 { + label = "0:DDRCONFIG_1"; + reg = <0x5760000 0x0120000>; + read-only; + }; + partition@5880000 { + label = "0:SSD_1"; + reg = <0x5880000 0x0120000>; + read-only; + }; + partition@59a0000 { + label = "0:TZ_1"; + reg = <0x59a0000 0x0280000>; + read-only; + }; + partition@5c20000 { + label = "0:RPM_1"; + reg = <0x5c20000 0x0280000>; + read-only; + }; + partition@5ea0000 { + label = "0:BOOTCONFIG1"; + reg = <0x5ea0000 0x0060000>; + read-only; + }; + partition@5f00000 { + label = "0:APPSBL_1"; + reg = <0x5f00000 0x0500000>; + read-only; + }; + stock_partition@6400000 { + label = "stock_rootfs_1"; + reg = <0x6400000 0x4000000>; + }; + stock_partition@a400000 { + label = "stock_fw_env"; + reg = <0xa400000 0x0100000>; + }; + stock_partition@a500000 { + label = "stock_config"; + reg = <0xa500000 0x0800000>; + }; + stock_partition@ad00000 { + label = "stock_PKI"; + reg = <0xad00000 0x0200000>; + }; + stock_partition@af00000 { + label = "stock_scfgmgr"; + reg = <0xaf00000 0x0100000>; + }; + + partition@6400000 { + label = "fw_env"; + reg = <0x6400000 0x0100000>; + + compatible = "nvmem-cells"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_fw_env_0: macaddr@0 { + reg = <0x00 0x6>; + }; + macaddr_fw_env_6: macaddr@6 { + reg = <0x06 0x6>; + }; + macaddr_fw_env_c: macaddr@c { + reg = <0x0c 0x6>; + }; + macaddr_fw_env_12: macaddr@12 { + reg = <0x12 0x6>; + }; + macaddr_fw_env_18: macaddr@18 { + reg = <0x18 0x6>; + }; + }; + partition@6500000 { + label = "ubi"; + reg = <0x6500000 0x9b00000>; + }; + partition@1340000 { + label = "extra"; + reg = <0x1340000 0x4000000>; + }; + }; + }; +}; + +&mdio0 { + status = "okay"; + + pinctrl-0 = <&mdio0_pins>; + pinctrl-names = "default"; + + ethernet-phy@0 { + reg = <0x0>; + qca,ar8327-initvals = < + 0x00004 0x7600000 /* PAD0_MODE */ + 0x00008 0x1000000 /* PAD5_MODE */ + 0x0000c 0x80 /* PAD6_MODE */ + 0x000e4 0xaa545 /* MAC_POWER_SEL */ + 0x000e0 0xc74164de /* SGMII_CTRL */ + 0x0007c 0x4e /* PORT0_STATUS */ + 0x00094 0x4e /* PORT6_STATUS */ + >; + }; + + phy7: ethernet-phy@7 { + reg = <7>; + }; +}; + +&gmac0 { + status = "okay"; + phy-mode = "rgmii"; + qcom,id = <0>; + + nvmem-cells = <&macaddr_fw_env_18>; + nvmem-cell-names = "mac-address"; + + pinctrl-0 = <&rgmii2_pins>; + pinctrl-names = "default"; + + fixed-link { + speed = <1000>; + full-duplex; + }; +}; + +&gmac1 { + status = "okay"; + phy-mode = "sgmii"; + qcom,id = <1>; + + nvmem-cells = <&macaddr_fw_env_0>; + nvmem-cell-names = "mac-address"; + + fixed-link { + speed = <1000>; + full-duplex; + }; +}; + +&gmac3 { + status = "okay"; + phy-mode = "sgmii"; + qcom,id = <3>; + phy-handle = <&phy7>; + + nvmem-cells = <&macaddr_fw_env_6>; + nvmem-cell-names = "mac-address"; +}; + +&adm_dma { + status = "okay"; +}; + +&usb3_1 { + status = "okay"; +}; + +&pcie0 { + status = "okay"; + reset-gpio = <&qcom_pinmux 3 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&pcie0_pins>; + pinctrl-names = "default"; + + bridge@0,0 { + reg = <0x00000000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + + wifi0: wifi@1,0 { + compatible = "pci168c,0046"; + reg = <0x00010000 0 0 0 0>; + + nvmem-cells = <&precal_ART_1000>, <&macaddr_fw_env_12>; + nvmem-cell-names = "pre-calibration", "mac-address"; + }; + }; +}; + +&pcie1 { + status = "okay"; + reset-gpio = <&qcom_pinmux 48 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&pcie1_pins>; + pinctrl-names = "default"; + max-link-speed = <1>; + + bridge@0,0 { + reg = <0x00000000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + + wifi1: wifi@1,0 { + compatible = "pci168c,0040"; + reg = <0x00010000 0 0 0 0>; + + nvmem-cells = <&precal_ART_5000>, <&macaddr_fw_env_c>; + nvmem-cell-names = "pre-calibration", "mac-address"; + }; + }; +}; diff --git a/target/linux/ipq806x/image/generic.mk b/target/linux/ipq806x/image/generic.mk index 819c73d338..469f2c654e 100644 --- a/target/linux/ipq806x/image/generic.mk +++ b/target/linux/ipq806x/image/generic.mk @@ -65,6 +65,19 @@ define Device/ZyXELImage append-metadata endef +define Device/arris_tr4400-v2 + $(call Device/LegacyImage) + DEVICE_VENDOR := Arris + DEVICE_MODEL := TR4400 + DEVICE_VARIANT := v2 + SOC := qcom-ipq8065 + BLOCKSIZE := 128k + PAGESIZE := 2048 + DEVICE_PACKAGES := ath10k-firmware-qca9984-ct ath10k-firmware-qca99x0-ct + KERNEL_IN_UBI := 1 +endef +TARGET_DEVICES += arris_tr4400-v2 + define Device/askey_rt4230w-rev6 $(call Device/LegacyImage) DEVICE_VENDOR := Askey diff --git a/target/linux/ipq806x/patches-5.10/0069-arm-boot-add-dts-files.patch b/target/linux/ipq806x/patches-5.10/0069-arm-boot-add-dts-files.patch index 275b960c18..a7eacf311b 100644 --- a/target/linux/ipq806x/patches-5.10/0069-arm-boot-add-dts-files.patch +++ b/target/linux/ipq806x/patches-5.10/0069-arm-boot-add-dts-files.patch @@ -10,7 +10,7 @@ Signed-off-by: John Crispin --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile -@@ -908,8 +908,29 @@ dtb-$(CONFIG_ARCH_QCOM) += \ +@@ -908,8 +908,30 @@ dtb-$(CONFIG_ARCH_QCOM) += \ qcom-ipq4019-ap.dk04.1-c3.dtb \ qcom-ipq4019-ap.dk07.1-c1.dtb \ qcom-ipq4019-ap.dk07.1-c2.dtb \ @@ -33,6 +33,7 @@ Signed-off-by: John Crispin + qcom-ipq8065-nbg6817.dtb \ + qcom-ipq8065-r7800.dtb \ + qcom-ipq8065-rt4230w-rev6.dtb \ ++ qcom-ipq8065-tr4400-v2.dtb \ + qcom-ipq8065-xr500.dtb \ + qcom-ipq8068-ecw5410.dtb \ + qcom-ipq8068-mr42.dtb \ diff --git a/target/linux/ipq806x/patches-5.15/0069-arm-boot-add-dts-files.patch b/target/linux/ipq806x/patches-5.15/0069-arm-boot-add-dts-files.patch index db12b32d94..05f39f6465 100644 --- a/target/linux/ipq806x/patches-5.15/0069-arm-boot-add-dts-files.patch +++ b/target/linux/ipq806x/patches-5.15/0069-arm-boot-add-dts-files.patch @@ -10,7 +10,7 @@ Signed-off-by: John Crispin --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile -@@ -956,8 +956,29 @@ dtb-$(CONFIG_ARCH_QCOM) += \ +@@ -956,8 +956,30 @@ dtb-$(CONFIG_ARCH_QCOM) += \ qcom-ipq4019-ap.dk04.1-c3.dtb \ qcom-ipq4019-ap.dk07.1-c1.dtb \ qcom-ipq4019-ap.dk07.1-c2.dtb \ @@ -32,8 +32,9 @@ Signed-off-by: John Crispin + qcom-ipq8064-wxr-2533dhp.dtb \ + qcom-ipq8065-nbg6817.dtb \ + qcom-ipq8065-r7800.dtb \ -+ qcom-ipq8065-xr500.dtb \ + qcom-ipq8065-rt4230w-rev6.dtb \ ++ qcom-ipq8065-tr4400-v2.dtb \ ++ qcom-ipq8065-xr500.dtb \ + qcom-ipq8068-ecw5410.dtb \ + qcom-ipq8068-mr42.dtb \ + qcom-ipq8068-mr52.dtb \ From b697b5c55e4b7f77913db2e74239bdfe3e47ad26 Mon Sep 17 00:00:00 2001 From: Ptilopsis Leucotis Date: Sat, 30 Apr 2022 23:57:04 +0300 Subject: [PATCH 04/24] ramips: add i2c in dts for GL-MT300N-V2 According wiki https://docs.gl-inet.com/en/2/hardware/mt300n-v2/ GL-MT300N-V2 have I2C interface on GPIO4, GPIO5. Adding I2C in device tree make possible using I2C on this device. Signed-off-by: Ptilopsis Leucotis --- target/linux/ramips/dts/mt7628an_glinet_gl-mt300n-v2.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target/linux/ramips/dts/mt7628an_glinet_gl-mt300n-v2.dts b/target/linux/ramips/dts/mt7628an_glinet_gl-mt300n-v2.dts index 48f0fbd92b..b002b618b3 100644 --- a/target/linux/ramips/dts/mt7628an_glinet_gl-mt300n-v2.dts +++ b/target/linux/ramips/dts/mt7628an_glinet_gl-mt300n-v2.dts @@ -131,6 +131,10 @@ }; }; +&i2c { + status = "okay"; +}; + &uart1 { status = "okay"; }; From 1526ccebd427051dad01c81f34e0d176697c7990 Mon Sep 17 00:00:00 2001 From: Nick Hainke Date: Sun, 1 May 2022 21:06:52 +0200 Subject: [PATCH 05/24] ipq40xx: 5.15: fix ar40xx driver Also apply commit ab7e53e5cce7 ("ipq40xx: 5.10: fix ar40xx driver") to 5.15 driver. The commit fixes the data corruption on TX packets. Packets are transmitted, but their contents are replaced with zeros. This error is caused by the lack of guard (50 ms) intervals between calibration phases. This error is treated by adding mdelay(50) to the calibration function code. In the original qca-ssda code, these mdelays were existing, but in the ar41xx.c they are gone. Fixes: 87318eb17936 ("ipq40xx: 5:15: copy config and patch from 5.10") Signed-off-by: Nick Hainke --- target/linux/ipq40xx/files-5.15/drivers/net/mdio/ar40xx.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/target/linux/ipq40xx/files-5.15/drivers/net/mdio/ar40xx.c b/target/linux/ipq40xx/files-5.15/drivers/net/mdio/ar40xx.c index f7ce42b9ff..d5ef7af151 100644 --- a/target/linux/ipq40xx/files-5.15/drivers/net/mdio/ar40xx.c +++ b/target/linux/ipq40xx/files-5.15/drivers/net/mdio/ar40xx.c @@ -936,6 +936,7 @@ ar40xx_malibu_psgmii_ess_reset(struct ar40xx_priv *priv) */ mdelay(2); } + mdelay(50); /*check malibu psgmii calibration done end..*/ @@ -954,6 +955,7 @@ ar40xx_malibu_psgmii_ess_reset(struct ar40xx_priv *priv) /* Polling interval to check PSGMII PLL in ESS is ready */ mdelay(2); } + mdelay(50); /* check dakota psgmii calibration done end..*/ @@ -961,6 +963,7 @@ ar40xx_malibu_psgmii_ess_reset(struct ar40xx_priv *priv) mdiobus_write(bus, 5, 0x1a, 0x3230); /* release phy psgmii RX 20bit */ mdiobus_write(bus, 5, 0x0, 0x005f); + mdelay(200); } static void From cb1dc49c18e54fde6f8892d728c043b93dc995c3 Mon Sep 17 00:00:00 2001 From: Sungbo Eo Date: Thu, 5 May 2022 00:54:43 +0900 Subject: [PATCH 06/24] ipq40xx: consolidate ar40xx driver files Commit f4fb63d2ab4f ("ipq40xx: 5.10: move AR40xx to MDIO drivers") moved the ar40xx driver files to kernel version specific directories to place them in different subdirectory in kernel tree. But now kernel 5.4 is gone and there is no reason to keep them separate. Move them back to common files/ directory. Signed-off-by: Sungbo Eo --- .../files-5.15/drivers/net/mdio/ar40xx.c | 1893 ----------------- .../files-5.15/drivers/net/mdio/ar40xx.h | 342 --- .../drivers/net/mdio/ar40xx.c | 0 .../drivers/net/mdio/ar40xx.h | 0 4 files changed, 2235 deletions(-) delete mode 100644 target/linux/ipq40xx/files-5.15/drivers/net/mdio/ar40xx.c delete mode 100644 target/linux/ipq40xx/files-5.15/drivers/net/mdio/ar40xx.h rename target/linux/ipq40xx/{files-5.10 => files}/drivers/net/mdio/ar40xx.c (100%) rename target/linux/ipq40xx/{files-5.10 => files}/drivers/net/mdio/ar40xx.h (100%) diff --git a/target/linux/ipq40xx/files-5.15/drivers/net/mdio/ar40xx.c b/target/linux/ipq40xx/files-5.15/drivers/net/mdio/ar40xx.c deleted file mode 100644 index d5ef7af151..0000000000 --- a/target/linux/ipq40xx/files-5.15/drivers/net/mdio/ar40xx.c +++ /dev/null @@ -1,1893 +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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ar40xx.h" - -static struct ar40xx_priv *ar40xx_priv; - -#define MIB_DESC(_s , _o, _n) \ - { \ - .size = (_s), \ - .offset = (_o), \ - .name = (_n), \ - } - -static const struct ar40xx_mib_desc ar40xx_mibs[] = { - MIB_DESC(1, AR40XX_STATS_RXBROAD, "RxBroad"), - MIB_DESC(1, AR40XX_STATS_RXPAUSE, "RxPause"), - MIB_DESC(1, AR40XX_STATS_RXMULTI, "RxMulti"), - MIB_DESC(1, AR40XX_STATS_RXFCSERR, "RxFcsErr"), - MIB_DESC(1, AR40XX_STATS_RXALIGNERR, "RxAlignErr"), - MIB_DESC(1, AR40XX_STATS_RXRUNT, "RxRunt"), - MIB_DESC(1, AR40XX_STATS_RXFRAGMENT, "RxFragment"), - MIB_DESC(1, AR40XX_STATS_RX64BYTE, "Rx64Byte"), - MIB_DESC(1, AR40XX_STATS_RX128BYTE, "Rx128Byte"), - MIB_DESC(1, AR40XX_STATS_RX256BYTE, "Rx256Byte"), - MIB_DESC(1, AR40XX_STATS_RX512BYTE, "Rx512Byte"), - MIB_DESC(1, AR40XX_STATS_RX1024BYTE, "Rx1024Byte"), - MIB_DESC(1, AR40XX_STATS_RX1518BYTE, "Rx1518Byte"), - MIB_DESC(1, AR40XX_STATS_RXMAXBYTE, "RxMaxByte"), - MIB_DESC(1, AR40XX_STATS_RXTOOLONG, "RxTooLong"), - MIB_DESC(2, AR40XX_STATS_RXGOODBYTE, "RxGoodByte"), - MIB_DESC(2, AR40XX_STATS_RXBADBYTE, "RxBadByte"), - MIB_DESC(1, AR40XX_STATS_RXOVERFLOW, "RxOverFlow"), - MIB_DESC(1, AR40XX_STATS_FILTERED, "Filtered"), - MIB_DESC(1, AR40XX_STATS_TXBROAD, "TxBroad"), - MIB_DESC(1, AR40XX_STATS_TXPAUSE, "TxPause"), - MIB_DESC(1, AR40XX_STATS_TXMULTI, "TxMulti"), - MIB_DESC(1, AR40XX_STATS_TXUNDERRUN, "TxUnderRun"), - MIB_DESC(1, AR40XX_STATS_TX64BYTE, "Tx64Byte"), - MIB_DESC(1, AR40XX_STATS_TX128BYTE, "Tx128Byte"), - MIB_DESC(1, AR40XX_STATS_TX256BYTE, "Tx256Byte"), - MIB_DESC(1, AR40XX_STATS_TX512BYTE, "Tx512Byte"), - MIB_DESC(1, AR40XX_STATS_TX1024BYTE, "Tx1024Byte"), - MIB_DESC(1, AR40XX_STATS_TX1518BYTE, "Tx1518Byte"), - MIB_DESC(1, AR40XX_STATS_TXMAXBYTE, "TxMaxByte"), - MIB_DESC(1, AR40XX_STATS_TXOVERSIZE, "TxOverSize"), - MIB_DESC(2, AR40XX_STATS_TXBYTE, "TxByte"), - MIB_DESC(1, AR40XX_STATS_TXCOLLISION, "TxCollision"), - MIB_DESC(1, AR40XX_STATS_TXABORTCOL, "TxAbortCol"), - MIB_DESC(1, AR40XX_STATS_TXMULTICOL, "TxMultiCol"), - MIB_DESC(1, AR40XX_STATS_TXSINGLECOL, "TxSingleCol"), - MIB_DESC(1, AR40XX_STATS_TXEXCDEFER, "TxExcDefer"), - MIB_DESC(1, AR40XX_STATS_TXDEFER, "TxDefer"), - MIB_DESC(1, AR40XX_STATS_TXLATECOL, "TxLateCol"), -}; - -static u32 -ar40xx_read(struct ar40xx_priv *priv, int reg) -{ - return readl(priv->hw_addr + reg); -} - -static u32 -ar40xx_psgmii_read(struct ar40xx_priv *priv, int reg) -{ - return readl(priv->psgmii_hw_addr + reg); -} - -static void -ar40xx_write(struct ar40xx_priv *priv, int reg, u32 val) -{ - writel(val, priv->hw_addr + reg); -} - -static u32 -ar40xx_rmw(struct ar40xx_priv *priv, int reg, u32 mask, u32 val) -{ - u32 ret; - - ret = ar40xx_read(priv, reg); - ret &= ~mask; - ret |= val; - ar40xx_write(priv, reg, ret); - return ret; -} - -static void -ar40xx_psgmii_write(struct ar40xx_priv *priv, int reg, u32 val) -{ - writel(val, priv->psgmii_hw_addr + reg); -} - -static void -ar40xx_phy_dbg_write(struct ar40xx_priv *priv, int phy_addr, - u16 dbg_addr, u16 dbg_data) -{ - struct mii_bus *bus = priv->mii_bus; - - mutex_lock(&bus->mdio_lock); - bus->write(bus, phy_addr, AR40XX_MII_ATH_DBG_ADDR, dbg_addr); - bus->write(bus, phy_addr, AR40XX_MII_ATH_DBG_DATA, dbg_data); - mutex_unlock(&bus->mdio_lock); -} - -static void -ar40xx_phy_dbg_read(struct ar40xx_priv *priv, int phy_addr, - u16 dbg_addr, u16 *dbg_data) -{ - struct mii_bus *bus = priv->mii_bus; - - mutex_lock(&bus->mdio_lock); - bus->write(bus, phy_addr, AR40XX_MII_ATH_DBG_ADDR, dbg_addr); - *dbg_data = bus->read(bus, phy_addr, AR40XX_MII_ATH_DBG_DATA); - mutex_unlock(&bus->mdio_lock); -} - -static void -ar40xx_phy_mmd_write(struct ar40xx_priv *priv, u32 phy_id, - u16 mmd_num, u16 reg_id, u16 reg_val) -{ - struct mii_bus *bus = priv->mii_bus; - - mutex_lock(&bus->mdio_lock); - bus->write(bus, phy_id, - AR40XX_MII_ATH_MMD_ADDR, mmd_num); - bus->write(bus, phy_id, - AR40XX_MII_ATH_MMD_DATA, reg_id); - bus->write(bus, phy_id, - AR40XX_MII_ATH_MMD_ADDR, - 0x4000 | mmd_num); - bus->write(bus, phy_id, - AR40XX_MII_ATH_MMD_DATA, reg_val); - mutex_unlock(&bus->mdio_lock); -} - -static u16 -ar40xx_phy_mmd_read(struct ar40xx_priv *priv, u32 phy_id, - u16 mmd_num, u16 reg_id) -{ - u16 value; - struct mii_bus *bus = priv->mii_bus; - - mutex_lock(&bus->mdio_lock); - bus->write(bus, phy_id, - AR40XX_MII_ATH_MMD_ADDR, mmd_num); - bus->write(bus, phy_id, - AR40XX_MII_ATH_MMD_DATA, reg_id); - bus->write(bus, phy_id, - AR40XX_MII_ATH_MMD_ADDR, - 0x4000 | mmd_num); - value = bus->read(bus, phy_id, AR40XX_MII_ATH_MMD_DATA); - mutex_unlock(&bus->mdio_lock); - return value; -} - -/* Start of swconfig support */ - -static void -ar40xx_phy_poll_reset(struct ar40xx_priv *priv) -{ - u32 i, in_reset, retries = 500; - struct mii_bus *bus = priv->mii_bus; - - /* Assume RESET was recently issued to some or all of the phys */ - in_reset = GENMASK(AR40XX_NUM_PHYS - 1, 0); - - while (retries--) { - /* 1ms should be plenty of time. - * 802.3 spec allows for a max wait time of 500ms - */ - usleep_range(1000, 2000); - - for (i = 0; i < AR40XX_NUM_PHYS; i++) { - int val; - - /* skip devices which have completed reset */ - if (!(in_reset & BIT(i))) - continue; - - val = mdiobus_read(bus, i, MII_BMCR); - if (val < 0) - continue; - - /* mark when phy is no longer in reset state */ - if (!(val & BMCR_RESET)) - in_reset &= ~BIT(i); - } - - if (!in_reset) - return; - } - - dev_warn(&bus->dev, "Failed to reset all phys! (in_reset: 0x%x)\n", - in_reset); -} - -static void -ar40xx_phy_init(struct ar40xx_priv *priv) -{ - int i; - struct mii_bus *bus; - u16 val; - - bus = priv->mii_bus; - for (i = 0; i < AR40XX_NUM_PORTS - 1; i++) { - ar40xx_phy_dbg_read(priv, i, AR40XX_PHY_DEBUG_0, &val); - val &= ~AR40XX_PHY_MANU_CTRL_EN; - ar40xx_phy_dbg_write(priv, i, AR40XX_PHY_DEBUG_0, val); - mdiobus_write(bus, i, - MII_ADVERTISE, ADVERTISE_ALL | - ADVERTISE_PAUSE_CAP | - ADVERTISE_PAUSE_ASYM); - mdiobus_write(bus, i, MII_CTRL1000, ADVERTISE_1000FULL); - mdiobus_write(bus, i, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); - } - - ar40xx_phy_poll_reset(priv); -} - -static void -ar40xx_port_phy_linkdown(struct ar40xx_priv *priv) -{ - struct mii_bus *bus; - int i; - u16 val; - - bus = priv->mii_bus; - for (i = 0; i < AR40XX_NUM_PORTS - 1; i++) { - mdiobus_write(bus, i, MII_CTRL1000, 0); - mdiobus_write(bus, i, MII_ADVERTISE, 0); - mdiobus_write(bus, i, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); - ar40xx_phy_dbg_read(priv, i, AR40XX_PHY_DEBUG_0, &val); - val |= AR40XX_PHY_MANU_CTRL_EN; - ar40xx_phy_dbg_write(priv, i, AR40XX_PHY_DEBUG_0, val); - /* disable transmit */ - ar40xx_phy_dbg_read(priv, i, AR40XX_PHY_DEBUG_2, &val); - val &= 0xf00f; - ar40xx_phy_dbg_write(priv, i, AR40XX_PHY_DEBUG_2, val); - } -} - -static void -ar40xx_set_mirror_regs(struct ar40xx_priv *priv) -{ - int port; - - /* reset all mirror registers */ - ar40xx_rmw(priv, AR40XX_REG_FWD_CTRL0, - AR40XX_FWD_CTRL0_MIRROR_PORT, - (0xF << AR40XX_FWD_CTRL0_MIRROR_PORT_S)); - for (port = 0; port < AR40XX_NUM_PORTS; port++) { - ar40xx_rmw(priv, AR40XX_REG_PORT_LOOKUP(port), - AR40XX_PORT_LOOKUP_ING_MIRROR_EN, 0); - - ar40xx_rmw(priv, AR40XX_REG_PORT_HOL_CTRL1(port), - AR40XX_PORT_HOL_CTRL1_EG_MIRROR_EN, 0); - } - - /* now enable mirroring if necessary */ - if (priv->source_port >= AR40XX_NUM_PORTS || - priv->monitor_port >= AR40XX_NUM_PORTS || - priv->source_port == priv->monitor_port) { - return; - } - - ar40xx_rmw(priv, AR40XX_REG_FWD_CTRL0, - AR40XX_FWD_CTRL0_MIRROR_PORT, - (priv->monitor_port << AR40XX_FWD_CTRL0_MIRROR_PORT_S)); - - if (priv->mirror_rx) - ar40xx_rmw(priv, AR40XX_REG_PORT_LOOKUP(priv->source_port), 0, - AR40XX_PORT_LOOKUP_ING_MIRROR_EN); - - if (priv->mirror_tx) - ar40xx_rmw(priv, AR40XX_REG_PORT_HOL_CTRL1(priv->source_port), - 0, AR40XX_PORT_HOL_CTRL1_EG_MIRROR_EN); -} - -static int -ar40xx_sw_get_ports(struct switch_dev *dev, struct switch_val *val) -{ - struct ar40xx_priv *priv = swdev_to_ar40xx(dev); - u8 ports = priv->vlan_table[val->port_vlan]; - int i; - - val->len = 0; - for (i = 0; i < dev->ports; i++) { - struct switch_port *p; - - if (!(ports & BIT(i))) - continue; - - p = &val->value.ports[val->len++]; - p->id = i; - if ((priv->vlan_tagged & BIT(i)) || - (priv->pvid[i] != val->port_vlan)) - p->flags = BIT(SWITCH_PORT_FLAG_TAGGED); - else - p->flags = 0; - } - return 0; -} - -static int -ar40xx_sw_set_ports(struct switch_dev *dev, struct switch_val *val) -{ - struct ar40xx_priv *priv = swdev_to_ar40xx(dev); - u8 *vt = &priv->vlan_table[val->port_vlan]; - int i; - - *vt = 0; - for (i = 0; i < val->len; i++) { - struct switch_port *p = &val->value.ports[i]; - - if (p->flags & BIT(SWITCH_PORT_FLAG_TAGGED)) { - if (val->port_vlan == priv->pvid[p->id]) - priv->vlan_tagged |= BIT(p->id); - } else { - priv->vlan_tagged &= ~BIT(p->id); - priv->pvid[p->id] = val->port_vlan; - } - - *vt |= BIT(p->id); - } - return 0; -} - -static int -ar40xx_reg_wait(struct ar40xx_priv *priv, u32 reg, u32 mask, u32 val, - unsigned timeout) -{ - int i; - - for (i = 0; i < timeout; i++) { - u32 t; - - t = ar40xx_read(priv, reg); - if ((t & mask) == val) - return 0; - - usleep_range(1000, 2000); - } - - return -ETIMEDOUT; -} - -static int -ar40xx_mib_op(struct ar40xx_priv *priv, u32 op) -{ - int ret; - - lockdep_assert_held(&priv->mib_lock); - - /* Capture the hardware statistics for all ports */ - ar40xx_rmw(priv, AR40XX_REG_MIB_FUNC, - AR40XX_MIB_FUNC, (op << AR40XX_MIB_FUNC_S)); - - /* Wait for the capturing to complete. */ - ret = ar40xx_reg_wait(priv, AR40XX_REG_MIB_FUNC, - AR40XX_MIB_BUSY, 0, 10); - - return ret; -} - -static void -ar40xx_mib_fetch_port_stat(struct ar40xx_priv *priv, int port, bool flush) -{ - unsigned int base; - u64 *mib_stats; - int i; - u32 num_mibs = ARRAY_SIZE(ar40xx_mibs); - - WARN_ON(port >= priv->dev.ports); - - lockdep_assert_held(&priv->mib_lock); - - base = AR40XX_REG_PORT_STATS_START + - AR40XX_REG_PORT_STATS_LEN * port; - - mib_stats = &priv->mib_stats[port * num_mibs]; - if (flush) { - u32 len; - - len = num_mibs * sizeof(*mib_stats); - memset(mib_stats, 0, len); - return; - } - for (i = 0; i < num_mibs; i++) { - const struct ar40xx_mib_desc *mib; - u64 t; - - mib = &ar40xx_mibs[i]; - t = ar40xx_read(priv, base + mib->offset); - if (mib->size == 2) { - u64 hi; - - hi = ar40xx_read(priv, base + mib->offset + 4); - t |= hi << 32; - } - - mib_stats[i] += t; - } -} - -static int -ar40xx_mib_capture(struct ar40xx_priv *priv) -{ - return ar40xx_mib_op(priv, AR40XX_MIB_FUNC_CAPTURE); -} - -static int -ar40xx_mib_flush(struct ar40xx_priv *priv) -{ - return ar40xx_mib_op(priv, AR40XX_MIB_FUNC_FLUSH); -} - -static int -ar40xx_sw_set_reset_mibs(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar40xx_priv *priv = swdev_to_ar40xx(dev); - unsigned int len; - int ret; - u32 num_mibs = ARRAY_SIZE(ar40xx_mibs); - - mutex_lock(&priv->mib_lock); - - len = priv->dev.ports * num_mibs * sizeof(*priv->mib_stats); - memset(priv->mib_stats, 0, len); - ret = ar40xx_mib_flush(priv); - - mutex_unlock(&priv->mib_lock); - return ret; -} - -static int -ar40xx_sw_set_vlan(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar40xx_priv *priv = swdev_to_ar40xx(dev); - - priv->vlan = !!val->value.i; - return 0; -} - -static int -ar40xx_sw_get_vlan(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar40xx_priv *priv = swdev_to_ar40xx(dev); - - val->value.i = priv->vlan; - return 0; -} - -static int -ar40xx_sw_set_mirror_rx_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar40xx_priv *priv = swdev_to_ar40xx(dev); - - mutex_lock(&priv->reg_mutex); - priv->mirror_rx = !!val->value.i; - ar40xx_set_mirror_regs(priv); - mutex_unlock(&priv->reg_mutex); - - return 0; -} - -static int -ar40xx_sw_get_mirror_rx_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar40xx_priv *priv = swdev_to_ar40xx(dev); - - mutex_lock(&priv->reg_mutex); - val->value.i = priv->mirror_rx; - mutex_unlock(&priv->reg_mutex); - return 0; -} - -static int -ar40xx_sw_set_mirror_tx_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar40xx_priv *priv = swdev_to_ar40xx(dev); - - mutex_lock(&priv->reg_mutex); - priv->mirror_tx = !!val->value.i; - ar40xx_set_mirror_regs(priv); - mutex_unlock(&priv->reg_mutex); - - return 0; -} - -static int -ar40xx_sw_get_mirror_tx_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar40xx_priv *priv = swdev_to_ar40xx(dev); - - mutex_lock(&priv->reg_mutex); - val->value.i = priv->mirror_tx; - mutex_unlock(&priv->reg_mutex); - return 0; -} - -static int -ar40xx_sw_set_mirror_monitor_port(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar40xx_priv *priv = swdev_to_ar40xx(dev); - - mutex_lock(&priv->reg_mutex); - priv->monitor_port = val->value.i; - ar40xx_set_mirror_regs(priv); - mutex_unlock(&priv->reg_mutex); - - return 0; -} - -static int -ar40xx_sw_get_mirror_monitor_port(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar40xx_priv *priv = swdev_to_ar40xx(dev); - - mutex_lock(&priv->reg_mutex); - val->value.i = priv->monitor_port; - mutex_unlock(&priv->reg_mutex); - return 0; -} - -static int -ar40xx_sw_set_mirror_source_port(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar40xx_priv *priv = swdev_to_ar40xx(dev); - - mutex_lock(&priv->reg_mutex); - priv->source_port = val->value.i; - ar40xx_set_mirror_regs(priv); - mutex_unlock(&priv->reg_mutex); - - return 0; -} - -static int -ar40xx_sw_get_mirror_source_port(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar40xx_priv *priv = swdev_to_ar40xx(dev); - - mutex_lock(&priv->reg_mutex); - val->value.i = priv->source_port; - mutex_unlock(&priv->reg_mutex); - return 0; -} - -static int -ar40xx_sw_set_linkdown(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar40xx_priv *priv = swdev_to_ar40xx(dev); - - if (val->value.i == 1) - ar40xx_port_phy_linkdown(priv); - else - ar40xx_phy_init(priv); - - return 0; -} - -static int -ar40xx_sw_set_port_reset_mib(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar40xx_priv *priv = swdev_to_ar40xx(dev); - int port; - int ret; - - port = val->port_vlan; - if (port >= dev->ports) - return -EINVAL; - - mutex_lock(&priv->mib_lock); - ret = ar40xx_mib_capture(priv); - if (ret) - goto unlock; - - ar40xx_mib_fetch_port_stat(priv, port, true); - -unlock: - mutex_unlock(&priv->mib_lock); - return ret; -} - -static int -ar40xx_sw_get_port_mib(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar40xx_priv *priv = swdev_to_ar40xx(dev); - u64 *mib_stats; - int port; - int ret; - char *buf = priv->buf; - int i, len = 0; - u32 num_mibs = ARRAY_SIZE(ar40xx_mibs); - - port = val->port_vlan; - if (port >= dev->ports) - return -EINVAL; - - mutex_lock(&priv->mib_lock); - ret = ar40xx_mib_capture(priv); - if (ret) - goto unlock; - - ar40xx_mib_fetch_port_stat(priv, port, false); - - len += snprintf(buf + len, sizeof(priv->buf) - len, - "Port %d MIB counters\n", - port); - - mib_stats = &priv->mib_stats[port * num_mibs]; - for (i = 0; i < num_mibs; i++) - len += snprintf(buf + len, sizeof(priv->buf) - len, - "%-12s: %llu\n", - ar40xx_mibs[i].name, - mib_stats[i]); - - val->value.s = buf; - val->len = len; - -unlock: - mutex_unlock(&priv->mib_lock); - return ret; -} - -static int -ar40xx_sw_set_vid(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar40xx_priv *priv = swdev_to_ar40xx(dev); - - priv->vlan_id[val->port_vlan] = val->value.i; - return 0; -} - -static int -ar40xx_sw_get_vid(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar40xx_priv *priv = swdev_to_ar40xx(dev); - - val->value.i = priv->vlan_id[val->port_vlan]; - return 0; -} - -static int -ar40xx_sw_get_pvid(struct switch_dev *dev, int port, int *vlan) -{ - struct ar40xx_priv *priv = swdev_to_ar40xx(dev); - *vlan = priv->pvid[port]; - return 0; -} - -static int -ar40xx_sw_set_pvid(struct switch_dev *dev, int port, int vlan) -{ - struct ar40xx_priv *priv = swdev_to_ar40xx(dev); - - /* make sure no invalid PVIDs get set */ - if (vlan >= dev->vlans) - return -EINVAL; - - priv->pvid[port] = vlan; - return 0; -} - -static void -ar40xx_read_port_link(struct ar40xx_priv *priv, int port, - struct switch_port_link *link) -{ - u32 status; - u32 speed; - - memset(link, 0, sizeof(*link)); - - status = ar40xx_read(priv, AR40XX_REG_PORT_STATUS(port)); - - link->aneg = !!(status & AR40XX_PORT_AUTO_LINK_EN); - if (link->aneg || (port != AR40XX_PORT_CPU)) - link->link = !!(status & AR40XX_PORT_STATUS_LINK_UP); - else - link->link = true; - - if (!link->link) - return; - - link->duplex = !!(status & AR40XX_PORT_DUPLEX); - link->tx_flow = !!(status & AR40XX_PORT_STATUS_TXFLOW); - link->rx_flow = !!(status & AR40XX_PORT_STATUS_RXFLOW); - - speed = (status & AR40XX_PORT_SPEED) >> - AR40XX_PORT_STATUS_SPEED_S; - - switch (speed) { - case AR40XX_PORT_SPEED_10M: - link->speed = SWITCH_PORT_SPEED_10; - break; - case AR40XX_PORT_SPEED_100M: - link->speed = SWITCH_PORT_SPEED_100; - break; - case AR40XX_PORT_SPEED_1000M: - link->speed = SWITCH_PORT_SPEED_1000; - break; - default: - link->speed = SWITCH_PORT_SPEED_UNKNOWN; - break; - } -} - -static int -ar40xx_sw_get_port_link(struct switch_dev *dev, int port, - struct switch_port_link *link) -{ - struct ar40xx_priv *priv = swdev_to_ar40xx(dev); - - ar40xx_read_port_link(priv, port, link); - return 0; -} - -static const struct switch_attr ar40xx_sw_attr_globals[] = { - { - .type = SWITCH_TYPE_INT, - .name = "enable_vlan", - .description = "Enable VLAN mode", - .set = ar40xx_sw_set_vlan, - .get = ar40xx_sw_get_vlan, - .max = 1 - }, - { - .type = SWITCH_TYPE_NOVAL, - .name = "reset_mibs", - .description = "Reset all MIB counters", - .set = ar40xx_sw_set_reset_mibs, - }, - { - .type = SWITCH_TYPE_INT, - .name = "enable_mirror_rx", - .description = "Enable mirroring of RX packets", - .set = ar40xx_sw_set_mirror_rx_enable, - .get = ar40xx_sw_get_mirror_rx_enable, - .max = 1 - }, - { - .type = SWITCH_TYPE_INT, - .name = "enable_mirror_tx", - .description = "Enable mirroring of TX packets", - .set = ar40xx_sw_set_mirror_tx_enable, - .get = ar40xx_sw_get_mirror_tx_enable, - .max = 1 - }, - { - .type = SWITCH_TYPE_INT, - .name = "mirror_monitor_port", - .description = "Mirror monitor port", - .set = ar40xx_sw_set_mirror_monitor_port, - .get = ar40xx_sw_get_mirror_monitor_port, - .max = AR40XX_NUM_PORTS - 1 - }, - { - .type = SWITCH_TYPE_INT, - .name = "mirror_source_port", - .description = "Mirror source port", - .set = ar40xx_sw_set_mirror_source_port, - .get = ar40xx_sw_get_mirror_source_port, - .max = AR40XX_NUM_PORTS - 1 - }, - { - .type = SWITCH_TYPE_INT, - .name = "linkdown", - .description = "Link down all the PHYs", - .set = ar40xx_sw_set_linkdown, - .max = 1 - }, -}; - -static const struct switch_attr ar40xx_sw_attr_port[] = { - { - .type = SWITCH_TYPE_NOVAL, - .name = "reset_mib", - .description = "Reset single port MIB counters", - .set = ar40xx_sw_set_port_reset_mib, - }, - { - .type = SWITCH_TYPE_STRING, - .name = "mib", - .description = "Get port's MIB counters", - .set = NULL, - .get = ar40xx_sw_get_port_mib, - }, -}; - -const struct switch_attr ar40xx_sw_attr_vlan[] = { - { - .type = SWITCH_TYPE_INT, - .name = "vid", - .description = "VLAN ID (0-4094)", - .set = ar40xx_sw_set_vid, - .get = ar40xx_sw_get_vid, - .max = 4094, - }, -}; - -/* End of swconfig support */ - -static int -ar40xx_wait_bit(struct ar40xx_priv *priv, int reg, u32 mask, u32 val) -{ - int timeout = 20; - u32 t; - - while (1) { - t = ar40xx_read(priv, reg); - if ((t & mask) == val) - return 0; - - if (timeout-- <= 0) - break; - - usleep_range(10, 20); - } - - pr_err("ar40xx: timeout for reg %08x: %08x & %08x != %08x\n", - (unsigned int)reg, t, mask, val); - return -ETIMEDOUT; -} - -static int -ar40xx_atu_flush(struct ar40xx_priv *priv) -{ - int ret; - - ret = ar40xx_wait_bit(priv, AR40XX_REG_ATU_FUNC, - AR40XX_ATU_FUNC_BUSY, 0); - if (!ret) - ar40xx_write(priv, AR40XX_REG_ATU_FUNC, - AR40XX_ATU_FUNC_OP_FLUSH | - AR40XX_ATU_FUNC_BUSY); - - return ret; -} - -static void -ar40xx_ess_reset(struct ar40xx_priv *priv) -{ - reset_control_assert(priv->ess_rst); - mdelay(10); - reset_control_deassert(priv->ess_rst); - /* Waiting for all inner tables init done. - * It cost 5~10ms. - */ - mdelay(10); - - pr_info("ESS reset ok!\n"); -} - -/* Start of psgmii self test */ - -static void -ar40xx_malibu_psgmii_ess_reset(struct ar40xx_priv *priv) -{ - u32 n; - struct mii_bus *bus = priv->mii_bus; - /* reset phy psgmii */ - /* fix phy psgmii RX 20bit */ - mdiobus_write(bus, 5, 0x0, 0x005b); - /* reset phy psgmii */ - mdiobus_write(bus, 5, 0x0, 0x001b); - /* release reset phy psgmii */ - mdiobus_write(bus, 5, 0x0, 0x005b); - - for (n = 0; n < AR40XX_PSGMII_CALB_NUM; n++) { - u16 status; - - status = ar40xx_phy_mmd_read(priv, 5, 1, 0x28); - if (status & BIT(0)) - break; - /* Polling interval to check PSGMII PLL in malibu is ready - * the worst time is 8.67ms - * for 25MHz reference clock - * [512+(128+2048)*49]*80ns+100us - */ - mdelay(2); - } - mdelay(50); - - /*check malibu psgmii calibration done end..*/ - - /*freeze phy psgmii RX CDR*/ - mdiobus_write(bus, 5, 0x1a, 0x2230); - - ar40xx_ess_reset(priv); - - /*check psgmii calibration done start*/ - for (n = 0; n < AR40XX_PSGMII_CALB_NUM; n++) { - u32 status; - - status = ar40xx_psgmii_read(priv, 0xa0); - if (status & BIT(0)) - break; - /* Polling interval to check PSGMII PLL in ESS is ready */ - mdelay(2); - } - mdelay(50); - - /* check dakota psgmii calibration done end..*/ - - /* relesae phy psgmii RX CDR */ - mdiobus_write(bus, 5, 0x1a, 0x3230); - /* release phy psgmii RX 20bit */ - mdiobus_write(bus, 5, 0x0, 0x005f); - mdelay(200); -} - -static void -ar40xx_psgmii_single_phy_testing(struct ar40xx_priv *priv, int phy) -{ - int j; - u32 tx_ok, tx_error; - u32 rx_ok, rx_error; - u32 tx_ok_high16; - u32 rx_ok_high16; - u32 tx_all_ok, rx_all_ok; - struct mii_bus *bus = priv->mii_bus; - - mdiobus_write(bus, phy, 0x0, 0x9000); - mdiobus_write(bus, phy, 0x0, 0x4140); - - for (j = 0; j < AR40XX_PSGMII_CALB_NUM; j++) { - u16 status; - - status = mdiobus_read(bus, phy, 0x11); - if (status & AR40XX_PHY_SPEC_STATUS_LINK) - break; - /* the polling interval to check if the PHY link up or not - * maxwait_timer: 750 ms +/-10 ms - * minwait_timer : 1 us +/- 0.1us - * time resides in minwait_timer ~ maxwait_timer - * see IEEE 802.3 section 40.4.5.2 - */ - mdelay(8); - } - - /* enable check */ - ar40xx_phy_mmd_write(priv, phy, 7, 0x8029, 0x0000); - ar40xx_phy_mmd_write(priv, phy, 7, 0x8029, 0x0003); - - /* start traffic */ - ar40xx_phy_mmd_write(priv, phy, 7, 0x8020, 0xa000); - /* wait for all traffic end - * 4096(pkt num)*1524(size)*8ns(125MHz)=49.9ms - */ - mdelay(50); - - /* check counter */ - tx_ok = ar40xx_phy_mmd_read(priv, phy, 7, 0x802e); - tx_ok_high16 = ar40xx_phy_mmd_read(priv, phy, 7, 0x802d); - tx_error = ar40xx_phy_mmd_read(priv, phy, 7, 0x802f); - rx_ok = ar40xx_phy_mmd_read(priv, phy, 7, 0x802b); - rx_ok_high16 = ar40xx_phy_mmd_read(priv, phy, 7, 0x802a); - rx_error = ar40xx_phy_mmd_read(priv, phy, 7, 0x802c); - tx_all_ok = tx_ok + (tx_ok_high16 << 16); - rx_all_ok = rx_ok + (rx_ok_high16 << 16); - if (tx_all_ok == 0x1000 && tx_error == 0) { - /* success */ - priv->phy_t_status &= (~BIT(phy)); - } else { - pr_info("PHY %d single test PSGMII issue happen!\n", phy); - priv->phy_t_status |= BIT(phy); - } - - mdiobus_write(bus, phy, 0x0, 0x1840); -} - -static void -ar40xx_psgmii_all_phy_testing(struct ar40xx_priv *priv) -{ - int phy, j; - struct mii_bus *bus = priv->mii_bus; - - mdiobus_write(bus, 0x1f, 0x0, 0x9000); - mdiobus_write(bus, 0x1f, 0x0, 0x4140); - - for (j = 0; j < AR40XX_PSGMII_CALB_NUM; j++) { - for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) { - u16 status; - - status = mdiobus_read(bus, phy, 0x11); - if (!(status & BIT(10))) - break; - } - - if (phy >= (AR40XX_NUM_PORTS - 1)) - break; - /* The polling interva to check if the PHY link up or not */ - mdelay(8); - } - /* enable check */ - ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8029, 0x0000); - ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8029, 0x0003); - - /* start traffic */ - ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8020, 0xa000); - /* wait for all traffic end - * 4096(pkt num)*1524(size)*8ns(125MHz)=49.9ms - */ - mdelay(50); - - for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) { - u32 tx_ok, tx_error; - u32 rx_ok, rx_error; - u32 tx_ok_high16; - u32 rx_ok_high16; - u32 tx_all_ok, rx_all_ok; - - /* check counter */ - tx_ok = ar40xx_phy_mmd_read(priv, phy, 7, 0x802e); - tx_ok_high16 = ar40xx_phy_mmd_read(priv, phy, 7, 0x802d); - tx_error = ar40xx_phy_mmd_read(priv, phy, 7, 0x802f); - rx_ok = ar40xx_phy_mmd_read(priv, phy, 7, 0x802b); - rx_ok_high16 = ar40xx_phy_mmd_read(priv, phy, 7, 0x802a); - rx_error = ar40xx_phy_mmd_read(priv, phy, 7, 0x802c); - tx_all_ok = tx_ok + (tx_ok_high16<<16); - rx_all_ok = rx_ok + (rx_ok_high16<<16); - if (tx_all_ok == 0x1000 && tx_error == 0) { - /* success */ - priv->phy_t_status &= ~BIT(phy + 8); - } else { - pr_info("PHY%d test see issue!\n", phy); - priv->phy_t_status |= BIT(phy + 8); - } - } - - pr_debug("PHY all test 0x%x \r\n", priv->phy_t_status); -} - -void -ar40xx_psgmii_self_test(struct ar40xx_priv *priv) -{ - u32 i, phy; - struct mii_bus *bus = priv->mii_bus; - - ar40xx_malibu_psgmii_ess_reset(priv); - - /* switch to access MII reg for copper */ - mdiobus_write(bus, 4, 0x1f, 0x8500); - for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) { - /*enable phy mdio broadcast write*/ - ar40xx_phy_mmd_write(priv, phy, 7, 0x8028, 0x801f); - } - /* force no link by power down */ - mdiobus_write(bus, 0x1f, 0x0, 0x1840); - /*packet number*/ - ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8021, 0x1000); - ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8062, 0x05e0); - - /*fix mdi status */ - mdiobus_write(bus, 0x1f, 0x10, 0x6800); - for (i = 0; i < AR40XX_PSGMII_CALB_NUM; i++) { - priv->phy_t_status = 0; - - for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) { - ar40xx_rmw(priv, AR40XX_REG_PORT_LOOKUP(phy + 1), - AR40XX_PORT_LOOKUP_LOOPBACK, - AR40XX_PORT_LOOKUP_LOOPBACK); - } - - for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) - ar40xx_psgmii_single_phy_testing(priv, phy); - - ar40xx_psgmii_all_phy_testing(priv); - - if (priv->phy_t_status) - ar40xx_malibu_psgmii_ess_reset(priv); - else - break; - } - - if (i >= AR40XX_PSGMII_CALB_NUM) - pr_info("PSGMII cannot recover\n"); - else - pr_debug("PSGMII recovered after %d times reset\n", i); - - /* configuration recover */ - /* packet number */ - ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8021, 0x0); - /* disable check */ - ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8029, 0x0); - /* disable traffic */ - ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8020, 0x0); -} - -void -ar40xx_psgmii_self_test_clean(struct ar40xx_priv *priv) -{ - int phy; - struct mii_bus *bus = priv->mii_bus; - - /* disable phy internal loopback */ - mdiobus_write(bus, 0x1f, 0x10, 0x6860); - mdiobus_write(bus, 0x1f, 0x0, 0x9040); - - for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) { - /* disable mac loop back */ - ar40xx_rmw(priv, AR40XX_REG_PORT_LOOKUP(phy + 1), - AR40XX_PORT_LOOKUP_LOOPBACK, 0); - /* disable phy mdio broadcast write */ - ar40xx_phy_mmd_write(priv, phy, 7, 0x8028, 0x001f); - } - - /* clear fdb entry */ - ar40xx_atu_flush(priv); -} - -/* End of psgmii self test */ - -static void -ar40xx_mac_mode_init(struct ar40xx_priv *priv, u32 mode) -{ - if (mode == PORT_WRAPPER_PSGMII) { - ar40xx_psgmii_write(priv, AR40XX_PSGMII_MODE_CONTROL, 0x2200); - ar40xx_psgmii_write(priv, AR40XX_PSGMIIPHY_TX_CONTROL, 0x8380); - } -} - -static -int ar40xx_cpuport_setup(struct ar40xx_priv *priv) -{ - u32 t; - - t = AR40XX_PORT_STATUS_TXFLOW | - AR40XX_PORT_STATUS_RXFLOW | - AR40XX_PORT_TXHALF_FLOW | - AR40XX_PORT_DUPLEX | - AR40XX_PORT_SPEED_1000M; - ar40xx_write(priv, AR40XX_REG_PORT_STATUS(0), t); - usleep_range(10, 20); - - t |= AR40XX_PORT_TX_EN | - AR40XX_PORT_RX_EN; - ar40xx_write(priv, AR40XX_REG_PORT_STATUS(0), t); - - return 0; -} - -static void -ar40xx_init_port(struct ar40xx_priv *priv, int port) -{ - u32 t; - - ar40xx_write(priv, AR40XX_REG_PORT_STATUS(port), 0); - - ar40xx_write(priv, AR40XX_REG_PORT_HEADER(port), 0); - - ar40xx_write(priv, AR40XX_REG_PORT_VLAN0(port), 0); - - t = AR40XX_PORT_VLAN1_OUT_MODE_UNTOUCH << AR40XX_PORT_VLAN1_OUT_MODE_S; - ar40xx_write(priv, AR40XX_REG_PORT_VLAN1(port), t); - - t = AR40XX_PORT_LOOKUP_LEARN; - t |= AR40XX_PORT_STATE_FORWARD << AR40XX_PORT_LOOKUP_STATE_S; - ar40xx_write(priv, AR40XX_REG_PORT_LOOKUP(port), t); -} - -void -ar40xx_init_globals(struct ar40xx_priv *priv) -{ - u32 t; - - /* enable CPU port and disable mirror port */ - t = AR40XX_FWD_CTRL0_CPU_PORT_EN | - AR40XX_FWD_CTRL0_MIRROR_PORT; - ar40xx_write(priv, AR40XX_REG_FWD_CTRL0, t); - - /* forward multicast and broadcast frames to CPU */ - t = (AR40XX_PORTS_ALL << AR40XX_FWD_CTRL1_UC_FLOOD_S) | - (AR40XX_PORTS_ALL << AR40XX_FWD_CTRL1_MC_FLOOD_S) | - (AR40XX_PORTS_ALL << AR40XX_FWD_CTRL1_BC_FLOOD_S); - ar40xx_write(priv, AR40XX_REG_FWD_CTRL1, t); - - /* enable jumbo frames */ - ar40xx_rmw(priv, AR40XX_REG_MAX_FRAME_SIZE, - AR40XX_MAX_FRAME_SIZE_MTU, 9018 + 8 + 2); - - /* Enable MIB counters */ - ar40xx_rmw(priv, AR40XX_REG_MODULE_EN, 0, - AR40XX_MODULE_EN_MIB); - - /* Disable AZ */ - ar40xx_write(priv, AR40XX_REG_EEE_CTRL, 0); - - /* set flowctrl thershold for cpu port */ - t = (AR40XX_PORT0_FC_THRESH_ON_DFLT << 16) | - AR40XX_PORT0_FC_THRESH_OFF_DFLT; - ar40xx_write(priv, AR40XX_REG_PORT_FLOWCTRL_THRESH(0), t); -} - -static int -ar40xx_hw_init(struct ar40xx_priv *priv) -{ - u32 i; - - ar40xx_ess_reset(priv); - - if (!priv->mii_bus) - return -1; - - ar40xx_psgmii_self_test(priv); - ar40xx_psgmii_self_test_clean(priv); - - ar40xx_mac_mode_init(priv, priv->mac_mode); - - for (i = 0; i < priv->dev.ports; i++) - ar40xx_init_port(priv, i); - - ar40xx_init_globals(priv); - - return 0; -} - -/* Start of qm error WAR */ - -static -int ar40xx_force_1g_full(struct ar40xx_priv *priv, u32 port_id) -{ - u32 reg; - - if (port_id < 0 || port_id > 6) - return -1; - - reg = AR40XX_REG_PORT_STATUS(port_id); - return ar40xx_rmw(priv, reg, AR40XX_PORT_SPEED, - (AR40XX_PORT_SPEED_1000M | AR40XX_PORT_DUPLEX)); -} - -static -int ar40xx_get_qm_status(struct ar40xx_priv *priv, - u32 port_id, u32 *qm_buffer_err) -{ - u32 reg; - u32 qm_val; - - if (port_id < 1 || port_id > 5) { - *qm_buffer_err = 0; - return -1; - } - - if (port_id < 4) { - reg = AR40XX_REG_QM_PORT0_3_QNUM; - ar40xx_write(priv, AR40XX_REG_QM_DEBUG_ADDR, reg); - qm_val = ar40xx_read(priv, AR40XX_REG_QM_DEBUG_VALUE); - /* every 8 bits for each port */ - *qm_buffer_err = (qm_val >> (port_id * 8)) & 0xFF; - } else { - reg = AR40XX_REG_QM_PORT4_6_QNUM; - ar40xx_write(priv, AR40XX_REG_QM_DEBUG_ADDR, reg); - qm_val = ar40xx_read(priv, AR40XX_REG_QM_DEBUG_VALUE); - /* every 8 bits for each port */ - *qm_buffer_err = (qm_val >> ((port_id-4) * 8)) & 0xFF; - } - - return 0; -} - -static void -ar40xx_sw_mac_polling_task(struct ar40xx_priv *priv) -{ - static int task_count; - u32 i; - u32 reg, value; - u32 link, speed, duplex; - u32 qm_buffer_err; - u16 port_phy_status[AR40XX_NUM_PORTS]; - static u32 qm_err_cnt[AR40XX_NUM_PORTS] = {0, 0, 0, 0, 0, 0}; - static u32 link_cnt[AR40XX_NUM_PORTS] = {0, 0, 0, 0, 0, 0}; - struct mii_bus *bus = NULL; - - if (!priv || !priv->mii_bus) - return; - - bus = priv->mii_bus; - - ++task_count; - - for (i = 1; i < AR40XX_NUM_PORTS; ++i) { - port_phy_status[i] = - mdiobus_read(bus, i-1, AR40XX_PHY_SPEC_STATUS); - - speed = FIELD_GET(AR40XX_PHY_SPEC_STATUS_SPEED, - port_phy_status[i]); - link = FIELD_GET(AR40XX_PHY_SPEC_STATUS_LINK, - port_phy_status[i]); - duplex = FIELD_GET(AR40XX_PHY_SPEC_STATUS_DUPLEX, - port_phy_status[i]); - - if (link != priv->ar40xx_port_old_link[i]) { - ++link_cnt[i]; - /* Up --> Down */ - if ((priv->ar40xx_port_old_link[i] == - AR40XX_PORT_LINK_UP) && - (link == AR40XX_PORT_LINK_DOWN)) { - /* LINK_EN disable(MAC force mode)*/ - reg = AR40XX_REG_PORT_STATUS(i); - ar40xx_rmw(priv, reg, - AR40XX_PORT_AUTO_LINK_EN, 0); - - /* Check queue buffer */ - qm_err_cnt[i] = 0; - ar40xx_get_qm_status(priv, i, &qm_buffer_err); - if (qm_buffer_err) { - priv->ar40xx_port_qm_buf[i] = - AR40XX_QM_NOT_EMPTY; - } else { - u16 phy_val = 0; - - priv->ar40xx_port_qm_buf[i] = - AR40XX_QM_EMPTY; - ar40xx_force_1g_full(priv, i); - /* Ref:QCA8337 Datasheet,Clearing - * MENU_CTRL_EN prevents phy to - * stuck in 100BT mode when - * bringing up the link - */ - ar40xx_phy_dbg_read(priv, i-1, - AR40XX_PHY_DEBUG_0, - &phy_val); - phy_val &= (~AR40XX_PHY_MANU_CTRL_EN); - ar40xx_phy_dbg_write(priv, i-1, - AR40XX_PHY_DEBUG_0, - phy_val); - } - priv->ar40xx_port_old_link[i] = link; - } else if ((priv->ar40xx_port_old_link[i] == - AR40XX_PORT_LINK_DOWN) && - (link == AR40XX_PORT_LINK_UP)) { - /* Down --> Up */ - if (priv->port_link_up[i] < 1) { - ++priv->port_link_up[i]; - } else { - /* Change port status */ - reg = AR40XX_REG_PORT_STATUS(i); - value = ar40xx_read(priv, reg); - priv->port_link_up[i] = 0; - - value &= ~(AR40XX_PORT_DUPLEX | - AR40XX_PORT_SPEED); - value |= speed | (duplex ? BIT(6) : 0); - ar40xx_write(priv, reg, value); - /* clock switch need such time - * to avoid glitch - */ - usleep_range(100, 200); - - value |= AR40XX_PORT_AUTO_LINK_EN; - ar40xx_write(priv, reg, value); - /* HW need such time to make sure link - * stable before enable MAC - */ - usleep_range(100, 200); - - if (speed == AR40XX_PORT_SPEED_100M) { - u16 phy_val = 0; - /* Enable @100M, if down to 10M - * clock will change smoothly - */ - ar40xx_phy_dbg_read(priv, i-1, - 0, - &phy_val); - phy_val |= - AR40XX_PHY_MANU_CTRL_EN; - ar40xx_phy_dbg_write(priv, i-1, - 0, - phy_val); - } - priv->ar40xx_port_old_link[i] = link; - } - } - } - - if (priv->ar40xx_port_qm_buf[i] == AR40XX_QM_NOT_EMPTY) { - /* Check QM */ - ar40xx_get_qm_status(priv, i, &qm_buffer_err); - if (qm_buffer_err) { - ++qm_err_cnt[i]; - } else { - priv->ar40xx_port_qm_buf[i] = - AR40XX_QM_EMPTY; - qm_err_cnt[i] = 0; - ar40xx_force_1g_full(priv, i); - } - } - } -} - -static void -ar40xx_qm_err_check_work_task(struct work_struct *work) -{ - struct ar40xx_priv *priv = container_of(work, struct ar40xx_priv, - qm_dwork.work); - - mutex_lock(&priv->qm_lock); - - ar40xx_sw_mac_polling_task(priv); - - mutex_unlock(&priv->qm_lock); - - schedule_delayed_work(&priv->qm_dwork, - msecs_to_jiffies(AR40XX_QM_WORK_DELAY)); -} - -static int -ar40xx_qm_err_check_work_start(struct ar40xx_priv *priv) -{ - mutex_init(&priv->qm_lock); - - INIT_DELAYED_WORK(&priv->qm_dwork, ar40xx_qm_err_check_work_task); - - schedule_delayed_work(&priv->qm_dwork, - msecs_to_jiffies(AR40XX_QM_WORK_DELAY)); - - return 0; -} - -/* End of qm error WAR */ - -static int -ar40xx_vlan_init(struct ar40xx_priv *priv) -{ - int port; - unsigned long bmp; - - /* By default Enable VLAN */ - priv->vlan = 1; - priv->vlan_table[AR40XX_LAN_VLAN] = priv->cpu_bmp | priv->lan_bmp; - priv->vlan_table[AR40XX_WAN_VLAN] = priv->cpu_bmp | priv->wan_bmp; - priv->vlan_tagged = priv->cpu_bmp; - bmp = priv->lan_bmp; - for_each_set_bit(port, &bmp, AR40XX_NUM_PORTS) - priv->pvid[port] = AR40XX_LAN_VLAN; - - bmp = priv->wan_bmp; - for_each_set_bit(port, &bmp, AR40XX_NUM_PORTS) - priv->pvid[port] = AR40XX_WAN_VLAN; - - return 0; -} - -static void -ar40xx_mib_work_func(struct work_struct *work) -{ - struct ar40xx_priv *priv; - int err; - - priv = container_of(work, struct ar40xx_priv, mib_work.work); - - mutex_lock(&priv->mib_lock); - - err = ar40xx_mib_capture(priv); - if (err) - goto next_port; - - ar40xx_mib_fetch_port_stat(priv, priv->mib_next_port, false); - -next_port: - priv->mib_next_port++; - if (priv->mib_next_port >= priv->dev.ports) - priv->mib_next_port = 0; - - mutex_unlock(&priv->mib_lock); - - schedule_delayed_work(&priv->mib_work, - msecs_to_jiffies(AR40XX_MIB_WORK_DELAY)); -} - -static void -ar40xx_setup_port(struct ar40xx_priv *priv, int port, u32 members) -{ - u32 t; - u32 egress, ingress; - u32 pvid = priv->vlan_id[priv->pvid[port]]; - - if (priv->vlan) { - egress = AR40XX_PORT_VLAN1_OUT_MODE_UNMOD; - - ingress = AR40XX_IN_SECURE; - } else { - egress = AR40XX_PORT_VLAN1_OUT_MODE_UNTOUCH; - ingress = AR40XX_IN_PORT_ONLY; - } - - t = pvid << AR40XX_PORT_VLAN0_DEF_SVID_S; - t |= pvid << AR40XX_PORT_VLAN0_DEF_CVID_S; - ar40xx_write(priv, AR40XX_REG_PORT_VLAN0(port), t); - - t = AR40XX_PORT_VLAN1_PORT_VLAN_PROP; - t |= egress << AR40XX_PORT_VLAN1_OUT_MODE_S; - - ar40xx_write(priv, AR40XX_REG_PORT_VLAN1(port), t); - - t = members; - t |= AR40XX_PORT_LOOKUP_LEARN; - t |= ingress << AR40XX_PORT_LOOKUP_IN_MODE_S; - t |= AR40XX_PORT_STATE_FORWARD << AR40XX_PORT_LOOKUP_STATE_S; - ar40xx_write(priv, AR40XX_REG_PORT_LOOKUP(port), t); -} - -static void -ar40xx_vtu_op(struct ar40xx_priv *priv, u32 op, u32 val) -{ - if (ar40xx_wait_bit(priv, AR40XX_REG_VTU_FUNC1, - AR40XX_VTU_FUNC1_BUSY, 0)) - return; - - if ((op & AR40XX_VTU_FUNC1_OP) == AR40XX_VTU_FUNC1_OP_LOAD) - ar40xx_write(priv, AR40XX_REG_VTU_FUNC0, val); - - op |= AR40XX_VTU_FUNC1_BUSY; - ar40xx_write(priv, AR40XX_REG_VTU_FUNC1, op); -} - -static void -ar40xx_vtu_load_vlan(struct ar40xx_priv *priv, u32 vid, u32 port_mask) -{ - u32 op; - u32 val; - int i; - - op = AR40XX_VTU_FUNC1_OP_LOAD | (vid << AR40XX_VTU_FUNC1_VID_S); - val = AR40XX_VTU_FUNC0_VALID | AR40XX_VTU_FUNC0_IVL; - for (i = 0; i < AR40XX_NUM_PORTS; i++) { - u32 mode; - - if ((port_mask & BIT(i)) == 0) - mode = AR40XX_VTU_FUNC0_EG_MODE_NOT; - else if (priv->vlan == 0) - mode = AR40XX_VTU_FUNC0_EG_MODE_KEEP; - else if ((priv->vlan_tagged & BIT(i)) || - (priv->vlan_id[priv->pvid[i]] != vid)) - mode = AR40XX_VTU_FUNC0_EG_MODE_TAG; - else - mode = AR40XX_VTU_FUNC0_EG_MODE_UNTAG; - - val |= mode << AR40XX_VTU_FUNC0_EG_MODE_S(i); - } - ar40xx_vtu_op(priv, op, val); -} - -static void -ar40xx_vtu_flush(struct ar40xx_priv *priv) -{ - ar40xx_vtu_op(priv, AR40XX_VTU_FUNC1_OP_FLUSH, 0); -} - -static int -ar40xx_sw_hw_apply(struct switch_dev *dev) -{ - struct ar40xx_priv *priv = swdev_to_ar40xx(dev); - u8 portmask[AR40XX_NUM_PORTS]; - int i, j; - - mutex_lock(&priv->reg_mutex); - /* flush all vlan entries */ - ar40xx_vtu_flush(priv); - - memset(portmask, 0, sizeof(portmask)); - if (priv->vlan) { - for (j = 0; j < AR40XX_MAX_VLANS; j++) { - u8 vp = priv->vlan_table[j]; - - if (!vp) - continue; - - for (i = 0; i < dev->ports; i++) { - u8 mask = BIT(i); - - if (vp & mask) - portmask[i] |= vp & ~mask; - } - - ar40xx_vtu_load_vlan(priv, priv->vlan_id[j], - priv->vlan_table[j]); - } - } else { - /* 8021q vlan disabled */ - for (i = 0; i < dev->ports; i++) { - if (i == AR40XX_PORT_CPU) - continue; - - portmask[i] = BIT(AR40XX_PORT_CPU); - portmask[AR40XX_PORT_CPU] |= BIT(i); - } - } - - /* update the port destination mask registers and tag settings */ - for (i = 0; i < dev->ports; i++) - ar40xx_setup_port(priv, i, portmask[i]); - - ar40xx_set_mirror_regs(priv); - - mutex_unlock(&priv->reg_mutex); - return 0; -} - -static int -ar40xx_sw_reset_switch(struct switch_dev *dev) -{ - struct ar40xx_priv *priv = swdev_to_ar40xx(dev); - int i, rv; - - mutex_lock(&priv->reg_mutex); - memset(&priv->vlan, 0, sizeof(struct ar40xx_priv) - - offsetof(struct ar40xx_priv, vlan)); - - for (i = 0; i < AR40XX_MAX_VLANS; i++) - priv->vlan_id[i] = i; - - ar40xx_vlan_init(priv); - - priv->mirror_rx = false; - priv->mirror_tx = false; - priv->source_port = 0; - priv->monitor_port = 0; - - mutex_unlock(&priv->reg_mutex); - - rv = ar40xx_sw_hw_apply(dev); - return rv; -} - -static int -ar40xx_start(struct ar40xx_priv *priv) -{ - int ret; - - ret = ar40xx_hw_init(priv); - if (ret) - return ret; - - ret = ar40xx_sw_reset_switch(&priv->dev); - if (ret) - return ret; - - /* at last, setup cpu port */ - ret = ar40xx_cpuport_setup(priv); - if (ret) - return ret; - - schedule_delayed_work(&priv->mib_work, - msecs_to_jiffies(AR40XX_MIB_WORK_DELAY)); - - ar40xx_qm_err_check_work_start(priv); - - return 0; -} - -static const struct switch_dev_ops ar40xx_sw_ops = { - .attr_global = { - .attr = ar40xx_sw_attr_globals, - .n_attr = ARRAY_SIZE(ar40xx_sw_attr_globals), - }, - .attr_port = { - .attr = ar40xx_sw_attr_port, - .n_attr = ARRAY_SIZE(ar40xx_sw_attr_port), - }, - .attr_vlan = { - .attr = ar40xx_sw_attr_vlan, - .n_attr = ARRAY_SIZE(ar40xx_sw_attr_vlan), - }, - .get_port_pvid = ar40xx_sw_get_pvid, - .set_port_pvid = ar40xx_sw_set_pvid, - .get_vlan_ports = ar40xx_sw_get_ports, - .set_vlan_ports = ar40xx_sw_set_ports, - .apply_config = ar40xx_sw_hw_apply, - .reset_switch = ar40xx_sw_reset_switch, - .get_port_link = ar40xx_sw_get_port_link, -}; - -/* Platform driver probe function */ - -static int ar40xx_probe(struct platform_device *pdev) -{ - struct device_node *switch_node; - struct device_node *psgmii_node; - struct device_node *mdio_node; - const __be32 *mac_mode; - struct clk *ess_clk; - struct switch_dev *swdev; - struct ar40xx_priv *priv; - u32 len; - u32 num_mibs; - struct resource psgmii_base = {0}; - struct resource switch_base = {0}; - int ret; - - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - platform_set_drvdata(pdev, priv); - ar40xx_priv = priv; - - switch_node = of_node_get(pdev->dev.of_node); - if (of_address_to_resource(switch_node, 0, &switch_base) != 0) - return -EIO; - - priv->hw_addr = devm_ioremap_resource(&pdev->dev, &switch_base); - if (IS_ERR(priv->hw_addr)) { - dev_err(&pdev->dev, "Failed to ioremap switch_base!\n"); - return PTR_ERR(priv->hw_addr); - } - - /*psgmii dts get*/ - psgmii_node = of_find_node_by_name(NULL, "ess-psgmii"); - if (!psgmii_node) { - dev_err(&pdev->dev, "Failed to find ess-psgmii node!\n"); - return -EINVAL; - } - - if (of_address_to_resource(psgmii_node, 0, &psgmii_base) != 0) - return -EIO; - - priv->psgmii_hw_addr = devm_ioremap_resource(&pdev->dev, &psgmii_base); - if (IS_ERR(priv->psgmii_hw_addr)) { - dev_err(&pdev->dev, "psgmii ioremap fail!\n"); - return PTR_ERR(priv->psgmii_hw_addr); - } - - mac_mode = of_get_property(switch_node, "switch_mac_mode", &len); - if (!mac_mode) { - dev_err(&pdev->dev, "Failed to read switch_mac_mode\n"); - return -EINVAL; - } - priv->mac_mode = be32_to_cpup(mac_mode); - - ess_clk = of_clk_get_by_name(switch_node, "ess_clk"); - if (ess_clk) - clk_prepare_enable(ess_clk); - - priv->ess_rst = devm_reset_control_get(&pdev->dev, "ess_rst"); - if (IS_ERR(priv->ess_rst)) { - dev_err(&pdev->dev, "Failed to get ess_rst control!\n"); - return PTR_ERR(priv->ess_rst); - } - - if (of_property_read_u32(switch_node, "switch_cpu_bmp", - &priv->cpu_bmp) || - of_property_read_u32(switch_node, "switch_lan_bmp", - &priv->lan_bmp) || - of_property_read_u32(switch_node, "switch_wan_bmp", - &priv->wan_bmp)) { - dev_err(&pdev->dev, "Failed to read port properties\n"); - return -EIO; - } - - mutex_init(&priv->reg_mutex); - mutex_init(&priv->mib_lock); - INIT_DELAYED_WORK(&priv->mib_work, ar40xx_mib_work_func); - - /* register switch */ - swdev = &priv->dev; - - mdio_node = of_find_compatible_node(NULL, NULL, "qcom,ipq4019-mdio"); - if (!mdio_node) { - dev_err(&pdev->dev, "Probe failed - Cannot find mdio node by phandle!\n"); - ret = -ENODEV; - goto err_missing_phy; - } - - priv->mii_bus = of_mdio_find_bus(mdio_node); - - if (priv->mii_bus == NULL) { - dev_err(&pdev->dev, "Probe failed - Missing PHYs!\n"); - ret = -ENODEV; - goto err_missing_phy; - } - - swdev->alias = dev_name(&priv->mii_bus->dev); - - swdev->cpu_port = AR40XX_PORT_CPU; - swdev->name = "QCA AR40xx"; - swdev->vlans = AR40XX_MAX_VLANS; - swdev->ports = AR40XX_NUM_PORTS; - swdev->ops = &ar40xx_sw_ops; - ret = register_switch(swdev, NULL); - if (ret < 0) { - dev_err(&pdev->dev, "Switch registration failed!\n"); - return ret; - } - - num_mibs = ARRAY_SIZE(ar40xx_mibs); - len = priv->dev.ports * num_mibs * - sizeof(*priv->mib_stats); - priv->mib_stats = devm_kzalloc(&pdev->dev, len, GFP_KERNEL); - if (!priv->mib_stats) { - ret = -ENOMEM; - goto err_unregister_switch; - } - - ar40xx_start(priv); - - return 0; - -err_unregister_switch: - unregister_switch(&priv->dev); -err_missing_phy: - platform_set_drvdata(pdev, NULL); - return ret; -} - -static int ar40xx_remove(struct platform_device *pdev) -{ - struct ar40xx_priv *priv = platform_get_drvdata(pdev); - - cancel_delayed_work_sync(&priv->qm_dwork); - cancel_delayed_work_sync(&priv->mib_work); - - unregister_switch(&priv->dev); - - return 0; -} - -static const struct of_device_id ar40xx_of_mtable[] = { - {.compatible = "qcom,ess-switch" }, - {} -}; - -struct platform_driver ar40xx_drv = { - .probe = ar40xx_probe, - .remove = ar40xx_remove, - .driver = { - .name = "ar40xx", - .of_match_table = ar40xx_of_mtable, - }, -}; - -module_platform_driver(ar40xx_drv); - -MODULE_DESCRIPTION("IPQ40XX ESS driver"); -MODULE_LICENSE("Dual BSD/GPL"); diff --git a/target/linux/ipq40xx/files-5.15/drivers/net/mdio/ar40xx.h b/target/linux/ipq40xx/files-5.15/drivers/net/mdio/ar40xx.h deleted file mode 100644 index 7ba40ccf75..0000000000 --- a/target/linux/ipq40xx/files-5.15/drivers/net/mdio/ar40xx.h +++ /dev/null @@ -1,342 +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. - */ - - #ifndef __AR40XX_H -#define __AR40XX_H - -#define AR40XX_MAX_VLANS 128 -#define AR40XX_NUM_PORTS 6 -#define AR40XX_NUM_PHYS 5 - -#define BITS(_s, _n) (((1UL << (_n)) - 1) << _s) - -struct ar40xx_priv { - struct switch_dev dev; - - u8 __iomem *hw_addr; - u8 __iomem *psgmii_hw_addr; - u32 mac_mode; - struct reset_control *ess_rst; - u32 cpu_bmp; - u32 lan_bmp; - u32 wan_bmp; - - struct mii_bus *mii_bus; - struct phy_device *phy; - - /* mutex for qm task */ - struct mutex qm_lock; - struct delayed_work qm_dwork; - u32 port_link_up[AR40XX_NUM_PORTS]; - u32 ar40xx_port_old_link[AR40XX_NUM_PORTS]; - u32 ar40xx_port_qm_buf[AR40XX_NUM_PORTS]; - - u32 phy_t_status; - - /* mutex for switch reg access */ - struct mutex reg_mutex; - - /* mutex for mib task */ - struct mutex mib_lock; - struct delayed_work mib_work; - int mib_next_port; - u64 *mib_stats; - - char buf[2048]; - - /* all fields below will be cleared on reset */ - bool vlan; - u16 vlan_id[AR40XX_MAX_VLANS]; - u8 vlan_table[AR40XX_MAX_VLANS]; - u8 vlan_tagged; - u16 pvid[AR40XX_NUM_PORTS]; - - /* mirror */ - bool mirror_rx; - bool mirror_tx; - int source_port; - int monitor_port; -}; - -#define AR40XX_PORT_LINK_UP 1 -#define AR40XX_PORT_LINK_DOWN 0 -#define AR40XX_QM_NOT_EMPTY 1 -#define AR40XX_QM_EMPTY 0 - -#define AR40XX_LAN_VLAN 1 -#define AR40XX_WAN_VLAN 2 - -enum ar40xx_port_wrapper_cfg { - PORT_WRAPPER_PSGMII = 0, -}; - -struct ar40xx_mib_desc { - u32 size; - u32 offset; - const char *name; -}; - -#define AR40XX_PORT_CPU 0 - -#define AR40XX_PSGMII_MODE_CONTROL 0x1b4 -#define AR40XX_PSGMII_ATHR_CSCO_MODE_25M BIT(0) - -#define AR40XX_PSGMIIPHY_TX_CONTROL 0x288 - -#define AR40XX_MII_ATH_MMD_ADDR 0x0d -#define AR40XX_MII_ATH_MMD_DATA 0x0e -#define AR40XX_MII_ATH_DBG_ADDR 0x1d -#define AR40XX_MII_ATH_DBG_DATA 0x1e - -#define AR40XX_STATS_RXBROAD 0x00 -#define AR40XX_STATS_RXPAUSE 0x04 -#define AR40XX_STATS_RXMULTI 0x08 -#define AR40XX_STATS_RXFCSERR 0x0c -#define AR40XX_STATS_RXALIGNERR 0x10 -#define AR40XX_STATS_RXRUNT 0x14 -#define AR40XX_STATS_RXFRAGMENT 0x18 -#define AR40XX_STATS_RX64BYTE 0x1c -#define AR40XX_STATS_RX128BYTE 0x20 -#define AR40XX_STATS_RX256BYTE 0x24 -#define AR40XX_STATS_RX512BYTE 0x28 -#define AR40XX_STATS_RX1024BYTE 0x2c -#define AR40XX_STATS_RX1518BYTE 0x30 -#define AR40XX_STATS_RXMAXBYTE 0x34 -#define AR40XX_STATS_RXTOOLONG 0x38 -#define AR40XX_STATS_RXGOODBYTE 0x3c -#define AR40XX_STATS_RXBADBYTE 0x44 -#define AR40XX_STATS_RXOVERFLOW 0x4c -#define AR40XX_STATS_FILTERED 0x50 -#define AR40XX_STATS_TXBROAD 0x54 -#define AR40XX_STATS_TXPAUSE 0x58 -#define AR40XX_STATS_TXMULTI 0x5c -#define AR40XX_STATS_TXUNDERRUN 0x60 -#define AR40XX_STATS_TX64BYTE 0x64 -#define AR40XX_STATS_TX128BYTE 0x68 -#define AR40XX_STATS_TX256BYTE 0x6c -#define AR40XX_STATS_TX512BYTE 0x70 -#define AR40XX_STATS_TX1024BYTE 0x74 -#define AR40XX_STATS_TX1518BYTE 0x78 -#define AR40XX_STATS_TXMAXBYTE 0x7c -#define AR40XX_STATS_TXOVERSIZE 0x80 -#define AR40XX_STATS_TXBYTE 0x84 -#define AR40XX_STATS_TXCOLLISION 0x8c -#define AR40XX_STATS_TXABORTCOL 0x90 -#define AR40XX_STATS_TXMULTICOL 0x94 -#define AR40XX_STATS_TXSINGLECOL 0x98 -#define AR40XX_STATS_TXEXCDEFER 0x9c -#define AR40XX_STATS_TXDEFER 0xa0 -#define AR40XX_STATS_TXLATECOL 0xa4 - -#define AR40XX_REG_MODULE_EN 0x030 -#define AR40XX_MODULE_EN_MIB BIT(0) - -#define AR40XX_REG_MIB_FUNC 0x034 -#define AR40XX_MIB_BUSY BIT(17) -#define AR40XX_MIB_CPU_KEEP BIT(20) -#define AR40XX_MIB_FUNC BITS(24, 3) -#define AR40XX_MIB_FUNC_S 24 -#define AR40XX_MIB_FUNC_NO_OP 0x0 -#define AR40XX_MIB_FUNC_FLUSH 0x1 - -#define AR40XX_ESS_SERVICE_TAG 0x48 -#define AR40XX_ESS_SERVICE_TAG_STAG BIT(17) - -#define AR40XX_REG_PORT_STATUS(_i) (0x07c + (_i) * 4) -#define AR40XX_PORT_SPEED BITS(0, 2) -#define AR40XX_PORT_STATUS_SPEED_S 0 -#define AR40XX_PORT_TX_EN BIT(2) -#define AR40XX_PORT_RX_EN BIT(3) -#define AR40XX_PORT_STATUS_TXFLOW BIT(4) -#define AR40XX_PORT_STATUS_RXFLOW BIT(5) -#define AR40XX_PORT_DUPLEX BIT(6) -#define AR40XX_PORT_TXHALF_FLOW BIT(7) -#define AR40XX_PORT_STATUS_LINK_UP BIT(8) -#define AR40XX_PORT_AUTO_LINK_EN BIT(9) -#define AR40XX_PORT_STATUS_FLOW_CONTROL BIT(12) - -#define AR40XX_REG_MAX_FRAME_SIZE 0x078 -#define AR40XX_MAX_FRAME_SIZE_MTU BITS(0, 14) - -#define AR40XX_REG_PORT_HEADER(_i) (0x09c + (_i) * 4) - -#define AR40XX_REG_EEE_CTRL 0x100 -#define AR40XX_EEE_CTRL_DISABLE_PHY(_i) BIT(4 + (_i) * 2) - -#define AR40XX_REG_PORT_VLAN0(_i) (0x420 + (_i) * 0x8) -#define AR40XX_PORT_VLAN0_DEF_SVID BITS(0, 12) -#define AR40XX_PORT_VLAN0_DEF_SVID_S 0 -#define AR40XX_PORT_VLAN0_DEF_CVID BITS(16, 12) -#define AR40XX_PORT_VLAN0_DEF_CVID_S 16 - -#define AR40XX_REG_PORT_VLAN1(_i) (0x424 + (_i) * 0x8) -#define AR40XX_PORT_VLAN1_CORE_PORT BIT(9) -#define AR40XX_PORT_VLAN1_PORT_TLS_MODE BIT(7) -#define AR40XX_PORT_VLAN1_PORT_VLAN_PROP BIT(6) -#define AR40XX_PORT_VLAN1_OUT_MODE BITS(12, 2) -#define AR40XX_PORT_VLAN1_OUT_MODE_S 12 -#define AR40XX_PORT_VLAN1_OUT_MODE_UNMOD 0 -#define AR40XX_PORT_VLAN1_OUT_MODE_UNTAG 1 -#define AR40XX_PORT_VLAN1_OUT_MODE_TAG 2 -#define AR40XX_PORT_VLAN1_OUT_MODE_UNTOUCH 3 - -#define AR40XX_REG_VTU_FUNC0 0x0610 -#define AR40XX_VTU_FUNC0_EG_MODE BITS(4, 14) -#define AR40XX_VTU_FUNC0_EG_MODE_S(_i) (4 + (_i) * 2) -#define AR40XX_VTU_FUNC0_EG_MODE_KEEP 0 -#define AR40XX_VTU_FUNC0_EG_MODE_UNTAG 1 -#define AR40XX_VTU_FUNC0_EG_MODE_TAG 2 -#define AR40XX_VTU_FUNC0_EG_MODE_NOT 3 -#define AR40XX_VTU_FUNC0_IVL BIT(19) -#define AR40XX_VTU_FUNC0_VALID BIT(20) - -#define AR40XX_REG_VTU_FUNC1 0x0614 -#define AR40XX_VTU_FUNC1_OP BITS(0, 3) -#define AR40XX_VTU_FUNC1_OP_NOOP 0 -#define AR40XX_VTU_FUNC1_OP_FLUSH 1 -#define AR40XX_VTU_FUNC1_OP_LOAD 2 -#define AR40XX_VTU_FUNC1_OP_PURGE 3 -#define AR40XX_VTU_FUNC1_OP_REMOVE_PORT 4 -#define AR40XX_VTU_FUNC1_OP_GET_NEXT 5 -#define AR40XX7_VTU_FUNC1_OP_GET_ONE 6 -#define AR40XX_VTU_FUNC1_FULL BIT(4) -#define AR40XX_VTU_FUNC1_PORT BIT(8, 4) -#define AR40XX_VTU_FUNC1_PORT_S 8 -#define AR40XX_VTU_FUNC1_VID BIT(16, 12) -#define AR40XX_VTU_FUNC1_VID_S 16 -#define AR40XX_VTU_FUNC1_BUSY BIT(31) - -#define AR40XX_REG_FWD_CTRL0 0x620 -#define AR40XX_FWD_CTRL0_CPU_PORT_EN BIT(10) -#define AR40XX_FWD_CTRL0_MIRROR_PORT BITS(4, 4) -#define AR40XX_FWD_CTRL0_MIRROR_PORT_S 4 - -#define AR40XX_REG_FWD_CTRL1 0x624 -#define AR40XX_FWD_CTRL1_UC_FLOOD BITS(0, 7) -#define AR40XX_FWD_CTRL1_UC_FLOOD_S 0 -#define AR40XX_FWD_CTRL1_MC_FLOOD BITS(8, 7) -#define AR40XX_FWD_CTRL1_MC_FLOOD_S 8 -#define AR40XX_FWD_CTRL1_BC_FLOOD BITS(16, 7) -#define AR40XX_FWD_CTRL1_BC_FLOOD_S 16 -#define AR40XX_FWD_CTRL1_IGMP BITS(24, 7) -#define AR40XX_FWD_CTRL1_IGMP_S 24 - -#define AR40XX_REG_PORT_LOOKUP(_i) (0x660 + (_i) * 0xc) -#define AR40XX_PORT_LOOKUP_MEMBER BITS(0, 7) -#define AR40XX_PORT_LOOKUP_IN_MODE BITS(8, 2) -#define AR40XX_PORT_LOOKUP_IN_MODE_S 8 -#define AR40XX_PORT_LOOKUP_STATE BITS(16, 3) -#define AR40XX_PORT_LOOKUP_STATE_S 16 -#define AR40XX_PORT_LOOKUP_LEARN BIT(20) -#define AR40XX_PORT_LOOKUP_LOOPBACK BIT(21) -#define AR40XX_PORT_LOOKUP_ING_MIRROR_EN BIT(25) - -#define AR40XX_REG_ATU_FUNC 0x60c -#define AR40XX_ATU_FUNC_OP BITS(0, 4) -#define AR40XX_ATU_FUNC_OP_NOOP 0x0 -#define AR40XX_ATU_FUNC_OP_FLUSH 0x1 -#define AR40XX_ATU_FUNC_OP_LOAD 0x2 -#define AR40XX_ATU_FUNC_OP_PURGE 0x3 -#define AR40XX_ATU_FUNC_OP_FLUSH_LOCKED 0x4 -#define AR40XX_ATU_FUNC_OP_FLUSH_UNICAST 0x5 -#define AR40XX_ATU_FUNC_OP_GET_NEXT 0x6 -#define AR40XX_ATU_FUNC_OP_SEARCH_MAC 0x7 -#define AR40XX_ATU_FUNC_OP_CHANGE_TRUNK 0x8 -#define AR40XX_ATU_FUNC_BUSY BIT(31) - -#define AR40XX_REG_QM_DEBUG_ADDR 0x820 -#define AR40XX_REG_QM_DEBUG_VALUE 0x824 -#define AR40XX_REG_QM_PORT0_3_QNUM 0x1d -#define AR40XX_REG_QM_PORT4_6_QNUM 0x1e - -#define AR40XX_REG_PORT_HOL_CTRL1(_i) (0x974 + (_i) * 0x8) -#define AR40XX_PORT_HOL_CTRL1_EG_MIRROR_EN BIT(16) - -#define AR40XX_REG_PORT_FLOWCTRL_THRESH(_i) (0x9b0 + (_i) * 0x4) -#define AR40XX_PORT0_FC_THRESH_ON_DFLT 0x60 -#define AR40XX_PORT0_FC_THRESH_OFF_DFLT 0x90 - -#define AR40XX_PHY_DEBUG_0 0 -#define AR40XX_PHY_MANU_CTRL_EN BIT(12) - -#define AR40XX_PHY_DEBUG_2 2 - -#define AR40XX_PHY_SPEC_STATUS 0x11 -#define AR40XX_PHY_SPEC_STATUS_LINK BIT(10) -#define AR40XX_PHY_SPEC_STATUS_DUPLEX BIT(13) -#define AR40XX_PHY_SPEC_STATUS_SPEED BITS(14, 2) - -/* port forwarding state */ -enum { - AR40XX_PORT_STATE_DISABLED = 0, - AR40XX_PORT_STATE_BLOCK = 1, - AR40XX_PORT_STATE_LISTEN = 2, - AR40XX_PORT_STATE_LEARN = 3, - AR40XX_PORT_STATE_FORWARD = 4 -}; - -/* ingress 802.1q mode */ -enum { - AR40XX_IN_PORT_ONLY = 0, - AR40XX_IN_PORT_FALLBACK = 1, - AR40XX_IN_VLAN_ONLY = 2, - AR40XX_IN_SECURE = 3 -}; - -/* egress 802.1q mode */ -enum { - AR40XX_OUT_KEEP = 0, - AR40XX_OUT_STRIP_VLAN = 1, - AR40XX_OUT_ADD_VLAN = 2 -}; - -/* port speed */ -enum { - AR40XX_PORT_SPEED_10M = 0, - AR40XX_PORT_SPEED_100M = 1, - AR40XX_PORT_SPEED_1000M = 2, - AR40XX_PORT_SPEED_ERR = 3, -}; - -#define AR40XX_MIB_WORK_DELAY 2000 /* msecs */ - -#define AR40XX_QM_WORK_DELAY 100 - -#define AR40XX_MIB_FUNC_CAPTURE 0x3 - -#define AR40XX_REG_PORT_STATS_START 0x1000 -#define AR40XX_REG_PORT_STATS_LEN 0x100 - -#define AR40XX_PORTS_ALL 0x3f - -#define AR40XX_PSGMII_ID 5 -#define AR40XX_PSGMII_CALB_NUM 100 -#define AR40XX_MALIBU_PSGMII_MODE_CTRL 0x6d -#define AR40XX_MALIBU_PHY_PSGMII_MODE_CTRL_ADJUST_VAL 0x220c -#define AR40XX_MALIBU_PHY_MMD7_DAC_CTRL 0x801a -#define AR40XX_MALIBU_DAC_CTRL_MASK 0x380 -#define AR40XX_MALIBU_DAC_CTRL_VALUE 0x280 -#define AR40XX_MALIBU_PHY_RLP_CTRL 0x805a -#define AR40XX_PSGMII_TX_DRIVER_1_CTRL 0xb -#define AR40XX_MALIBU_PHY_PSGMII_REDUCE_SERDES_TX_AMP 0x8a -#define AR40XX_MALIBU_PHY_LAST_ADDR 4 - -static inline struct ar40xx_priv * -swdev_to_ar40xx(struct switch_dev *swdev) -{ - return container_of(swdev, struct ar40xx_priv, dev); -} - -#endif diff --git a/target/linux/ipq40xx/files-5.10/drivers/net/mdio/ar40xx.c b/target/linux/ipq40xx/files/drivers/net/mdio/ar40xx.c similarity index 100% rename from target/linux/ipq40xx/files-5.10/drivers/net/mdio/ar40xx.c rename to target/linux/ipq40xx/files/drivers/net/mdio/ar40xx.c diff --git a/target/linux/ipq40xx/files-5.10/drivers/net/mdio/ar40xx.h b/target/linux/ipq40xx/files/drivers/net/mdio/ar40xx.h similarity index 100% rename from target/linux/ipq40xx/files-5.10/drivers/net/mdio/ar40xx.h rename to target/linux/ipq40xx/files/drivers/net/mdio/ar40xx.h From 726ef8ba2dbe4d4a693c4d9300bc69e234e6d67d Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 6 May 2022 15:49:58 +0200 Subject: [PATCH 07/24] kernel: fix flow offload issues with pppoe sync xt_FLOWOFFLOAD code with latest version of nft_flow_offload Signed-off-by: Felix Fietkau --- ...-netfilter-add-xt_FLOWOFFLOAD-target.patch | 343 ++++++++++-------- ...ble-fix-excessive-hw-offload-attempt.patch | 27 ++ ...ow_offload-skip-dst-neigh-lookup-for.patch | 64 ++++ ..._fill_forward_path-with-pppoe-bridge.patch | 66 ++++ ...ow_offload-fix-offload-with-pppoe-vl.patch | 24 ++ 5 files changed, 371 insertions(+), 153 deletions(-) create mode 100644 target/linux/generic/pending-5.15/704-00-netfilter-flowtable-fix-excessive-hw-offload-attempt.patch create mode 100644 target/linux/generic/pending-5.15/704-01-netfilter-nft_flow_offload-skip-dst-neigh-lookup-for.patch create mode 100644 target/linux/generic/pending-5.15/704-02-net-fix-dev_fill_forward_path-with-pppoe-bridge.patch create mode 100644 target/linux/generic/pending-5.15/704-03-netfilter-nft_flow_offload-fix-offload-with-pppoe-vl.patch diff --git a/target/linux/generic/hack-5.15/650-netfilter-add-xt_FLOWOFFLOAD-target.patch b/target/linux/generic/hack-5.15/650-netfilter-add-xt_FLOWOFFLOAD-target.patch index fa21ca1229..0eca9f8d8f 100644 --- a/target/linux/generic/hack-5.15/650-netfilter-add-xt_FLOWOFFLOAD-target.patch +++ b/target/linux/generic/hack-5.15/650-netfilter-add-xt_FLOWOFFLOAD-target.patch @@ -98,7 +98,7 @@ Signed-off-by: Felix Fietkau obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o --- /dev/null +++ b/net/netfilter/xt_FLOWOFFLOAD.c -@@ -0,0 +1,657 @@ +@@ -0,0 +1,694 @@ +/* + * Copyright (C) 2018-2021 Felix Fietkau + * @@ -110,6 +110,7 @@ Signed-off-by: Felix Fietkau +#include +#include +#include ++#include +#include +#include +#include @@ -130,6 +131,21 @@ Signed-off-by: Felix Fietkau + struct delayed_work work; +}; + ++struct nf_forward_info { ++ const struct net_device *indev; ++ const struct net_device *outdev; ++ const struct net_device *hw_outdev; ++ struct id { ++ __u16 id; ++ __be16 proto; ++ } encap[NF_FLOW_TABLE_ENCAP_MAX]; ++ u8 num_encaps; ++ u8 ingress_vlans; ++ u8 h_source[ETH_ALEN]; ++ u8 h_dest[ETH_ALEN]; ++ enum flow_offload_xmit_type xmit_type; ++}; ++ +static DEFINE_SPINLOCK(hooks_lock); + +struct xt_flowoffload_table flowtable[2]; @@ -138,12 +154,23 @@ Signed-off-by: Felix Fietkau +xt_flowoffload_net_hook(void *priv, struct sk_buff *skb, + const struct nf_hook_state *state) +{ -+ struct nf_flowtable *ft = priv; -+ -+ if (!atomic_read(&ft->rhashtable.nelems)) -+ return NF_ACCEPT; ++ struct vlan_ethhdr *veth; ++ __be16 proto; + + switch (skb->protocol) { ++ case htons(ETH_P_8021Q): ++ veth = (struct vlan_ethhdr *)skb_mac_header(skb); ++ proto = veth->h_vlan_encapsulated_proto; ++ break; ++ case htons(ETH_P_PPP_SES): ++ proto = nf_flow_pppoe_proto(skb); ++ break; ++ default: ++ proto = skb->protocol; ++ break; ++ } ++ ++ switch (proto) { + case htons(ETH_P_IP): + return nf_flow_offload_ip_hook(priv, skb, state); + case htons(ETH_P_IPV6): @@ -323,7 +350,26 @@ Signed-off-by: Felix Fietkau + return false; +} + -+static bool flow_is_valid_ether_device(const struct net_device *dev) ++static enum flow_offload_xmit_type nf_xmit_type(struct dst_entry *dst) ++{ ++ if (dst_xfrm(dst)) ++ return FLOW_OFFLOAD_XMIT_XFRM; ++ ++ return FLOW_OFFLOAD_XMIT_NEIGH; ++} ++ ++static void nf_default_forward_path(struct nf_flow_route *route, ++ struct dst_entry *dst_cache, ++ enum ip_conntrack_dir dir, ++ struct net_device **dev) ++{ ++ dev[!dir] = dst_cache->dev; ++ route->tuple[!dir].in.ifindex = dst_cache->dev->ifindex; ++ route->tuple[dir].dst = dst_cache; ++ route->tuple[dir].xmit_type = nf_xmit_type(dst_cache); ++} ++ ++static bool nf_is_valid_ether_device(const struct net_device *dev) +{ + if (!dev || (dev->flags & IFF_LOOPBACK) || dev->type != ARPHRD_ETHER || + dev->addr_len != ETH_ALEN || !is_valid_ether_addr(dev->dev_addr)) @@ -332,174 +378,181 @@ Signed-off-by: Felix Fietkau + return true; +} + -+static void -+xt_flowoffload_route_check_path(struct nf_flow_route *route, -+ const struct nf_conn *ct, -+ enum ip_conntrack_dir dir, -+ struct net_device **out_dev) ++static void nf_dev_path_info(const struct net_device_path_stack *stack, ++ struct nf_forward_info *info, ++ unsigned char *ha) +{ -+ const struct dst_entry *dst = route->tuple[dir].dst; -+ const void *daddr = &ct->tuplehash[!dir].tuple.src.u3; -+ struct net_device_path_stack stack; -+ enum net_device_path_type prev_type; -+ struct net_device *dev = dst->dev; -+ struct neighbour *n; -+ bool last = false; -+ u8 nud_state; ++ const struct net_device_path *path; + int i; + -+ route->tuple[!dir].in.ifindex = dev->ifindex; -+ route->tuple[dir].out.ifindex = dev->ifindex; -+ -+ if (route->tuple[dir].xmit_type == FLOW_OFFLOAD_XMIT_XFRM) -+ return; -+ -+ if ((dev->flags & IFF_LOOPBACK) || -+ dev->type != ARPHRD_ETHER || dev->addr_len != ETH_ALEN || -+ !is_valid_ether_addr(dev->dev_addr)) -+ return; -+ -+ n = dst_neigh_lookup(dst, daddr); -+ if (!n) -+ return; -+ -+ read_lock_bh(&n->lock); -+ nud_state = n->nud_state; -+ memcpy(route->tuple[dir].out.h_dest, n->ha, ETH_ALEN); -+ read_unlock_bh(&n->lock); -+ neigh_release(n); -+ -+ if (!(nud_state & NUD_VALID)) -+ return; -+ -+ if (dev_fill_forward_path(dev, route->tuple[dir].out.h_dest, &stack) || -+ !stack.num_paths) -+ return; -+ -+ prev_type = DEV_PATH_ETHERNET; -+ for (i = 0; i <= stack.num_paths; i++) { -+ const struct net_device_path *path = &stack.path[i]; -+ int n_encaps = route->tuple[!dir].in.num_encaps; -+ -+ dev = (struct net_device *)path->dev; -+ if (flow_is_valid_ether_device(dev)) { -+ if (route->tuple[dir].xmit_type != FLOW_OFFLOAD_XMIT_DIRECT) { -+ memcpy(route->tuple[dir].out.h_source, -+ dev->dev_addr, ETH_ALEN); -+ route->tuple[dir].out.ifindex = dev->ifindex; -+ } -+ route->tuple[dir].xmit_type = FLOW_OFFLOAD_XMIT_DIRECT; -+ } ++ memcpy(info->h_dest, ha, ETH_ALEN); + ++ for (i = 0; i < stack->num_paths; i++) { ++ path = &stack->path[i]; + switch (path->type) { -+ case DEV_PATH_PPPOE: ++ case DEV_PATH_ETHERNET: ++ case DEV_PATH_DSA: + case DEV_PATH_VLAN: -+ if (n_encaps >= NF_FLOW_TABLE_ENCAP_MAX || -+ i == stack.num_paths) { -+ last = true; ++ case DEV_PATH_PPPOE: ++ info->indev = path->dev; ++ if (is_zero_ether_addr(info->h_source)) ++ memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN); ++ ++ if (path->type == DEV_PATH_ETHERNET) ++ break; ++ if (path->type == DEV_PATH_DSA) { ++ i = stack->num_paths; + break; + } + -+ route->tuple[!dir].in.num_encaps++; -+ route->tuple[!dir].in.encap[n_encaps].id = path->encap.id; -+ route->tuple[!dir].in.encap[n_encaps].proto = path->encap.proto; ++ /* DEV_PATH_VLAN and DEV_PATH_PPPOE */ ++ if (info->num_encaps >= NF_FLOW_TABLE_ENCAP_MAX) { ++ info->indev = NULL; ++ break; ++ } ++ if (!info->outdev) ++ info->outdev = path->dev; ++ info->encap[info->num_encaps].id = path->encap.id; ++ info->encap[info->num_encaps].proto = path->encap.proto; ++ info->num_encaps++; + if (path->type == DEV_PATH_PPPOE) -+ memcpy(route->tuple[dir].out.h_dest, -+ path->encap.h_dest, ETH_ALEN); ++ memcpy(info->h_dest, path->encap.h_dest, ETH_ALEN); + break; + case DEV_PATH_BRIDGE: -+ switch (path->bridge.vlan_mode) { -+ case DEV_PATH_BR_VLAN_TAG: -+ if (n_encaps >= NF_FLOW_TABLE_ENCAP_MAX || -+ i == stack.num_paths) { -+ last = true; -+ break; -+ } ++ if (is_zero_ether_addr(info->h_source)) ++ memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN); + -+ route->tuple[!dir].in.num_encaps++; -+ route->tuple[!dir].in.encap[n_encaps].id = -+ path->bridge.vlan_id; -+ route->tuple[!dir].in.encap[n_encaps].proto = -+ path->bridge.vlan_proto; ++ switch (path->bridge.vlan_mode) { ++ case DEV_PATH_BR_VLAN_UNTAG_HW: ++ info->ingress_vlans |= BIT(info->num_encaps - 1); ++ break; ++ case DEV_PATH_BR_VLAN_TAG: ++ info->encap[info->num_encaps].id = path->bridge.vlan_id; ++ info->encap[info->num_encaps].proto = path->bridge.vlan_proto; ++ info->num_encaps++; + break; + case DEV_PATH_BR_VLAN_UNTAG: -+ route->tuple[!dir].in.num_encaps--; -+ break; -+ case DEV_PATH_BR_VLAN_UNTAG_HW: -+ route->tuple[!dir].in.ingress_vlans |= BIT(n_encaps - 1); ++ info->num_encaps--; + break; + case DEV_PATH_BR_VLAN_KEEP: + break; + } + break; + default: -+ last = true; ++ info->indev = NULL; + break; + } -+ -+ if (last) -+ break; + } ++ if (!info->outdev) ++ info->outdev = info->indev; + -+ *out_dev = dev; -+ route->tuple[dir].out.hw_ifindex = dev->ifindex; -+ route->tuple[!dir].in.ifindex = dev->ifindex; ++ info->hw_outdev = info->indev; ++ ++ if (nf_is_valid_ether_device(info->indev)) ++ info->xmit_type = FLOW_OFFLOAD_XMIT_DIRECT; +} + -+static int -+xt_flowoffload_route_dir(struct nf_flow_route *route, const struct nf_conn *ct, -+ enum ip_conntrack_dir dir, -+ const struct xt_action_param *par, int ifindex) ++static int nf_dev_fill_forward_path(const struct nf_flow_route *route, ++ const struct dst_entry *dst_cache, ++ const struct nf_conn *ct, ++ enum ip_conntrack_dir dir, u8 *ha, ++ struct net_device_path_stack *stack) +{ -+ struct dst_entry *dst = NULL; -+ struct flowi fl; ++ const void *daddr = &ct->tuplehash[!dir].tuple.src.u3; ++ struct net_device *dev = dst_cache->dev; ++ struct neighbour *n; ++ u8 nud_state; + -+ 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; ++ if (!nf_is_valid_ether_device(dev)) ++ goto out; ++ ++ n = dst_neigh_lookup(dst_cache, daddr); ++ if (!n) ++ return -1; ++ ++ read_lock_bh(&n->lock); ++ nud_state = n->nud_state; ++ ether_addr_copy(ha, n->ha); ++ read_unlock_bh(&n->lock); ++ neigh_release(n); ++ ++ if (!(nud_state & NUD_VALID)) ++ return -1; ++ ++out: ++ return dev_fill_forward_path(dev, ha, stack); ++} ++ ++static void nf_dev_forward_path(struct nf_flow_route *route, ++ const struct nf_conn *ct, ++ enum ip_conntrack_dir dir, ++ struct net_device **devs) ++{ ++ const struct dst_entry *dst = route->tuple[dir].dst; ++ struct net_device_path_stack stack; ++ struct nf_forward_info info = {}; ++ unsigned char ha[ETH_ALEN]; ++ int i; ++ ++ if (nf_dev_fill_forward_path(route, dst, ct, dir, ha, &stack) >= 0) ++ nf_dev_path_info(&stack, &info, ha); ++ ++ devs[!dir] = (struct net_device *)info.indev; ++ if (!info.indev) ++ return; ++ ++ route->tuple[!dir].in.ifindex = info.indev->ifindex; ++ for (i = 0; i < info.num_encaps; i++) { ++ route->tuple[!dir].in.encap[i].id = info.encap[i].id; ++ route->tuple[!dir].in.encap[i].proto = info.encap[i].proto; + } ++ route->tuple[!dir].in.num_encaps = info.num_encaps; ++ route->tuple[!dir].in.ingress_vlans = info.ingress_vlans; + -+ nf_route(xt_net(par), &dst, &fl, false, xt_family(par)); -+ if (!dst) -+ return -ENOENT; -+ -+ route->tuple[dir].dst = dst; -+ if (dst_xfrm(dst)) -+ route->tuple[dir].xmit_type = FLOW_OFFLOAD_XMIT_XFRM; -+ else -+ route->tuple[dir].xmit_type = FLOW_OFFLOAD_XMIT_NEIGH; -+ -+ return 0; ++ if (info.xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) { ++ memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN); ++ memcpy(route->tuple[dir].out.h_dest, info.h_dest, ETH_ALEN); ++ route->tuple[dir].out.ifindex = info.outdev->ifindex; ++ route->tuple[dir].out.hw_ifindex = info.hw_outdev->ifindex; ++ route->tuple[dir].xmit_type = info.xmit_type; ++ } +} + +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 net_device **dev) ++ struct net_device **devs) +{ -+ int ret; ++ struct dst_entry *this_dst = skb_dst(skb); ++ struct dst_entry *other_dst = NULL; ++ struct flowi fl; + -+ ret = xt_flowoffload_route_dir(route, ct, dir, par, -+ dev[dir]->ifindex); -+ if (ret) -+ return ret; ++ 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 = xt_in(par)->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 = xt_in(par)->ifindex; ++ break; ++ } + -+ ret = xt_flowoffload_route_dir(route, ct, !dir, par, -+ dev[!dir]->ifindex); -+ if (ret) -+ return ret; ++ nf_route(xt_net(par), &other_dst, &fl, false, xt_family(par)); ++ if (!other_dst) ++ return -ENOENT; + -+ xt_flowoffload_route_check_path(route, ct, dir, &dev[!dir]); -+ xt_flowoffload_route_check_path(route, ct, !dir, &dev[dir]); ++ nf_default_forward_path(route, this_dst, dir, devs); ++ nf_default_forward_path(route, other_dst, !dir, devs); ++ ++ if (route->tuple[dir].xmit_type == FLOW_OFFLOAD_XMIT_NEIGH && ++ route->tuple[!dir].xmit_type == FLOW_OFFLOAD_XMIT_NEIGH) { ++ nf_dev_forward_path(route, ct, dir, devs); ++ nf_dev_forward_path(route, ct, !dir, devs); ++ } + + return 0; +} @@ -542,7 +595,7 @@ Signed-off-by: Felix Fietkau + } + + if (nf_ct_ext_exist(ct, NF_CT_EXT_HELPER) || -+ ct->status & IPS_SEQ_ADJUST) ++ ct->status & (IPS_SEQ_ADJUST | IPS_NAT_CLASH)) + return XT_CONTINUE; + + if (!nf_ct_is_confirmed(ct)) @@ -586,7 +639,6 @@ Signed-off-by: Felix Fietkau + xt_flowoffload_check_device(table, devs[0]); + xt_flowoffload_check_device(table, devs[1]); + -+ dst_release(route.tuple[dir].dst); + dst_release(route.tuple[!dir].dst); + + return XT_CONTINUE; @@ -594,7 +646,6 @@ Signed-off-by: Felix Fietkau +err_flow_add: + flow_offload_free(flow); +err_flow_alloc: -+ dst_release(route.tuple[dir].dst); + dst_release(route.tuple[!dir].dst); +err_flow_route: + clear_bit(IPS_OFFLOAD_BIT, &ct->status); @@ -661,20 +712,6 @@ Signed-off-by: Felix Fietkau + .notifier_call = flow_offload_netdev_event, +}; + -+static unsigned int -+nf_flow_offload_inet_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; -+} -+ +static int nf_flow_rule_route_inet(struct net *net, + const struct flow_offload *flow, + enum flow_offload_tuple_dir dir, @@ -704,7 +741,7 @@ Signed-off-by: Felix Fietkau + .setup = nf_flow_table_offload_setup, + .action = nf_flow_rule_route_inet, + .free = nf_flow_table_free, -+ .hook = nf_flow_offload_inet_hook, ++ .hook = xt_flowoffload_net_hook, + .owner = THIS_MODULE, +}; + @@ -766,7 +803,7 @@ Signed-off-by: Felix Fietkau #include #include #include -@@ -397,8 +396,7 @@ flow_offload_lookup(struct nf_flowtable +@@ -399,8 +398,7 @@ flow_offload_lookup(struct nf_flowtable } EXPORT_SYMBOL_GPL(flow_offload_lookup); @@ -776,7 +813,7 @@ Signed-off-by: Felix Fietkau void (*iter)(struct flow_offload *flow, void *data), void *data) { -@@ -430,6 +428,7 @@ nf_flow_table_iterate(struct nf_flowtabl +@@ -432,6 +430,7 @@ nf_flow_table_iterate(struct nf_flowtabl return err; } diff --git a/target/linux/generic/pending-5.15/704-00-netfilter-flowtable-fix-excessive-hw-offload-attempt.patch b/target/linux/generic/pending-5.15/704-00-netfilter-flowtable-fix-excessive-hw-offload-attempt.patch new file mode 100644 index 0000000000..c03cb5ae46 --- /dev/null +++ b/target/linux/generic/pending-5.15/704-00-netfilter-flowtable-fix-excessive-hw-offload-attempt.patch @@ -0,0 +1,27 @@ +From: Felix Fietkau +Date: Fri, 6 May 2022 12:37:23 +0200 +Subject: [PATCH] netfilter: flowtable: fix excessive hw offload attempts + after failure + +If a flow cannot be offloaded, the code currently repeatedly tries again as +quickly as possible, which can significantly increase system load. +Fix this by limiting flow timeout update and hardware offload retry to once +per second. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -329,8 +329,10 @@ void flow_offload_refresh(struct nf_flow + u32 timeout; + + timeout = nf_flowtable_time_stamp + flow_offload_get_timeout(flow); +- if (READ_ONCE(flow->timeout) != timeout) ++ if (timeout - READ_ONCE(flow->timeout) > HZ) + WRITE_ONCE(flow->timeout, timeout); ++ else ++ return; + + if (likely(!nf_flowtable_hw_offload(flow_table))) + return; diff --git a/target/linux/generic/pending-5.15/704-01-netfilter-nft_flow_offload-skip-dst-neigh-lookup-for.patch b/target/linux/generic/pending-5.15/704-01-netfilter-nft_flow_offload-skip-dst-neigh-lookup-for.patch new file mode 100644 index 0000000000..6683a53f76 --- /dev/null +++ b/target/linux/generic/pending-5.15/704-01-netfilter-nft_flow_offload-skip-dst-neigh-lookup-for.patch @@ -0,0 +1,64 @@ +From: Felix Fietkau +Date: Fri, 6 May 2022 12:43:58 +0200 +Subject: [PATCH] netfilter: nft_flow_offload: skip dst neigh lookup for + ppp devices + +The dst entry does not contain a valid hardware address, so skip the lookup +in order to avoid running into errors here. +The proper hardware address is filled in from nft_dev_path_info + +Signed-off-by: Felix Fietkau +--- + +--- a/net/netfilter/nft_flow_offload.c ++++ b/net/netfilter/nft_flow_offload.c +@@ -36,6 +36,15 @@ static void nft_default_forward_path(str + route->tuple[dir].xmit_type = nft_xmit_type(dst_cache); + } + ++static bool nft_is_valid_ether_device(const struct net_device *dev) ++{ ++ if (!dev || (dev->flags & IFF_LOOPBACK) || dev->type != ARPHRD_ETHER || ++ dev->addr_len != ETH_ALEN || !is_valid_ether_addr(dev->dev_addr)) ++ return false; ++ ++ return true; ++} ++ + static int nft_dev_fill_forward_path(const struct nf_flow_route *route, + const struct dst_entry *dst_cache, + const struct nf_conn *ct, +@@ -47,6 +56,9 @@ static int nft_dev_fill_forward_path(con + struct neighbour *n; + u8 nud_state; + ++ if (!nft_is_valid_ether_device(dev)) ++ goto out; ++ + n = dst_neigh_lookup(dst_cache, daddr); + if (!n) + return -1; +@@ -60,6 +72,7 @@ static int nft_dev_fill_forward_path(con + if (!(nud_state & NUD_VALID)) + return -1; + ++out: + return dev_fill_forward_path(dev, ha, stack); + } + +@@ -78,15 +91,6 @@ struct nft_forward_info { + enum flow_offload_xmit_type xmit_type; + }; + +-static bool nft_is_valid_ether_device(const struct net_device *dev) +-{ +- if (!dev || (dev->flags & IFF_LOOPBACK) || dev->type != ARPHRD_ETHER || +- dev->addr_len != ETH_ALEN || !is_valid_ether_addr(dev->dev_addr)) +- return false; +- +- return true; +-} +- + static void nft_dev_path_info(const struct net_device_path_stack *stack, + struct nft_forward_info *info, + unsigned char *ha, struct nf_flowtable *flowtable) diff --git a/target/linux/generic/pending-5.15/704-02-net-fix-dev_fill_forward_path-with-pppoe-bridge.patch b/target/linux/generic/pending-5.15/704-02-net-fix-dev_fill_forward_path-with-pppoe-bridge.patch new file mode 100644 index 0000000000..984733aeb8 --- /dev/null +++ b/target/linux/generic/pending-5.15/704-02-net-fix-dev_fill_forward_path-with-pppoe-bridge.patch @@ -0,0 +1,66 @@ +From: Felix Fietkau +Date: Fri, 6 May 2022 13:54:44 +0200 +Subject: [PATCH] net: fix dev_fill_forward_path with pppoe + bridge + +When calling dev_fill_forward_path on a pppoe device, the provided destination +address is invalid. In order for the bridge fdb lookup to succeed, the pppoe +code needs to update ctx->daddr to the correct value. +Fix this by storing the address inside struct net_device_path_ctx + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -90,7 +90,6 @@ mtk_flow_get_wdma_info(struct net_device + { + struct net_device_path_ctx ctx = { + .dev = dev, +- .daddr = addr, + }; + struct net_device_path path = {}; + +@@ -100,6 +99,7 @@ mtk_flow_get_wdma_info(struct net_device + if (!dev->netdev_ops->ndo_fill_forward_path) + return -1; + ++ memcpy(ctx.daddr, addr, sizeof(ctx.daddr)); + if (dev->netdev_ops->ndo_fill_forward_path(&ctx, &path)) + return -1; + +--- a/drivers/net/ppp/pppoe.c ++++ b/drivers/net/ppp/pppoe.c +@@ -988,6 +988,7 @@ static int pppoe_fill_forward_path(struc + path->encap.proto = htons(ETH_P_PPP_SES); + path->encap.id = be16_to_cpu(po->num); + memcpy(path->encap.h_dest, po->pppoe_pa.remote, ETH_ALEN); ++ memcpy(ctx->daddr, po->pppoe_pa.remote, ETH_ALEN); + path->dev = ctx->dev; + ctx->dev = dev; + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -894,7 +894,7 @@ struct net_device_path_stack { + + struct net_device_path_ctx { + const struct net_device *dev; +- const u8 *daddr; ++ u8 daddr[ETH_ALEN]; + + int num_vlans; + struct { +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -741,11 +741,11 @@ int dev_fill_forward_path(const struct n + const struct net_device *last_dev; + struct net_device_path_ctx ctx = { + .dev = dev, +- .daddr = daddr, + }; + struct net_device_path *path; + int ret = 0; + ++ memcpy(ctx.daddr, daddr, sizeof(ctx.daddr)); + stack->num_paths = 0; + while (ctx.dev && ctx.dev->netdev_ops->ndo_fill_forward_path) { + last_dev = ctx.dev; diff --git a/target/linux/generic/pending-5.15/704-03-netfilter-nft_flow_offload-fix-offload-with-pppoe-vl.patch b/target/linux/generic/pending-5.15/704-03-netfilter-nft_flow_offload-fix-offload-with-pppoe-vl.patch new file mode 100644 index 0000000000..1e0dc9957d --- /dev/null +++ b/target/linux/generic/pending-5.15/704-03-netfilter-nft_flow_offload-fix-offload-with-pppoe-vl.patch @@ -0,0 +1,24 @@ +From: Felix Fietkau +Date: Fri, 6 May 2022 15:15:06 +0200 +Subject: [PATCH] netfilter: nft_flow_offload: fix offload with pppoe + + vlan + +When running a combination of PPPoE on top of a VLAN, we need to set +info->outdev to the PPPoE device, otherwise PPPoE encap is skipped +during software offload. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/netfilter/nft_flow_offload.c ++++ b/net/netfilter/nft_flow_offload.c +@@ -123,7 +123,8 @@ static void nft_dev_path_info(const stru + info->indev = NULL; + break; + } +- info->outdev = path->dev; ++ if (!info->outdev) ++ info->outdev = path->dev; + info->encap[info->num_encaps].id = path->encap.id; + info->encap[info->num_encaps].proto = path->encap.proto; + info->num_encaps++; From b5f25d43b7e8eb78bde9659b3ecb651ee5e2f5be Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 6 May 2022 15:49:58 +0200 Subject: [PATCH 08/24] kernel: backport flow offload fixes to 5.10 Signed-off-by: Felix Fietkau --- ...owtable-avoid-possible-false-sharing.patch | 27 ++ ...-netfilter-add-xt_FLOWOFFLOAD-target.patch | 361 ++++++++++-------- ...ble-fix-excessive-hw-offload-attempt.patch | 27 ++ ...ow_offload-skip-dst-neigh-lookup-for.patch | 64 ++++ ..._fill_forward_path-with-pppoe-bridge.patch | 66 ++++ ...ow_offload-fix-offload-with-pppoe-vl.patch | 24 ++ 6 files changed, 416 insertions(+), 153 deletions(-) create mode 100644 target/linux/generic/backport-5.10/610-v5.15-58-netfilter-flowtable-avoid-possible-false-sharing.patch create mode 100644 target/linux/generic/pending-5.10/704-00-netfilter-flowtable-fix-excessive-hw-offload-attempt.patch create mode 100644 target/linux/generic/pending-5.10/704-01-netfilter-nft_flow_offload-skip-dst-neigh-lookup-for.patch create mode 100644 target/linux/generic/pending-5.10/704-02-net-fix-dev_fill_forward_path-with-pppoe-bridge.patch create mode 100644 target/linux/generic/pending-5.10/704-03-netfilter-nft_flow_offload-fix-offload-with-pppoe-vl.patch diff --git a/target/linux/generic/backport-5.10/610-v5.15-58-netfilter-flowtable-avoid-possible-false-sharing.patch b/target/linux/generic/backport-5.10/610-v5.15-58-netfilter-flowtable-avoid-possible-false-sharing.patch new file mode 100644 index 0000000000..69c06c51d8 --- /dev/null +++ b/target/linux/generic/backport-5.10/610-v5.15-58-netfilter-flowtable-avoid-possible-false-sharing.patch @@ -0,0 +1,27 @@ +From: Pablo Neira Ayuso +Date: Sat, 17 Jul 2021 10:10:29 +0200 +Subject: [PATCH] netfilter: flowtable: avoid possible false sharing + +The flowtable follows the same timeout approach as conntrack, use the +same idiom as in cc16921351d8 ("netfilter: conntrack: avoid same-timeout +update") but also include the fix provided by e37542ba111f ("netfilter: +conntrack: avoid possible false sharing"). + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -328,7 +328,11 @@ EXPORT_SYMBOL_GPL(flow_offload_add); + void flow_offload_refresh(struct nf_flowtable *flow_table, + struct flow_offload *flow) + { +- flow->timeout = nf_flowtable_time_stamp + flow_offload_get_timeout(flow); ++ u32 timeout; ++ ++ timeout = nf_flowtable_time_stamp + flow_offload_get_timeout(flow); ++ if (READ_ONCE(flow->timeout) != timeout) ++ WRITE_ONCE(flow->timeout, timeout); + + if (likely(!nf_flowtable_hw_offload(flow_table))) + return; diff --git a/target/linux/generic/hack-5.10/650-netfilter-add-xt_FLOWOFFLOAD-target.patch b/target/linux/generic/hack-5.10/650-netfilter-add-xt_FLOWOFFLOAD-target.patch index 23332534bb..8435ae71cd 100644 --- a/target/linux/generic/hack-5.10/650-netfilter-add-xt_FLOWOFFLOAD-target.patch +++ b/target/linux/generic/hack-5.10/650-netfilter-add-xt_FLOWOFFLOAD-target.patch @@ -98,7 +98,7 @@ Signed-off-by: Felix Fietkau obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o --- /dev/null +++ b/net/netfilter/xt_FLOWOFFLOAD.c -@@ -0,0 +1,657 @@ +@@ -0,0 +1,712 @@ +/* + * Copyright (C) 2018-2021 Felix Fietkau + * @@ -110,6 +110,9 @@ Signed-off-by: Felix Fietkau +#include +#include +#include ++#include ++#include ++#include +#include +#include +#include @@ -130,20 +133,62 @@ Signed-off-by: Felix Fietkau + struct delayed_work work; +}; + ++struct nf_forward_info { ++ const struct net_device *indev; ++ const struct net_device *outdev; ++ const struct net_device *hw_outdev; ++ struct id { ++ __u16 id; ++ __be16 proto; ++ } encap[NF_FLOW_TABLE_ENCAP_MAX]; ++ u8 num_encaps; ++ u8 ingress_vlans; ++ u8 h_source[ETH_ALEN]; ++ u8 h_dest[ETH_ALEN]; ++ enum flow_offload_xmit_type xmit_type; ++}; ++ +static DEFINE_SPINLOCK(hooks_lock); + +struct xt_flowoffload_table flowtable[2]; + ++static inline __be16 nf_flow_pppoe_proto(const struct sk_buff *skb) ++{ ++ __be16 proto; ++ ++ proto = *((__be16 *)(skb_mac_header(skb) + ETH_HLEN + ++ sizeof(struct pppoe_hdr))); ++ switch (proto) { ++ case htons(PPP_IP): ++ return htons(ETH_P_IP); ++ case htons(PPP_IPV6): ++ return htons(ETH_P_IPV6); ++ } ++ ++ return 0; ++} ++ +static unsigned int +xt_flowoffload_net_hook(void *priv, struct sk_buff *skb, + const struct nf_hook_state *state) +{ -+ struct nf_flowtable *ft = priv; -+ -+ if (!atomic_read(&ft->rhashtable.nelems)) -+ return NF_ACCEPT; ++ struct vlan_ethhdr *veth; ++ __be16 proto; + + switch (skb->protocol) { ++ case htons(ETH_P_8021Q): ++ veth = (struct vlan_ethhdr *)skb_mac_header(skb); ++ proto = veth->h_vlan_encapsulated_proto; ++ break; ++ case htons(ETH_P_PPP_SES): ++ proto = nf_flow_pppoe_proto(skb); ++ break; ++ default: ++ proto = skb->protocol; ++ break; ++ } ++ ++ switch (proto) { + case htons(ETH_P_IP): + return nf_flow_offload_ip_hook(priv, skb, state); + case htons(ETH_P_IPV6): @@ -323,7 +368,26 @@ Signed-off-by: Felix Fietkau + return false; +} + -+static bool flow_is_valid_ether_device(const struct net_device *dev) ++static enum flow_offload_xmit_type nf_xmit_type(struct dst_entry *dst) ++{ ++ if (dst_xfrm(dst)) ++ return FLOW_OFFLOAD_XMIT_XFRM; ++ ++ return FLOW_OFFLOAD_XMIT_NEIGH; ++} ++ ++static void nf_default_forward_path(struct nf_flow_route *route, ++ struct dst_entry *dst_cache, ++ enum ip_conntrack_dir dir, ++ struct net_device **dev) ++{ ++ dev[!dir] = dst_cache->dev; ++ route->tuple[!dir].in.ifindex = dst_cache->dev->ifindex; ++ route->tuple[dir].dst = dst_cache; ++ route->tuple[dir].xmit_type = nf_xmit_type(dst_cache); ++} ++ ++static bool nf_is_valid_ether_device(const struct net_device *dev) +{ + if (!dev || (dev->flags & IFF_LOOPBACK) || dev->type != ARPHRD_ETHER || + dev->addr_len != ETH_ALEN || !is_valid_ether_addr(dev->dev_addr)) @@ -332,174 +396,181 @@ Signed-off-by: Felix Fietkau + return true; +} + -+static void -+xt_flowoffload_route_check_path(struct nf_flow_route *route, -+ const struct nf_conn *ct, -+ enum ip_conntrack_dir dir, -+ struct net_device **out_dev) ++static void nf_dev_path_info(const struct net_device_path_stack *stack, ++ struct nf_forward_info *info, ++ unsigned char *ha) +{ -+ const struct dst_entry *dst = route->tuple[dir].dst; -+ const void *daddr = &ct->tuplehash[!dir].tuple.src.u3; -+ struct net_device_path_stack stack; -+ enum net_device_path_type prev_type; -+ struct net_device *dev = dst->dev; -+ struct neighbour *n; -+ bool last = false; -+ u8 nud_state; ++ const struct net_device_path *path; + int i; + -+ route->tuple[!dir].in.ifindex = dev->ifindex; -+ route->tuple[dir].out.ifindex = dev->ifindex; -+ -+ if (route->tuple[dir].xmit_type == FLOW_OFFLOAD_XMIT_XFRM) -+ return; -+ -+ if ((dev->flags & IFF_LOOPBACK) || -+ dev->type != ARPHRD_ETHER || dev->addr_len != ETH_ALEN || -+ !is_valid_ether_addr(dev->dev_addr)) -+ return; -+ -+ n = dst_neigh_lookup(dst, daddr); -+ if (!n) -+ return; -+ -+ read_lock_bh(&n->lock); -+ nud_state = n->nud_state; -+ memcpy(route->tuple[dir].out.h_dest, n->ha, ETH_ALEN); -+ read_unlock_bh(&n->lock); -+ neigh_release(n); -+ -+ if (!(nud_state & NUD_VALID)) -+ return; -+ -+ if (dev_fill_forward_path(dev, route->tuple[dir].out.h_dest, &stack) || -+ !stack.num_paths) -+ return; -+ -+ prev_type = DEV_PATH_ETHERNET; -+ for (i = 0; i <= stack.num_paths; i++) { -+ const struct net_device_path *path = &stack.path[i]; -+ int n_encaps = route->tuple[!dir].in.num_encaps; -+ -+ dev = (struct net_device *)path->dev; -+ if (flow_is_valid_ether_device(dev)) { -+ if (route->tuple[dir].xmit_type != FLOW_OFFLOAD_XMIT_DIRECT) { -+ memcpy(route->tuple[dir].out.h_source, -+ dev->dev_addr, ETH_ALEN); -+ route->tuple[dir].out.ifindex = dev->ifindex; -+ } -+ route->tuple[dir].xmit_type = FLOW_OFFLOAD_XMIT_DIRECT; -+ } ++ memcpy(info->h_dest, ha, ETH_ALEN); + ++ for (i = 0; i < stack->num_paths; i++) { ++ path = &stack->path[i]; + switch (path->type) { -+ case DEV_PATH_PPPOE: ++ case DEV_PATH_ETHERNET: ++ case DEV_PATH_DSA: + case DEV_PATH_VLAN: -+ if (n_encaps >= NF_FLOW_TABLE_ENCAP_MAX || -+ i == stack.num_paths) { -+ last = true; ++ case DEV_PATH_PPPOE: ++ info->indev = path->dev; ++ if (is_zero_ether_addr(info->h_source)) ++ memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN); ++ ++ if (path->type == DEV_PATH_ETHERNET) ++ break; ++ if (path->type == DEV_PATH_DSA) { ++ i = stack->num_paths; + break; + } + -+ route->tuple[!dir].in.num_encaps++; -+ route->tuple[!dir].in.encap[n_encaps].id = path->encap.id; -+ route->tuple[!dir].in.encap[n_encaps].proto = path->encap.proto; ++ /* DEV_PATH_VLAN and DEV_PATH_PPPOE */ ++ if (info->num_encaps >= NF_FLOW_TABLE_ENCAP_MAX) { ++ info->indev = NULL; ++ break; ++ } ++ if (!info->outdev) ++ info->outdev = path->dev; ++ info->encap[info->num_encaps].id = path->encap.id; ++ info->encap[info->num_encaps].proto = path->encap.proto; ++ info->num_encaps++; + if (path->type == DEV_PATH_PPPOE) -+ memcpy(route->tuple[dir].out.h_dest, -+ path->encap.h_dest, ETH_ALEN); ++ memcpy(info->h_dest, path->encap.h_dest, ETH_ALEN); + break; + case DEV_PATH_BRIDGE: -+ switch (path->bridge.vlan_mode) { -+ case DEV_PATH_BR_VLAN_TAG: -+ if (n_encaps >= NF_FLOW_TABLE_ENCAP_MAX || -+ i == stack.num_paths) { -+ last = true; -+ break; -+ } ++ if (is_zero_ether_addr(info->h_source)) ++ memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN); + -+ route->tuple[!dir].in.num_encaps++; -+ route->tuple[!dir].in.encap[n_encaps].id = -+ path->bridge.vlan_id; -+ route->tuple[!dir].in.encap[n_encaps].proto = -+ path->bridge.vlan_proto; ++ switch (path->bridge.vlan_mode) { ++ case DEV_PATH_BR_VLAN_UNTAG_HW: ++ info->ingress_vlans |= BIT(info->num_encaps - 1); ++ break; ++ case DEV_PATH_BR_VLAN_TAG: ++ info->encap[info->num_encaps].id = path->bridge.vlan_id; ++ info->encap[info->num_encaps].proto = path->bridge.vlan_proto; ++ info->num_encaps++; + break; + case DEV_PATH_BR_VLAN_UNTAG: -+ route->tuple[!dir].in.num_encaps--; -+ break; -+ case DEV_PATH_BR_VLAN_UNTAG_HW: -+ route->tuple[!dir].in.ingress_vlans |= BIT(n_encaps - 1); ++ info->num_encaps--; + break; + case DEV_PATH_BR_VLAN_KEEP: + break; + } + break; + default: -+ last = true; ++ info->indev = NULL; + break; + } -+ -+ if (last) -+ break; + } ++ if (!info->outdev) ++ info->outdev = info->indev; + -+ *out_dev = dev; -+ route->tuple[dir].out.hw_ifindex = dev->ifindex; -+ route->tuple[!dir].in.ifindex = dev->ifindex; ++ info->hw_outdev = info->indev; ++ ++ if (nf_is_valid_ether_device(info->indev)) ++ info->xmit_type = FLOW_OFFLOAD_XMIT_DIRECT; +} + -+static int -+xt_flowoffload_route_dir(struct nf_flow_route *route, const struct nf_conn *ct, -+ enum ip_conntrack_dir dir, -+ const struct xt_action_param *par, int ifindex) ++static int nf_dev_fill_forward_path(const struct nf_flow_route *route, ++ const struct dst_entry *dst_cache, ++ const struct nf_conn *ct, ++ enum ip_conntrack_dir dir, u8 *ha, ++ struct net_device_path_stack *stack) +{ -+ struct dst_entry *dst = NULL; -+ struct flowi fl; ++ const void *daddr = &ct->tuplehash[!dir].tuple.src.u3; ++ struct net_device *dev = dst_cache->dev; ++ struct neighbour *n; ++ u8 nud_state; + -+ 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; ++ if (!nf_is_valid_ether_device(dev)) ++ goto out; ++ ++ n = dst_neigh_lookup(dst_cache, daddr); ++ if (!n) ++ return -1; ++ ++ read_lock_bh(&n->lock); ++ nud_state = n->nud_state; ++ ether_addr_copy(ha, n->ha); ++ read_unlock_bh(&n->lock); ++ neigh_release(n); ++ ++ if (!(nud_state & NUD_VALID)) ++ return -1; ++ ++out: ++ return dev_fill_forward_path(dev, ha, stack); ++} ++ ++static void nf_dev_forward_path(struct nf_flow_route *route, ++ const struct nf_conn *ct, ++ enum ip_conntrack_dir dir, ++ struct net_device **devs) ++{ ++ const struct dst_entry *dst = route->tuple[dir].dst; ++ struct net_device_path_stack stack; ++ struct nf_forward_info info = {}; ++ unsigned char ha[ETH_ALEN]; ++ int i; ++ ++ if (nf_dev_fill_forward_path(route, dst, ct, dir, ha, &stack) >= 0) ++ nf_dev_path_info(&stack, &info, ha); ++ ++ devs[!dir] = (struct net_device *)info.indev; ++ if (!info.indev) ++ return; ++ ++ route->tuple[!dir].in.ifindex = info.indev->ifindex; ++ for (i = 0; i < info.num_encaps; i++) { ++ route->tuple[!dir].in.encap[i].id = info.encap[i].id; ++ route->tuple[!dir].in.encap[i].proto = info.encap[i].proto; + } ++ route->tuple[!dir].in.num_encaps = info.num_encaps; ++ route->tuple[!dir].in.ingress_vlans = info.ingress_vlans; + -+ nf_route(xt_net(par), &dst, &fl, false, xt_family(par)); -+ if (!dst) -+ return -ENOENT; -+ -+ route->tuple[dir].dst = dst; -+ if (dst_xfrm(dst)) -+ route->tuple[dir].xmit_type = FLOW_OFFLOAD_XMIT_XFRM; -+ else -+ route->tuple[dir].xmit_type = FLOW_OFFLOAD_XMIT_NEIGH; -+ -+ return 0; ++ if (info.xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) { ++ memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN); ++ memcpy(route->tuple[dir].out.h_dest, info.h_dest, ETH_ALEN); ++ route->tuple[dir].out.ifindex = info.outdev->ifindex; ++ route->tuple[dir].out.hw_ifindex = info.hw_outdev->ifindex; ++ route->tuple[dir].xmit_type = info.xmit_type; ++ } +} + +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 net_device **dev) ++ struct net_device **devs) +{ -+ int ret; ++ struct dst_entry *this_dst = skb_dst(skb); ++ struct dst_entry *other_dst = NULL; ++ struct flowi fl; + -+ ret = xt_flowoffload_route_dir(route, ct, dir, par, -+ dev[dir]->ifindex); -+ if (ret) -+ return ret; ++ 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 = xt_in(par)->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 = xt_in(par)->ifindex; ++ break; ++ } + -+ ret = xt_flowoffload_route_dir(route, ct, !dir, par, -+ dev[!dir]->ifindex); -+ if (ret) -+ return ret; ++ nf_route(xt_net(par), &other_dst, &fl, false, xt_family(par)); ++ if (!other_dst) ++ return -ENOENT; + -+ xt_flowoffload_route_check_path(route, ct, dir, &dev[!dir]); -+ xt_flowoffload_route_check_path(route, ct, !dir, &dev[dir]); ++ nf_default_forward_path(route, this_dst, dir, devs); ++ nf_default_forward_path(route, other_dst, !dir, devs); ++ ++ if (route->tuple[dir].xmit_type == FLOW_OFFLOAD_XMIT_NEIGH && ++ route->tuple[!dir].xmit_type == FLOW_OFFLOAD_XMIT_NEIGH) { ++ nf_dev_forward_path(route, ct, dir, devs); ++ nf_dev_forward_path(route, ct, !dir, devs); ++ } + + return 0; +} @@ -542,7 +613,7 @@ Signed-off-by: Felix Fietkau + } + + if (nf_ct_ext_exist(ct, NF_CT_EXT_HELPER) || -+ ct->status & IPS_SEQ_ADJUST) ++ ct->status & (IPS_SEQ_ADJUST | IPS_NAT_CLASH)) + return XT_CONTINUE; + + if (!nf_ct_is_confirmed(ct)) @@ -586,7 +657,6 @@ Signed-off-by: Felix Fietkau + xt_flowoffload_check_device(table, devs[0]); + xt_flowoffload_check_device(table, devs[1]); + -+ dst_release(route.tuple[dir].dst); + dst_release(route.tuple[!dir].dst); + + return XT_CONTINUE; @@ -594,7 +664,6 @@ Signed-off-by: Felix Fietkau +err_flow_add: + flow_offload_free(flow); +err_flow_alloc: -+ dst_release(route.tuple[dir].dst); + dst_release(route.tuple[!dir].dst); +err_flow_route: + clear_bit(IPS_OFFLOAD_BIT, &ct->status); @@ -661,20 +730,6 @@ Signed-off-by: Felix Fietkau + .notifier_call = flow_offload_netdev_event, +}; + -+static unsigned int -+nf_flow_offload_inet_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; -+} -+ +static int nf_flow_rule_route_inet(struct net *net, + const struct flow_offload *flow, + enum flow_offload_tuple_dir dir, @@ -704,7 +759,7 @@ Signed-off-by: Felix Fietkau + .setup = nf_flow_table_offload_setup, + .action = nf_flow_rule_route_inet, + .free = nf_flow_table_free, -+ .hook = nf_flow_offload_inet_hook, ++ .hook = xt_flowoffload_net_hook, + .owner = THIS_MODULE, +}; + @@ -766,7 +821,7 @@ Signed-off-by: Felix Fietkau #include #include #include -@@ -395,8 +394,7 @@ flow_offload_lookup(struct nf_flowtable +@@ -401,8 +400,7 @@ flow_offload_lookup(struct nf_flowtable } EXPORT_SYMBOL_GPL(flow_offload_lookup); @@ -776,7 +831,7 @@ Signed-off-by: Felix Fietkau void (*iter)(struct flow_offload *flow, void *data), void *data) { -@@ -428,6 +426,7 @@ nf_flow_table_iterate(struct nf_flowtabl +@@ -434,6 +432,7 @@ nf_flow_table_iterate(struct nf_flowtabl return err; } diff --git a/target/linux/generic/pending-5.10/704-00-netfilter-flowtable-fix-excessive-hw-offload-attempt.patch b/target/linux/generic/pending-5.10/704-00-netfilter-flowtable-fix-excessive-hw-offload-attempt.patch new file mode 100644 index 0000000000..c15f090f71 --- /dev/null +++ b/target/linux/generic/pending-5.10/704-00-netfilter-flowtable-fix-excessive-hw-offload-attempt.patch @@ -0,0 +1,27 @@ +From: Felix Fietkau +Date: Fri, 6 May 2022 12:37:23 +0200 +Subject: [PATCH] netfilter: flowtable: fix excessive hw offload attempts + after failure + +If a flow cannot be offloaded, the code currently repeatedly tries again as +quickly as possible, which can significantly increase system load. +Fix this by limiting flow timeout update and hardware offload retry to once +per second. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -331,8 +331,10 @@ void flow_offload_refresh(struct nf_flow + u32 timeout; + + timeout = nf_flowtable_time_stamp + flow_offload_get_timeout(flow); +- if (READ_ONCE(flow->timeout) != timeout) ++ if (timeout - READ_ONCE(flow->timeout) > HZ) + WRITE_ONCE(flow->timeout, timeout); ++ else ++ return; + + if (likely(!nf_flowtable_hw_offload(flow_table))) + return; diff --git a/target/linux/generic/pending-5.10/704-01-netfilter-nft_flow_offload-skip-dst-neigh-lookup-for.patch b/target/linux/generic/pending-5.10/704-01-netfilter-nft_flow_offload-skip-dst-neigh-lookup-for.patch new file mode 100644 index 0000000000..6683a53f76 --- /dev/null +++ b/target/linux/generic/pending-5.10/704-01-netfilter-nft_flow_offload-skip-dst-neigh-lookup-for.patch @@ -0,0 +1,64 @@ +From: Felix Fietkau +Date: Fri, 6 May 2022 12:43:58 +0200 +Subject: [PATCH] netfilter: nft_flow_offload: skip dst neigh lookup for + ppp devices + +The dst entry does not contain a valid hardware address, so skip the lookup +in order to avoid running into errors here. +The proper hardware address is filled in from nft_dev_path_info + +Signed-off-by: Felix Fietkau +--- + +--- a/net/netfilter/nft_flow_offload.c ++++ b/net/netfilter/nft_flow_offload.c +@@ -36,6 +36,15 @@ static void nft_default_forward_path(str + route->tuple[dir].xmit_type = nft_xmit_type(dst_cache); + } + ++static bool nft_is_valid_ether_device(const struct net_device *dev) ++{ ++ if (!dev || (dev->flags & IFF_LOOPBACK) || dev->type != ARPHRD_ETHER || ++ dev->addr_len != ETH_ALEN || !is_valid_ether_addr(dev->dev_addr)) ++ return false; ++ ++ return true; ++} ++ + static int nft_dev_fill_forward_path(const struct nf_flow_route *route, + const struct dst_entry *dst_cache, + const struct nf_conn *ct, +@@ -47,6 +56,9 @@ static int nft_dev_fill_forward_path(con + struct neighbour *n; + u8 nud_state; + ++ if (!nft_is_valid_ether_device(dev)) ++ goto out; ++ + n = dst_neigh_lookup(dst_cache, daddr); + if (!n) + return -1; +@@ -60,6 +72,7 @@ static int nft_dev_fill_forward_path(con + if (!(nud_state & NUD_VALID)) + return -1; + ++out: + return dev_fill_forward_path(dev, ha, stack); + } + +@@ -78,15 +91,6 @@ struct nft_forward_info { + enum flow_offload_xmit_type xmit_type; + }; + +-static bool nft_is_valid_ether_device(const struct net_device *dev) +-{ +- if (!dev || (dev->flags & IFF_LOOPBACK) || dev->type != ARPHRD_ETHER || +- dev->addr_len != ETH_ALEN || !is_valid_ether_addr(dev->dev_addr)) +- return false; +- +- return true; +-} +- + static void nft_dev_path_info(const struct net_device_path_stack *stack, + struct nft_forward_info *info, + unsigned char *ha, struct nf_flowtable *flowtable) diff --git a/target/linux/generic/pending-5.10/704-02-net-fix-dev_fill_forward_path-with-pppoe-bridge.patch b/target/linux/generic/pending-5.10/704-02-net-fix-dev_fill_forward_path-with-pppoe-bridge.patch new file mode 100644 index 0000000000..04698f6d80 --- /dev/null +++ b/target/linux/generic/pending-5.10/704-02-net-fix-dev_fill_forward_path-with-pppoe-bridge.patch @@ -0,0 +1,66 @@ +From: Felix Fietkau +Date: Fri, 6 May 2022 13:54:44 +0200 +Subject: [PATCH] net: fix dev_fill_forward_path with pppoe + bridge + +When calling dev_fill_forward_path on a pppoe device, the provided destination +address is invalid. In order for the bridge fdb lookup to succeed, the pppoe +code needs to update ctx->daddr to the correct value. +Fix this by storing the address inside struct net_device_path_ctx + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -91,7 +91,6 @@ mtk_flow_get_wdma_info(struct net_device + { + struct net_device_path_ctx ctx = { + .dev = dev, +- .daddr = addr, + }; + struct net_device_path path = {}; + +@@ -101,6 +100,7 @@ mtk_flow_get_wdma_info(struct net_device + if (!dev->netdev_ops->ndo_fill_forward_path) + return -1; + ++ memcpy(ctx.daddr, addr, sizeof(ctx.daddr)); + if (dev->netdev_ops->ndo_fill_forward_path(&ctx, &path)) + return -1; + +--- a/drivers/net/ppp/pppoe.c ++++ b/drivers/net/ppp/pppoe.c +@@ -988,6 +988,7 @@ static int pppoe_fill_forward_path(struc + path->encap.proto = htons(ETH_P_PPP_SES); + path->encap.id = be16_to_cpu(po->num); + memcpy(path->encap.h_dest, po->pppoe_pa.remote, ETH_ALEN); ++ memcpy(ctx->daddr, po->pppoe_pa.remote, ETH_ALEN); + path->dev = ctx->dev; + ctx->dev = dev; + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -878,7 +878,7 @@ struct net_device_path_stack { + + struct net_device_path_ctx { + const struct net_device *dev; +- const u8 *daddr; ++ u8 daddr[ETH_ALEN]; + + int num_vlans; + struct { +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -863,11 +863,11 @@ int dev_fill_forward_path(const struct n + const struct net_device *last_dev; + struct net_device_path_ctx ctx = { + .dev = dev, +- .daddr = daddr, + }; + struct net_device_path *path; + int ret = 0; + ++ memcpy(ctx.daddr, daddr, sizeof(ctx.daddr)); + stack->num_paths = 0; + while (ctx.dev && ctx.dev->netdev_ops->ndo_fill_forward_path) { + last_dev = ctx.dev; diff --git a/target/linux/generic/pending-5.10/704-03-netfilter-nft_flow_offload-fix-offload-with-pppoe-vl.patch b/target/linux/generic/pending-5.10/704-03-netfilter-nft_flow_offload-fix-offload-with-pppoe-vl.patch new file mode 100644 index 0000000000..1e0dc9957d --- /dev/null +++ b/target/linux/generic/pending-5.10/704-03-netfilter-nft_flow_offload-fix-offload-with-pppoe-vl.patch @@ -0,0 +1,24 @@ +From: Felix Fietkau +Date: Fri, 6 May 2022 15:15:06 +0200 +Subject: [PATCH] netfilter: nft_flow_offload: fix offload with pppoe + + vlan + +When running a combination of PPPoE on top of a VLAN, we need to set +info->outdev to the PPPoE device, otherwise PPPoE encap is skipped +during software offload. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/netfilter/nft_flow_offload.c ++++ b/net/netfilter/nft_flow_offload.c +@@ -123,7 +123,8 @@ static void nft_dev_path_info(const stru + info->indev = NULL; + break; + } +- info->outdev = path->dev; ++ if (!info->outdev) ++ info->outdev = path->dev; + info->encap[info->num_encaps].id = path->encap.id; + info->encap[info->num_encaps].proto = path->encap.proto; + info->num_encaps++; From 203ffc4ca75d43ac32b164c5a474e3ce36999809 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 6 May 2022 21:54:48 +0200 Subject: [PATCH 09/24] kernel: fix corrupted padding on small packets with mt753x dsa Signed-off-by: Felix Fietkau --- ...a-tag_mtk-add-padding-for-tx-packets.patch | 29 +++++++++++++++++++ ...a-tag_mtk-add-padding-for-tx-packets.patch | 29 +++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 target/linux/generic/pending-5.10/705-net-dsa-tag_mtk-add-padding-for-tx-packets.patch create mode 100644 target/linux/generic/pending-5.15/705-net-dsa-tag_mtk-add-padding-for-tx-packets.patch diff --git a/target/linux/generic/pending-5.10/705-net-dsa-tag_mtk-add-padding-for-tx-packets.patch b/target/linux/generic/pending-5.10/705-net-dsa-tag_mtk-add-padding-for-tx-packets.patch new file mode 100644 index 0000000000..e27ac3595f --- /dev/null +++ b/target/linux/generic/pending-5.10/705-net-dsa-tag_mtk-add-padding-for-tx-packets.patch @@ -0,0 +1,29 @@ +From: Felix Fietkau +Date: Fri, 6 May 2022 21:38:42 +0200 +Subject: [PATCH] net: dsa: tag_mtk: add padding for tx packets + +Padding for transmitted packets needs to account for the special tag. +With not enough padding, garbage bytes are inserted by the switch at the +end of small packets. + +Fixes: 5cd8985a1909 ("net-next: dsa: add Mediatek tag RX/TX handler") +Signed-off-by: Felix Fietkau +--- + +--- a/net/dsa/tag_mtk.c ++++ b/net/dsa/tag_mtk.c +@@ -25,6 +25,14 @@ static struct sk_buff *mtk_tag_xmit(stru + u8 xmit_tpid; + u8 *mtk_tag; + ++ /* The Ethernet switch we are interfaced with needs packets to be at ++ * least 64 bytes (including FCS) otherwise their padding might be ++ * corrupted. With tags enabled, we need to make sure that packets are ++ * at least 68 bytes (including FCS and tag). ++ */ ++ if (__skb_put_padto(skb, ETH_ZLEN + MTK_HDR_LEN, false)) ++ return NULL; ++ + /* Build the special tag after the MAC Source Address. If VLAN header + * is present, it's required that VLAN header and special tag is + * being combined. Only in this way we can allow the switch can parse diff --git a/target/linux/generic/pending-5.15/705-net-dsa-tag_mtk-add-padding-for-tx-packets.patch b/target/linux/generic/pending-5.15/705-net-dsa-tag_mtk-add-padding-for-tx-packets.patch new file mode 100644 index 0000000000..e27ac3595f --- /dev/null +++ b/target/linux/generic/pending-5.15/705-net-dsa-tag_mtk-add-padding-for-tx-packets.patch @@ -0,0 +1,29 @@ +From: Felix Fietkau +Date: Fri, 6 May 2022 21:38:42 +0200 +Subject: [PATCH] net: dsa: tag_mtk: add padding for tx packets + +Padding for transmitted packets needs to account for the special tag. +With not enough padding, garbage bytes are inserted by the switch at the +end of small packets. + +Fixes: 5cd8985a1909 ("net-next: dsa: add Mediatek tag RX/TX handler") +Signed-off-by: Felix Fietkau +--- + +--- a/net/dsa/tag_mtk.c ++++ b/net/dsa/tag_mtk.c +@@ -25,6 +25,14 @@ static struct sk_buff *mtk_tag_xmit(stru + u8 xmit_tpid; + u8 *mtk_tag; + ++ /* The Ethernet switch we are interfaced with needs packets to be at ++ * least 64 bytes (including FCS) otherwise their padding might be ++ * corrupted. With tags enabled, we need to make sure that packets are ++ * at least 68 bytes (including FCS and tag). ++ */ ++ if (__skb_put_padto(skb, ETH_ZLEN + MTK_HDR_LEN, false)) ++ return NULL; ++ + /* Build the special tag after the MAC Source Address. If VLAN header + * is present, it's required that VLAN header and special tag is + * being combined. Only in this way we can allow the switch can parse From cb203adda00118501ecf6c74b126abe5fb851e71 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 1 May 2022 14:10:07 +0200 Subject: [PATCH 10/24] kernel: provide i6300esb for qemu/libvirt the Intel i6300esb is QEMU's default watchdog. And unlike the real "Intel i6300ESB I/O Controller hub" hardware, the i6300esb watchdog driver works on non-x86 targets like for ARM (armvirt 32bit) and potentially virtual PowerPC and MIPS targets (if there was any). Signed-off-by: Christian Lamparter --- package/kernel/linux/modules/other.mk | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/package/kernel/linux/modules/other.mk b/package/kernel/linux/modules/other.mk index c8fea034c4..985652e945 100644 --- a/package/kernel/linux/modules/other.mk +++ b/package/kernel/linux/modules/other.mk @@ -1274,6 +1274,24 @@ endef $(eval $(call KernelPackage,tpm-i2c-infineon)) +define KernelPackage/i6300esb-wdt + SUBMENU:=$(OTHER_MENU) + TITLE:=Intel 6300ESB Timer/Watchdog + DEPENDS:=@PCI_SUPPORT @!SMALL_FLASH + KCONFIG:=CONFIG_I6300ESB_WDT \ + CONFIG_WATCHDOG_CORE=y + FILES:=$(LINUX_DIR)/drivers/$(WATCHDOG_DIR)/i6300esb.ko + AUTOLOAD:=$(call AutoLoad,50,i6300esb,1) +endef + +define KernelPackage/i6300esb-wdt/description + Kernel module for the watchdog timer built into the Intel + 6300ESB controller hub. Also used by QEMU/libvirt. +endef + +$(eval $(call KernelPackage,i6300esb-wdt)) + + define KernelPackage/w83627hf-wdt SUBMENU:=$(OTHER_MENU) TITLE:=Winbond 83627HF Watchdog Timer From afcb6b1524e4987c9b6ed9f870f40e2ae8ddb368 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 1 May 2022 14:10:18 +0200 Subject: [PATCH 11/24] armvirt: 64: enable driver for QEMU' supported watchdog QEMU can emulate several watchdogs: aspeed SoC, i6300esb, ib700wdt, imx2, cmsdk-apb and sbsa_gwdt. Out of these, the ARM SBSA Generic Watchdog (sbsa_gwdt) makes the most sense for the armvirt' 64 target. Both imx2 and aspeed are guarded by special vendor specific CONFIG_ in the upstream kernel. Signed-off-by: Christian Lamparter --- target/linux/armvirt/64/config-5.10 | 2 ++ target/linux/armvirt/64/config-5.15 | 2 ++ 2 files changed, 4 insertions(+) diff --git a/target/linux/armvirt/64/config-5.10 b/target/linux/armvirt/64/config-5.10 index 1389a2a60a..8c29bdc017 100644 --- a/target/linux/armvirt/64/config-5.10 +++ b/target/linux/armvirt/64/config-5.10 @@ -36,6 +36,7 @@ CONFIG_ARM64_WORKAROUND_CLEAN_CACHE=y CONFIG_ARM64_WORKAROUND_REPEAT_TLBI=y CONFIG_ARM64_WORKAROUND_SPECULATIVE_AT=y CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND=y +CONFIG_ARM_SBSA_WATCHDOG=y CONFIG_ATOMIC64_SELFTEST=y CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y CONFIG_BACKLIGHT_CLASS_DEVICE=y @@ -147,4 +148,5 @@ CONFIG_VEXPRESS_CONFIG=y CONFIG_VIDEOMODE_HELPERS=y CONFIG_VIRTIO_DMA_SHARED_BUFFER=y CONFIG_VMAP_STACK=y +CONFIG_WATCHDOG_CORE=y CONFIG_ZONE_DMA32=y diff --git a/target/linux/armvirt/64/config-5.15 b/target/linux/armvirt/64/config-5.15 index 5818dcaf70..c1047c8009 100644 --- a/target/linux/armvirt/64/config-5.15 +++ b/target/linux/armvirt/64/config-5.15 @@ -38,6 +38,7 @@ CONFIG_ARM64_WORKAROUND_CLEAN_CACHE=y CONFIG_ARM64_WORKAROUND_REPEAT_TLBI=y CONFIG_ARM64_WORKAROUND_SPECULATIVE_AT=y CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND=y +CONFIG_ARM_SBSA_WATCHDOG=y CONFIG_ATOMIC64_SELFTEST=y CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y CONFIG_BACKLIGHT_CLASS_DEVICE=y @@ -147,4 +148,5 @@ CONFIG_VEXPRESS_CONFIG=y CONFIG_VIDEOMODE_HELPERS=y CONFIG_VIRTIO_DMA_SHARED_BUFFER=y CONFIG_VMAP_STACK=y +CONFIG_WATCHDOG_CORE=y CONFIG_ZONE_DMA32=y From d022451906915c1bf4e36cbee723f323bbb659d1 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 1 May 2022 14:10:25 +0200 Subject: [PATCH 12/24] x86: add ib700wdt module for x86 qemu watchdogs QEMU+Libvirt can emulate the ib700wdt watchdogs which due to its I/O-Port mapping makes it x86 specific. Signed-off-by: Christian Lamparter --- target/linux/x86/modules.mk | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/target/linux/x86/modules.mk b/target/linux/x86/modules.mk index fcf8dfcdff..a57a470e8d 100644 --- a/target/linux/x86/modules.mk +++ b/target/linux/x86/modules.mk @@ -67,6 +67,24 @@ endef $(eval $(call KernelPackage,sp5100-tco)) +define KernelPackage/ib700-wdt + SUBMENU:=$(OTHER_MENU) + TITLE:=IB700 SBC Watchdog Timer + DEPENDS:=@TARGET_x86 + KCONFIG:=CONFIG_IB700_WDT + FILES:=$(LINUX_DIR)/drivers/watchdog/ib700wdt.ko + AUTOLOAD:=$(call AutoLoad,50,ib700wdt,1) +endef + +define KernelPackage/ib700-wdt/description + Kernel module for the hardware watchdog on the IB700 Single + Board Computer produced by TMC Technology (www.tmc-uk.com). + Also used by QEMU/libvirt. +endef + +$(eval $(call KernelPackage,ib700-wdt)) + + define KernelPackage/pcengines-apuv2 SUBMENU:=$(OTHER_MENU) TITLE:=PC Engines APUv2/3 front button and LEDs driver From 0cd1fc0fe543eaff04b0263b10b92b056cdef6dd Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 1 May 2022 14:10:35 +0200 Subject: [PATCH 13/24] x86: detangle meraki-mx100 / nu801 build confusion Grommish reported the dreaded build error that happend with 5.4 since the kernel didn't have the cgpio v2 interface. His reason for the removed 5.4 was that the octeon target had a memory leak issue, so he had to backport the removed 5.4 kernel for his tests. Chen Minqiang chimed in and noted that no matter what (i.e. @TARGET_x86 in depends) didn't prevent the package from being build on other targets. From what I can tell, the reason for this was that +nu801 meant that kmod-meraki-mx100 pulled in an unconditional dependency as part of to the kernel build. |scripts/package-metadata.pl mk tmp/.packageinfo | |$(curdir)/kernel/linux/compile += $(curdir)/firmware/linux-firmware/compile \ | $(curdir)/firmware/prism54-firmware/compile \ | $(curdir)/kernel/gpio-button-hotplug/compile \ | >>> $(curdir)/system/gpio-cdev/nu801/compile <<< change this by making the dependency conditional on the meraki-mx100 module itself. Note that the nu801 enables/sets the KCONFIG for the cgpio v2 interface itself, since the userspace program and not the kernel meraki-mx100 relies on it. Reference: Reported-by: Grommish Reported-by: Chen Minqiang Signed-off-by: Christian Lamparter --- target/linux/x86/modules.mk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/target/linux/x86/modules.mk b/target/linux/x86/modules.mk index a57a470e8d..2f7f783c16 100644 --- a/target/linux/x86/modules.mk +++ b/target/linux/x86/modules.mk @@ -106,7 +106,8 @@ define KernelPackage/meraki-mx100 SUBMENU:=$(OTHER_MENU) TITLE:=Cisco Meraki MX100 Platform Driver DEPENDS:=@TARGET_x86 +kmod-tg3 +kmod-gpio-button-hotplug +kmod-leds-gpio \ - +kmod-usb-ledtrig-usbport +nu801 +kmod-itco-wdt +kmod-leds-uleds + +kmod-usb-ledtrig-usbport +PACKAGE_kmod-meraki-mx100:nu801 +kmod-itco-wdt \ + +kmod-leds-uleds KCONFIG:=CONFIG_MERAKI_MX100 FILES:=$(LINUX_DIR)/drivers/platform/x86/meraki-mx100.ko AUTOLOAD:=$(call AutoLoad,60,meraki-mx100,1) From c97c8b814acc3b56fa15350ecefb0c246687e892 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 1 May 2022 14:10:43 +0200 Subject: [PATCH 14/24] kernel/x86: move x86' specific watchdogs to the x86 target upstream linux have these watchdogs locked behind X86. These will not build on other architectures. So move them to target/linux/x86/modules.mk drivers/watchdog/Kconfig: |config F71808E_WDT | tristate "Fintek F718xx, F818xx Super I/O Watchdog" | depends on X86 |[...] |config IT87_WDT | tristate "IT87 Watchdog Timer" | depends on X86 |[...] |config ITCO_WDT | tristate "Intel TCO Timer/Watchdog" | depends on (X86 || IA64) && PCI |[...] |config W83627HF_WDT | tristate "Watchdog timer for W83627HF/W83627DHG and compatibles" | depends on X86 |[...] Signed-off-by: Christian Lamparter --- package/kernel/linux/modules/other.mk | 65 -------------------------- target/linux/x86/modules.mk | 67 +++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 65 deletions(-) diff --git a/package/kernel/linux/modules/other.mk b/package/kernel/linux/modules/other.mk index 985652e945..802dd81bed 100644 --- a/package/kernel/linux/modules/other.mk +++ b/package/kernel/linux/modules/other.mk @@ -1292,71 +1292,6 @@ endef $(eval $(call KernelPackage,i6300esb-wdt)) -define KernelPackage/w83627hf-wdt - SUBMENU:=$(OTHER_MENU) - TITLE:=Winbond 83627HF Watchdog Timer - KCONFIG:=CONFIG_W83627HF_WDT - FILES:=$(LINUX_DIR)/drivers/$(WATCHDOG_DIR)/w83627hf_wdt.ko - AUTOLOAD:=$(call AutoLoad,50,w83627hf-wdt,1) -endef - -define KernelPackage/w83627hf-wdt/description - Kernel module for Winbond 83627HF Watchdog Timer -endef - -$(eval $(call KernelPackage,w83627hf-wdt)) - - -define KernelPackage/itco-wdt - SUBMENU:=$(OTHER_MENU) - TITLE:=Intel iTCO Watchdog Timer - KCONFIG:=CONFIG_ITCO_WDT \ - CONFIG_ITCO_VENDOR_SUPPORT=y - FILES:=$(LINUX_DIR)/drivers/$(WATCHDOG_DIR)/iTCO_wdt.ko \ - $(LINUX_DIR)/drivers/$(WATCHDOG_DIR)/iTCO_vendor_support.ko - AUTOLOAD:=$(call AutoLoad,50,iTCO_vendor_support iTCO_wdt,1) -endef - -define KernelPackage/itco-wdt/description - Kernel module for Intel iTCO Watchdog Timer -endef - -$(eval $(call KernelPackage,itco-wdt)) - - -define KernelPackage/it87-wdt - SUBMENU:=$(OTHER_MENU) - TITLE:=ITE IT87 Watchdog Timer - KCONFIG:=CONFIG_IT87_WDT - FILES:=$(LINUX_DIR)/drivers/$(WATCHDOG_DIR)/it87_wdt.ko - AUTOLOAD:=$(call AutoLoad,50,it87-wdt,1) - MODPARAMS.it87-wdt:= \ - nogameport=1 \ - nocir=1 -endef - -define KernelPackage/it87-wdt/description - Kernel module for ITE IT87 Watchdog Timer -endef - -$(eval $(call KernelPackage,it87-wdt)) - - -define KernelPackage/f71808e-wdt - SUBMENU:=$(OTHER_MENU) - TITLE:=Fintek F718xx/F818xx Watchdog Timer - DEPENDS:=@TARGET_x86 - KCONFIG:=CONFIG_F71808E_WDT - FILES:=$(LINUX_DIR)/drivers/$(WATCHDOG_DIR)/f71808e_wdt.ko - AUTOLOAD:=$(call AutoProbe,f71808e-wdt,1) -endef - -define KernelPackage/f71808e-wdt/description - Kernel module for the watchdog timer found on many Fintek Super-IO chips. -endef - -$(eval $(call KernelPackage,f71808e-wdt)) - define KernelPackage/mhi-bus SUBMENU:=$(OTHER_MENU) TITLE:=MHI bus diff --git a/target/linux/x86/modules.mk b/target/linux/x86/modules.mk index 2f7f783c16..28cb276f7e 100644 --- a/target/linux/x86/modules.mk +++ b/target/linux/x86/modules.mk @@ -35,6 +35,22 @@ endef $(eval $(call KernelPackage,amd-xgbe)) +define KernelPackage/f71808e-wdt + SUBMENU:=$(OTHER_MENU) + TITLE:=Fintek F718xx/F818xx Watchdog Timer + DEPENDS:=@TARGET_x86 + KCONFIG:=CONFIG_F71808E_WDT + FILES:=$(LINUX_DIR)/drivers/watchdog/f71808e_wdt.ko + AUTOLOAD:=$(call AutoProbe,f71808e-wdt,1) +endef + +define KernelPackage/f71808e-wdt/description + Kernel module for the watchdog timer found on many Fintek Super-IO chips. +endef + +$(eval $(call KernelPackage,f71808e-wdt)) + + define KernelPackage/sound-cs5535audio TITLE:=CS5535/CS5536 Audio Controller DEPENDS:=@TARGET_x86_geode +kmod-ac97 @@ -84,6 +100,42 @@ endef $(eval $(call KernelPackage,ib700-wdt)) +define KernelPackage/it87-wdt + SUBMENU:=$(OTHER_MENU) + TITLE:=ITE IT87 Watchdog Timer + DEPENDS:=@TARGET_x86 + KCONFIG:=CONFIG_IT87_WDT + FILES:=$(LINUX_DIR)/drivers/watchdog/it87_wdt.ko + AUTOLOAD:=$(call AutoLoad,50,it87-wdt,1) + MODPARAMS.it87-wdt:= \ + nogameport=1 \ + nocir=1 +endef + +define KernelPackage/it87-wdt/description + Kernel module for ITE IT87 Watchdog Timer +endef + +$(eval $(call KernelPackage,it87-wdt)) + + +define KernelPackage/itco-wdt + SUBMENU:=$(OTHER_MENU) + TITLE:=Intel iTCO Watchdog Timer + DEPENDS:=@TARGET_x86 + KCONFIG:=CONFIG_ITCO_WDT \ + CONFIG_ITCO_VENDOR_SUPPORT=y + FILES:=$(LINUX_DIR)/drivers/watchdog/iTCO_wdt.ko \ + $(LINUX_DIR)/drivers/watchdog/iTCO_vendor_support.ko + AUTOLOAD:=$(call AutoLoad,50,iTCO_vendor_support iTCO_wdt,1) +endef + +define KernelPackage/itco-wdt/description + Kernel module for Intel iTCO Watchdog Timer +endef + +$(eval $(call KernelPackage,itco-wdt)) + define KernelPackage/pcengines-apuv2 SUBMENU:=$(OTHER_MENU) @@ -121,3 +173,18 @@ define KernelPackage/meraki-mx100/description endef $(eval $(call KernelPackage,meraki-mx100)) + +define KernelPackage/w83627hf-wdt + SUBMENU:=$(OTHER_MENU) + TITLE:=Winbond 83627HF Watchdog Timer + DEPENDS:=@TARGET_x86 + KCONFIG:=CONFIG_W83627HF_WDT + FILES:=$(LINUX_DIR)/drivers/watchdog/w83627hf_wdt.ko + AUTOLOAD:=$(call AutoLoad,50,w83627hf-wdt,1) +endef + +define KernelPackage/w83627hf-wdt/description + Kernel module for Winbond 83627HF Watchdog Timer +endef + +$(eval $(call KernelPackage,w83627hf-wdt)) From b47c641ee3210c0bcd4520cf74b15176566e7eeb Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Thu, 5 May 2022 20:19:32 +0200 Subject: [PATCH 15/24] generic: 5.15: add missing symbol Found during apm821xx refresh. Signed-off-by: Christian Lamparter --- target/linux/generic/config-5.15 | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/generic/config-5.15 b/target/linux/generic/config-5.15 index 35be3aa406..488e9c16e8 100644 --- a/target/linux/generic/config-5.15 +++ b/target/linux/generic/config-5.15 @@ -4117,6 +4117,7 @@ CONFIG_NET_SCH_FQ_CODEL=y # CONFIG_NET_SCH_TBF is not set # CONFIG_NET_SCH_TEQL is not set # CONFIG_NET_SCTPPROBE is not set +# CONFIG_NET_SELFTESTS is not set CONFIG_NET_SOCK_MSG=y # CONFIG_NET_SWITCHDEV is not set # CONFIG_NET_TCPPROBE is not set From fd836f3d15fdfcb15b8b94303d102cb1e37f53ba Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Thu, 5 May 2022 21:15:57 +0200 Subject: [PATCH 16/24] kernel: usb-xhci-pci-renesas: remove LINUX_5_10 dependency symbol With 5.4 out of the picture, remove LINUX_5_10 here. This is needed for the WNDR4700 as otherwise kmod-usb3 isn't available for 5.15. Signed-off-by: Christian Lamparter --- package/kernel/linux/modules/usb.mk | 1 - 1 file changed, 1 deletion(-) diff --git a/package/kernel/linux/modules/usb.mk b/package/kernel/linux/modules/usb.mk index c9c1dfd75f..0bc578e5a7 100644 --- a/package/kernel/linux/modules/usb.mk +++ b/package/kernel/linux/modules/usb.mk @@ -1803,7 +1803,6 @@ $(eval $(call KernelPackage,usb-xhci-mtk)) define KernelPackage/usb-xhci-pci-renesas TITLE:=Support for additional Renesas xHCI controller with firmware - DEPENDS:=@LINUX_5_10 KCONFIG:=CONFIG_USB_XHCI_PCI_RENESAS HIDDEN:=1 FILES:=$(LINUX_DIR)/drivers/usb/host/xhci-pci-renesas.ko From b2c9c4dda28dd9bd82df629d96d626d2c236f382 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Thu, 5 May 2022 18:16:25 +0200 Subject: [PATCH 17/24] apm821xx: add support for kernel 5.15 for testing This patch copies over refreshed config and patches from 5.10 with the following changes: - dropped superfluous tc654/tc655 variant detection patch (tc654 support will become available upstream starting with 5.17-rc7+). - dropped xhci msi(x) workaround... as the broken MSI(X) is now gone. - dropped dwc2 workaround since the driver was fixed and it works without it. Please note: Netgear WNDAP660 & WNDAP620 users: Due to the kernel's size increase, uboot will likely break because it is overwrite the kernel during decompression. To fix this (and debrick affected devices, no reflash necessary), attach the RJ45-Serial-Console cable and enter the following in the uboot prompt during bootup: setenv kernel_addr_r 1100000 saveenv run bootcmd to restore the old/previous behavior: setenv kernel_addr_r 600000 saveenv run bootcmd Signed-off-by: Christian Lamparter --- target/linux/apm821xx/Makefile | 1 + target/linux/apm821xx/config-5.15 | 245 ++++++++++++++++++ ...mon-tc654-add-thermal_cooling-device.patch | 166 ++++++++++++ .../201-add-amcc-apollo3g-support.patch | 30 +++ .../300-fix-atheros-nics-on-apm82181.patch | 51 ++++ .../301-fix-memory-map-wndr4700.patch | 14 + ...per-force-gzip-as-mkimage-s-compress.patch | 29 +++ 7 files changed, 536 insertions(+) create mode 100644 target/linux/apm821xx/config-5.15 create mode 100644 target/linux/apm821xx/patches-5.15/010-hwmon-tc654-add-thermal_cooling-device.patch create mode 100644 target/linux/apm821xx/patches-5.15/201-add-amcc-apollo3g-support.patch create mode 100644 target/linux/apm821xx/patches-5.15/300-fix-atheros-nics-on-apm82181.patch create mode 100644 target/linux/apm821xx/patches-5.15/301-fix-memory-map-wndr4700.patch create mode 100644 target/linux/apm821xx/patches-5.15/900-powerpc-bootwrapper-force-gzip-as-mkimage-s-compress.patch diff --git a/target/linux/apm821xx/Makefile b/target/linux/apm821xx/Makefile index 7d31ac8d67..f36274bd98 100644 --- a/target/linux/apm821xx/Makefile +++ b/target/linux/apm821xx/Makefile @@ -10,6 +10,7 @@ FEATURES:=fpu dt gpio ramdisk squashfs usb SUBTARGETS:=nand sata KERNEL_PATCHVER:=5.10 +KERNEL_TESTING_PATCHVER:=5.15 define Target/Description Build images for AppliedMicro APM821xx based boards. diff --git a/target/linux/apm821xx/config-5.15 b/target/linux/apm821xx/config-5.15 new file mode 100644 index 0000000000..c3f520c8a1 --- /dev/null +++ b/target/linux/apm821xx/config-5.15 @@ -0,0 +1,245 @@ +# CONFIG_40x is not set +CONFIG_44x=y +CONFIG_4xx=y +CONFIG_4xx_SOC=y +# CONFIG_ADVANCED_OPTIONS is not set +CONFIG_APM821xx=y +# CONFIG_APOLLO3G is not set +# CONFIG_ARCHES is not set +CONFIG_ARCH_32BIT_OFF_T=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_KEEP_MEMBLOCK=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y +CONFIG_ARCH_MMAP_RND_BITS=11 +CONFIG_ARCH_MMAP_RND_BITS_MAX=17 +CONFIG_ARCH_MMAP_RND_BITS_MIN=11 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=17 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 +CONFIG_ARCH_STACKWALK=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_WEAK_RELEASE_ACQUIRE=y +CONFIG_AUDIT_ARCH=y +# CONFIG_BAMBOO is not set +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_BLK_MQ_PCI=y +CONFIG_BLUESTONE=y +CONFIG_BOOKE=y +CONFIG_BOOKE_WDT=y +# CONFIG_CANYONLANDS is not set +CONFIG_CLONE_BACKWARDS=y +CONFIG_CMDLINE="rootfstype=squashfs noinitrd" +CONFIG_CMDLINE_FROM_BOOTLOADER=y +CONFIG_COMMON_CLK=y +CONFIG_COMPAT_32BIT_TIME=y +CONFIG_CPU_BIG_ENDIAN=y +CONFIG_CRC16=y +# CONFIG_CRC32_SARWATE is not set +CONFIG_CRC32_SLICEBY8=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_DEV_PPC4XX=y +CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_LIB_POLY1305_RSIZE=1 +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_MD5_PPC is not set +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +# CONFIG_CRYPTO_SHA1_PPC is not set +CONFIG_DATA_SHIFT=12 +CONFIG_DMADEVICES=y +CONFIG_DMA_DIRECT_REMAP=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_OF=y +CONFIG_DMA_REMAP=y +CONFIG_DTC=y +CONFIG_DW_DMAC=y +CONFIG_DW_DMAC_CORE=y +CONFIG_EARLY_PRINTK=y +# CONFIG_EBONY is not set +CONFIG_EDAC_ATOMIC_SCRUB=y +CONFIG_EDAC_SUPPORT=y +# CONFIG_EIGER is not set +CONFIG_EXTRA_TARGETS="uImage" +CONFIG_FIXED_PHY=y +CONFIG_FORCE_PCI=y +# CONFIG_FSL_LBC is not set +CONFIG_FWNODE_MDIO=y +CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_ATOMIC64=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_CPU=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_MSI_IRQ_DOMAIN=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_TIME_VSYSCALL=y +# CONFIG_GEN_RTC is not set +# CONFIG_GLACIER is not set +CONFIG_GPIOLIB=y +CONFIG_GPIO_CDEV=y +CONFIG_GPIO_GENERIC=y +CONFIG_GPIO_GENERIC_PLATFORM=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_PPC4XX=y +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_IBM_IIC=y +CONFIG_IBM_EMAC=y +CONFIG_IBM_EMAC_EMAC4=y +CONFIG_IBM_EMAC_POLL_WEIGHT=32 +CONFIG_IBM_EMAC_RGMII=y +CONFIG_IBM_EMAC_RXB=128 +CONFIG_IBM_EMAC_RX_COPY_THRESHOLD=256 +CONFIG_IBM_EMAC_TAH=y +CONFIG_IBM_EMAC_TXB=128 +# CONFIG_ICON is not set +CONFIG_ILLEGAL_POINTER_VALUE=0 +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_WORK=y +CONFIG_ISA_DMA_API=y +# CONFIG_JFFS2_FS is not set +# CONFIG_KATMAI is not set +CONFIG_KERNEL_START=0xc0000000 +CONFIG_LEDS_TRIGGER_MTD=y +CONFIG_LEDS_TRIGGER_PATTERN=y +CONFIG_LIBFDT=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +# CONFIG_MATH_EMULATION is not set +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_DEVRES=y +CONFIG_MEMFD_CREATE=y +CONFIG_MIGRATION=y +CONFIG_MMU_GATHER_PAGE_SIZE=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +# CONFIG_MTD_CFI_GEOMETRY is not set +# CONFIG_MTD_SPLIT_SQUASHFS_ROOT is not set +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_PER_CPU_KM=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_NET_SELFTESTS=y +CONFIG_NOT_COHERENT_CACHE=y +CONFIG_NO_HZ=y +CONFIG_NO_HZ_COMMON=y +CONFIG_NO_HZ_IDLE=y +CONFIG_NR_CPUS=1 +CONFIG_NR_IRQS=512 +CONFIG_NVMEM=y +CONFIG_NVMEM_SYSFS=y +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_KOBJ=y +CONFIG_OF_MDIO=y +CONFIG_OLD_SIGACTION=y +CONFIG_OLD_SIGSUSPEND=y +CONFIG_PACKING=y +CONFIG_PAGE_OFFSET=0xc0000000 +CONFIG_PCI=y +CONFIG_PCIEAER=y +CONFIG_PCIEPORTBUS=y +CONFIG_PCI_DISABLE_COMMON_QUIRKS=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_ARCH_FALLBACKS=y +CONFIG_PCI_MSI_IRQ_DOMAIN=y +CONFIG_PGTABLE_LEVELS=2 +CONFIG_PHYLIB=y +CONFIG_PHYSICAL_START=0x00000000 +CONFIG_PHYS_64BIT=y +CONFIG_PHYS_ADDR_T_64BIT=y +# CONFIG_PMU_SYSFS is not set +CONFIG_PPC=y +CONFIG_PPC32=y +CONFIG_PPC44x_SIMPLE=y +CONFIG_PPC4xx_GPIO=y +CONFIG_PPC4xx_MSI=y +CONFIG_PPC4xx_PCI_EXPRESS=y +# CONFIG_PPC64 is not set +# CONFIG_PPC_47x is not set +# CONFIG_PPC_85xx is not set +# CONFIG_PPC_8xx is not set +CONFIG_PPC_ADV_DEBUG_DACS=2 +CONFIG_PPC_ADV_DEBUG_DAC_RANGE=y +CONFIG_PPC_ADV_DEBUG_DVCS=2 +CONFIG_PPC_ADV_DEBUG_IACS=4 +CONFIG_PPC_ADV_DEBUG_REGS=y +# CONFIG_PPC_BOOK3S_32 is not set +CONFIG_PPC_DCR=y +CONFIG_PPC_DCR_NATIVE=y +# CONFIG_PPC_EARLY_DEBUG is not set +CONFIG_PPC_FPU=y +CONFIG_PPC_FPU_REGS=y +CONFIG_PPC_HAVE_KUEP=y +CONFIG_PPC_INDIRECT_PCI=y +CONFIG_PPC_KUEP=y +CONFIG_PPC_MMU_NOHASH=y +CONFIG_PPC_MSI_BITMAP=y +CONFIG_PPC_PAGE_SHIFT=12 +CONFIG_PPC_UDBG_16550=y +CONFIG_PPC_WERROR=y +CONFIG_PTE_64BIT=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +# CONFIG_RAINIER is not set +CONFIG_RAS=y +CONFIG_RATIONAL=y +CONFIG_REGULATOR=y +CONFIG_RSEQ=y +# CONFIG_SAM440EP is not set +# CONFIG_SCOM_DEBUGFS is not set +# CONFIG_SEQUOIA is not set +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SGL_ALLOC=y +CONFIG_SPARSE_IRQ=y +CONFIG_SRCU=y +CONFIG_SWPHY=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +# CONFIG_TAISHAN is not set +CONFIG_TASK_SIZE=0xc0000000 +CONFIG_THREAD_INFO_IN_TASK=y +CONFIG_THREAD_SHIFT=13 +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TINY_SRCU=y +CONFIG_USB_SUPPORT=y +CONFIG_VDSO32=y +# CONFIG_VIRTIO_MENU is not set +# CONFIG_VIRT_CPU_ACCOUNTING_NATIVE is not set +# CONFIG_WARP is not set +CONFIG_WATCHDOG_CORE=y +CONFIG_XZ_DEC_BCJ=y +CONFIG_XZ_DEC_POWERPC=y +# CONFIG_YOSEMITE is not set +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y diff --git a/target/linux/apm821xx/patches-5.15/010-hwmon-tc654-add-thermal_cooling-device.patch b/target/linux/apm821xx/patches-5.15/010-hwmon-tc654-add-thermal_cooling-device.patch new file mode 100644 index 0000000000..74f8e38150 --- /dev/null +++ b/target/linux/apm821xx/patches-5.15/010-hwmon-tc654-add-thermal_cooling-device.patch @@ -0,0 +1,166 @@ +From 4d49367c5303e3ebd17502a45b74de280f6be539 Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Sun, 13 Feb 2022 01:47:33 +0100 +Subject: hwmon: (tc654) Add thermal_cooling device support + +Adds thermal_cooling device support to the tc654/tc655 +driver. This make it possible to integrate it into a +device-tree supported thermal-zone node as a +cooling device. + +I have been using this patch as part of the Netgear WNDR4700 +Centria NAS Router support within OpenWrt since 2016. + +Signed-off-by: Christian Lamparter +Link: https://lore.kernel.org/r/20220213004733.2421193-1-chunkeey@gmail.com +Signed-off-by: Guenter Roeck +--- +--- a/drivers/hwmon/tc654.c ++++ b/drivers/hwmon/tc654.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + + enum tc654_regs { +@@ -379,28 +380,20 @@ static ssize_t pwm_show(struct device *d + return sprintf(buf, "%d\n", pwm); + } + +-static ssize_t pwm_store(struct device *dev, struct device_attribute *da, +- const char *buf, size_t count) ++static int _set_pwm(struct tc654_data *data, unsigned long val) + { +- struct tc654_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; +- unsigned long val; + int ret; + +- if (kstrtoul(buf, 10, &val)) +- return -EINVAL; +- if (val > 255) +- return -EINVAL; +- + mutex_lock(&data->update_lock); + +- if (val == 0) ++ if (val == 0) { + data->config |= TC654_REG_CONFIG_SDM; +- else ++ data->duty_cycle = 0; ++ } else { + data->config &= ~TC654_REG_CONFIG_SDM; +- +- data->duty_cycle = find_closest(val, tc654_pwm_map, +- ARRAY_SIZE(tc654_pwm_map)); ++ data->duty_cycle = val - 1; ++ } + + ret = i2c_smbus_write_byte_data(client, TC654_REG_CONFIG, data->config); + if (ret < 0) +@@ -411,6 +404,24 @@ static ssize_t pwm_store(struct device * + + out: + mutex_unlock(&data->update_lock); ++ return ret; ++} ++ ++static ssize_t pwm_store(struct device *dev, struct device_attribute *da, ++ const char *buf, size_t count) ++{ ++ struct tc654_data *data = dev_get_drvdata(dev); ++ unsigned long val; ++ int ret; ++ ++ if (kstrtoul(buf, 10, &val)) ++ return -EINVAL; ++ if (val > 255) ++ return -EINVAL; ++ if (val > 0) ++ val = find_closest(val, tc654_pwm_map, ARRAY_SIZE(tc654_pwm_map)) + 1; ++ ++ ret = _set_pwm(data, val); + return ret < 0 ? ret : count; + } + +@@ -443,6 +454,58 @@ static struct attribute *tc654_attrs[] = + ATTRIBUTE_GROUPS(tc654); + + /* ++ * thermal cooling device functions ++ * ++ * Account for the "ShutDown Mode (SDM)" state by offsetting ++ * the 16 PWM duty cycle states by 1. ++ * ++ * State 0 = 0% PWM | Shutdown - Fan(s) are off ++ * State 1 = 30% PWM | duty_cycle = 0 ++ * State 2 = ~35% PWM | duty_cycle = 1 ++ * [...] ++ * State 15 = ~95% PWM | duty_cycle = 14 ++ * State 16 = 100% PWM | duty_cycle = 15 ++ */ ++#define TC654_MAX_COOLING_STATE 16 ++ ++static int tc654_get_max_state(struct thermal_cooling_device *cdev, unsigned long *state) ++{ ++ *state = TC654_MAX_COOLING_STATE; ++ return 0; ++} ++ ++static int tc654_get_cur_state(struct thermal_cooling_device *cdev, unsigned long *state) ++{ ++ struct tc654_data *data = tc654_update_client(cdev->devdata); ++ ++ if (IS_ERR(data)) ++ return PTR_ERR(data); ++ ++ if (data->config & TC654_REG_CONFIG_SDM) ++ *state = 0; /* FAN is off */ ++ else ++ *state = data->duty_cycle + 1; /* offset PWM States by 1 */ ++ ++ return 0; ++} ++ ++static int tc654_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state) ++{ ++ struct tc654_data *data = tc654_update_client(cdev->devdata); ++ ++ if (IS_ERR(data)) ++ return PTR_ERR(data); ++ ++ return _set_pwm(data, clamp_val(state, 0, TC654_MAX_COOLING_STATE)); ++} ++ ++static const struct thermal_cooling_device_ops tc654_fan_cool_ops = { ++ .get_max_state = tc654_get_max_state, ++ .get_cur_state = tc654_get_cur_state, ++ .set_cur_state = tc654_set_cur_state, ++}; ++ ++/* + * device probe and removal + */ + +@@ -472,7 +535,18 @@ static int tc654_probe(struct i2c_client + hwmon_dev = + devm_hwmon_device_register_with_groups(dev, client->name, data, + tc654_groups); +- return PTR_ERR_OR_ZERO(hwmon_dev); ++ if (IS_ERR(hwmon_dev)) ++ return PTR_ERR(hwmon_dev); ++ ++ if (IS_ENABLED(CONFIG_THERMAL)) { ++ struct thermal_cooling_device *cdev; ++ ++ cdev = devm_thermal_of_cooling_device_register(dev, dev->of_node, client->name, ++ hwmon_dev, &tc654_fan_cool_ops); ++ return PTR_ERR_OR_ZERO(cdev); ++ } ++ ++ return 0; + } + + static const struct i2c_device_id tc654_id[] = { diff --git a/target/linux/apm821xx/patches-5.15/201-add-amcc-apollo3g-support.patch b/target/linux/apm821xx/patches-5.15/201-add-amcc-apollo3g-support.patch new file mode 100644 index 0000000000..e188954094 --- /dev/null +++ b/target/linux/apm821xx/patches-5.15/201-add-amcc-apollo3g-support.patch @@ -0,0 +1,30 @@ +--- a/arch/powerpc/platforms/44x/Kconfig ++++ b/arch/powerpc/platforms/44x/Kconfig +@@ -121,6 +121,17 @@ config CANYONLANDS + help + This option enables support for the AMCC PPC460EX evaluation board. + ++config APOLLO3G ++ bool "Apollo3G" ++ depends on 44x ++ default n ++ select PPC44x_SIMPLE ++ select APM821xx ++ select IBM_EMAC_RGMII ++ select 460EX ++ help ++ This option enables support for the AMCC Apollo 3G board. ++ + config GLACIER + bool "Glacier" + depends on 44x +--- a/arch/powerpc/platforms/44x/ppc44x_simple.c ++++ b/arch/powerpc/platforms/44x/ppc44x_simple.c +@@ -47,6 +47,7 @@ machine_device_initcall(ppc44x_simple, p + * board.c file for it rather than adding it to this list. + */ + static char *board[] __initdata = { ++ "amcc,apollo3g", + "amcc,arches", + "amcc,bamboo", + "apm,bluestone", diff --git a/target/linux/apm821xx/patches-5.15/300-fix-atheros-nics-on-apm82181.patch b/target/linux/apm821xx/patches-5.15/300-fix-atheros-nics-on-apm82181.patch new file mode 100644 index 0000000000..110726d258 --- /dev/null +++ b/target/linux/apm821xx/patches-5.15/300-fix-atheros-nics-on-apm82181.patch @@ -0,0 +1,51 @@ +--- a/arch/powerpc/platforms/4xx/pci.c ++++ b/arch/powerpc/platforms/4xx/pci.c +@@ -1060,15 +1060,24 @@ static int __init apm821xx_pciex_init_po + u32 val; + + /* +- * Do a software reset on PCIe ports. +- * This code is to fix the issue that pci drivers doesn't re-assign +- * bus number for PCIE devices after Uboot +- * scanned and configured all the buses (eg. PCIE NIC IntelPro/1000 +- * PT quad port, SAS LSI 1064E) ++ * Only reset the PHY when no link is currently established. ++ * This is for the Atheros PCIe board which has problems to establish ++ * the link (again) after this PHY reset. All other currently tested ++ * PCIe boards don't show this problem. + */ +- +- mtdcri(SDR0, PESDR0_460EX_PHY_CTL_RST, 0x0); +- mdelay(10); ++ val = mfdcri(SDR0, port->sdr_base + PESDRn_LOOP); ++ if (!(val & 0x00001000)) { ++ /* ++ * Do a software reset on PCIe ports. ++ * This code is to fix the issue that pci drivers doesn't re-assign ++ * bus number for PCIE devices after Uboot ++ * scanned and configured all the buses (eg. PCIE NIC IntelPro/1000 ++ * PT quad port, SAS LSI 1064E) ++ */ ++ ++ mtdcri(SDR0, PESDR0_460EX_PHY_CTL_RST, 0x0); ++ mdelay(10); ++ } + + if (port->endpoint) + val = PTYPE_LEGACY_ENDPOINT << 20; +@@ -1085,9 +1094,12 @@ static int __init apm821xx_pciex_init_po + mtdcri(SDR0, PESDR0_460EX_L0DRV, 0x00000130); + mtdcri(SDR0, PESDR0_460EX_L0CLK, 0x00000006); + +- mtdcri(SDR0, PESDR0_460EX_PHY_CTL_RST, 0x10000000); +- mdelay(50); +- mtdcri(SDR0, PESDR0_460EX_PHY_CTL_RST, 0x30000000); ++ val = mfdcri(SDR0, port->sdr_base + PESDRn_LOOP); ++ if (!(val & 0x00001000)) { ++ mtdcri(SDR0, PESDR0_460EX_PHY_CTL_RST, 0x10000000); ++ mdelay(50); ++ mtdcri(SDR0, PESDR0_460EX_PHY_CTL_RST, 0x30000000); ++ } + + mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET, + mfdcri(SDR0, port->sdr_base + PESDRn_RCSSET) | diff --git a/target/linux/apm821xx/patches-5.15/301-fix-memory-map-wndr4700.patch b/target/linux/apm821xx/patches-5.15/301-fix-memory-map-wndr4700.patch new file mode 100644 index 0000000000..452d97e85a --- /dev/null +++ b/target/linux/apm821xx/patches-5.15/301-fix-memory-map-wndr4700.patch @@ -0,0 +1,14 @@ +--- a/arch/powerpc/platforms/4xx/pci.c ++++ b/arch/powerpc/platforms/4xx/pci.c +@@ -1902,9 +1902,9 @@ static void __init ppc4xx_configure_pcie + * if it works + */ + out_le32(mbase + PECFG_PIM0LAL, 0x00000000); +- out_le32(mbase + PECFG_PIM0LAH, 0x00000000); ++ out_le32(mbase + PECFG_PIM0LAH, 0x00000008); + out_le32(mbase + PECFG_PIM1LAL, 0x00000000); +- out_le32(mbase + PECFG_PIM1LAH, 0x00000000); ++ out_le32(mbase + PECFG_PIM1LAH, 0x0000000c); + out_le32(mbase + PECFG_PIM01SAH, 0xffff0000); + out_le32(mbase + PECFG_PIM01SAL, 0x00000000); + diff --git a/target/linux/apm821xx/patches-5.15/900-powerpc-bootwrapper-force-gzip-as-mkimage-s-compress.patch b/target/linux/apm821xx/patches-5.15/900-powerpc-bootwrapper-force-gzip-as-mkimage-s-compress.patch new file mode 100644 index 0000000000..3a9f48d0ab --- /dev/null +++ b/target/linux/apm821xx/patches-5.15/900-powerpc-bootwrapper-force-gzip-as-mkimage-s-compress.patch @@ -0,0 +1,29 @@ +From c9395ad54e2cabb87d408becc37566f3d8248933 Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Sun, 1 Dec 2019 02:08:23 +0100 +Subject: [PATCH] powerpc: bootwrapper: force gzip as mkimage's compression + method + +Due to CONFIG_KERNEL_XZ symbol, the bootwrapper code tries to +instruct the mkimage to use the xz compression, which isn't +supported. This patch forces the gzip compression, which is +supported and doesn't matter because the generated uImage for +the apm821xx target gets ignored as the OpenWrt toolchain will +do separate U-Boot kernel images for each device individually. + +Signed-off-by: Christian Lamparter +--- + arch/powerpc/boot/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/powerpc/boot/Makefile ++++ b/arch/powerpc/boot/Makefile +@@ -257,7 +257,7 @@ compressor-$(CONFIG_KERNEL_LZO) := lzo + + # args (to if_changed): 1 = (this rule), 2 = platform, 3 = dts 4=dtb 5=initrd + quiet_cmd_wrap = WRAP $@ +- cmd_wrap =$(CONFIG_SHELL) $(wrapper) -Z $(compressor-y) -c -o $@ -p $2 \ ++ cmd_wrap =$(CONFIG_SHELL) $(wrapper) -Z gzip -c -o $@ -p $2 \ + $(CROSSWRAP) $(if $3, -s $3)$(if $4, -d $4)$(if $5, -i $5) \ + vmlinux + From d9fae43202f3d43cb199bd527cca8f170da70b7d Mon Sep 17 00:00:00 2001 From: Matthew Hagan Date: Wed, 4 May 2022 08:26:44 +0100 Subject: [PATCH 18/24] kernel: backports: add Huawei MA5671A tx-fault workaround This workaround will allow the MA5671A to function, ignoring the persistently asserted tx-fault. Signed-off-by: Matthew Hagan (added 5.15 backport) Signed-off-by: Christian Lamparter --- ...workaround-for-Huawei-MA5671A-SFP-ON.patch | 57 +++++++++++++++++++ ...workaround-for-Huawei-MA5671A-SFP-ON.patch | 57 +++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 target/linux/generic/backport-5.10/890-v5.19-net-sfp-Add-tx-fault-workaround-for-Huawei-MA5671A-SFP-ON.patch create mode 100644 target/linux/generic/backport-5.15/890-v5.19-net-sfp-Add-tx-fault-workaround-for-Huawei-MA5671A-SFP-ON.patch diff --git a/target/linux/generic/backport-5.10/890-v5.19-net-sfp-Add-tx-fault-workaround-for-Huawei-MA5671A-SFP-ON.patch b/target/linux/generic/backport-5.10/890-v5.19-net-sfp-Add-tx-fault-workaround-for-Huawei-MA5671A-SFP-ON.patch new file mode 100644 index 0000000000..7a9de8ee1e --- /dev/null +++ b/target/linux/generic/backport-5.10/890-v5.19-net-sfp-Add-tx-fault-workaround-for-Huawei-MA5671A-SFP-ON.patch @@ -0,0 +1,57 @@ +From f81d97cb646ab8b90fb181d66fccaf9589990de6 Mon Sep 17 00:00:00 2001 +From: Matthew Hagan +Date: Sat, 30 Apr 2022 11:00:49 +0100 +Subject: [PATCH v2] net: sfp: Add tx-fault workaround for Huawei MA5671A SFP + ONT + +As noted elsewhere, various GPON SFP modules exhibit non-standard +TX-fault behaviour. In the tested case, the Huawei MA5671A, when used +in combination with a Marvell mv88e6085 switch, was found to +persistently assert TX-fault, resulting in the module being disabled. + +This patch adds a quirk to ignore the SFP_F_TX_FAULT state, allowing the +module to function. + +Change from v1: removal of erroneous return statment (Andrew Lunn) + +Signed-off-by: Matthew Hagan +Reviewed-by: Andrew Lunn +--- + drivers/net/phy/sfp.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +--- a/drivers/net/phy/sfp.c ++++ b/drivers/net/phy/sfp.c +@@ -249,6 +249,7 @@ struct sfp { + struct sfp_eeprom_id id; + unsigned int module_power_mW; + unsigned int module_t_start_up; ++ bool tx_fault_ignore; + + #if IS_ENABLED(CONFIG_HWMON) + struct sfp_diag diag; +@@ -1893,6 +1894,12 @@ static int sfp_sm_mod_probe(struct sfp * + else + sfp->module_t_start_up = T_START_UP; + ++ if (!memcmp(id.base.vendor_name, "HUAWEI ", 16) && ++ !memcmp(id.base.vendor_pn, "MA5671A ", 16)) ++ sfp->tx_fault_ignore = true; ++ else ++ sfp->tx_fault_ignore = false; ++ + return 0; + } + +@@ -2320,7 +2327,10 @@ static void sfp_check_state(struct sfp * + mutex_lock(&sfp->st_mutex); + state = sfp_get_state(sfp); + changed = state ^ sfp->state; +- changed &= SFP_F_PRESENT | SFP_F_LOS | SFP_F_TX_FAULT; ++ if (sfp->tx_fault_ignore) ++ changed &= SFP_F_PRESENT | SFP_F_LOS; ++ else ++ changed &= SFP_F_PRESENT | SFP_F_LOS | SFP_F_TX_FAULT; + + for (i = 0; i < GPIO_MAX; i++) + if (changed & BIT(i)) diff --git a/target/linux/generic/backport-5.15/890-v5.19-net-sfp-Add-tx-fault-workaround-for-Huawei-MA5671A-SFP-ON.patch b/target/linux/generic/backport-5.15/890-v5.19-net-sfp-Add-tx-fault-workaround-for-Huawei-MA5671A-SFP-ON.patch new file mode 100644 index 0000000000..bcada79fb2 --- /dev/null +++ b/target/linux/generic/backport-5.15/890-v5.19-net-sfp-Add-tx-fault-workaround-for-Huawei-MA5671A-SFP-ON.patch @@ -0,0 +1,57 @@ +From f81d97cb646ab8b90fb181d66fccaf9589990de6 Mon Sep 17 00:00:00 2001 +From: Matthew Hagan +Date: Sat, 30 Apr 2022 11:00:49 +0100 +Subject: [PATCH v2] net: sfp: Add tx-fault workaround for Huawei MA5671A SFP + ONT + +As noted elsewhere, various GPON SFP modules exhibit non-standard +TX-fault behaviour. In the tested case, the Huawei MA5671A, when used +in combination with a Marvell mv88e6085 switch, was found to +persistently assert TX-fault, resulting in the module being disabled. + +This patch adds a quirk to ignore the SFP_F_TX_FAULT state, allowing the +module to function. + +Change from v1: removal of erroneous return statment (Andrew Lunn) + +Signed-off-by: Matthew Hagan +Reviewed-by: Andrew Lunn +--- + drivers/net/phy/sfp.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +--- a/drivers/net/phy/sfp.c ++++ b/drivers/net/phy/sfp.c +@@ -250,6 +250,7 @@ struct sfp { + struct sfp_eeprom_id id; + unsigned int module_power_mW; + unsigned int module_t_start_up; ++ bool tx_fault_ignore; + + #if IS_ENABLED(CONFIG_HWMON) + struct sfp_diag diag; +@@ -1945,6 +1946,12 @@ static int sfp_sm_mod_probe(struct sfp * + else + sfp->module_t_start_up = T_START_UP; + ++ if (!memcmp(id.base.vendor_name, "HUAWEI ", 16) && ++ !memcmp(id.base.vendor_pn, "MA5671A ", 16)) ++ sfp->tx_fault_ignore = true; ++ else ++ sfp->tx_fault_ignore = false; ++ + return 0; + } + +@@ -2397,7 +2404,10 @@ static void sfp_check_state(struct sfp * + mutex_lock(&sfp->st_mutex); + state = sfp_get_state(sfp); + changed = state ^ sfp->state; +- changed &= SFP_F_PRESENT | SFP_F_LOS | SFP_F_TX_FAULT; ++ if (sfp->tx_fault_ignore) ++ changed &= SFP_F_PRESENT | SFP_F_LOS; ++ else ++ changed &= SFP_F_PRESENT | SFP_F_LOS | SFP_F_TX_FAULT; + + for (i = 0; i < GPIO_MAX; i++) + if (changed & BIT(i)) From 580723e86ae53f14273ff8c3a0ebf5d15b4ce1f1 Mon Sep 17 00:00:00 2001 From: Raylynn Knight Date: Sun, 10 Apr 2022 03:26:59 -0400 Subject: [PATCH 19/24] realtek: add support for ZyXEL GS1900-16 The ZyXEL GS1900-16 is a 16 port gigabit switch similar to other GS1900 switches. Specifications -------------- * Device: ZyXEL GS1900-16 * SoC: Realtek RTL8382M 500 MHz MIPS 4KEc * Flash: 16 MiB Macronix MX25L12835F * RAM: 128 MiB DDR2 SDRAM Nanya NT5TU128M8HE * Ethernet: 16x 10/100/1000 Mbps * LEDs: 1 PWR LED (green, not configurable) 1 SYS LED (green, configurable) 16 ethernet port link/activity LEDs (green, SoC controlled) * Buttons: 1 "RESET" button on front panel * Power 120-240V AC C13 * UART: 1 serial header (J12) with populated standard pin connector on the right back of the PCB. Pinout (front to back): + Pin 1 - VCC marked with white dot + Pin 2 - RX + Pin 3 - TX + PIn 4 - GND Serial connection parameters: 115200 8N1. Installation ------------ OEM upgrade method: * Log in to OEM management web interface * Navigate to Maintenance > Firmware * Select the HTTP radio button * Select the Active radio button * Use the browse button to locate the realtek-generic-zyxel_gs1900-16-initramfs-kernel.bin file amd select open so File Path is update with filename. * Select the Apply button. Screen will display "Prepare for firmware upgrade ...". *Wait until screen shows "Do you really want to reboot?" then select the OK button * Once OpenWrt has booted, scp the sysupgrade image to /tmp and flash it: > sysupgrade -n /tmp/realtek-generic-zyxel_gs1900-16-squashfs-sysupgrade.bin it may be necessary to restart the network (/etc/init.d/network restart) on the running initramfs image. U-Boot TFTP method: * Configure your client with a static 192.168.1.x IP (e.g. 192.168.1.10). * Set up a TFTP server on your client and make it serve the initramfs image. * Connect serial, power up the switch, interrupt U-boot by hitting the space bar, and enable the network: > rtk network on * Since the GS1900-16 is a dual-partition device, you want to keep the OEM firmware on the backup partition for the time being. OpenWrt can only boot from the first partition anyway (hardcoded in the DTS). To make sure we are manipulating the first partition, issue the following commands: > setsys bootpartition 0 > savesys * Download the image onto the device and boot from it: > tftpboot 0x84f00000 192.168.1.10:openwrt-realtek-generic-zyxel_gs1900-16-initramfs-kernel.bin > bootm * Once OpenWrt has booted, scp the sysupgrade image to /tmp and flash it: > sysupgrade -n /tmp/openwrt-realtek-generic-zyxel_gs1900-16-squashfs-sysupgrade.bin it may be necessary to restart the network (/etc/init.d/network restart) on the running initramfs image. Signed-off-by: Raylynn Knight [removed duplicate patch title, align RAM specification] Signed-off-by: Sander Vanheule --- package/boot/uboot-envtools/files/realtek | 1 + .../dts-5.10/rtl8382_zyxel_gs1900-16.dts | 36 +++++++++++++++++++ target/linux/realtek/image/rtl838x.mk | 8 +++++ 3 files changed, 45 insertions(+) create mode 100644 target/linux/realtek/dts-5.10/rtl8382_zyxel_gs1900-16.dts diff --git a/package/boot/uboot-envtools/files/realtek b/package/boot/uboot-envtools/files/realtek index c07175a357..99a73a6ab1 100644 --- a/package/boot/uboot-envtools/files/realtek +++ b/package/boot/uboot-envtools/files/realtek @@ -15,6 +15,7 @@ zyxel,gs1900-8|\ zyxel,gs1900-8hp-v1|\ zyxel,gs1900-8hp-v2|\ zyxel,gs1900-10hp|\ +zyxel,gs1900-16|\ zyxel,gs1900-24-v1|\ zyxel,gs1900-24hp-v1|\ zyxel,gs1900-24hp-v2) diff --git a/target/linux/realtek/dts-5.10/rtl8382_zyxel_gs1900-16.dts b/target/linux/realtek/dts-5.10/rtl8382_zyxel_gs1900-16.dts new file mode 100644 index 0000000000..ac2eea7015 --- /dev/null +++ b/target/linux/realtek/dts-5.10/rtl8382_zyxel_gs1900-16.dts @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "rtl8380_zyxel_gs1900.dtsi" + +/ { + compatible = "zyxel,gs1900-16", "realtek,rtl838x-soc"; + model = "ZyXEL GS1900-16"; +}; + +&mdio { + EXTERNAL_PHY(16) + EXTERNAL_PHY(17) + EXTERNAL_PHY(18) + EXTERNAL_PHY(19) + EXTERNAL_PHY(20) + EXTERNAL_PHY(21) + EXTERNAL_PHY(22) + EXTERNAL_PHY(23) +}; + +&switch0 { + ports { + SWITCH_PORT(16, 9, qsgmii) + SWITCH_PORT(17, 10, qsgmii) + SWITCH_PORT(18, 11, qsgmii) + SWITCH_PORT(19, 12, qsgmii) + SWITCH_PORT(20, 13, qsgmii) + SWITCH_PORT(21, 14, qsgmii) + SWITCH_PORT(22, 15, qsgmii) + SWITCH_PORT(23, 16, qsgmii) + }; +}; + +&gpio1 { + /delete-node/ poe_enable; +}; diff --git a/target/linux/realtek/image/rtl838x.mk b/target/linux/realtek/image/rtl838x.mk index 29e7ff2695..e17dc8c62d 100644 --- a/target/linux/realtek/image/rtl838x.mk +++ b/target/linux/realtek/image/rtl838x.mk @@ -111,6 +111,14 @@ define Device/zyxel_gs1900-10hp endef TARGET_DEVICES += zyxel_gs1900-10hp +define Device/zyxel_gs1900-16 + $(Device/zyxel_gs1900) + SOC := rtl8382 + DEVICE_MODEL := GS1900-16 + ZYXEL_VERS := AAHJ +endef +TARGET_DEVICES += zyxel_gs1900-16 + define Device/zyxel_gs1900-8 $(Device/zyxel_gs1900) DEVICE_MODEL := GS1900-8 From 98bb26f9f762408e42bd8a906f0eb01c41ada10a Mon Sep 17 00:00:00 2001 From: Birger Koblitz Date: Sun, 24 Apr 2022 20:37:33 +0200 Subject: [PATCH 20/24] realtek: Trap all frames with switch as destination to CPU-port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a bug where frames sent to the switch itself were flooded to all ports unless the MAC address of the CPU-port was learned otherwise. Tested-by: Wenli Looi Tested-by: Bjørn Mork Signed-off-by: Birger Koblitz [fix code formatting] Signed-off-by: Sander Vanheule --- .../realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c index 4780632983..2e3ab4a805 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c @@ -205,6 +205,15 @@ static int rtl83xx_setup(struct dsa_switch *ds) priv->r->l2_learning_setup(); + /* + * Make sure all frames sent to the switch's MAC are trapped to the CPU-port + * 0: FWD, 1: DROP, 2: TRAP2CPU + */ + if (priv->family_id == RTL8380_FAMILY_ID) + sw_w32(0x2, RTL838X_SPCL_TRAP_SWITCH_MAC_CTRL); + else + sw_w32(0x2, RTL839X_SPCL_TRAP_SWITCH_MAC_CTRL); + /* Enable MAC Polling PHY again */ rtl83xx_enable_phy_polling(priv); pr_debug("Please wait until PHY is settled\n"); From 4a8eaa5c7c9235212c4af022c18b2dfbadfe557f Mon Sep 17 00:00:00 2001 From: Alessio Prescenzo Date: Wed, 22 Sep 2021 16:45:19 +0200 Subject: [PATCH 21/24] ramips: add support for Cudy X6 Specifications: SoC: MediaTek MT7621 RAM: 256 MB Flash: 32 MB WiFi: MediaTek MT7915E Switch: 1 WAN, 4 LAN (Gigabit) Ports: 1 USB 3.0 Buttons: Reset, WPS LEDs: Power, System, Wan, Lan 1-4, WiFi 2.4G, WiFi 5G, WPS, USB Power: DC 12V 1A tip positive Installation: Download and flash the manufacturer's built OpenWRT image available at http://www.cudytech.com/openwrt_software_download Install the new OpenWRT image via luci (System -> Backup/Flash firmware) Be sure to NOT keep settings. The force upgrade may need to be checked due to differences in router naming conventions. Recovery: Loads only signed manufacture firmware due to bootloader RSA verification serve tftp-recovery image as /recovery.bin on 192.168.1.88/24 connect to any lan ethernet port power on the device while holding the reset button wait at least 8 seconds before releasing reset button for image to download Signed-off-by: Alessio Prescenzo [ensure unique wireless MAC, fix GPIO pingroup] Signed-off-by: David Bauer --- target/linux/ramips/dts/mt7621_cudy_x6.dts | 178 ++++++++++++++++++ target/linux/ramips/image/mt7621.mk | 10 + .../etc/hotplug.d/ieee80211/10_fix_wifi_mac | 4 + 3 files changed, 192 insertions(+) create mode 100644 target/linux/ramips/dts/mt7621_cudy_x6.dts diff --git a/target/linux/ramips/dts/mt7621_cudy_x6.dts b/target/linux/ramips/dts/mt7621_cudy_x6.dts new file mode 100644 index 0000000000..ebb2149172 --- /dev/null +++ b/target/linux/ramips/dts/mt7621_cudy_x6.dts @@ -0,0 +1,178 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "mt7621.dtsi" + +#include +#include + +/ { + compatible = "cudy,x6", "mediatek,mt7621-soc"; + model = "CUDY X6"; + + aliases { + led-boot = &led_internet_blue; + led-failsafe = &led_internet_blue; + led-running = &led_internet_blue; + led-upgrade = &led_internet_blue; + label-mac-device = &gmac0; + }; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&gpio 8 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + wps { + label = "wps"; + gpios = <&gpio 7 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_internet_blue: internet_blue { + label = "blue:internet"; + gpios = <&gpio 15 GPIO_ACTIVE_LOW>; + }; + + internet_red { + label = "red:internet"; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; + }; + }; + +}; + +&spi0 { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <50000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + compatible = "denx,uimage"; + label = "firmware"; + reg = <0x50000 0x1f80000>; + }; + + partition@1fd0000 { + label = "debug"; + reg = <0x1fd0000 0x10000>; + read-only; + }; + + partition@1fe0000 { + label = "backup"; + reg = <0x1fe0000 0x10000>; + read-only; + }; + + bdinfo: partition@1ff0000 { + label = "bdinfo"; + reg = <0x1ff0000 0x10000>; + read-only; + }; + }; + }; +}; + +&pcie { + status = "okay"; +}; + +&pcie1 { + wifi@0,0 { + compatible = "mediatek,mt76"; + reg = <0x0000 0 0 0 0>; + mediatek,mtd-eeprom = <&factory 0x0000>; + }; +}; + +&gmac0 { + nvmem-cells = <&macaddr_bdinfo_de00>; + nvmem-cell-names = "mac-address"; +}; + +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + + port@4 { + status = "okay"; + label = "wan"; + nvmem-cells = <&macaddr_bdinfo_de00>; + nvmem-cell-names = "mac-address"; + mac-address-increment = <1>; + }; + }; +}; + +&state_default { + gpio { + groups = "uart3", "jtag"; + function = "gpio"; + }; +}; + +&bdinfo { + compatible = "nvmem-cells"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_bdinfo_de00: macaddr@de00 { + reg = <0xde00 0x6>; + }; +}; diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk index 5844682a40..cbdc63247d 100644 --- a/target/linux/ramips/image/mt7621.mk +++ b/target/linux/ramips/image/mt7621.mk @@ -318,6 +318,16 @@ define Device/cudy_wr2100 endef TARGET_DEVICES += cudy_wr2100 +define Device/cudy_x6 + $(Device/dsa-migration) + IMAGE_SIZE := 32256k + DEVICE_VENDOR := Cudy + DEVICE_MODEL := X6 + UIMAGE_NAME := R13 + DEVICE_PACKAGES := kmod-mt7915e +endef +TARGET_DEVICES += cudy_x6 + define Device/dlink_dir-8xx-a1 $(Device/dsa-migration) IMAGE_SIZE := 16000k diff --git a/target/linux/ramips/mt7621/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac b/target/linux/ramips/mt7621/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac index 61285182d2..a35e9dcc28 100644 --- a/target/linux/ramips/mt7621/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac +++ b/target/linux/ramips/mt7621/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac @@ -16,6 +16,10 @@ case "$board" in [ "$PHYNBR" = "0" ] && echo -n $hw_mac_addr_ra0 > /sys${DEVPATH}/macaddress [ "$PHYNBR" = "1" ] && echo -n $hw_mac_addr_rax0 > /sys${DEVPATH}/macaddress ;; + cudy,x6) + hw_mac_addr="$(mtd_get_mac_binary factory 0x4)" + macaddr_add $hw_mac_addr "$PHYNBR" > /sys${DEVPATH}/macaddress + ;; dlink,dir-853-a3) [ "$PHYNBR" = "0" ] && \ macaddr_setbit_la "$(mtd_get_mac_binary factory 0xe000)" \ From c3569a70c6911e29fffa9155086be9c4f3d18ee3 Mon Sep 17 00:00:00 2001 From: Rui Salvaterra Date: Sun, 1 May 2022 00:40:39 +0100 Subject: [PATCH 22/24] kernel: bump 5.15 to 5.15.36 Patches automatically rebased. Signed-off-by: Rui Salvaterra --- include/kernel-5.15 | 4 ++-- .../910-unaligned_access_hacks.patch | 4 ++-- .../pending-5.15/630-packet_socket_type.patch | 6 +++--- ...ing-with-source-address-failed-policy.patch | 18 +++++++++--------- .../420-firmware-qcom-scm-disable-SDI.patch | 2 +- .../patches-5.15/104-mt7622-add-snor-irq.patch | 2 +- ...ll-the-spi_mem_dtr_supports_op-helper.patch | 4 ++-- ...22-specify-the-number-of-DMA-requests.patch | 2 +- ...tek-Split-PCIe-node-for-MT2712-and-MT.patch | 2 +- ...ts-mediatek-add-mt7622-pcie-slot-node.patch | 4 ++-- ...mediatek-add-support-for-coherent-DMA.patch | 4 ++-- .../patches-5.15/200-add-ralink-eth.patch | 4 ++-- 12 files changed, 28 insertions(+), 28 deletions(-) diff --git a/include/kernel-5.15 b/include/kernel-5.15 index 1d8ca84d70..efac5d1b14 100644 --- a/include/kernel-5.15 +++ b/include/kernel-5.15 @@ -1,2 +1,2 @@ -LINUX_VERSION-5.15 = .35 -LINUX_KERNEL_HASH-5.15.35 = 0a1a5ae2f30eb2b38215e59077f045aabd7f4e2857a881482f02ea48186105d8 +LINUX_VERSION-5.15 = .36 +LINUX_KERNEL_HASH-5.15.36 = 36345db17a937c197c72ca9c7f34c262b3a12f927c237ff7770193014e29c690 diff --git a/target/linux/ath79/patches-5.15/910-unaligned_access_hacks.patch b/target/linux/ath79/patches-5.15/910-unaligned_access_hacks.patch index 46f5be3d4e..260cf4f45a 100644 --- a/target/linux/ath79/patches-5.15/910-unaligned_access_hacks.patch +++ b/target/linux/ath79/patches-5.15/910-unaligned_access_hacks.patch @@ -785,7 +785,7 @@ *sum = csum_fold(csum_partial(diff, sizeof(diff), --- a/include/linux/etherdevice.h +++ b/include/linux/etherdevice.h -@@ -512,7 +512,7 @@ static inline bool is_etherdev_addr(cons +@@ -511,7 +511,7 @@ static inline bool is_etherdev_addr(cons * @b: Pointer to Ethernet header * * Compare two Ethernet headers, returns 0 if equal. @@ -794,7 +794,7 @@ * aligned OR the platform can handle unaligned access. This is the * case for all packets coming into netif_receive_skb or similar * entry points. -@@ -535,11 +535,12 @@ static inline unsigned long compare_ethe +@@ -534,11 +534,12 @@ static inline unsigned long compare_ethe fold |= *(unsigned long *)(a + 6) ^ *(unsigned long *)(b + 6); return fold; #else diff --git a/target/linux/generic/pending-5.15/630-packet_socket_type.patch b/target/linux/generic/pending-5.15/630-packet_socket_type.patch index 70f07baebb..c61935ffb0 100644 --- a/target/linux/generic/pending-5.15/630-packet_socket_type.patch +++ b/target/linux/generic/pending-5.15/630-packet_socket_type.patch @@ -87,7 +87,7 @@ Signed-off-by: Felix Fietkau if (!net_eq(dev_net(dev), sock_net(sk))) goto drop; -@@ -3325,6 +3327,7 @@ static int packet_create(struct net *net +@@ -3330,6 +3332,7 @@ static int packet_create(struct net *net mutex_init(&po->pg_vec_lock); po->rollover = NULL; po->prot_hook.func = packet_rcv; @@ -95,7 +95,7 @@ Signed-off-by: Felix Fietkau if (sock->type == SOCK_PACKET) po->prot_hook.func = packet_rcv_spkt; -@@ -3966,6 +3969,16 @@ packet_setsockopt(struct socket *sock, i +@@ -3971,6 +3974,16 @@ packet_setsockopt(struct socket *sock, i po->xmit = val ? packet_direct_xmit : dev_queue_xmit; return 0; } @@ -112,7 +112,7 @@ Signed-off-by: Felix Fietkau default: return -ENOPROTOOPT; } -@@ -4022,6 +4035,13 @@ static int packet_getsockopt(struct sock +@@ -4027,6 +4040,13 @@ static int packet_getsockopt(struct sock case PACKET_VNET_HDR: val = po->has_vnet_hdr; break; diff --git a/target/linux/generic/pending-5.15/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch b/target/linux/generic/pending-5.15/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch index 3fb053ab49..3a00359b73 100644 --- a/target/linux/generic/pending-5.15/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch +++ b/target/linux/generic/pending-5.15/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch @@ -157,7 +157,7 @@ Signed-off-by: Jonas Gorski case RTN_THROW: case RTN_UNREACHABLE: default: -@@ -4559,6 +4578,17 @@ static int ip6_pkt_prohibit_out(struct n +@@ -4560,6 +4579,17 @@ static int ip6_pkt_prohibit_out(struct n return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES); } @@ -175,7 +175,7 @@ Signed-off-by: Jonas Gorski /* * Allocate a dst for local (unicast / anycast) address. */ -@@ -5039,7 +5069,8 @@ static int rtm_to_fib6_config(struct sk_ +@@ -5040,7 +5070,8 @@ static int rtm_to_fib6_config(struct sk_ if (rtm->rtm_type == RTN_UNREACHABLE || rtm->rtm_type == RTN_BLACKHOLE || rtm->rtm_type == RTN_PROHIBIT || @@ -185,7 +185,7 @@ Signed-off-by: Jonas Gorski cfg->fc_flags |= RTF_REJECT; if (rtm->rtm_type == RTN_LOCAL) -@@ -6292,6 +6323,8 @@ static int ip6_route_dev_notify(struct n +@@ -6293,6 +6324,8 @@ static int ip6_route_dev_notify(struct n #ifdef CONFIG_IPV6_MULTIPLE_TABLES net->ipv6.ip6_prohibit_entry->dst.dev = dev; net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); @@ -194,7 +194,7 @@ Signed-off-by: Jonas Gorski net->ipv6.ip6_blk_hole_entry->dst.dev = dev; net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); #endif -@@ -6303,6 +6336,7 @@ static int ip6_route_dev_notify(struct n +@@ -6304,6 +6337,7 @@ static int ip6_route_dev_notify(struct n in6_dev_put_clear(&net->ipv6.ip6_null_entry->rt6i_idev); #ifdef CONFIG_IPV6_MULTIPLE_TABLES in6_dev_put_clear(&net->ipv6.ip6_prohibit_entry->rt6i_idev); @@ -202,7 +202,7 @@ Signed-off-by: Jonas Gorski in6_dev_put_clear(&net->ipv6.ip6_blk_hole_entry->rt6i_idev); #endif } -@@ -6494,6 +6528,8 @@ static int __net_init ip6_route_net_init +@@ -6495,6 +6529,8 @@ static int __net_init ip6_route_net_init #ifdef CONFIG_IPV6_MULTIPLE_TABLES net->ipv6.fib6_has_custom_rules = false; @@ -211,7 +211,7 @@ Signed-off-by: Jonas Gorski net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, sizeof(*net->ipv6.ip6_prohibit_entry), GFP_KERNEL); -@@ -6504,11 +6540,21 @@ static int __net_init ip6_route_net_init +@@ -6505,11 +6541,21 @@ static int __net_init ip6_route_net_init ip6_template_metrics, true); INIT_LIST_HEAD(&net->ipv6.ip6_prohibit_entry->rt6i_uncached); @@ -234,7 +234,7 @@ Signed-off-by: Jonas Gorski net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst, ip6_template_metrics, true); -@@ -6535,6 +6581,8 @@ out: +@@ -6536,6 +6582,8 @@ out: return ret; #ifdef CONFIG_IPV6_MULTIPLE_TABLES @@ -243,7 +243,7 @@ Signed-off-by: Jonas Gorski out_ip6_prohibit_entry: kfree(net->ipv6.ip6_prohibit_entry); out_ip6_null_entry: -@@ -6554,6 +6602,7 @@ static void __net_exit ip6_route_net_exi +@@ -6555,6 +6603,7 @@ static void __net_exit ip6_route_net_exi kfree(net->ipv6.ip6_null_entry); #ifdef CONFIG_IPV6_MULTIPLE_TABLES kfree(net->ipv6.ip6_prohibit_entry); @@ -251,7 +251,7 @@ Signed-off-by: Jonas Gorski kfree(net->ipv6.ip6_blk_hole_entry); #endif dst_entries_destroy(&net->ipv6.ip6_dst_ops); -@@ -6631,6 +6680,9 @@ void __init ip6_route_init_special_entri +@@ -6632,6 +6681,9 @@ void __init ip6_route_init_special_entri init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); diff --git a/target/linux/ipq40xx/patches-5.15/420-firmware-qcom-scm-disable-SDI.patch b/target/linux/ipq40xx/patches-5.15/420-firmware-qcom-scm-disable-SDI.patch index b2d7a403cf..a0074103cc 100644 --- a/target/linux/ipq40xx/patches-5.15/420-firmware-qcom-scm-disable-SDI.patch +++ b/target/linux/ipq40xx/patches-5.15/420-firmware-qcom-scm-disable-SDI.patch @@ -21,7 +21,7 @@ static void qcom_scm_set_download_mode(bool enable) { bool avail; -@@ -1320,6 +1334,13 @@ static int qcom_scm_probe(struct platfor +@@ -1314,6 +1328,13 @@ static int qcom_scm_probe(struct platfor if (download_mode) qcom_scm_set_download_mode(true); diff --git a/target/linux/mediatek/patches-5.15/104-mt7622-add-snor-irq.patch b/target/linux/mediatek/patches-5.15/104-mt7622-add-snor-irq.patch index 506db69152..fa2cd96f97 100644 --- a/target/linux/mediatek/patches-5.15/104-mt7622-add-snor-irq.patch +++ b/target/linux/mediatek/patches-5.15/104-mt7622-add-snor-irq.patch @@ -1,6 +1,6 @@ --- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -577,6 +577,7 @@ +@@ -558,6 +558,7 @@ compatible = "mediatek,mt7622-nor", "mediatek,mt8173-nor"; reg = <0 0x11014000 0 0xe0>; diff --git a/target/linux/mediatek/patches-5.15/120-06-v5.18-spi-spi-mem-Kill-the-spi_mem_dtr_supports_op-helper.patch b/target/linux/mediatek/patches-5.15/120-06-v5.18-spi-spi-mem-Kill-the-spi_mem_dtr_supports_op-helper.patch index 0c9e723151..6a967f99ee 100644 --- a/target/linux/mediatek/patches-5.15/120-06-v5.18-spi-spi-mem-Kill-the-spi_mem_dtr_supports_op-helper.patch +++ b/target/linux/mediatek/patches-5.15/120-06-v5.18-spi-spi-mem-Kill-the-spi_mem_dtr_supports_op-helper.patch @@ -25,9 +25,9 @@ Link: https://lore.kernel.org/linux-mtd/20220127091808.1043392-6-miquel.raynal@b --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c -@@ -1230,10 +1230,7 @@ static bool cqspi_supports_mem_op(struct - if (!(all_true || all_false)) +@@ -1245,10 +1245,7 @@ static bool cqspi_supports_mem_op(struct return false; + } - if (all_true) - return spi_mem_dtr_supports_op(mem, op); diff --git a/target/linux/mediatek/patches-5.15/192-arm64-dts-mt7622-specify-the-number-of-DMA-requests.patch b/target/linux/mediatek/patches-5.15/192-arm64-dts-mt7622-specify-the-number-of-DMA-requests.patch index f8100b20b8..905d84d317 100644 --- a/target/linux/mediatek/patches-5.15/192-arm64-dts-mt7622-specify-the-number-of-DMA-requests.patch +++ b/target/linux/mediatek/patches-5.15/192-arm64-dts-mt7622-specify-the-number-of-DMA-requests.patch @@ -112,7 +112,7 @@ Signed-off-by: Rui Salvaterra --- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -940,6 +940,7 @@ +@@ -941,6 +941,7 @@ clock-names = "hsdma"; power-domains = <&scpsys MT7622_POWER_DOMAIN_ETHSYS>; #dma-cells = <1>; diff --git a/target/linux/mediatek/patches-5.15/600-arm64-dts-mediatek-Split-PCIe-node-for-MT2712-and-MT.patch b/target/linux/mediatek/patches-5.15/600-arm64-dts-mediatek-Split-PCIe-node-for-MT2712-and-MT.patch index 0c9b6d915b..cdcb8eefd0 100644 --- a/target/linux/mediatek/patches-5.15/600-arm64-dts-mediatek-Split-PCIe-node-for-MT2712-and-MT.patch +++ b/target/linux/mediatek/patches-5.15/600-arm64-dts-mediatek-Split-PCIe-node-for-MT2712-and-MT.patch @@ -194,7 +194,7 @@ Signed-off-by: Matthias Brugger &pio { --- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -807,75 +807,83 @@ +@@ -808,75 +808,83 @@ #reset-cells = <1>; }; diff --git a/target/linux/mediatek/patches-5.15/602-arm64-dts-mediatek-add-mt7622-pcie-slot-node.patch b/target/linux/mediatek/patches-5.15/602-arm64-dts-mediatek-add-mt7622-pcie-slot-node.patch index 4ac5685c2c..0ecceecebe 100644 --- a/target/linux/mediatek/patches-5.15/602-arm64-dts-mediatek-add-mt7622-pcie-slot-node.patch +++ b/target/linux/mediatek/patches-5.15/602-arm64-dts-mediatek-add-mt7622-pcie-slot-node.patch @@ -1,6 +1,6 @@ --- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -847,6 +847,12 @@ +@@ -848,6 +848,12 @@ #address-cells = <0>; #interrupt-cells = <1>; }; @@ -13,7 +13,7 @@ }; pcie1: pcie@1a145000 { -@@ -885,6 +891,12 @@ +@@ -886,6 +892,12 @@ #address-cells = <0>; #interrupt-cells = <1>; }; diff --git a/target/linux/mediatek/patches-5.15/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch b/target/linux/mediatek/patches-5.15/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch index 8a577459b0..47de683681 100644 --- a/target/linux/mediatek/patches-5.15/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch +++ b/target/linux/mediatek/patches-5.15/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch @@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau --- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -835,6 +835,9 @@ +@@ -836,6 +836,9 @@ bus-range = <0x00 0xff>; ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x8000000>; status = "disabled"; @@ -20,7 +20,7 @@ Signed-off-by: Felix Fietkau #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 7>; -@@ -879,6 +882,9 @@ +@@ -880,6 +883,9 @@ bus-range = <0x00 0xff>; ranges = <0x82000000 0 0x28000000 0x0 0x28000000 0 0x8000000>; status = "disabled"; diff --git a/target/linux/ramips/patches-5.15/200-add-ralink-eth.patch b/target/linux/ramips/patches-5.15/200-add-ralink-eth.patch index 4a0262eaad..63c864ff7c 100644 --- a/target/linux/ramips/patches-5.15/200-add-ralink-eth.patch +++ b/target/linux/ramips/patches-5.15/200-add-ralink-eth.patch @@ -1,8 +1,8 @@ --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig -@@ -162,6 +162,7 @@ source "drivers/net/ethernet/pasemi/Kcon - source "drivers/net/ethernet/pensando/Kconfig" +@@ -162,6 +162,7 @@ source "drivers/net/ethernet/pensando/Kc source "drivers/net/ethernet/qlogic/Kconfig" + source "drivers/net/ethernet/brocade/Kconfig" source "drivers/net/ethernet/qualcomm/Kconfig" +source "drivers/net/ethernet/ralink/Kconfig" source "drivers/net/ethernet/rdc/Kconfig" From 634a45cf1d7e85d633314910bc030d40dbe476bb Mon Sep 17 00:00:00 2001 From: Rui Salvaterra Date: Sun, 1 May 2022 22:23:46 +0100 Subject: [PATCH 23/24] kernel: bump 5.15 to 5.15.37 Patches automatically rebased. Signed-off-by: Rui Salvaterra --- include/kernel-5.15 | 4 ++-- ...-spi-spi-mem-Kill-the-spi_mem_dtr_supports_op-helper.patch | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/kernel-5.15 b/include/kernel-5.15 index efac5d1b14..2f7ef8d59d 100644 --- a/include/kernel-5.15 +++ b/include/kernel-5.15 @@ -1,2 +1,2 @@ -LINUX_VERSION-5.15 = .36 -LINUX_KERNEL_HASH-5.15.36 = 36345db17a937c197c72ca9c7f34c262b3a12f927c237ff7770193014e29c690 +LINUX_VERSION-5.15 = .37 +LINUX_KERNEL_HASH-5.15.37 = 18bf091a2157faa8d92a1aba2ecb66b5124bb0e033fc7797343984e069a2c026 diff --git a/target/linux/mediatek/patches-5.15/120-06-v5.18-spi-spi-mem-Kill-the-spi_mem_dtr_supports_op-helper.patch b/target/linux/mediatek/patches-5.15/120-06-v5.18-spi-spi-mem-Kill-the-spi_mem_dtr_supports_op-helper.patch index 6a967f99ee..c313a455b6 100644 --- a/target/linux/mediatek/patches-5.15/120-06-v5.18-spi-spi-mem-Kill-the-spi_mem_dtr_supports_op-helper.patch +++ b/target/linux/mediatek/patches-5.15/120-06-v5.18-spi-spi-mem-Kill-the-spi_mem_dtr_supports_op-helper.patch @@ -25,7 +25,7 @@ Link: https://lore.kernel.org/linux-mtd/20220127091808.1043392-6-miquel.raynal@b --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c -@@ -1245,10 +1245,7 @@ static bool cqspi_supports_mem_op(struct +@@ -1249,10 +1249,7 @@ static bool cqspi_supports_mem_op(struct return false; } From d9a063c3967c72773616cf5eadd4f978b9724c50 Mon Sep 17 00:00:00 2001 From: Rui Salvaterra Date: Mon, 9 May 2022 09:41:30 +0100 Subject: [PATCH 24/24] kernel: bump 5.15 to 5.15.38 Deleted (upstreamed): mediatek/patches-5.15/120-10-v5.18-mtd-nand-fix-ecc-parameters-for-mt7622.patch [1] Other patches automatically rebased. [1] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v5.15.38&id=3ec920d755ae69c201b358e8d8e96c32f51145d8 Signed-off-by: Rui Salvaterra --- include/kernel-5.15 | 4 +- .../910-unaligned_access_hacks.patch | 8 +- .../780-usb-net-MeigLink_modem_support.patch | 2 +- .../400-mtd-mtdsplit-support.patch | 4 +- ...-mtd-core-add-get_mtd_device_by_node.patch | 2 +- ...m_nandc-add-boot_layout_mode-support.patch | 6 +- ...d-nand-fix-ecc-parameters-for-mt7622.patch | 88 ------------------- 7 files changed, 13 insertions(+), 101 deletions(-) delete mode 100644 target/linux/mediatek/patches-5.15/120-10-v5.18-mtd-nand-fix-ecc-parameters-for-mt7622.patch diff --git a/include/kernel-5.15 b/include/kernel-5.15 index 2f7ef8d59d..1575a9ad0e 100644 --- a/include/kernel-5.15 +++ b/include/kernel-5.15 @@ -1,2 +1,2 @@ -LINUX_VERSION-5.15 = .37 -LINUX_KERNEL_HASH-5.15.37 = 18bf091a2157faa8d92a1aba2ecb66b5124bb0e033fc7797343984e069a2c026 +LINUX_VERSION-5.15 = .38 +LINUX_KERNEL_HASH-5.15.38 = 7e415d420990b88bfec038d56e920b9b28f99d54f31dbbd7aa82e66acca11052 diff --git a/target/linux/ath79/patches-5.15/910-unaligned_access_hacks.patch b/target/linux/ath79/patches-5.15/910-unaligned_access_hacks.patch index 260cf4f45a..436d6e0907 100644 --- a/target/linux/ath79/patches-5.15/910-unaligned_access_hacks.patch +++ b/target/linux/ath79/patches-5.15/910-unaligned_access_hacks.patch @@ -305,7 +305,7 @@ list_for_each_entry(p, head, list) { --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c -@@ -612,48 +612,53 @@ static void tcp_options_write(__be32 *pt +@@ -613,48 +613,53 @@ static void tcp_options_write(__be32 *pt u16 options = opts->options; /* mungable copy */ if (unlikely(OPTION_MD5 & options)) { @@ -382,7 +382,7 @@ } if (unlikely(opts->num_sack_blocks)) { -@@ -661,16 +666,17 @@ static void tcp_options_write(__be32 *pt +@@ -662,16 +667,17 @@ static void tcp_options_write(__be32 *pt tp->duplicate_sack : tp->selective_acks; int this_sack; @@ -406,7 +406,7 @@ } tp->rx_opt.dsack = 0; -@@ -683,13 +689,14 @@ static void tcp_options_write(__be32 *pt +@@ -684,13 +690,14 @@ static void tcp_options_write(__be32 *pt if (foc->exp) { len = TCPOLEN_EXP_FASTOPEN_BASE + foc->len; @@ -706,7 +706,7 @@ EXPORT_SYMBOL(xfrm_parse_spi); --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c -@@ -4129,14 +4129,16 @@ static bool tcp_parse_aligned_timestamp( +@@ -4130,14 +4130,16 @@ static bool tcp_parse_aligned_timestamp( { const __be32 *ptr = (const __be32 *)(th + 1); diff --git a/target/linux/generic/hack-5.15/780-usb-net-MeigLink_modem_support.patch b/target/linux/generic/hack-5.15/780-usb-net-MeigLink_modem_support.patch index 85dc3db98d..8affabdab6 100644 --- a/target/linux/generic/hack-5.15/780-usb-net-MeigLink_modem_support.patch +++ b/target/linux/generic/hack-5.15/780-usb-net-MeigLink_modem_support.patch @@ -19,7 +19,7 @@ #define QUECTEL_VENDOR_ID 0x2c7c /* These Quectel products use Quectel's vendor ID */ -@@ -1127,6 +1129,11 @@ static const struct usb_device_id option +@@ -1129,6 +1131,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) }, diff --git a/target/linux/generic/pending-5.15/400-mtd-mtdsplit-support.patch b/target/linux/generic/pending-5.15/400-mtd-mtdsplit-support.patch index 18f26d9941..1acb8d718f 100644 --- a/target/linux/generic/pending-5.15/400-mtd-mtdsplit-support.patch +++ b/target/linux/generic/pending-5.15/400-mtd-mtdsplit-support.patch @@ -272,7 +272,7 @@ obj-$(CONFIG_MTD_BLOCK) += mtdblock.o --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h -@@ -615,6 +615,24 @@ static inline void mtd_align_erase_req(s +@@ -613,6 +613,24 @@ static inline void mtd_align_erase_req(s req->len += mtd->erasesize - mod; } @@ -297,7 +297,7 @@ static inline uint32_t mtd_div_by_ws(uint64_t sz, struct mtd_info *mtd) { if (mtd->writesize_shift) -@@ -687,6 +705,13 @@ extern void __put_mtd_device(struct mtd_ +@@ -685,6 +703,13 @@ extern void __put_mtd_device(struct mtd_ extern struct mtd_info *get_mtd_device_nm(const char *name); extern void put_mtd_device(struct mtd_info *mtd); diff --git a/target/linux/generic/pending-5.15/495-mtd-core-add-get_mtd_device_by_node.patch b/target/linux/generic/pending-5.15/495-mtd-core-add-get_mtd_device_by_node.patch index 45fbcf7658..a708a46b04 100644 --- a/target/linux/generic/pending-5.15/495-mtd-core-add-get_mtd_device_by_node.patch +++ b/target/linux/generic/pending-5.15/495-mtd-core-add-get_mtd_device_by_node.patch @@ -64,7 +64,7 @@ Reviewed-by: Miquel Raynal mutex_lock(&mtd_table_mutex); --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h -@@ -705,6 +705,8 @@ extern struct mtd_info *get_mtd_device(s +@@ -703,6 +703,8 @@ extern struct mtd_info *get_mtd_device(s extern int __get_mtd_device(struct mtd_info *mtd); extern void __put_mtd_device(struct mtd_info *mtd); extern struct mtd_info *get_mtd_device_nm(const char *name); diff --git a/target/linux/ipq806x/patches-5.15/099-1-mtd-nand-raw-qcom_nandc-add-boot_layout_mode-support.patch b/target/linux/ipq806x/patches-5.15/099-1-mtd-nand-raw-qcom_nandc-add-boot_layout_mode-support.patch index ec1d0e5f4d..08c067255e 100644 --- a/target/linux/ipq806x/patches-5.15/099-1-mtd-nand-raw-qcom_nandc-add-boot_layout_mode-support.patch +++ b/target/linux/ipq806x/patches-5.15/099-1-mtd-nand-raw-qcom_nandc-add-boot_layout_mode-support.patch @@ -204,7 +204,7 @@ Signed-off-by: Ansuel Smith host->use_ecc = true; clear_bam_transaction(nandc); -@@ -2899,6 +2958,7 @@ static int qcom_nand_host_init_and_regis +@@ -2912,6 +2971,7 @@ static int qcom_nand_host_init_and_regis struct nand_chip *chip = &host->chip; struct mtd_info *mtd = nand_to_mtd(chip); struct device *dev = nandc->dev; @@ -212,7 +212,7 @@ Signed-off-by: Ansuel Smith int ret; ret = of_property_read_u32(dn, "reg", &host->cs); -@@ -2960,6 +3020,17 @@ static int qcom_nand_host_init_and_regis +@@ -2962,6 +3022,17 @@ static int qcom_nand_host_init_and_regis if (ret) nand_cleanup(chip); @@ -230,7 +230,7 @@ Signed-off-by: Ansuel Smith return ret; } -@@ -3125,6 +3196,7 @@ static int qcom_nandc_remove(struct plat +@@ -3127,6 +3198,7 @@ static int qcom_nandc_remove(struct plat static const struct qcom_nandc_props ipq806x_nandc_props = { .ecc_modes = (ECC_RS_4BIT | ECC_BCH_8BIT), .is_bam = false, diff --git a/target/linux/mediatek/patches-5.15/120-10-v5.18-mtd-nand-fix-ecc-parameters-for-mt7622.patch b/target/linux/mediatek/patches-5.15/120-10-v5.18-mtd-nand-fix-ecc-parameters-for-mt7622.patch deleted file mode 100644 index e1c9493a1c..0000000000 --- a/target/linux/mediatek/patches-5.15/120-10-v5.18-mtd-nand-fix-ecc-parameters-for-mt7622.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 41825166744c6e5664281611f5e6d9a2e9333c2b Mon Sep 17 00:00:00 2001 -From: Chuanhong Guo -Date: Sat, 2 Apr 2022 22:31:20 +0800 -Subject: [PATCH 10/15] mtd: nand: fix ecc parameters for mt7622 - -According to the datasheet, mt7622 only has 5 ECC capabilities instead -of 7, and the decoding error register is arranged as follows: -+------+---------+---------+---------+---------+ -| Bits | 19:15 | 14:10 | 9:5 | 4:0 | -+------+---------+---------+---------+---------+ -| Name | ERRNUM3 | ERRNUM2 | ERRNUM1 | ERRNUM0 | -+------+---------+---------+---------+---------+ -This means err_mask should be 0x1f instead of 0x3f and the number of -bits shifted in mtk_ecc_get_stats should be 5 instead of 8. - -This commit introduces err_shift for the difference in this register -and fix other existing parameters. - -Public MT7622 reference manual can be found on [0] and the info this -commit is based on is from page 656 and page 660. - -[0]: https://wiki.banana-pi.org/Banana_Pi_BPI-R64#Documents - -Fixes: 98dea8d71931 ("mtd: nand: mtk: Support MT7622 NAND flash controller.") -Signed-off-by: Chuanhong Guo -(cherry picked from commit 088b769abd1bd21753002b17b696ae1778b16e8c) ---- - drivers/mtd/nand/raw/mtk_ecc.c | 12 ++++++++---- - 1 file changed, 8 insertions(+), 4 deletions(-) - ---- a/drivers/mtd/nand/raw/mtk_ecc.c -+++ b/drivers/mtd/nand/raw/mtk_ecc.c -@@ -43,6 +43,7 @@ - - struct mtk_ecc_caps { - u32 err_mask; -+ u32 err_shift; - const u8 *ecc_strength; - const u32 *ecc_regs; - u8 num_ecc_strength; -@@ -76,7 +77,7 @@ static const u8 ecc_strength_mt2712[] = - }; - - static const u8 ecc_strength_mt7622[] = { -- 4, 6, 8, 10, 12, 14, 16 -+ 4, 6, 8, 10, 12 - }; - - enum mtk_ecc_regs { -@@ -221,7 +222,7 @@ void mtk_ecc_get_stats(struct mtk_ecc *e - for (i = 0; i < sectors; i++) { - offset = (i >> 2) << 2; - err = readl(ecc->regs + ECC_DECENUM0 + offset); -- err = err >> ((i % 4) * 8); -+ err = err >> ((i % 4) * ecc->caps->err_shift); - err &= ecc->caps->err_mask; - if (err == ecc->caps->err_mask) { - /* uncorrectable errors */ -@@ -449,6 +450,7 @@ EXPORT_SYMBOL(mtk_ecc_get_parity_bits); - - static const struct mtk_ecc_caps mtk_ecc_caps_mt2701 = { - .err_mask = 0x3f, -+ .err_shift = 8, - .ecc_strength = ecc_strength_mt2701, - .ecc_regs = mt2701_ecc_regs, - .num_ecc_strength = 20, -@@ -459,6 +461,7 @@ static const struct mtk_ecc_caps mtk_ecc - - static const struct mtk_ecc_caps mtk_ecc_caps_mt2712 = { - .err_mask = 0x7f, -+ .err_shift = 8, - .ecc_strength = ecc_strength_mt2712, - .ecc_regs = mt2712_ecc_regs, - .num_ecc_strength = 23, -@@ -468,10 +471,11 @@ static const struct mtk_ecc_caps mtk_ecc - }; - - static const struct mtk_ecc_caps mtk_ecc_caps_mt7622 = { -- .err_mask = 0x3f, -+ .err_mask = 0x1f, -+ .err_shift = 5, - .ecc_strength = ecc_strength_mt7622, - .ecc_regs = mt7622_ecc_regs, -- .num_ecc_strength = 7, -+ .num_ecc_strength = 5, - .ecc_mode_shift = 4, - .parity_bits = 13, - .pg_irq_sel = 0,