Merge Official Source

Signed-off-by: Tianling Shen <cnsztl@immortalwrt.org>
This commit is contained in:
Tianling Shen
2026-05-20 10:16:28 +08:00
190 changed files with 5775 additions and 12173 deletions
+4
View File
@@ -122,6 +122,10 @@ fs-subtypes-$(CONFIG_TARGET_ROOTFS_JFFS2) += $(addsuffix -raw,$(addprefix jffs2-
TARGET_FILESYSTEMS := $(fs-types-y)
ifneq ($(ROOTFS_FILESYSTEM),)
TARGET_FILESYSTEMS := $(filter $(ROOTFS_FILESYSTEM) $(ROOTFS_FILESYSTEM)-%,$(TARGET_FILESYSTEMS))
endif
FS_64K := $(filter-out jffs2-%,$(TARGET_FILESYSTEMS)) jffs2-64k
FS_128K := $(filter-out jffs2-%,$(TARGET_FILESYSTEMS)) jffs2-128k
FS_256K := $(filter-out jffs2-%,$(TARGET_FILESYSTEMS)) jffs2-256k
+17 -1
View File
@@ -328,6 +328,22 @@ endif
APK_SCRIPTS_$(1)+=--script "post-deinstall:$$(ADIR_$(1))/postrm"
endif
ifneq ($(CONFIG_USE_APK),)
APK_TAGS_$(1):=
ifneq ($$(ABIV_$(1)),)
APK_TAGS_$(1)+=openwrt:abiversion=$$(ABIV_$(1))
endif
ifneq ($(SECTION),)
APK_TAGS_$(1)+=openwrt:section=$(SECTION)
endif
ifneq ($(PKG_CPE_ID),)
APK_TAGS_$(1)+=openwrt:cpe=$(PKG_CPE_ID)
endif
endif
TARGET_VARIANT:=$$(if $(ALL_VARIANTS),$$(if $$(VARIANT),$$(filter-out *,$$(VARIANT)),$(firstword $(ALL_VARIANTS))))
ifeq ($(BUILD_VARIANT),$$(if $$(TARGET_VARIANT),$$(TARGET_VARIANT),$(BUILD_VARIANT)))
do_install=
@@ -593,7 +609,7 @@ else
$(FAKEROOT) $(STAGING_DIR_HOST)/bin/apk mkpkg \
--info "name:$(1)$$(ABIV_$(1))" \
--info "version:$(VERSION)" \
$$(if $$(ABIV_$(1)),--info "tags:openwrt:abiversion=$$(ABIV_$(1))") \
$$(if $$(APK_TAGS_$(1)),--info "tags:$$(APK_TAGS_$(1))") \
--info "description:$$(call description_escape,$$(strip $$(Package/$(1)/description)))" \
$(if $(findstring all,$(PKGARCH)),--info "arch:noarch",--info "arch:$(PKGARCH)") \
--info "license:$(LICENSE)" \
+10
View File
@@ -143,6 +143,16 @@ ifneq ($(CONFIG_USE_APK),)
$(STAGING_DIR_HOST)/bin/apk adbdump --format json packages.adb | \
$(SCRIPT_DIR)/make-index-json.py -f apk -a "$(ARCH_PACKAGES)" - > index.json; \
done
ifdef CONFIG_JSON_CYCLONEDX_SBOM
@echo Creating CycloneDX package SBOMs...
@for d in $(PACKAGE_SUBDIRS); do \
[ -d $$d ] && \
cd $$d || continue; \
[ -f packages.adb ] || continue; \
$(STAGING_DIR_HOST)/bin/apk adbdump --format json packages.adb | \
$(SCRIPT_DIR)/make-sbom.py - -f apk > Packages.bom.cdx.json || true; \
done
endif
else
@for d in $(PACKAGE_SUBDIRS); do ( \
mkdir -p $$d; \
+10
View File
@@ -264,6 +264,16 @@ else
$(if $(CONFIG_IPK_FILES_CHECKSUMS),, \
rm -f $(1)/sbin/pkg_check)
endif
$(if $(CONFIG_TARGET_BUTTON_CUSTOMIZATION_FAILSAFE_DISABLED), \
rm -f $(1)/etc/rc.button/failsafe)
$(if $(CONFIG_TARGET_BUTTON_CUSTOMIZATION_POWER_DISABLED), \
rm -f $(1)/etc/rc.button/power)
$(if $(CONFIG_TARGET_BUTTON_CUSTOMIZATION_REBOOT_DISABLED), \
rm -f $(1)/etc/rc.button/reboot)
$(if $(CONFIG_TARGET_BUTTON_CUSTOMIZATION_RESET_DISABLED), \
rm -f $(1)/etc/rc.button/reset)
$(if $(CONFIG_TARGET_BUTTON_CUSTOMIZATION_RF_KILL_DISABLED), \
rm -f $(1)/etc/rc.button/rfkill)
endef
ifneq ($(DUMP),1)
+44
View File
@@ -287,6 +287,50 @@ if VERSIONOPT
file names
endif
menuconfig TARGET_BUTTON_CUSTOMIZATION
bool "Target button customization" if IMAGEOPT
default n
help
These options allow to customize the behaviour of the buttons defined in
the target's /etc/rc.button/* scripts. This is useful for release builds
or custom OpenWrt redistributions where certain default button handling logic
may be undesired.
config TARGET_BUTTON_CUSTOMIZATION_FAILSAFE_DISABLED
bool
prompt "Disable failsafe button handling" if TARGET_BUTTON_CUSTOMIZATION
default n
help
If set, the failsafe button handling logic in /etc/rc.button/failsafe is disabled.
config TARGET_BUTTON_CUSTOMIZATION_POWER_DISABLED
bool
prompt "Disable power button handling" if TARGET_BUTTON_CUSTOMIZATION
default n
help
If set, the power button handling logic in /etc/rc.button/power is disabled.
config TARGET_BUTTON_CUSTOMIZATION_REBOOT_DISABLED
bool
prompt "Disable reboot button handling" if TARGET_BUTTON_CUSTOMIZATION
default n
help
If set, the reboot button handling logic in /etc/rc.button/reboot is disabled.
config TARGET_BUTTON_CUSTOMIZATION_RESET_DISABLED
bool
prompt "Disable reset button handling" if TARGET_BUTTON_CUSTOMIZATION
default n
help
If set, the reset button handling logic in /etc/rc.button/reset is disabled.
config TARGET_BUTTON_CUSTOMIZATION_RF_KILL_DISABLED
bool
prompt "Disable rfkill button handling" if TARGET_BUTTON_CUSTOMIZATION
default n
help
If set, the rfkill button handling logic in /etc/rc.button/rfkill is disabled.
menuconfig PER_FEED_REPO
bool "Separate feed repositories" if IMAGEOPT
+15 -2
View File
@@ -347,8 +347,8 @@ define U-Boot/mt7981_comfast_cf-wr632ax
UBOOT_IMAGE:=u-boot.fip
BL2_BOOTDEV:=spim-nand
BL2_SOC:=mt7981
BL2_DDRTYPE:=ddr3
DEPENDS:=+trusted-firmware-a-mt7981-spim-nand-ddr3
BL2_DDRTYPE:=ddr3-1866
DEPENDS:=+trusted-firmware-a-mt7981-spim-nand-ddr3-1866
endef
define U-Boot/mt7981_cudy_tr3000-v1
@@ -736,6 +736,18 @@ define U-Boot/mt7981_snr_snr-cpe-ax2
DEPENDS:=+trusted-firmware-a-mt7981-spim-nand-ddr3
endef
define U-Boot/mt7981_wavlink_wl-wnt100x3
NAME:=WAVLINK WL-WNT100X3
BUILD_SUBTARGET:=filogic
BUILD_DEVICES:=wavlink_wl-wnt100x3-ubootmod
UBOOT_CONFIG:=mt7981_wavlink_wl-wnt100x3
UBOOT_IMAGE:=u-boot.fip
BL2_BOOTDEV:=spim-nand
BL2_SOC:=mt7981
BL2_DDRTYPE:=ddr3
DEPENDS:=+trusted-firmware-a-mt7981-spim-nand-ddr3
endef
define U-Boot/mt7981_xiaomi_mi-router-ax3000t
NAME:=Xiaomi Router AX3000T
BUILD_SUBTARGET:=filogic
@@ -1353,6 +1365,7 @@ UBOOT_TARGETS := \
mt7981_qihoo_360t7 \
mt7981_qihoo_360t7-ubi \
mt7981_snr_snr-cpe-ax2 \
mt7981_wavlink_wl-wnt100x3 \
mt7981_xiaomi_mi-router-ax3000t \
mt7981_xiaomi_mi-router-wr30u \
mt7986_acer_predator-w6x \
@@ -1,6 +1,6 @@
--- /dev/null
+++ b/arch/arm/dts/mt7981-comfast-cf-wr632ax.dts
@@ -0,0 +1,153 @@
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/dts-v1/;
@@ -9,10 +9,8 @@
+#include <dt-bindings/input/linux-event-codes.h>
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ model = "COMFAST CF-WR632AX";
+ compatible = "mediatek,mt7981", "mediatek,mt7981-rfb";
+ compatible = "comfast,cf-wr632ax", "mediatek,mt7981";
+
+ chosen {
+ stdout-path = &uart0;
@@ -82,13 +80,13 @@
+ conf-pu {
+ pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP";
+ drive-strength = <MTK_DRIVE_4mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_00>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_11>;
+ };
+
+ conf-pd {
+ pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO";
+ drive-strength = <MTK_DRIVE_4mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_00>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_11>;
+ };
+ };
+};
@@ -118,7 +116,7 @@
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "bl2";
+ label = "BL2";
+ reg = <0x0 0x100000>;
+ };
+
@@ -128,12 +126,12 @@
+ };
+
+ partition@180000 {
+ label = "factory";
+ label = "Factory";
+ reg = <0x180000 0x200000>;
+ };
+
+ partition@380000 {
+ label = "fip";
+ label = "FIP";
+ reg = <0x380000 0x200000>;
+ };
+
@@ -311,8 +309,8 @@
+boot_tftp_write_fip=tftpboot $loadaddr $bootfile_fip && run mtd_write_fip && run reset_factory
+boot_tftp_write_bl2=tftpboot $loadaddr $bootfile_bl2 && run mtd_write_bl2
+reset_factory=ubi part ubi ; mw $loadaddr 0x0 0x800 ; ubi write $loadaddr ubootenv 0x800 ; ubi write $loadaddr ubootenv2 0x800
+mtd_write_fip=mtd erase fip && mtd write fip $loadaddr
+mtd_write_bl2=mtd erase bl2 && mtd write bl2 $loadaddr
+mtd_write_fip=mtd erase FIP && mtd write FIP $loadaddr
+mtd_write_bl2=mtd erase BL2 && mtd write BL2 $loadaddr
+ubi_create_env=ubi check ubootenv || ubi create ubootenv 0x100000 dynamic || run ubi_format ; ubi check ubootenv2 || ubi create ubootenv2 0x100000 dynamic || run ubi_format
+ubi_format=ubi detach ; mtd erase ubi && ubi part ubi ; reset
+ubi_prepare_rootfs=if ubi check rootfs_data ; then else if env exists rootfs_data_max ; then ubi create rootfs_data $rootfs_data_max dynamic || ubi create rootfs_data - dynamic ; else ubi create rootfs_data - dynamic ; fi ; fi
@@ -0,0 +1,319 @@
--- /dev/null
+++ b/configs/mt7981_wavlink_wl-wnt100x3_defconfig
@@ -0,0 +1,108 @@
+CONFIG_ARM=y
+CONFIG_SYS_HAS_NONCACHED_MEMORY=y
+CONFIG_POSITION_INDEPENDENT=y
+CONFIG_ARCH_MEDIATEK=y
+CONFIG_TEXT_BASE=0x41e00000
+CONFIG_SYS_MALLOC_F_LEN=0x4000
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_DEFAULT_DEVICE_TREE="mt7981-wavlink_wl-wnt100x3"
+CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_TARGET_MT7981=y
+CONFIG_SYS_LOAD_ADDR=0x46000000
+CONFIG_PRE_CON_BUF_ADDR=0x4007ef00
+CONFIG_DEBUG_UART_BASE=0x11002000
+CONFIG_DEBUG_UART_CLOCK=40000000
+CONFIG_DEBUG_UART=y
+CONFIG_FIT=y
+CONFIG_BOOTDELAY=30
+CONFIG_AUTOBOOT_KEYED=y
+CONFIG_AUTOBOOT_MENU_SHOW=y
+CONFIG_DEFAULT_FDT_FILE="mediatek/mt7981-wavlink_wl-wnt100x3.dtb"
+CONFIG_LOGLEVEL=7
+CONFIG_PRE_CONSOLE_BUFFER=y
+CONFIG_LOG=y
+# CONFIG_BOARD_INIT is not set
+CONFIG_BOARD_LATE_INIT=y
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_PROMPT="MT7981> "
+CONFIG_CMD_CPU=y
+CONFIG_CMD_LICENSE=y
+CONFIG_CMD_BOOTMENU=y
+CONFIG_CMD_ASKENV=y
+CONFIG_CMD_ERASEENV=y
+CONFIG_CMD_ENV_FLAGS=y
+CONFIG_CMD_STRINGS=y
+CONFIG_CMD_DM=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_MTD=y
+CONFIG_CMD_PART=y
+CONFIG_CMD_TFTPSRV=y
+CONFIG_CMD_RARP=y
+CONFIG_CMD_CDP=y
+CONFIG_CMD_SNTP=y
+CONFIG_CMD_LINK_LOCAL=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_DNS=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_PXE=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_PSTORE=y
+CONFIG_CMD_PSTORE_MEM_ADDR=0x42ff0000
+CONFIG_CMD_UUID=y
+CONFIG_CMD_HASH=y
+CONFIG_CMD_SMC=y
+CONFIG_CMD_UBI=y
+CONFIG_CMD_UBI_RENAME=y
+CONFIG_OF_EMBED=y
+CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_UBI=y
+CONFIG_ENV_REDUNDANT=y
+CONFIG_ENV_UBI_PART="ubi"
+CONFIG_ENV_UBI_VOLUME="ubootenv"
+CONFIG_ENV_UBI_VOLUME_REDUND="ubootenv2"
+CONFIG_ENV_RELOC_GD_ENV_ADDR=y
+CONFIG_ENV_USE_DEFAULT_ENV_TEXT_FILE=y
+CONFIG_ENV_DEFAULT_ENV_TEXT_FILE="defenvs/wavlink_wl-wnt100x3_env"
+CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
+CONFIG_VERSION_VARIABLE=y
+CONFIG_NETCONSOLE=y
+CONFIG_USE_IPADDR=y
+CONFIG_IPADDR="192.168.1.1"
+CONFIG_USE_SERVERIP=y
+CONFIG_SERVERIP="192.168.1.254"
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_BUTTON=y
+CONFIG_BUTTON_GPIO=y
+CONFIG_CLK=y
+CONFIG_GPIO_HOG=y
+CONFIG_LED=y
+CONFIG_LED_BLINK=y
+CONFIG_LED_GPIO=y
+# CONFIG_MMC is not set
+CONFIG_MTD=y
+CONFIG_DM_MTD=y
+CONFIG_MTD_SPI_NAND=y
+CONFIG_MTD_UBI_FASTMAP=y
+CONFIG_PHY_FIXED=y
+CONFIG_MEDIATEK_ETH=y
+CONFIG_PHY=y
+CONFIG_PINCTRL=y
+CONFIG_PINCONF=y
+CONFIG_PINCTRL_MT7981=y
+CONFIG_POWER_DOMAIN=y
+CONFIG_MTK_POWER_DOMAIN=y
+CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DM_REGULATOR_GPIO=y
+CONFIG_RAM=y
+CONFIG_DM_SERIAL=y
+CONFIG_SERIAL_RX_BUFFER=y
+CONFIG_MTK_SERIAL=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_MTK_SPIM=y
+CONFIG_ZSTD=y
+CONFIG_HEXDUMP=y
--- /dev/null
+++ b/arch/arm/dts/mt7981-wavlink_wl-wnt100x3.dts
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/dts-v1/;
+#include "mt7981.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/linux-event-codes.h>
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ model = "WAVLINK WL-WNT100X3";
+ compatible = "mediatek,mt7981", "mediatek,mt7981-rfb";
+
+ chosen {
+ stdout-path = &uart0;
+ tick-timer = &timer0;
+ };
+
+ memory@40000000 {
+ device_type = "memory";
+ reg = <0x40000000 0x20000000>;
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ button-reset {
+ label = "reset";
+ linux,code = <KEY_RESTART>;
+ gpios = <&pio 11 GPIO_ACTIVE_LOW>;
+ };
+
+ button-mode {
+ label = "mode";
+ linux,code = <BTN_0>;
+ linux,input-type = <EV_SW>;
+ gpios = <&pio 25 GPIO_ACTIVE_LOW>;
+ debounce-interval = <60>;
+ };
+ };
+
+ gpio-leds {
+ compatible = "gpio-leds";
+
+ led_status: led-0 {
+ label = "blue:status";
+ gpios = <&pio 13 GPIO_ACTIVE_LOW>;
+ };
+ };
+};
+
+&uart0 {
+ mediatek,force-highspeed;
+ status = "okay";
+};
+
+&eth {
+ status = "okay";
+ mediatek,gmac-id = <1>;
+ phy-mode = "gmii";
+ phy-handle = <&phy0>;
+
+ mdio {
+ phy0: ethernet-phy@0 {
+ compatible = "ethernet-phy-id03a2.9461";
+ reg = <0x0>;
+ phy-mode = "gmii";
+ };
+ };
+};
+
+&pio {
+ spi_flash_pins: spi0-pins-func-1 {
+ mux {
+ function = "flash";
+ groups = "spi0", "spi0_wp_hold";
+ };
+
+ conf-pu {
+ pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP";
+ drive-strength = <MTK_DRIVE_8mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_00>;
+ };
+
+ conf-pd {
+ pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO";
+ drive-strength = <MTK_DRIVE_8mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_00>;
+ };
+ };
+};
+
+&spi0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi_flash_pins>;
+ status = "okay";
+ must_tx;
+ enhance_timing;
+ dma_ext;
+ ipm_design;
+ support_quad;
+ tick_dly = <2>;
+ sample_sel = <0>;
+
+ spi_nand@0 {
+ compatible = "spi-nand";
+ reg = <0>;
+ spi-max-frequency = <52000000>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "bl2";
+ reg = <0x0 0x100000>;
+ };
+
+ partition@100000 {
+ label = "u-boot-env";
+ reg = <0x100000 0x80000>;
+ };
+
+ partition@180000 {
+ label = "factory";
+ reg = <0x180000 0x200000>;
+ };
+
+ partition@380000 {
+ label = "fip";
+ reg = <0x380000 0x200000>;
+ };
+
+ partition@580000 {
+ label = "ubi";
+ reg = <0x580000 0x7a80000>;
+ compatible = "linux,ubi";
+ };
+ };
+ };
+};
+
+&watchdog {
+ status = "disabled";
+};
--- /dev/null
+++ b/defenvs/wavlink_wl-wnt100x3_env
@@ -0,0 +1,53 @@
+ipaddr=192.168.1.1
+serverip=192.168.1.254
+loadaddr=0x46000000
+console=earlycon=uart8250,mmio32,0x11002000 console=ttyS0
+bootcmd=if pstore check ; then run boot_recovery ; else run boot_ubi ; fi
+bootconf=config-1
+bootdelay=0
+bootfile=immortalwrt-mediatek-filogic-wavlink_wl-wnt100x3-ubootmod-initramfs-recovery.itb
+bootfile_bl2=immortalwrt-mediatek-filogic-wavlink_wl-wnt100x3-ubootmod-preloader.bin
+bootfile_fip=immortalwrt-mediatek-filogic-wavlink_wl-wnt100x3-ubootmod-bl31-uboot.fip
+bootfile_upg=immortalwrt-mediatek-filogic-wavlink_wl-wnt100x3-ubootmod-squashfs-sysupgrade.itb
+bootled_pwr=blue:status
+bootled_rec=blue:status
+bootmenu_confirm_return=askenv - Press ENTER to return to menu ; bootmenu 60
+bootmenu_default=0
+bootmenu_delay=0
+bootmenu_title= ␛[0;34m( ( ( ␛[1;39mOpenWrt␛[0;34m ) ) )
+bootmenu_0=Initialize environment.=run _firstboot
+bootmenu_0d=Run default boot command.=run boot_default
+bootmenu_1=Boot system via TFTP.=run boot_tftp ; run bootmenu_confirm_return
+bootmenu_2=Boot production system from NAND.=run boot_production ; run bootmenu_confirm_return
+bootmenu_3=Boot recovery system from NAND.=run boot_recovery ; run bootmenu_confirm_return
+bootmenu_4=Load production system via TFTP then write to NAND.=setenv noboot 1 ; setenv replacevol 1 ; run boot_tftp_production ; setenv noboot ; setenv replacevol ; run bootmenu_confirm_return
+bootmenu_5=Load recovery system via TFTP then write to NAND.=setenv noboot 1 ; setenv replacevol 1 ; run boot_tftp_recovery ; setenv noboot ; setenv replacevol ; run bootmenu_confirm_return
+bootmenu_6=␛[31mLoad BL31+U-Boot FIP via TFTP then write to NAND.␛[0m=run boot_tftp_write_fip ; run bootmenu_confirm_return
+bootmenu_7=␛[31mLoad BL2 preloader via TFTP then write to NAND.␛[0m=run boot_tftp_write_bl2 ; run bootmenu_confirm_return
+bootmenu_8=Reboot.=reset
+bootmenu_9=Reset all settings to factory defaults.=run reset_factory ; reset
+boot_first=if button reset ; then led $bootled_rec on ; run boot_tftp_recovery ; setenv flag_recover 1 ; run boot_default ; fi ; bootmenu
+boot_default=if env exists flag_recover ; then else run bootcmd ; fi ; run boot_recovery ; setenv replacevol 1 ; run boot_tftp_forever
+boot_production=led $bootled_pwr on ; run ubi_read_production && bootm $loadaddr#$bootconf ; led $bootled_pwr off
+boot_recovery=led $bootled_rec on ; run ubi_read_recovery && bootm $loadaddr#$bootconf ; led $bootled_rec off
+boot_ubi=run boot_production ; run boot_recovery ; run boot_tftp_forever
+boot_tftp_forever=led $bootled_rec on ; while true ; do run boot_tftp_recovery ; sleep 1 ; done
+boot_tftp_production=tftpboot $loadaddr $bootfile_upg && env exists replacevol && iminfo $loadaddr && run ubi_write_production ; if env exists noboot ; then else bootm $loadaddr#$bootconf ; fi
+boot_tftp_recovery=tftpboot $loadaddr $bootfile && env exists replacevol && iminfo $loadaddr && run ubi_write_recovery ; if env exists noboot ; then else bootm $loadaddr#$bootconf ; fi
+boot_tftp=tftpboot $loadaddr $bootfile && bootm $loadaddr#$bootconf
+boot_tftp_write_fip=tftpboot $loadaddr $bootfile_fip && run mtd_write_fip && run reset_factory
+boot_tftp_write_bl2=tftpboot $loadaddr $bootfile_bl2 && run mtd_write_bl2
+reset_factory=ubi part ubi ; mw $loadaddr 0x0 0x800 ; ubi write $loadaddr ubootenv 0x800 ; ubi write $loadaddr ubootenv2 0x800
+mtd_write_fip=mtd erase fip && mtd write fip $loadaddr
+mtd_write_bl2=mtd erase bl2 && mtd write bl2 $loadaddr
+ubi_create_env=ubi check ubootenv || ubi create ubootenv 0x100000 dynamic || run ubi_format ; ubi check ubootenv2 || ubi create ubootenv2 0x100000 dynamic || run ubi_format
+ubi_format=ubi detach ; mtd erase ubi && ubi part ubi ; reset
+ubi_prepare_rootfs=if ubi check rootfs_data ; then else if env exists rootfs_data_max ; then ubi create rootfs_data $rootfs_data_max dynamic || ubi create rootfs_data - dynamic ; else ubi create rootfs_data - dynamic ; fi ; fi
+ubi_read_production=ubi read $loadaddr fit && iminfo $loadaddr && run ubi_prepare_rootfs
+ubi_read_recovery=ubi check recovery && ubi read $loadaddr recovery
+ubi_remove_rootfs=ubi check rootfs_data && ubi remove rootfs_data
+ubi_write_production=ubi check fit && ubi remove fit ; run ubi_remove_rootfs ; ubi create fit $filesize dynamic && ubi write $loadaddr fit $filesize
+ubi_write_recovery=ubi check recovery && ubi remove recovery ; run ubi_remove_rootfs ; ubi create recovery $filesize dynamic && ubi write $loadaddr recovery $filesize
+_init_env=setenv _init_env ; run ubi_create_env ; saveenv ; saveenv
+_firstboot=setenv _firstboot ; run _switch_to_menu ; run _init_env ; run boot_first
+_switch_to_menu=setenv _switch_to_menu ; setenv bootdelay 3 ; setenv bootmenu_delay 3 ; setenv bootmenu_0 $bootmenu_0d ; setenv bootmenu_0d ; run _bootmenu_update_title
+_bootmenu_update_title=setenv _bootmenu_update_title ; setenv bootmenu_title "$bootmenu_title ␛[33m$ver␛[0m"
@@ -58,6 +58,7 @@ tplink,tl-xdr4288|\
tplink,tl-xdr6086|\
tplink,tl-xdr6088|\
tplink,tl-xtr8488|\
wavlink,wl-wnt100x3-ubootmod|\
xiaomi,mi-router-ax3000t-ubootmod|\
xiaomi,mi-router-wr30u-ubootmod|\
xiaomi,redmi-router-ax6000-ubootmod)
@@ -140,6 +141,12 @@ gatonetworks,gdsp)
glinet,gl-mt3000)
ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x80000" "0x20000"
;;
jiorouter,ax6000-jidu6101)
. /lib/upgrade/nand.sh
envubi=$(nand_find_ubi ubi)
envdev=/dev/$(nand_find_volume "$envubi" u-boot-env)
ubootenv_add_uci_config "$envdev" "0x0" "0x80000" "0x80000" "1"
;;
openembed,som7981)
ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x80000" "0x80000"
ubootenv_add_uci_sys_config "/dev/mtd3" "0x0" "0x100000" "0x100000"
@@ -25,7 +25,8 @@ linksys,mx6200|\
linksys,spnmx56)
ubootenv_add_mtd "u_env" "0x0" "0x40000" "0x20000"
;;
xiaomi,ax6000)
xiaomi,ax6000|\
xiaomi,redmi-ax5400)
ubootenv_add_mtd "0:appsblenv" "0x0" "0x10000" "0x20000"
ubootenv_add_sys_mtd "bdata" "0x0" "0x10000" "0x20000"
;;
+5 -3
View File
@@ -6,9 +6,9 @@ PKG_RELEASE:=1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=$(PROJECT_GIT)/project/firmware/qca-wireless.git
PKG_SOURCE_DATE:=2026-05-05
PKG_SOURCE_VERSION:=fc4cf4873873b20e454fba257452cd31fec502bb
PKG_MIRROR_HASH:=9e02a31c27234f7570743578b473c597b69c89e244696de5b0bee87f4009c23c
PKG_SOURCE_DATE:=2026-05-18
PKG_SOURCE_VERSION:=e20f4c6ff197823762319e4b7e31af01816503cf
PKG_MIRROR_HASH:=a0109d830c474aeca2716496cb2eab05319c4d6671ae2d02c43449a94da183fa
PKG_FLAGS:=nonshared
include $(INCLUDE_DIR)/package.mk
@@ -105,6 +105,7 @@ ALLWIFIBOARDS:= \
xiaomi_ax3600 \
xiaomi_ax6000 \
xiaomi_ax9000 \
xiaomi_redmi-ax5400 \
yuncore_ax830 \
yuncore_ax850 \
yuncore_ax880 \
@@ -300,6 +301,7 @@ $(eval $(call generate-ipq-wifi-package,xiaomi_aiot-ac2350,Xiaomi AIoT AC2350))
$(eval $(call generate-ipq-wifi-package,xiaomi_ax3600,Xiaomi AX3600))
$(eval $(call generate-ipq-wifi-package,xiaomi_ax6000,Xiaomi AX6000))
$(eval $(call generate-ipq-wifi-package,xiaomi_ax9000,Xiaomi AX9000))
$(eval $(call generate-ipq-wifi-package,xiaomi_redmi-ax5400,Xiaomi Redmi AX5400))
$(eval $(call generate-ipq-wifi-package,yuncore_ax830,Yuncore AX830))
$(eval $(call generate-ipq-wifi-package,yuncore_ax850,Yuncore AX850))
$(eval $(call generate-ipq-wifi-package,yuncore_ax880,Yuncore AX880))
@@ -87,6 +87,8 @@ static const struct bh_map button_map[] = {
BH_MAP(KEY_POWER, "power"),
BH_MAP(KEY_POWER2, "reboot"),
BH_MAP(KEY_RFKILL, "rfkill"),
BH_MAP(KEY_SETUP, "setup"),
BH_MAP(KEY_VENDOR, "vendor"),
BH_MAP(KEY_WPS_BUTTON, "wps"),
BH_MAP(KEY_WIMAX, "wwan"),
};
+1
View File
@@ -921,6 +921,7 @@ $(eval $(call KernelPackage,thermal))
define KernelPackage/echo
SUBMENU:=$(OTHER_MENU)
TITLE:=Line Echo Canceller
DEPENDS:=@LINUX_6_12
KCONFIG:=CONFIG_ECHO
FILES:=$(LINUX_DIR)/drivers/misc/echo/echo.ko
AUTOLOAD:=$(call AutoLoad,50,echo)
@@ -1,3 +1,10 @@
config WIFI_SCRIPTS_UCODE
bool "Use new ucode based scripts"
default y
config WIFI_SCRIPTS_WPS_BUTTON_DISABLED
bool
prompt "Disable WPS button handling"
default n
help
If set, the WPS button handling logic in /etc/rc.button/wps is disabled.
@@ -48,6 +48,9 @@ define Package/wifi-scripts/install
ifeq ($(CONFIG_WIFI_SCRIPTS_UCODE),y)
$(CP) ./files-ucode/* $(1)/
endif
ifeq ($(CONFIG_WIFI_SCRIPTS_WPS_BUTTON_DISABLED),y)
rm -f $(1)/etc/rc.button/wps
endif
endef
$(eval $(call BuildPackage,wifi-scripts))
+2 -2
View File
@@ -8,12 +8,12 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=util-linux
PKG_VERSION:=2.42
PKG_VERSION:=2.42.1
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=@KERNEL/linux/utils/$(PKG_NAME)/v2.42
PKG_HASH:=3452b260bbaa775d6e749ac3bb22111785003fc1f444970025c8da26dfa758e9
PKG_HASH:=82e9158eb12a9b0b569d84e1687fed9dd18fe89ccd8ef5ac3427218a7c0d7f7f
PKG_CPE_ID:=cpe:/a:kernel:util-linux
PKG_INSTALL:=1
@@ -1,30 +0,0 @@
From af6168533cb011489bd0b4b1a2fbbaaeec6859b2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= <thomas@t-8ch.de>
Date: Fri, 10 Apr 2026 18:04:58 +0200
Subject: [PATCH] meson: test for statx::stx_mnt_id in sys/stat.h
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Both the check for the general availability of 'struct statx' and the
code actual code use sys/stat.h and not linux/stat.h.
The test for stx_mnt_id also needs to test in sys/stat.h as otherwise
the detection result is wrong.
Signed-off-by: Thomas Weißschuh <thomas@t-8ch.de>
---
meson.build | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/meson.build
+++ b/meson.build
@@ -111,7 +111,7 @@ conf.set('HAVE_MOUNTFD_API', have_mountf
have_struct_statx = cc.has_type('struct statx', args : '-D_GNU_SOURCE', prefix : '#include <sys/stat.h>')
conf.set('HAVE_STRUCT_STATX', have_struct_statx ? 1 : false)
have = cc.has_member('struct statx', 'stx_mnt_id',
- prefix : '#include <linux/stat.h>')
+ prefix : '#include <sys/stat.h>')
conf.set('HAVE_STRUCT_STATX_STX_MNT_ID', have ? 1 : false)
@@ -1,30 +0,0 @@
From 5452239f6e69d2d3aaa427d2d2253247cfb7cb7b Mon Sep 17 00:00:00 2001
From: Aleksi Hannula <ahannula4+nixgit@gmail.com>
Date: Tue, 7 Apr 2026 14:52:16 +0300
Subject: [PATCH] nsenter: Fix AT_HANDLE_FID on musl
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Aleksi Hannula <ahannula4+nixgit@gmail.com>
---
sys-utils/nsenter.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/sys-utils/nsenter.c b/sys-utils/nsenter.c
index e10ba9cf90ab..98507958c0f1 100644
--- a/sys-utils/nsenter.c
+++ b/sys-utils/nsenter.c
@@ -29,6 +29,9 @@
#ifdef HAVE_LINUX_NSFS_H
# include <linux/nsfs.h>
#endif
+#ifndef AT_HANDLE_FID
+# define AT_HANDLE_FID 0x200
+#endif
#ifndef NS_GET_USERNS
# define NS_GET_USERNS _IO(0xb7, 0x1)
#endif
--
2.53.0
+178
View File
@@ -0,0 +1,178 @@
#!/usr/bin/env python3
"""
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Parse the native package index files into a json file for use by
# downstream tools.
#
"""
import datetime
import email.parser
import json
import uuid
def parse_args():
from argparse import ArgumentParser
parser = ArgumentParser()
# fmt: off
parser.add_argument(dest="source",
help="File name for input, '-' for stdin")
parser.add_argument("-f", "--source-format", required=True,
choices=['apk', 'opkg'],
help=("Required source format of"
" input: 'apk' or 'opkg'"))
parser.add_argument("-m", "--manifest",
help=("File includes the packages to"
" be included in the output"))
# fmt: on
args = parser.parse_args()
return args
def get_apk_sbom(text: str, installed: set) -> list:
packages: dict = json.loads(text)
components: list = []
type_allowed: dict = {
"kernel": "operating-system",
"firmware": "firmware",
"libs": "library"
}
for package in packages["packages"]:
element: dict = {}
# required
if 'name' in package:
name: str = package['name']
element.update({"name": name})
if installed:
if name not in installed:
continue
if 'version' in package:
element.update({"version": package["version"]})
for tag in package.get("tags", []):
if tag.startswith("openwrt:cpe="):
cpe: str = tag.split("=")[-1]
element.update({"cpe": cpe})
# required
type_category: str = ''
for tag in package.get("tags", []):
if tag.startswith("openwrt:section="):
category: str = tag.split("=")[-1]
if type_allowed.get(category):
type_category = type_allowed.get(category)
if type_category:
element.update({"type": type_category})
else:
element.update({"type": "application"})
if 'license' in package:
licenses: list = []
for license in package["license"].split():
licenses.append({"license": {"name": license}})
element.update({"licenses": licenses})
components.append(element)
return components
def get_opkg_sbom(text: str, installed: set) -> list:
components: list = []
type_allowed: dict = {
"kernel": "operating-system",
"firmware": "firmware",
"libs": "library"
}
parser: email.parser.Parser = email.parser.Parser()
chunks: list[str] = text.strip().split("\n\n")
for chunk in chunks:
element: dict = {}
package: dict = parser.parsestr(chunk, headersonly=True)
# required
if 'Package' in package:
name: str = package['Package']
element.update({"name": name})
if installed:
if name not in installed:
continue
if 'Version' in package:
element.update({"version": package['Version']})
if 'CPE-ID' in package:
element.update({"cpe": package['CPE-ID']})
# required
if 'Section' in package:
type_category: str = ''
if type_allowed.get(package['Section']):
type_category = type_allowed.get(package['Section'])
if type_category:
element.update({"type": type_category})
else:
element.update({"type": "application"})
if 'license' in package:
licenses: list = []
for license in package["license"].split():
licenses.append({"license": {"name": license}})
element.update({"licenses": licenses})
if element:
components.append(element)
return components
if __name__ == "__main__":
import sys
args = parse_args()
input = sys.stdin if args.source == "-" else open(args.source, "r")
with input:
text: str = input.read()
# Read manifest file (installed packages)
packages: set = set()
if args.manifest:
with open(args.manifest, 'r') as file:
for line in file:
packages.add(line.split(' - ')[0].strip())
components: list = []
if args.source_format == "apk":
components = get_apk_sbom(text, packages)
elif args.source_format == "opkg":
components = get_opkg_sbom(text, packages)
else:
print("Source format unknown")
raise SystemExit
timestamp: str = datetime.datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")
cyclonedx: dict = {
"bomFormat": "CycloneDX",
"specVersion": "1.4",
"serialNumber": "urn:uuid:" + str(uuid.uuid4()),
"version": "1",
"metadata": {
"timestamp": timestamp,
},
"components": components,
}
print(json.dumps(cyclonedx, indent=2))
+28 -1
View File
@@ -53,6 +53,7 @@ image:
make image DISABLED_SERVICES="<svc1> [<svc2> [<svc3> ..]]" # Which services in /etc/init.d/ should be disabled
make image ADD_LOCAL_KEY=1 # store locally generated signing key in built images
make image ROOTFS_PARTSIZE="<size>" # override the default rootfs partition size in MegaBytes
make image ROOTFS_FILESYSTEM="<fs>" # restrict images to one filesystem (e.g. squashfs, ext4, jffs2)
manifest:
List "all" packages which get installed into the image.
@@ -108,6 +109,17 @@ include $(INCLUDE_DIR)/target.mk
include $(INCLUDE_DIR)/default-packages.mk
-include .profiles.mk
# Filesystems this ImageBuilder was built with (used to validate ROOTFS_FILESYSTEM)
IB_FILESYSTEMS := \
$(if $(CONFIG_TARGET_ROOTFS_SQUASHFS),squashfs) \
$(if $(CONFIG_TARGET_ROOTFS_EXT4FS),ext4) \
$(if $(CONFIG_TARGET_ROOTFS_UBIFS),ubifs) \
$(if $(CONFIG_TARGET_ROOTFS_EROFS),erofs) \
$(if $(CONFIG_TARGET_ROOTFS_JFFS2),jffs2) \
$(if $(CONFIG_TARGET_ROOTFS_JFFS2_NAND),jffs2-nand) \
$(if $(CONFIG_TARGET_ROOTFS_TARGZ),targz) \
$(if $(CONFIG_TARGET_ROOTFS_CPIOGZ),cpiogz)
USER_PROFILE ?= $(firstword $(PROFILE_NAMES))
PROFILE_LIST = $(foreach p,$(PROFILE_NAMES), \
echo '$(patsubst DEVICE_%,%,$(p)):'; $(if $($(p)_NAME),echo ' $(subst ','"'"',$($(p)_NAME))'; ) \
@@ -324,6 +336,19 @@ ifneq ($(PROFILE),)
endif
endif
_check_rootfs_filesystem: FORCE
ifneq ($(ROOTFS_FILESYSTEM),)
ifneq ($(words $(ROOTFS_FILESYSTEM)),1)
@echo 'ROOTFS_FILESYSTEM must be a single value, got "$(ROOTFS_FILESYSTEM)"'
@exit 1
endif
ifeq ($(filter $(ROOTFS_FILESYSTEM),$(IB_FILESYSTEMS)),)
@echo 'Filesystem "$(ROOTFS_FILESYSTEM)" is not available!'
@echo 'Available filesystems: $(strip $(IB_FILESYSTEMS))'
@exit 1
endif
endif
_check_keys: FORCE
ifneq ($(CONFIG_SIGNATURE_CHECK),)
ifeq ($(CONFIG_USE_APK),)
@@ -353,6 +378,7 @@ endif
image:
$(MAKE) -s _check_profile
$(MAKE) -s _check_rootfs_filesystem
$(MAKE) -s _check_keys
(unset PROFILE FILES PACKAGES MAKEFLAGS; \
$(MAKE) -s _call_image \
@@ -361,7 +387,8 @@ image:
$(if $(PACKAGES),USER_PACKAGES="$(PACKAGES)") \
$(if $(BIN_DIR),BIN_DIR="$(BIN_DIR)") \
$(if $(DISABLED_SERVICES),DISABLED_SERVICES="$(DISABLED_SERVICES)") \
$(if $(ROOTFS_PARTSIZE),CONFIG_TARGET_ROOTFS_PARTSIZE="$(ROOTFS_PARTSIZE)"))
$(if $(ROOTFS_PARTSIZE),CONFIG_TARGET_ROOTFS_PARTSIZE="$(ROOTFS_PARTSIZE)") \
$(if $(ROOTFS_FILESYSTEM),ROOTFS_FILESYSTEM="$(ROOTFS_FILESYSTEM)"))
manifest: FORCE
$(MAKE) -s _check_profile
@@ -0,0 +1,75 @@
From c06a2f2903f6fba0a3088ad05fc5cf61a66e5d89 Mon Sep 17 00:00:00 2001
From: Lorenzo Bianconi <lorenzo@kernel.org>
Date: Tue, 28 Apr 2026 07:23:38 +0200
Subject: [PATCH] net: airoha: Rename get_src_port_id callback in get_sport
For code consistency, rename get_src_port_id callback in get_sport.
Please note this patch does not introduce any logical change and it is
just a cosmetic patch.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://patch.msgid.link/20260428-airoha-get_src_port_id-callback-v1-1-3f765c91c1e8@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/airoha/airoha_eth.c | 10 +++++-----
drivers/net/ethernet/airoha/airoha_eth.h | 2 +-
2 files changed, 6 insertions(+), 6 deletions(-)
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -1823,7 +1823,7 @@ static int airoha_set_gdm2_loopback(stru
airoha_fe_clear(eth, REG_FE_VIP_PORT_EN, BIT(AIROHA_GDM2_IDX));
airoha_fe_clear(eth, REG_FE_IFC_PORT_EN, BIT(AIROHA_GDM2_IDX));
- src_port = eth->soc->ops.get_src_port_id(port, port->nbq);
+ src_port = eth->soc->ops.get_sport(port, port->nbq);
if (src_port < 0)
return src_port;
@@ -3199,7 +3199,7 @@ static const char * const en7581_xsi_rst
"xfp-mac",
};
-static int airoha_en7581_get_src_port_id(struct airoha_gdm_port *port, int nbq)
+static int airoha_en7581_get_sport(struct airoha_gdm_port *port, int nbq)
{
switch (port->id) {
case AIROHA_GDM3_IDX:
@@ -3252,7 +3252,7 @@ static const char * const an7583_xsi_rst
"xfp-mac",
};
-static int airoha_an7583_get_src_port_id(struct airoha_gdm_port *port, int nbq)
+static int airoha_an7583_get_sport(struct airoha_gdm_port *port, int nbq)
{
switch (port->id) {
case AIROHA_GDM3_IDX:
@@ -3300,7 +3300,7 @@ static const struct airoha_eth_soc_data
.num_xsi_rsts = ARRAY_SIZE(en7581_xsi_rsts_names),
.num_ppe = 2,
.ops = {
- .get_src_port_id = airoha_en7581_get_src_port_id,
+ .get_sport = airoha_en7581_get_sport,
.get_vip_port = airoha_en7581_get_vip_port,
},
};
@@ -3311,7 +3311,7 @@ static const struct airoha_eth_soc_data
.num_xsi_rsts = ARRAY_SIZE(an7583_xsi_rsts_names),
.num_ppe = 1,
.ops = {
- .get_src_port_id = airoha_an7583_get_src_port_id,
+ .get_sport = airoha_an7583_get_sport,
.get_vip_port = airoha_an7583_get_vip_port,
},
};
--- a/drivers/net/ethernet/airoha/airoha_eth.h
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
@@ -578,7 +578,7 @@ struct airoha_eth_soc_data {
int num_xsi_rsts;
int num_ppe;
struct {
- int (*get_src_port_id)(struct airoha_gdm_port *port, int nbq);
+ int (*get_sport)(struct airoha_gdm_port *port, int nbq);
u32 (*get_vip_port)(struct airoha_gdm_port *port, int nbq);
} ops;
};
@@ -0,0 +1,36 @@
From 4ca01292ea2f2363660610a65ba0285d7c3309ed Mon Sep 17 00:00:00 2001
From: Lorenzo Bianconi <lorenzo@kernel.org>
Date: Tue, 28 Apr 2026 08:53:16 +0200
Subject: [PATCH] net: airoha: Do not return err in ndo_stop() callback
Always complete the airoha_dev_stop() routine regardless of the
airoha_set_vip_for_gdm_port() return value, since errors from
ndo_stop() are ignored by the networking stack and the interface is
always considered down after the call.
Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://patch.msgid.link/20260428-airoha-ndo-stop-not-err-v1-1-674506d29a91@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/airoha/airoha_eth.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -1747,13 +1747,10 @@ static int airoha_dev_stop(struct net_de
{
struct airoha_gdm_port *port = netdev_priv(dev);
struct airoha_qdma *qdma = port->qdma;
- int i, err;
+ int i;
netif_tx_disable(dev);
- err = airoha_set_vip_for_gdm_port(port, false);
- if (err)
- return err;
-
+ airoha_set_vip_for_gdm_port(port, false);
for (i = 0; i < dev->num_tx_queues; i++)
netdev_tx_reset_subqueue(dev, i);
@@ -0,0 +1,38 @@
From 75df490c9e8457990c8b227650f6491218ce018b Mon Sep 17 00:00:00 2001
From: Lorenzo Bianconi <lorenzo@kernel.org>
Date: Wed, 29 Apr 2026 14:02:31 +0200
Subject: [PATCH] net: airoha: Move entries to queue head in case of DMA
mapping failure in airoha_dev_xmit()
In order to respect the original descriptor order and avoid any
potential IOMMU fault or memory corruption, move pending queue entries
to the head of hw queue tx_list if the DMA mapping of current inflight
packet fails in airoha_dev_xmit routine.
Fixes: 3f47e67dff1f7 ("net: airoha: Add the capability to consume out-of-order DMA tx descriptors")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://patch.msgid.link/20260429-airoha-xmit-unmap-error-path-v2-1-32e43b7c6d25@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/airoha/airoha_eth.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -2120,14 +2120,12 @@ static netdev_tx_t airoha_dev_xmit(struc
return NETDEV_TX_OK;
error_unmap:
- while (!list_empty(&tx_list)) {
- e = list_first_entry(&tx_list, struct airoha_queue_entry,
- list);
+ list_for_each_entry(e, &tx_list, list) {
dma_unmap_single(dev->dev.parent, e->dma_addr, e->dma_len,
DMA_TO_DEVICE);
e->dma_addr = 0;
- list_move_tail(&e->list, &q->tx_list);
}
+ list_splice(&tx_list, &q->tx_list);
spin_unlock_bh(&q->lock);
error:
@@ -0,0 +1,44 @@
From 286efd34d1a1ef5d83f9441b5e59421a26738169 Mon Sep 17 00:00:00 2001
From: Lorenzo Bianconi <lorenzo@kernel.org>
Date: Thu, 30 Apr 2026 10:47:38 +0200
Subject: [PATCH] net: airoha: configure QoS channel for HW accelerated
flowtable traffic
As done for the SW path, configure the QoS channel for HW accelerated
traffic according to the user port index when forwarding to a DSA port,
or rely on the GDM port identifier otherwise. This allows HTB shaping
to be applied to HW accelerated traffic.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://patch.msgid.link/20260430-airoha-ppe-qos-channel-v1-1-5ef9221e85c1@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/airoha/airoha_ppe.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
--- a/drivers/net/ethernet/airoha/airoha_ppe.c
+++ b/drivers/net/ethernet/airoha/airoha_ppe.c
@@ -332,7 +332,7 @@ static int airoha_ppe_foe_entry_prepare(
info.wcid);
} else {
struct airoha_gdm_port *port = netdev_priv(dev);
- u8 pse_port;
+ u8 pse_port, channel;
if (!airoha_is_valid_gdm_port(eth, port))
return -EINVAL;
@@ -345,6 +345,14 @@ static int airoha_ppe_foe_entry_prepare(
* loopback
*/
+ /* For traffic forwarded to DSA devices select QoS
+ * channel according to the DSA user port index, rely
+ * on port id otherwise.
+ */
+ channel = dsa_port >= 0 ? dsa_port : port->id;
+ channel = channel % AIROHA_NUM_QOS_CHANNELS;
+ qdata |= FIELD_PREP(AIROHA_FOE_CHANNEL, channel);
+
val |= FIELD_PREP(AIROHA_FOE_IB2_PSE_PORT, pse_port) |
AIROHA_FOE_IB2_PSE_QOS;
/* For downlink traffic consume SRAM memory for hw
@@ -0,0 +1,95 @@
From 98e490930de3af9afa0bbb2d1d79d6d5b5513012 Mon Sep 17 00:00:00 2001
From: Lorenzo Bianconi <lorenzo@kernel.org>
Date: Fri, 1 May 2026 09:49:11 +0200
Subject: [PATCH] net: airoha: Introduce airoha_fe_get()/airoha_qdma_get()
register read helpers
Add airoha_fe_get() and airoha_qdma_get() as utility routines for reading
a masked field from a specified register.
This is a non-functional refactor, no logical changes are introduced to
the existing codebase.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://patch.msgid.link/20260501-airoha_fe_get-airoha_qdma_get-v3-1-126c6f647ccb@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/airoha/airoha_eth.c | 13 ++++---------
drivers/net/ethernet/airoha/airoha_eth.h | 4 ++++
drivers/net/ethernet/airoha/airoha_ppe.c | 5 ++---
3 files changed, 10 insertions(+), 12 deletions(-)
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -201,15 +201,13 @@ static void airoha_fe_vip_setup(struct a
static u32 airoha_fe_get_pse_queue_rsv_pages(struct airoha_eth *eth,
u32 port, u32 queue)
{
- u32 val;
-
airoha_fe_rmw(eth, REG_FE_PSE_QUEUE_CFG_WR,
PSE_CFG_PORT_ID_MASK | PSE_CFG_QUEUE_ID_MASK,
FIELD_PREP(PSE_CFG_PORT_ID_MASK, port) |
FIELD_PREP(PSE_CFG_QUEUE_ID_MASK, queue));
- val = airoha_fe_rr(eth, REG_FE_PSE_QUEUE_CFG_VAL);
- return FIELD_GET(PSE_CFG_OQ_RSV_MASK, val);
+ return airoha_fe_get(eth, REG_FE_PSE_QUEUE_CFG_VAL,
+ PSE_CFG_OQ_RSV_MASK);
}
static void airoha_fe_set_pse_queue_rsv_pages(struct airoha_eth *eth,
@@ -227,9 +225,7 @@ static void airoha_fe_set_pse_queue_rsv_
static u32 airoha_fe_get_pse_all_rsv(struct airoha_eth *eth)
{
- u32 val = airoha_fe_rr(eth, REG_FE_PSE_BUF_SET);
-
- return FIELD_GET(PSE_ALLRSV_MASK, val);
+ return airoha_fe_get(eth, REG_FE_PSE_BUF_SET, PSE_ALLRSV_MASK);
}
static int airoha_fe_set_pse_oq_rsv(struct airoha_eth *eth,
@@ -247,8 +243,7 @@ static int airoha_fe_set_pse_oq_rsv(stru
FIELD_PREP(PSE_ALLRSV_MASK, all_rsv));
/* modify hthd */
- tmp = airoha_fe_rr(eth, PSE_FQ_CFG);
- fq_limit = FIELD_GET(PSE_FQ_LIMIT_MASK, tmp);
+ fq_limit = airoha_fe_get(eth, PSE_FQ_CFG, PSE_FQ_LIMIT_MASK);
tmp = fq_limit - all_rsv - 0x20;
airoha_fe_rmw(eth, REG_PSE_SHARE_USED_THD,
PSE_SHARE_USED_HTHD_MASK,
--- a/drivers/net/ethernet/airoha/airoha_eth.h
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
@@ -619,6 +619,8 @@ u32 airoha_rmw(void __iomem *base, u32 o
airoha_rmw((eth)->fe_regs, (offset), 0, (val))
#define airoha_fe_clear(eth, offset, val) \
airoha_rmw((eth)->fe_regs, (offset), (val), 0)
+#define airoha_fe_get(eth, offset, mask) \
+ FIELD_GET((mask), airoha_fe_rr((eth), (offset)))
#define airoha_qdma_rr(qdma, offset) \
airoha_rr((qdma)->regs, (offset))
@@ -630,6 +632,8 @@ u32 airoha_rmw(void __iomem *base, u32 o
airoha_rmw((qdma)->regs, (offset), 0, (val))
#define airoha_qdma_clear(qdma, offset, val) \
airoha_rmw((qdma)->regs, (offset), (val), 0)
+#define airoha_qdma_get(qdma, offset, mask) \
+ FIELD_GET((mask), airoha_qdma_rr((qdma), (offset)))
static inline u16 airoha_qdma_get_txq(struct airoha_qdma *qdma, u16 qid)
{
--- a/drivers/net/ethernet/airoha/airoha_ppe.c
+++ b/drivers/net/ethernet/airoha/airoha_ppe.c
@@ -80,9 +80,8 @@ bool airoha_ppe_is_enabled(struct airoha
static u32 airoha_ppe_get_timestamp(struct airoha_ppe *ppe)
{
- u16 timestamp = airoha_fe_rr(ppe->eth, REG_FE_FOE_TS);
-
- return FIELD_GET(AIROHA_FOE_IB1_BIND_TIMESTAMP, timestamp);
+ return airoha_fe_get(ppe->eth, REG_FE_FOE_TS,
+ AIROHA_FOE_IB1_BIND_TIMESTAMP);
}
void airoha_ppe_set_cpu_port(struct airoha_gdm_port *port, u8 ppe_id, u8 fport)
@@ -0,0 +1,73 @@
From bbfb1983944f2eaa8ee192e0f7b59ecc0fda9981 Mon Sep 17 00:00:00 2001
From: Lorenzo Bianconi <lorenzo@kernel.org>
Date: Wed, 13 May 2026 17:03:59 +0200
Subject: [PATCH] net: airoha: Reserve RX headroom to avoid skb reallocation
Reserve NET_SKB_PAD + NET_IP_ALIGN bytes of headroom for received packets
to avoid skb head reallocation when pushing protocol headers into the skb.
Tested-by: Xuegang Lu <xuegang.lu@airoha.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://patch.msgid.link/20260513-airoha-rx-headroom-v1-1-bd87798e422d@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/airoha/airoha_eth.c | 14 ++++++++------
drivers/net/ethernet/airoha/airoha_eth.h | 2 ++
2 files changed, 10 insertions(+), 6 deletions(-)
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -543,9 +543,10 @@ static int airoha_qdma_fill_rx_queue(str
q->queued++;
nframes++;
+ offset += AIROHA_RX_HEADROOM;
e->buf = page_address(page) + offset;
e->dma_addr = page_pool_get_dma_addr(page) + offset;
- e->dma_len = SKB_WITH_OVERHEAD(q->buf_size);
+ e->dma_len = SKB_WITH_OVERHEAD(AIROHA_RX_LEN(q->buf_size));
val = FIELD_PREP(QDMA_DESC_LEN_MASK, e->dma_len);
WRITE_ONCE(desc->ctrl, cpu_to_le32(val));
@@ -611,13 +612,12 @@ static int airoha_qdma_rx_process(struct
q->tail = (q->tail + 1) % q->ndesc;
q->queued--;
- dma_sync_single_for_cpu(eth->dev, e->dma_addr,
- SKB_WITH_OVERHEAD(q->buf_size), dir);
+ dma_sync_single_for_cpu(eth->dev, e->dma_addr, e->dma_len,
+ dir);
page = virt_to_head_page(e->buf);
len = FIELD_GET(QDMA_DESC_LEN_MASK, desc_ctrl);
- data_len = q->skb ? q->buf_size
- : SKB_WITH_OVERHEAD(q->buf_size);
+ data_len = q->skb ? AIROHA_RX_LEN(q->buf_size) : e->dma_len;
if (!len || data_len < len)
goto free_frag;
@@ -627,10 +627,12 @@ static int airoha_qdma_rx_process(struct
port = eth->ports[p];
if (!q->skb) { /* first buffer */
- q->skb = napi_build_skb(e->buf, q->buf_size);
+ q->skb = napi_build_skb(e->buf - AIROHA_RX_HEADROOM,
+ q->buf_size);
if (!q->skb)
goto free_frag;
+ skb_reserve(q->skb, AIROHA_RX_HEADROOM);
__skb_put(q->skb, len);
skb_mark_for_recycle(q->skb);
q->skb->dev = port->dev;
--- a/drivers/net/ethernet/airoha/airoha_eth.h
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
@@ -32,6 +32,8 @@
#define AIROHA_FE_MC_MAX_VLAN_TABLE 64
#define AIROHA_FE_MC_MAX_VLAN_PORT 16
#define AIROHA_NUM_TX_IRQ 2
+#define AIROHA_RX_HEADROOM (NET_SKB_PAD + NET_IP_ALIGN)
+#define AIROHA_RX_LEN(_n) ((_n) - AIROHA_RX_HEADROOM)
#define HW_DSCP_NUM 2048
#define IRQ_QUEUE_LEN(_n) ((_n) ? 1024 : 2048)
#define TX_DSCP_NUM 1024
@@ -13,7 +13,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -1490,6 +1490,10 @@ static int airoha_hw_init(struct platfor
@@ -1487,6 +1487,10 @@ static int airoha_hw_init(struct platfor
if (err)
return err;
@@ -16,7 +16,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -578,8 +578,11 @@ static int airoha_qdma_get_gdm_port(stru
@@ -574,8 +574,11 @@ static int airoha_qdma_get_gdm_port(stru
sport = FIELD_GET(QDMA_ETH_RXMSG_SPORT_MASK, msg1);
switch (sport) {
@@ -15,7 +15,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -503,8 +503,10 @@ static int airoha_fe_init(struct airoha_
@@ -498,8 +498,10 @@ static int airoha_fe_init(struct airoha_
FIELD_PREP(IP_ASSEMBLE_PORT_MASK, 0) |
FIELD_PREP(IP_ASSEMBLE_NBQ_MASK, 22));
@@ -28,7 +28,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
airoha_fe_crsn_qsel_init(eth);
@@ -1722,7 +1724,8 @@ static int airoha_dev_open(struct net_de
@@ -1719,7 +1721,8 @@ static int airoha_dev_open(struct net_de
if (err)
return err;
@@ -15,7 +15,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -3202,7 +3202,6 @@ static void airoha_remove(struct platfor
@@ -3194,7 +3194,6 @@ static void airoha_remove(struct platfor
}
static const char * const en7581_xsi_rsts_names[] = {
@@ -23,7 +23,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
"hsi0-mac",
"hsi1-mac",
"hsi-mac",
@@ -3256,7 +3255,6 @@ static u32 airoha_en7581_get_vip_port(st
@@ -3248,7 +3247,6 @@ static u32 airoha_en7581_get_vip_port(st
}
static const char * const an7583_xsi_rsts_names[] = {
@@ -49,7 +49,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
static void airoha_set_macaddr(struct airoha_gdm_port *port, const u8 *addr)
{
struct airoha_eth *eth = port->qdma->eth;
@@ -1719,6 +1725,17 @@ static int airoha_dev_open(struct net_de
@@ -1716,6 +1722,17 @@ static int airoha_dev_open(struct net_de
struct airoha_qdma *qdma = port->qdma;
u32 pse_port = FE_PSE_PORT_PPE1;
@@ -67,7 +67,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
netif_tx_start_all_queues(dev);
err = airoha_set_vip_for_gdm_port(port, true);
if (err)
@@ -1783,6 +1800,11 @@ static int airoha_dev_stop(struct net_de
@@ -1777,6 +1794,11 @@ static int airoha_dev_stop(struct net_de
}
}
@@ -79,7 +79,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
return 0;
}
@@ -2922,6 +2944,11 @@ static const struct ethtool_ops airoha_e
@@ -2914,6 +2936,11 @@ static const struct ethtool_ops airoha_e
.get_link = ethtool_op_get_link,
};
@@ -91,7 +91,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
static int airoha_metadata_dst_alloc(struct airoha_gdm_port *port)
{
int i;
@@ -2966,6 +2993,124 @@ bool airoha_is_valid_gdm_port(struct air
@@ -2958,6 +2985,119 @@ bool airoha_is_valid_gdm_port(struct air
return false;
}
@@ -146,14 +146,22 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+ .mac_link_down = airoha_mac_link_down,
+};
+
+static int airoha_fill_available_pcs(struct phylink_config *config,
+ struct phylink_pcs **available_pcs,
+ unsigned int num_available_pcs)
+{
+ struct device *dev = config->dev;
+
+ return fwnode_phylink_pcs_parse(dev_fwnode(dev), available_pcs,
+ &num_available_pcs);
+}
+
+static int airoha_setup_phylink(struct net_device *dev)
+{
+ struct airoha_gdm_port *port = netdev_priv(dev);
+ struct device_node *np = dev->dev.of_node;
+ struct phylink_pcs **available_pcs;
+ phy_interface_t phy_mode;
+ struct phylink *phylink;
+ unsigned int num_pcs;
+ int err;
+
+ err = of_get_phy_mode(np, &phy_mode);
@@ -168,21 +176,12 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+ MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD |
+ MAC_5000FD | MAC_10000FD;
+
+ err = fwnode_phylink_pcs_parse(dev_fwnode(&dev->dev), NULL, &num_pcs);
+ err = fwnode_phylink_pcs_parse(dev_fwnode(&dev->dev), NULL,
+ &port->phylink_config.num_available_pcs);
+ if (err)
+ return err;
+
+ available_pcs = kcalloc(num_pcs, sizeof(*available_pcs), GFP_KERNEL);
+ if (!available_pcs)
+ return -ENOMEM;
+
+ err = fwnode_phylink_pcs_parse(dev_fwnode(&dev->dev), available_pcs,
+ &num_pcs);
+ if (err)
+ goto out;
+
+ port->phylink_config.available_pcs = available_pcs;
+ port->phylink_config.num_available_pcs = num_pcs;
+ port->phylink_config.fill_available_pcs = airoha_fill_available_pcs;
+
+ __set_bit(PHY_INTERFACE_MODE_SGMII,
+ port->phylink_config.supported_interfaces);
@@ -201,14 +200,10 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+ phylink = phylink_create(&port->phylink_config,
+ of_fwnode_handle(np),
+ phy_mode, &airoha_phylink_ops);
+ if (IS_ERR(phylink)) {
+ err = PTR_ERR(phylink);
+ goto out;
+ }
+ if (IS_ERR(phylink))
+ return PTR_ERR(phylink);
+
+ port->phylink = phylink;
+out:
+ kfree(available_pcs);
+
+ return err;
+}
@@ -216,7 +211,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
static int airoha_alloc_gdm_port(struct airoha_eth *eth,
struct device_node *np)
{
@@ -3039,6 +3184,12 @@ static int airoha_alloc_gdm_port(struct
@@ -3031,6 +3171,12 @@ static int airoha_alloc_gdm_port(struct
port->nbq = id == AIROHA_GDM3_IDX && airoha_is_7581(eth) ? 4 : 0;
eth->ports[p] = port;
@@ -229,7 +224,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
return airoha_metadata_dst_alloc(port);
}
@@ -3166,8 +3317,11 @@ error_napi_stop:
@@ -3158,8 +3304,11 @@ error_napi_stop:
if (!port)
continue;
@@ -242,7 +237,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
airoha_metadata_dst_free(port);
}
airoha_hw_cleanup(eth);
@@ -3192,6 +3346,8 @@ static void airoha_remove(struct platfor
@@ -3184,6 +3333,8 @@ static void airoha_remove(struct platfor
if (!port)
continue;
@@ -253,7 +248,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
}
--- a/drivers/net/ethernet/airoha/airoha_eth.h
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
@@ -540,6 +540,9 @@ struct airoha_gdm_port {
@@ -542,6 +542,9 @@ struct airoha_gdm_port {
int id;
int nbq;
@@ -14,7 +14,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -589,6 +589,9 @@ static int airoha_qdma_get_gdm_port(stru
@@ -585,6 +585,9 @@ static int airoha_qdma_get_gdm_port(stru
case 0x18:
port = 3; /* GDM4 */
break;
@@ -28,7 +28,7 @@ Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
static void airoha_set_macaddr(struct airoha_gdm_port *port, const u8 *addr)
{
@@ -1728,6 +1730,7 @@ static int airoha_dev_open(struct net_de
@@ -1725,6 +1727,7 @@ static int airoha_dev_open(struct net_de
struct airoha_qdma *qdma = port->qdma;
u32 pse_port = FE_PSE_PORT_PPE1;
@@ -36,7 +36,7 @@ Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
if (airhoa_is_phy_external(port)) {
err = phylink_of_phy_connect(port->phylink, dev->dev.of_node, 0);
if (err) {
@@ -1738,6 +1741,7 @@ static int airoha_dev_open(struct net_de
@@ -1735,6 +1738,7 @@ static int airoha_dev_open(struct net_de
phylink_start(port->phylink);
}
@@ -44,7 +44,7 @@ Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
netif_tx_start_all_queues(dev);
err = airoha_set_vip_for_gdm_port(port, true);
@@ -1803,10 +1807,12 @@ static int airoha_dev_stop(struct net_de
@@ -1797,10 +1801,12 @@ static int airoha_dev_stop(struct net_de
}
}
@@ -57,7 +57,7 @@ Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
return 0;
}
@@ -2996,6 +3002,7 @@ bool airoha_is_valid_gdm_port(struct air
@@ -2988,6 +2994,7 @@ bool airoha_is_valid_gdm_port(struct air
return false;
}
@@ -65,7 +65,7 @@ Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
static void airoha_mac_link_up(struct phylink_config *config, struct phy_device *phy,
unsigned int mode, phy_interface_t interface,
int speed, int duplex, bool tx_pause, bool rx_pause)
@@ -3113,6 +3120,7 @@ out:
@@ -3100,6 +3107,7 @@ static int airoha_setup_phylink(struct n
return err;
}
@@ -73,7 +73,7 @@ Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
static int airoha_alloc_gdm_port(struct airoha_eth *eth,
struct device_node *np)
@@ -3187,11 +3195,13 @@ static int airoha_alloc_gdm_port(struct
@@ -3174,11 +3182,13 @@ static int airoha_alloc_gdm_port(struct
port->nbq = id == AIROHA_GDM3_IDX && airoha_is_7581(eth) ? 4 : 0;
eth->ports[p] = port;
@@ -87,7 +87,7 @@ Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
return airoha_metadata_dst_alloc(port);
}
@@ -3321,8 +3331,10 @@ error_napi_stop:
@@ -3308,8 +3318,10 @@ error_napi_stop:
continue;
if (port->dev->reg_state == NETREG_REGISTERED) {
@@ -98,7 +98,7 @@ Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
unregister_netdev(port->dev);
}
airoha_metadata_dst_free(port);
@@ -3349,8 +3361,10 @@ static void airoha_remove(struct platfor
@@ -3336,8 +3348,10 @@ static void airoha_remove(struct platfor
if (!port)
continue;
@@ -111,7 +111,7 @@ Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
}
--- a/drivers/net/ethernet/airoha/airoha_eth.h
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
@@ -540,8 +540,10 @@ struct airoha_gdm_port {
@@ -542,8 +542,10 @@ struct airoha_gdm_port {
int id;
int nbq;
@@ -0,0 +1,150 @@
From 6408cdca652b1f85e5b8582c283203d11f4dedcb Mon Sep 17 00:00:00 2001
Message-ID: <6408cdca652b1f85e5b8582c283203d11f4dedcb.1779086987.git.lorenzo@kernel.org>
From: Lorenzo Bianconi <lorenzo@kernel.org>
Date: Sun, 17 May 2026 21:11:27 +0200
Subject: [PATCH net-next 1/2] net: netfilter: flowtable: Add the capability to
offload dscp field
Introduce the capability to hw offload via netfilter flowtable APIs the
IP TOS info. Implement the sw offloading for DSCP field via the
netfilter flowtable APIs.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
include/net/netfilter/nf_flow_table.h | 2 ++
net/netfilter/nf_flow_table_ip.c | 12 ++++++++++++
net/netfilter/nf_flow_table_offload.c | 5 +++++
net/netfilter/nft_flow_offload.c | 22 ++++++++++++++++++++++
4 files changed, 41 insertions(+)
--- a/include/net/netfilter/nf_flow_table.h
+++ b/include/net/netfilter/nf_flow_table.h
@@ -29,6 +29,7 @@ struct nf_flow_key {
struct flow_dissector_key_ipv4_addrs ipv4;
struct flow_dissector_key_ipv6_addrs ipv6;
};
+ struct flow_dissector_key_ip ip;
struct flow_dissector_key_keyid enc_key_id;
union {
struct flow_dissector_key_ipv4_addrs enc_ipv4;
@@ -138,6 +139,7 @@ struct flow_offload_tuple {
encap_num:2,
in_vlan_ingress:2;
u16 mtu;
+ u8 dscp;
union {
struct {
struct dst_entry *dst_cache;
--- a/net/netfilter/nf_flow_table_ip.c
+++ b/net/netfilter/nf_flow_table_ip.c
@@ -372,6 +372,7 @@ static int nf_flow_offload_forward(struc
struct flow_offload *flow;
unsigned int thoff, mtu;
struct iphdr *iph;
+ u8 dscp;
dir = tuplehash->tuple.dir;
flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]);
@@ -401,6 +402,12 @@ static int nf_flow_offload_forward(struc
iph = ip_hdr(skb);
nf_flow_nat_ip(flow, skb, thoff, dir, iph);
+ dscp = FIELD_GET(INET_DSCP_MASK, ipv4_get_dsfield(iph));
+ if (tuplehash->tuple.dscp != dscp)
+ ipv4_change_dsfield(iph, INET_ECN_MASK,
+ FIELD_PREP(INET_DSCP_MASK,
+ tuplehash->tuple.dscp));
+
ip_decrease_ttl(iph);
skb_clear_tstamp(skb);
@@ -651,6 +658,7 @@ static int nf_flow_offload_ipv6_forward(
struct flow_offload *flow;
unsigned int thoff, mtu;
struct ipv6hdr *ip6h;
+ u8 dscp;
dir = tuplehash->tuple.dir;
flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]);
@@ -679,6 +687,12 @@ static int nf_flow_offload_ipv6_forward(
ip6h = ipv6_hdr(skb);
nf_flow_nat_ipv6(flow, skb, dir, ip6h);
+ dscp = FIELD_GET(INET_DSCP_MASK, ipv6_get_dsfield(ip6h));
+ if (tuplehash->tuple.dscp != dscp)
+ ipv6_change_dsfield(ip6h, INET_ECN_MASK,
+ FIELD_PREP(INET_DSCP_MASK,
+ tuplehash->tuple.dscp));
+
ip6h->hop_limit--;
skb_clear_tstamp(skb);
--- a/net/netfilter/nf_flow_table_offload.c
+++ b/net/netfilter/nf_flow_table_offload.c
@@ -103,6 +103,7 @@ static int nf_flow_rule_match(struct nf_
NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_BASIC, basic);
NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4);
NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6);
+ NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_IP, ip);
NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_TCP, tcp);
NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_PORTS, tp);
@@ -168,6 +169,10 @@ static int nf_flow_rule_match(struct nf_
match->dissector.used_keys |= BIT_ULL(key->control.addr_type);
mask->basic.n_proto = 0xffff;
+ key->ip.tos = FIELD_PREP(INET_DSCP_MASK, tuple->dscp);
+ mask->ip.tos = 0xff;
+ match->dissector.used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_IP);
+
switch (tuple->l4proto) {
case IPPROTO_TCP:
key->tcp.flags = 0;
--- a/net/netfilter/nft_flow_offload.c
+++ b/net/netfilter/nft_flow_offload.c
@@ -8,6 +8,7 @@
#include <linux/spinlock.h>
#include <linux/netfilter/nf_conntrack_common.h>
#include <linux/netfilter/nf_tables.h>
+#include <net/dsfield.h>
#include <net/ip.h> /* for ipv4 options. */
#include <net/inet_dscp.h>
#include <net/netfilter/nf_tables.h>
@@ -279,6 +280,27 @@ static int nft_flow_route(const struct n
return 0;
}
+static void nft_flow_set_dscp(const struct nft_pktinfo *pkt,
+ struct flow_offload *flow,
+ enum ip_conntrack_dir dir)
+{
+ struct flow_offload_tuple *tuple = &flow->tuplehash[dir].tuple;
+ struct sk_buff *skb = pkt->skb;
+
+ switch (skb->protocol) {
+ case htons(ETH_P_IP):
+ tuple->dscp = FIELD_GET(INET_DSCP_MASK,
+ ipv4_get_dsfield(ip_hdr(skb)));
+ break;
+ case htons(ETH_P_IPV6):
+ tuple->dscp = FIELD_GET(INET_DSCP_MASK,
+ ipv6_get_dsfield(ipv6_hdr(skb)));
+ break;
+ default:
+ break;
+ }
+}
+
static bool nft_flow_offload_skip(struct sk_buff *skb, int family)
{
if (skb_sec_path(skb))
@@ -371,6 +393,9 @@ static void nft_flow_offload_eval(const
if (!flow)
goto err_flow_alloc;
+ nft_flow_set_dscp(pkt, flow, dir);
+ nft_flow_set_dscp(pkt, flow, !dir);
+
flow_offload_route_init(flow, &route);
if (tcph)
flow_offload_ct_tcp(ct);
@@ -0,0 +1,94 @@
From b9870ade9498f4119d3f8f8368fcd13e1fa0c7c9 Mon Sep 17 00:00:00 2001
Message-ID: <b9870ade9498f4119d3f8f8368fcd13e1fa0c7c9.1779086987.git.lorenzo@kernel.org>
In-Reply-To: <6408cdca652b1f85e5b8582c283203d11f4dedcb.1779086987.git.lorenzo@kernel.org>
References: <6408cdca652b1f85e5b8582c283203d11f4dedcb.1779086987.git.lorenzo@kernel.org>
From: Lorenzo Bianconi <lorenzo@kernel.org>
Date: Mon, 18 May 2026 08:36:20 +0200
Subject: [PATCH net-next 2/2] net: airoha: Set hw QoS parameter according to
the packet dscp
Introduce the capability to hw offload via netfilter flowtable APIs the
IP TOS info in order to configure hw queue and dscp field.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/ethernet/airoha/airoha_ppe.c | 24 ++++++++++++++++++------
1 file changed, 18 insertions(+), 6 deletions(-)
--- a/drivers/net/ethernet/airoha/airoha_ppe.c
+++ b/drivers/net/ethernet/airoha/airoha_ppe.c
@@ -11,6 +11,7 @@
#include <linux/rhashtable.h>
#include <net/ipv6.h>
#include <net/pkt_cls.h>
+#include <net/route.h>
#include "airoha_regs.h"
#include "airoha_eth.h"
@@ -298,7 +299,7 @@ static int airoha_ppe_foe_entry_prepare(
struct airoha_foe_entry *hwe,
struct net_device *dev, int type,
struct airoha_flow_data *data,
- int l4proto)
+ int l4proto, u8 dsfield)
{
u32 qdata = FIELD_PREP(AIROHA_FOE_SHAPER_ID, 0x7f), ports_pad, val;
int wlan_etype = -EINVAL, dsa_port = airoha_get_dsa_port(&dev);
@@ -331,7 +332,7 @@ static int airoha_ppe_foe_entry_prepare(
info.wcid);
} else {
struct airoha_gdm_port *port = netdev_priv(dev);
- u8 pse_port, channel;
+ u8 pse_port, channel, priority;
if (!airoha_is_valid_gdm_port(eth, port))
return -EINVAL;
@@ -350,9 +351,13 @@ static int airoha_ppe_foe_entry_prepare(
*/
channel = dsa_port >= 0 ? dsa_port : port->id;
channel = channel % AIROHA_NUM_QOS_CHANNELS;
- qdata |= FIELD_PREP(AIROHA_FOE_CHANNEL, channel);
+ priority = rt_tos2priority(dsfield);
+ priority = priority % AIROHA_NUM_QOS_QUEUES;
+ qdata |= FIELD_PREP(AIROHA_FOE_CHANNEL, channel) |
+ FIELD_PREP(AIROHA_FOE_QID, priority);
val |= FIELD_PREP(AIROHA_FOE_IB2_PSE_PORT, pse_port) |
+ FIELD_PREP(AIROHA_FOE_IB2_DSCP, dsfield) |
AIROHA_FOE_IB2_PSE_QOS;
/* For downlink traffic consume SRAM memory for hw
* forwarding descriptors queue.
@@ -1044,9 +1049,9 @@ static int airoha_ppe_flow_offload_repla
struct net_device *odev = NULL;
struct flow_action_entry *act;
struct airoha_foe_entry hwe;
+ u8 dsfield = 0, l4proto = 0;
int err, i, offload_type;
u16 addr_type = 0;
- u8 l4proto = 0;
if (rhashtable_lookup(&eth->flow_table, &f->cookie,
airoha_flow_table_params))
@@ -1076,6 +1081,13 @@ static int airoha_ppe_flow_offload_repla
return -EOPNOTSUPP;
}
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) {
+ struct flow_match_ip match;
+
+ flow_rule_match_ip(rule, &match);
+ dsfield = match.key->tos;
+ }
+
switch (addr_type) {
case 0:
offload_type = PPE_PKT_TYPE_BRIDGE;
@@ -1141,7 +1153,7 @@ static int airoha_ppe_flow_offload_repla
return -EINVAL;
err = airoha_ppe_foe_entry_prepare(eth, &hwe, odev, offload_type,
- &data, l4proto);
+ &data, l4proto, dsfield);
if (err)
return err;
@@ -0,0 +1,357 @@
From 598e1ddfe85ad0f4778eeadd5d878209dd931280 Mon Sep 17 00:00:00 2001
Message-ID: <598e1ddfe85ad0f4778eeadd5d878209dd931280.1779112628.git.lorenzo@kernel.org>
From: Lorenzo Bianconi <lorenzo@kernel.org>
Date: Thu, 14 May 2026 20:25:19 +0200
Subject: [PATCH] net: airoha: Implement LRO TCP support
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/ethernet/airoha/airoha_eth.c | 178 ++++++++++++++++++++--
drivers/net/ethernet/airoha/airoha_eth.h | 23 +++
drivers/net/ethernet/airoha/airoha_regs.h | 22 ++-
3 files changed, 208 insertions(+), 15 deletions(-)
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -13,6 +13,7 @@
#include <net/dst_metadata.h>
#include <net/page_pool/helpers.h>
#include <net/pkt_cls.h>
+#include <net/tcp.h>
#include <uapi/linux/ppp_defs.h>
#include "airoha_regs.h"
@@ -439,6 +440,41 @@ static void airoha_fe_crsn_qsel_init(str
CDM_CRSN_QSEL_Q1));
}
+static void airoha_fe_lro_init_rx_queue(struct airoha_eth *eth, int qdma_id,
+ int lro_queue_index, int qid,
+ int nbuf, int buf_size)
+{
+ int id = qdma_id + 1;
+
+ airoha_fe_rmw(eth, REG_CDM_LRO_LIMIT(id),
+ CDM_LRO_AGG_NUM_MASK | CDM_LRO_AGG_SIZE_MASK,
+ FIELD_PREP(CDM_LRO_AGG_NUM_MASK, nbuf) |
+ FIELD_PREP(CDM_LRO_AGG_SIZE_MASK, buf_size));
+ airoha_fe_rmw(eth, REG_CDM_LRO_AGE_TIME(id),
+ CDM_LRO_AGE_TIME_MASK | CDM_LRO_AGG_TIME_MASK,
+ FIELD_PREP(CDM_LRO_AGE_TIME_MASK,
+ AIROHA_RXQ_LRO_MAX_AGE_TIME) |
+ FIELD_PREP(CDM_LRO_AGG_TIME_MASK,
+ AIROHA_RXQ_LRO_MAX_AGG_TIME));
+ airoha_fe_rmw(eth, REG_CDM_LRO_RXQ(id, lro_queue_index),
+ LRO_RXQ_MASK(lro_queue_index),
+ __field_prep(LRO_RXQ_MASK(lro_queue_index), qid));
+ airoha_fe_set(eth, REG_CDM_LRO_EN(id), BIT(lro_queue_index));
+}
+
+static void airoha_fe_lro_disable(struct airoha_eth *eth, int qdma_id)
+{
+ int i, id = qdma_id + 1;
+
+ airoha_fe_clear(eth, REG_CDM_LRO_LIMIT(id),
+ CDM_LRO_AGG_NUM_MASK | CDM_LRO_AGG_SIZE_MASK);
+ airoha_fe_clear(eth, REG_CDM_LRO_AGE_TIME(id),
+ CDM_LRO_AGE_TIME_MASK | CDM_LRO_AGG_TIME_MASK);
+ airoha_fe_clear(eth, REG_CDM_LRO_EN(id), LRO_RXQ_EN_MASK);
+ for (i = 0; i < AIROHA_MAX_NUM_LRO_QUEUES; i++)
+ airoha_fe_clear(eth, REG_CDM_LRO_RXQ(id, i), LRO_RXQ_MASK(i));
+}
+
static int airoha_fe_init(struct airoha_eth *eth)
{
airoha_fe_maccr_init(eth);
@@ -603,9 +639,78 @@ static int airoha_qdma_get_gdm_port(stru
return port >= ARRAY_SIZE(eth->ports) ? -EINVAL : port;
}
+static int airoha_qdma_lro_rx_process(struct airoha_queue *q,
+ struct airoha_qdma_desc *desc)
+{
+ u32 msg1 = le32_to_cpu(READ_ONCE(desc->msg1));
+ u32 msg2 = le32_to_cpu(READ_ONCE(desc->msg2));
+ u32 msg3 = le32_to_cpu(READ_ONCE(desc->msg3));
+ bool ipv4 = FIELD_GET(QDMA_ETH_RXMSG_IP4_MASK, msg1);
+ bool ipv6 = FIELD_GET(QDMA_ETH_RXMSG_IP6_MASK, msg1);
+ struct sk_buff *skb = q->skb;
+ u32 th_off, tcp_ack_seq;
+ u16 tcp_win, l2_len;
+ struct tcphdr *th;
+
+ if (FIELD_GET(QDMA_ETH_RXMSG_AGG_COUNT_MASK, msg2) <= 1)
+ return 0;
+
+ if (!ipv4 && !ipv6)
+ return -EOPNOTSUPP;
+
+ l2_len = FIELD_GET(QDMA_ETH_RXMSG_L2_LEN_MASK, msg2);
+ if (ipv4) {
+ u16 agg_len = FIELD_GET(QDMA_ETH_RXMSG_AGG_LEN_MASK, msg3);
+ struct iphdr *iph = (struct iphdr *)(skb->data + l2_len);
+
+ if (iph->protocol != IPPROTO_TCP)
+ return -EOPNOTSUPP;
+
+ iph->tot_len = cpu_to_be16(agg_len);
+ iph->check = 0;
+ iph->check = ip_fast_csum((void *)iph, iph->ihl);
+ th_off = l2_len + (iph->ihl << 2);
+ } else {
+ struct ipv6hdr *ip6h = (struct ipv6hdr *)(skb->data + l2_len);
+ u32 len, desc_ctrl = le32_to_cpu(READ_ONCE(desc->ctrl));
+
+ if (ip6h->nexthdr != NEXTHDR_TCP)
+ return -EOPNOTSUPP;
+
+ len = FIELD_GET(QDMA_DESC_LEN_MASK, desc_ctrl);
+ ip6h->payload_len = cpu_to_be16(len - l2_len - sizeof(*ip6h));
+ th_off = l2_len + sizeof(*ip6h);
+ }
+
+ tcp_win = FIELD_GET(QDMA_ETH_RXMSG_TCP_WIN_MASK, msg3);
+ tcp_ack_seq = le32_to_cpu(READ_ONCE(desc->data));
+
+ th = (struct tcphdr *)(skb->data + th_off);
+ th->ack_seq = cpu_to_be32(tcp_ack_seq);
+ th->window = cpu_to_be16(tcp_win);
+
+ /* Check tcp timestamp option */
+ if (th->doff == (sizeof(*th) + TCPOLEN_TSTAMP_ALIGNED) / 4) {
+ __be32 *topt = (__be32 *)(th + 1);
+
+ if (*topt == cpu_to_be32((TCPOPT_NOP << 24) |
+ (TCPOPT_NOP << 16) |
+ (TCPOPT_TIMESTAMP << 8) |
+ TCPOLEN_TIMESTAMP)) {
+ __le32 tcp_ts_reply = READ_ONCE(desc->tcp_ts_reply);
+
+ put_unaligned_be32(le32_to_cpu(tcp_ts_reply),
+ topt + 2);
+ }
+ }
+
+ return 0;
+}
+
static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
{
enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool);
+ bool lro_q = airoha_qdma_is_lro_queue(q);
struct airoha_qdma *qdma = q->qdma;
struct airoha_eth *eth = qdma->eth;
int qid = q - &qdma->q_rx[0];
@@ -652,9 +757,14 @@ static int airoha_qdma_rx_process(struct
__skb_put(q->skb, len);
skb_mark_for_recycle(q->skb);
q->skb->dev = port->dev;
- q->skb->protocol = eth_type_trans(q->skb, port->dev);
q->skb->ip_summed = CHECKSUM_UNNECESSARY;
skb_record_rx_queue(q->skb, qid);
+
+ if (lro_q && (port->dev->features & NETIF_F_LRO) &&
+ airoha_qdma_lro_rx_process(q, desc) < 0)
+ goto free_frag;
+
+ q->skb->protocol = eth_type_trans(q->skb, port->dev);
} else { /* scattered frame */
struct skb_shared_info *shinfo = skb_shinfo(q->skb);
int nr_frags = shinfo->nr_frags;
@@ -743,23 +853,19 @@ static int airoha_qdma_rx_napi_poll(stru
static int airoha_qdma_init_rx_queue(struct airoha_queue *q,
struct airoha_qdma *qdma, int ndesc)
{
- const struct page_pool_params pp_params = {
- .order = 0,
- .pool_size = 256,
+ struct page_pool_params pp_params = {
.flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV,
.dma_dir = DMA_FROM_DEVICE,
- .max_len = PAGE_SIZE,
.nid = NUMA_NO_NODE,
.dev = qdma->eth->dev,
.napi = &q->napi,
};
+ int pp_order, qid = q - &qdma->q_rx[0], thr;
struct airoha_eth *eth = qdma->eth;
- int qid = q - &qdma->q_rx[0], thr;
dma_addr_t dma_addr;
+ bool lro_q;
- q->buf_size = PAGE_SIZE / 2;
q->qdma = qdma;
-
q->entry = devm_kzalloc(eth->dev, ndesc * sizeof(*q->entry),
GFP_KERNEL);
if (!q->entry)
@@ -770,6 +876,12 @@ static int airoha_qdma_init_rx_queue(str
if (!q->desc)
return -ENOMEM;
+ lro_q = airoha_qdma_is_lro_queue(q);
+ pp_order = lro_q ? AIROHA_LRO_PAGE_ORDER : 0;
+ pp_params.order = pp_order;
+ pp_params.pool_size = 256 >> pp_order;
+ pp_params.max_len = PAGE_SIZE << pp_order;
+
q->page_pool = page_pool_create(&pp_params);
if (IS_ERR(q->page_pool)) {
int err = PTR_ERR(q->page_pool);
@@ -778,6 +890,7 @@ static int airoha_qdma_init_rx_queue(str
return err;
}
+ q->buf_size = pp_params.max_len / (2 * (1 + lro_q));
q->ndesc = ndesc;
netif_napi_add(eth->napi_dev, &q->napi, airoha_qdma_rx_napi_poll);
@@ -2032,6 +2145,45 @@ int airoha_get_fe_port(struct airoha_gdm
}
}
+static int airoha_dev_set_features(struct net_device *dev,
+ netdev_features_t features)
+{
+
+ netdev_features_t diff = dev->features ^ features;
+ struct airoha_gdm_port *port = netdev_priv(dev);
+ struct airoha_qdma *qdma = port->qdma;
+ struct airoha_eth *eth = qdma->eth;
+ int qdma_id = qdma - &eth->qdma[0];
+
+ if (!(diff & NETIF_F_LRO))
+ return 0;
+
+ /* reset LRO configuration */
+ if (features & NETIF_F_LRO) {
+ int i, lro_queue_index = 0;
+
+ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
+ struct airoha_queue *q = &qdma->q_rx[i];
+
+ if (!q->ndesc)
+ continue;
+
+ if (!airoha_qdma_is_lro_queue(q))
+ continue;
+
+ airoha_fe_lro_init_rx_queue(eth, qdma_id,
+ lro_queue_index, i,
+ q->page_pool->p.pool_size,
+ q->buf_size);
+ lro_queue_index++;
+ }
+ } else {
+ airoha_fe_lro_disable(eth, qdma_id);
+ }
+
+ return 0;
+}
+
static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
struct net_device *dev)
{
@@ -2931,6 +3083,7 @@ static const struct net_device_ops airoh
.ndo_stop = airoha_dev_stop,
.ndo_change_mtu = airoha_dev_change_mtu,
.ndo_select_queue = airoha_dev_select_queue,
+ .ndo_set_features = airoha_dev_set_features,
.ndo_start_xmit = airoha_dev_xmit,
.ndo_get_stats64 = airoha_dev_get_stats64,
.ndo_set_mac_address = airoha_dev_set_macaddr,
@@ -3153,12 +3306,9 @@ static int airoha_alloc_gdm_port(struct
dev->ethtool_ops = &airoha_ethtool_ops;
dev->max_mtu = AIROHA_MAX_MTU;
dev->watchdog_timeo = 5 * HZ;
- dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
- NETIF_F_TSO6 | NETIF_F_IPV6_CSUM |
- NETIF_F_SG | NETIF_F_TSO |
- NETIF_F_HW_TC;
- dev->features |= dev->hw_features;
- dev->vlan_features = dev->hw_features;
+ dev->hw_features = AIROHA_HW_FEATURES | NETIF_F_LRO;
+ dev->features |= AIROHA_HW_FEATURES;
+ dev->vlan_features = AIROHA_HW_FEATURES;
dev->dev.of_node = np;
SET_NETDEV_DEV(dev, eth->dev);
--- a/drivers/net/ethernet/airoha/airoha_eth.h
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
@@ -43,6 +43,17 @@
(_n) == 15 ? 128 : \
(_n) == 0 ? 1024 : 16)
+#define AIROHA_LRO_PAGE_ORDER 2
+#define AIROHA_MAX_NUM_LRO_QUEUES 8
+#define AIROHA_RXQ_LRO_EN_MASK 0xff000
+#define AIROHA_RXQ_LRO_MAX_AGG_TIME 100
+#define AIROHA_RXQ_LRO_MAX_AGE_TIME 2000 /* 1ms */
+
+#define AIROHA_HW_FEATURES \
+ (NETIF_F_IP_CSUM | NETIF_F_RXCSUM | \
+ NETIF_F_TSO6 | NETIF_F_IPV6_CSUM | \
+ NETIF_F_SG | NETIF_F_TSO | NETIF_F_HW_TC)
+
#define PSE_RSV_PAGES 128
#define PSE_QUEUE_RSV_PAGES 64
@@ -666,6 +677,18 @@ static inline bool airoha_is_7583(struct
return eth->soc->version == 0x7583;
}
+static inline bool airoha_qdma_is_lro_queue(struct airoha_queue *q)
+{
+ struct airoha_qdma *qdma = q->qdma;
+ int qid = q - &qdma->q_rx[0];
+
+ /* EN7581 SoC supports at most 8 LRO rx queues */
+ BUILD_BUG_ON(hweight32(AIROHA_RXQ_LRO_EN_MASK) >
+ AIROHA_MAX_NUM_LRO_QUEUES);
+
+ return !!(AIROHA_RXQ_LRO_EN_MASK & BIT(qid));
+}
+
int airoha_get_fe_port(struct airoha_gdm_port *port);
bool airoha_is_valid_gdm_port(struct airoha_eth *eth,
struct airoha_gdm_port *port);
--- a/drivers/net/ethernet/airoha/airoha_regs.h
+++ b/drivers/net/ethernet/airoha/airoha_regs.h
@@ -122,6 +122,20 @@
#define CDM_CRSN_QSEL_REASON_MASK(_n) \
GENMASK(4 + (((_n) % 4) << 3), (((_n) % 4) << 3))
+#define REG_CDM_LRO_RXQ(_n, _m) (CDM_BASE(_n) + 0x78 + ((_m) & 0x4))
+#define LRO_RXQ_MASK(_n) GENMASK(4 + (((_n) & 0x3) << 3), ((_n) & 0x3) << 3)
+
+#define REG_CDM_LRO_EN(_n) (CDM_BASE(_n) + 0x80)
+#define LRO_RXQ_EN_MASK GENMASK(7, 0)
+
+#define REG_CDM_LRO_LIMIT(_n) (CDM_BASE(_n) + 0x84)
+#define CDM_LRO_AGG_NUM_MASK GENMASK(23, 16)
+#define CDM_LRO_AGG_SIZE_MASK GENMASK(15, 0)
+
+#define REG_CDM_LRO_AGE_TIME(_n) (CDM_BASE(_n) + 0x88)
+#define CDM_LRO_AGE_TIME_MASK GENMASK(31, 16)
+#define CDM_LRO_AGG_TIME_MASK GENMASK(15, 0)
+
#define REG_GDM_FWD_CFG(_n) GDM_BASE(_n)
#define GDM_PAD_EN_MASK BIT(28)
#define GDM_DROP_CRC_ERR_MASK BIT(23)
@@ -895,9 +909,15 @@
#define QDMA_ETH_RXMSG_SPORT_MASK GENMASK(25, 21)
#define QDMA_ETH_RXMSG_CRSN_MASK GENMASK(20, 16)
#define QDMA_ETH_RXMSG_PPE_ENTRY_MASK GENMASK(15, 0)
+/* RX MSG2 */
+#define QDMA_ETH_RXMSG_AGG_COUNT_MASK GENMASK(31, 24)
+#define QDMA_ETH_RXMSG_L2_LEN_MASK GENMASK(6, 0)
+/* RX MSG3 */
+#define QDMA_ETH_RXMSG_AGG_LEN_MASK GENMASK(31, 16)
+#define QDMA_ETH_RXMSG_TCP_WIN_MASK GENMASK(15, 0)
struct airoha_qdma_desc {
- __le32 rsv;
+ __le32 tcp_ts_reply;
__le32 ctrl;
__le32 addr;
__le32 data;
@@ -2011,10 +2011,10 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.com>
sdhci_dumpregs(host);
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -296,6 +296,7 @@ struct mmc_card {
#define MMC_QUIRK_BROKEN_CACHE_FLUSH (1<<16) /* Don't flush cache until the write has occurred */
@@ -297,6 +297,7 @@ struct mmc_card {
#define MMC_QUIRK_BROKEN_SD_POWEROFF_NOTIFY (1<<17) /* Disable broken SD poweroff notify support */
#define MMC_QUIRK_NO_UHS_DDR50_TUNING (1<<18) /* Disable DDR50 tuning */
#define MMC_QUIRK_FIXED_SECURE_ERASE_TRIM_TIME (1<<20) /* Secure erase/trim time is fixed regardless of size */
+#define MMC_QUIRK_ERASE_BROKEN (1<<31) /* Skip erase */
bool written_flag; /* Indicates eMMC has been written since power on */
@@ -24,7 +24,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.com>
--- a/drivers/video/fbdev/core/fb_defio.c
+++ b/drivers/video/fbdev/core/fb_defio.c
@@ -346,7 +346,8 @@ static void fb_deferred_io_lastclose(str
@@ -444,7 +444,8 @@ static void fb_deferred_io_lastclose(str
{
unsigned long i;
@@ -70,7 +70,7 @@ Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
* @fb_info: frame buffer info structure
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -511,6 +511,7 @@ struct fb_info {
@@ -513,6 +513,7 @@ struct fb_info {
bool skip_vt_switch; /* no VT switch on suspend/resume required */
bool skip_panic; /* Do not write to the fb after a panic */
@@ -78,7 +78,7 @@ Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
};
/* This will go away
@@ -600,6 +601,7 @@ extern ssize_t fb_sys_write(struct fb_in
@@ -602,6 +603,7 @@ extern ssize_t fb_sys_write(struct fb_in
.fb_imageblit = sys_imageblit
/* fbmem.c */
@@ -145,7 +145,7 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -321,6 +321,7 @@ struct mmc_card {
@@ -322,6 +322,7 @@ struct mmc_card {
struct sd_switch_caps sw_caps; /* switch (CMD6) caps */
struct sd_ext_reg ext_power; /* SD extension reg for PM */
struct sd_ext_reg ext_perf; /* SD extension reg for PERF */
@@ -103,7 +103,7 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
--- a/drivers/mmc/core/queue.c
+++ b/drivers/mmc/core/queue.c
@@ -266,6 +266,11 @@ static blk_status_t mmc_mq_queue_rq(stru
@@ -271,6 +271,11 @@ static blk_status_t mmc_mq_queue_rq(stru
spin_unlock_irq(&mq->lock);
return BLK_STS_RESOURCE;
}
@@ -115,7 +115,7 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
break;
default:
/*
@@ -282,6 +287,8 @@ static blk_status_t mmc_mq_queue_rq(stru
@@ -287,6 +292,8 @@ static blk_status_t mmc_mq_queue_rq(stru
/* Parallel dispatch of requests is not supported at the moment */
mq->busy = true;
@@ -124,7 +124,7 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
mq->in_flight[issue_type] += 1;
get_card = (mmc_tot_in_flight(mq) == 1);
cqe_retune_ok = (mmc_cqe_qcnt(mq) == 1);
@@ -321,6 +328,8 @@ static blk_status_t mmc_mq_queue_rq(stru
@@ -326,6 +333,8 @@ static blk_status_t mmc_mq_queue_rq(stru
bool put_card = false;
spin_lock_irq(&mq->lock);
@@ -171,7 +171,7 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -344,6 +344,8 @@ struct mmc_card {
@@ -345,6 +345,8 @@ struct mmc_card {
unsigned int nr_parts;
struct workqueue_struct *complete_wq; /* Private workqueue */
@@ -15,9 +15,9 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
--- a/drivers/mmc/core/quirks.h
+++ b/drivers/mmc/core/quirks.h
@@ -181,6 +181,15 @@ static const struct mmc_fixup __maybe_un
MMC_FIXUP("M62704", CID_MANFID_KINGSTON, 0x0100, add_quirk_mmc,
MMC_QUIRK_TRIM_BROKEN),
@@ -190,6 +190,15 @@ static const struct mmc_fixup __maybe_un
MMC_FIXUP("IB2932", CID_MANFID_KINGSTON, 0x0100, add_quirk_mmc,
MMC_QUIRK_FIXED_SECURE_ERASE_TRIM_TIME),
+ /*
+ * Larger Integral SD cards using rebranded Phison controllers trash
@@ -22,8 +22,8 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
--- a/drivers/mmc/core/card.h
+++ b/drivers/mmc/core/card.h
@@ -301,4 +301,9 @@ static inline int mmc_card_no_uhs_ddr50_
return c->quirks & MMC_QUIRK_NO_UHS_DDR50_TUNING;
@@ -306,4 +306,9 @@ static inline int mmc_card_fixed_secure_
return c->quirks & MMC_QUIRK_FIXED_SECURE_ERASE_TRIM_TIME;
}
+static inline int mmc_card_working_sd_cq(const struct mmc_card *c)
@@ -47,11 +47,11 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
/*
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -296,6 +296,7 @@ struct mmc_card {
#define MMC_QUIRK_BROKEN_CACHE_FLUSH (1<<16) /* Don't flush cache until the write has occurred */
#define MMC_QUIRK_BROKEN_SD_POWEROFF_NOTIFY (1<<17) /* Disable broken SD poweroff notify support */
@@ -298,6 +298,7 @@ struct mmc_card {
#define MMC_QUIRK_NO_UHS_DDR50_TUNING (1<<18) /* Disable DDR50 tuning */
+#define MMC_QUIRK_WORKING_SD_CQ (1<<30) /* SD card has known-good CQ implementation */
#define MMC_QUIRK_FIXED_SECURE_ERASE_TRIM_TIME (1<<20) /* Secure erase/trim time is fixed regardless of size */
#define MMC_QUIRK_ERASE_BROKEN (1<<31) /* Skip erase */
+#define MMC_QUIRK_WORKING_SD_CQ (1<<30) /* SD card has known-good CQ implementation */
bool written_flag; /* Indicates eMMC has been written since power on */
bool reenable_cmdq; /* Re-enable Command Queue */
@@ -19,7 +19,7 @@ Signed-off-by: Jens Axboe <axboe@kernel.dk>
--- a/block/blk.h
+++ b/block/blk.h
@@ -593,6 +593,7 @@ void blk_free_ext_minor(unsigned int min
@@ -595,6 +595,7 @@ void blk_free_ext_minor(unsigned int min
#define ADDPART_FLAG_NONE 0
#define ADDPART_FLAG_RAID 1
#define ADDPART_FLAG_WHOLEDISK 2
@@ -0,0 +1,30 @@
From 86f6dc05ea051fa03ebc03174bc00f734593465d Mon Sep 17 00:00:00 2001
From: Javier Achirica <jachirica@gmail.com>
Date: Fri, 3 Apr 2026 12:30:03 +0200
Subject: bus: mhi: host: pci_generic: Round up nr_irqs to power of two
When an MHI device uses standard MSI, the PCI core requires the allocated
number of vectors to be a strict power of two. But devices will only ask
for the irqs they need, so they might not be properly aligned.
Make sure a power-of-2 number of vectors is requested.
Signed-off-by: Javier Achirica <jachirica@gmail.com>
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
Link: https://patch.msgid.link/CACixm21q7b_diEx5COZxVZm9EhZ0hnakM_WBjEWcCsznfWeniw@mail.gmail.com
---
drivers/bus/mhi/host/pci_generic.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/bus/mhi/host/pci_generic.c
+++ b/drivers/bus/mhi/host/pci_generic.c
@@ -1014,7 +1014,8 @@ static int mhi_pci_get_irqs(struct mhi_c
*/
mhi_cntrl->nr_irqs = 1 + mhi_cntrl_config->num_events;
- nr_vectors = pci_alloc_irq_vectors(pdev, 1, mhi_cntrl->nr_irqs, PCI_IRQ_MSI);
+ nr_vectors = pci_alloc_irq_vectors(pdev, 1, roundup_pow_of_two(mhi_cntrl->nr_irqs),
+ PCI_IRQ_MSI);
if (nr_vectors < 0) {
dev_err(&pdev->dev, "Error allocating MSI vectors %d\n",
nr_vectors);
@@ -23,7 +23,7 @@ Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
}, {
.alg = "authenc(hmac(sha1),rfc3686(ctr(aes)))",
- .test = alg_test_null,
+ .generic_driver = "authenc(hmac-sha1-lib,rfc3686(ctr(aes-lib)))",
+ .generic_driver = "authenc(hmac-sha1-lib,rfc3686(ctr(aes-generic)))",
+ .test = alg_test_aead,
.fips_allowed = 1,
+ .suite = {
@@ -23,7 +23,7 @@ Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
}, {
.alg = "authenc(hmac(sha224),rfc3686(ctr(aes)))",
- .test = alg_test_null,
+ .generic_driver = "authenc(hmac-sha224-lib,rfc3686(ctr(aes-lib)))",
+ .generic_driver = "authenc(hmac-sha224-lib,rfc3686(ctr(aes-generic)))",
+ .test = alg_test_aead,
.fips_allowed = 1,
+ .suite = {
@@ -23,7 +23,7 @@ Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
}, {
.alg = "authenc(hmac(sha256),rfc3686(ctr(aes)))",
- .test = alg_test_null,
+ .generic_driver = "authenc(hmac-sha256-lib,rfc3686(ctr(aes-lib)))",
+ .generic_driver = "authenc(hmac-sha256-lib,rfc3686(ctr(aes-generic)))",
+ .test = alg_test_aead,
.fips_allowed = 1,
+ .suite = {
@@ -23,7 +23,7 @@ Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
}, {
.alg = "authenc(hmac(sha384),rfc3686(ctr(aes)))",
- .test = alg_test_null,
+ .generic_driver = "authenc(hmac-sha384-lib,rfc3686(ctr(aes-lib)))",
+ .generic_driver = "authenc(hmac-sha384-lib,rfc3686(ctr(aes-generic)))",
+ .test = alg_test_aead,
.fips_allowed = 1,
+ .suite = {
@@ -23,7 +23,7 @@ Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
}, {
.alg = "authenc(hmac(sha512),rfc3686(ctr(aes)))",
- .test = alg_test_null,
+ .generic_driver = "authenc(hmac-sha512-lib,rfc3686(ctr(aes-lib)))",
+ .generic_driver = "authenc(hmac-sha512-lib,rfc3686(ctr(aes-generic)))",
+ .test = alg_test_aead,
.fips_allowed = 1,
+ .suite = {
@@ -23,7 +23,7 @@ Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
}
}, {
+ .alg = "authenc(hmac(md5),rfc3686(ctr(aes)))",
+ .generic_driver = "authenc(hmac-md5-lib,rfc3686(ctr(aes-lib)))",
+ .generic_driver = "authenc(hmac-md5-lib,rfc3686(ctr(aes-generic)))",
+ .test = alg_test_aead,
+ .suite = {
+ .aead = __VECS(hmac_md5_aes_ctr_rfc3686_tv_temp)
@@ -23,7 +23,7 @@ Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
}
}, {
+ .alg = "authenc(hmac(md5),cbc(aes))",
+ .generic_driver = "authenc(hmac-md5-lib,cbc(aes-lib))",
+ .generic_driver = "authenc(hmac-md5-lib,cbc(aes-generic))",
+ .test = alg_test_aead,
+ .suite = {
+ .aead = __VECS(hmac_md5_aes_cbc_tv_temp)
@@ -0,0 +1,36 @@
From 32e76e3757e89f370bf2ac8dba8aeb133071834e Mon Sep 17 00:00:00 2001
From: Saeed Mirzamohammadi <saeed.mirzamohammadi@oracle.com>
Date: Mon, 2 Mar 2026 15:59:14 -0800
Subject: [PATCH] crypto: tcrypt - clamp num_mb to avoid divide-by-zero
Passing num_mb=0 to the multibuffer speed tests leaves test_mb_aead_cycles()
and test_mb_acipher_cycles() dividing by (8 * num_mb). With sec=0 (the
default), the module prints "1 operation in ..." and hits a divide-by-zero
fault.
Force num_mb to at least 1 during module init and warn the caller so the
warm-up loop and the final report stay well-defined.
To reproduce:
sudo modprobe tcrypt mode=600 num_mb=0
Signed-off-by: Saeed Mirzamohammadi <saeed.mirzamohammadi@oracle.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
crypto/tcrypt.c | 5 +++++
1 file changed, 5 insertions(+)
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -2832,6 +2832,11 @@ static int __init tcrypt_mod_init(void)
goto err_free_tv;
}
+ if (!num_mb) {
+ pr_warn("num_mb must be at least 1; forcing to 1\n");
+ num_mb = 1;
+ }
+
err = do_test(alg, type, mask, mode, num_mb);
if (err) {
@@ -0,0 +1,36 @@
From 03170b8f84354f1649a757e57c2130e1de237f5d Mon Sep 17 00:00:00 2001
From: Saeed Mirzamohammadi <saeed.mirzamohammadi@oracle.com>
Date: Mon, 2 Mar 2026 16:06:40 -0800
Subject: [PATCH] crypto: tcrypt - stop ahash speed tests when setkey fails
The async hash speed path ignores the return code from
crypto_ahash_setkey(). If the caller picks an unsupported key length,
the transform keeps whatever key state it already has and the speed test
still runs, producing misleading numbers, hence bail out of the loop when
setkey fails.
Signed-off-by: Saeed Mirzamohammadi <saeed.mirzamohammadi@oracle.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
crypto/tcrypt.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -911,8 +911,14 @@ static void test_ahash_speed_common(cons
break;
}
- if (klen)
- crypto_ahash_setkey(tfm, tvmem[0], klen);
+ if (klen) {
+ ret = crypto_ahash_setkey(tfm, tvmem[0], klen);
+ if (ret) {
+ pr_err("setkey() failed flags=%x: %d\n",
+ crypto_ahash_get_flags(tfm), ret);
+ break;
+ }
+ }
pr_info("test%3u "
"(%5u byte blocks,%5u bytes per update,%4u updates): ",
@@ -0,0 +1,30 @@
From 86f6dc05ea051fa03ebc03174bc00f734593465d Mon Sep 17 00:00:00 2001
From: Javier Achirica <jachirica@gmail.com>
Date: Fri, 3 Apr 2026 12:30:03 +0200
Subject: bus: mhi: host: pci_generic: Round up nr_irqs to power of two
When an MHI device uses standard MSI, the PCI core requires the allocated
number of vectors to be a strict power of two. But devices will only ask
for the irqs they need, so they might not be properly aligned.
Make sure a power-of-2 number of vectors is requested.
Signed-off-by: Javier Achirica <jachirica@gmail.com>
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
Link: https://patch.msgid.link/CACixm21q7b_diEx5COZxVZm9EhZ0hnakM_WBjEWcCsznfWeniw@mail.gmail.com
---
drivers/bus/mhi/host/pci_generic.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/bus/mhi/host/pci_generic.c
+++ b/drivers/bus/mhi/host/pci_generic.c
@@ -1139,7 +1139,8 @@ static int mhi_pci_get_irqs(struct mhi_c
*/
mhi_cntrl->nr_irqs = 1 + mhi_cntrl_config->num_events;
- nr_vectors = pci_alloc_irq_vectors(pdev, 1, mhi_cntrl->nr_irqs, PCI_IRQ_MSIX | PCI_IRQ_MSI);
+ nr_vectors = pci_alloc_irq_vectors(pdev, 1, roundup_pow_of_two(mhi_cntrl->nr_irqs),
+ PCI_IRQ_MSIX | PCI_IRQ_MSI);
if (nr_vectors < 0) {
dev_err(&pdev->dev, "Error allocating MSI vectors %d\n",
nr_vectors);
@@ -23,7 +23,7 @@ Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
}, {
.alg = "authenc(hmac(sha1),rfc3686(ctr(aes)))",
- .test = alg_test_null,
+ .generic_driver = "authenc(hmac-sha1-lib,rfc3686(ctr(aes-lib)))",
+ .generic_driver = "authenc(hmac-sha1-lib,rfc3686(ctr(aes-generic)))",
+ .test = alg_test_aead,
.fips_allowed = 1,
+ .suite = {
@@ -23,7 +23,7 @@ Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
}, {
.alg = "authenc(hmac(sha224),rfc3686(ctr(aes)))",
- .test = alg_test_null,
+ .generic_driver = "authenc(hmac-sha224-lib,rfc3686(ctr(aes-lib)))",
+ .generic_driver = "authenc(hmac-sha224-lib,rfc3686(ctr(aes-generic)))",
+ .test = alg_test_aead,
.fips_allowed = 1,
+ .suite = {
@@ -23,7 +23,7 @@ Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
}, {
.alg = "authenc(hmac(sha256),rfc3686(ctr(aes)))",
- .test = alg_test_null,
+ .generic_driver = "authenc(hmac-sha256-lib,rfc3686(ctr(aes-lib)))",
+ .generic_driver = "authenc(hmac-sha256-lib,rfc3686(ctr(aes-generic)))",
+ .test = alg_test_aead,
.fips_allowed = 1,
+ .suite = {
@@ -23,7 +23,7 @@ Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
}, {
.alg = "authenc(hmac(sha384),rfc3686(ctr(aes)))",
- .test = alg_test_null,
+ .generic_driver = "authenc(hmac-sha384-lib,rfc3686(ctr(aes-lib)))",
+ .generic_driver = "authenc(hmac-sha384-lib,rfc3686(ctr(aes-generic)))",
+ .test = alg_test_aead,
.fips_allowed = 1,
+ .suite = {
@@ -23,7 +23,7 @@ Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
}, {
.alg = "authenc(hmac(sha512),rfc3686(ctr(aes)))",
- .test = alg_test_null,
+ .generic_driver = "authenc(hmac-sha512-lib,rfc3686(ctr(aes-lib)))",
+ .generic_driver = "authenc(hmac-sha512-lib,rfc3686(ctr(aes-generic)))",
+ .test = alg_test_aead,
.fips_allowed = 1,
+ .suite = {
@@ -23,7 +23,7 @@ Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
}
}, {
+ .alg = "authenc(hmac(md5),rfc3686(ctr(aes)))",
+ .generic_driver = "authenc(hmac-md5-lib,rfc3686(ctr(aes-lib)))",
+ .generic_driver = "authenc(hmac-md5-lib,rfc3686(ctr(aes-generic)))",
+ .test = alg_test_aead,
+ .suite = {
+ .aead = __VECS(hmac_md5_aes_ctr_rfc3686_tv_temp)
@@ -1,6 +1,6 @@
From dd227f442774a570ffccdfbc9536fec3b4666305 Mon Sep 17 00:00:00 2001
From c8aadd63ab58ee75713ab487730563e7a160cc35 Mon Sep 17 00:00:00 2001
From: Aleksander Jan Bajkowski <olek2@wp.pl>
Date: Sat, 31 Jan 2026 12:35:30 +0100
Date: Tue, 3 Mar 2026 19:48:44 +0100
Subject: [PATCH] crypto: testmgr - Add test vectors for
authenc(hmac(md5),cbc(aes))
@@ -10,6 +10,7 @@ script. Then, the results were double-checked on Mediatek MT7981 (safexcel)
and NXP P2020 (talitos). Both platforms pass self-tests.
Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
crypto/testmgr.c | 7 ++
crypto/testmgr.h | 255 +++++++++++++++++++++++++++++++++++++++++++++++
@@ -0,0 +1,36 @@
From 32e76e3757e89f370bf2ac8dba8aeb133071834e Mon Sep 17 00:00:00 2001
From: Saeed Mirzamohammadi <saeed.mirzamohammadi@oracle.com>
Date: Mon, 2 Mar 2026 15:59:14 -0800
Subject: [PATCH] crypto: tcrypt - clamp num_mb to avoid divide-by-zero
Passing num_mb=0 to the multibuffer speed tests leaves test_mb_aead_cycles()
and test_mb_acipher_cycles() dividing by (8 * num_mb). With sec=0 (the
default), the module prints "1 operation in ..." and hits a divide-by-zero
fault.
Force num_mb to at least 1 during module init and warn the caller so the
warm-up loop and the final report stay well-defined.
To reproduce:
sudo modprobe tcrypt mode=600 num_mb=0
Signed-off-by: Saeed Mirzamohammadi <saeed.mirzamohammadi@oracle.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
crypto/tcrypt.c | 5 +++++
1 file changed, 5 insertions(+)
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -2820,6 +2820,11 @@ static int __init tcrypt_mod_init(void)
goto err_free_tv;
}
+ if (!num_mb) {
+ pr_warn("num_mb must be at least 1; forcing to 1\n");
+ num_mb = 1;
+ }
+
err = do_test(alg, type, mask, mode, num_mb);
if (err) {
@@ -0,0 +1,36 @@
From 03170b8f84354f1649a757e57c2130e1de237f5d Mon Sep 17 00:00:00 2001
From: Saeed Mirzamohammadi <saeed.mirzamohammadi@oracle.com>
Date: Mon, 2 Mar 2026 16:06:40 -0800
Subject: [PATCH] crypto: tcrypt - stop ahash speed tests when setkey fails
The async hash speed path ignores the return code from
crypto_ahash_setkey(). If the caller picks an unsupported key length,
the transform keeps whatever key state it already has and the speed test
still runs, producing misleading numbers, hence bail out of the loop when
setkey fails.
Signed-off-by: Saeed Mirzamohammadi <saeed.mirzamohammadi@oracle.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
crypto/tcrypt.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -911,8 +911,14 @@ static void test_ahash_speed_common(cons
break;
}
- if (klen)
- crypto_ahash_setkey(tfm, tvmem[0], klen);
+ if (klen) {
+ ret = crypto_ahash_setkey(tfm, tvmem[0], klen);
+ if (ret) {
+ pr_err("setkey() failed flags=%x: %d\n",
+ crypto_ahash_get_flags(tfm), ret);
+ break;
+ }
+ }
pr_info("test%3u "
"(%5u byte blocks,%5u bytes per update,%4u updates): ",
+1
View File
@@ -1864,6 +1864,7 @@ CONFIG_DVB_MAX_ADAPTERS=16
# CONFIG_DWMAC_LPC18XX is not set
# CONFIG_DWMAC_MESON is not set
# CONFIG_DWMAC_MOTORCOMM is not set
# CONFIG_DWMAC_QCOM_ETHQOS is not set
# CONFIG_DWMAC_ROCKCHIP is not set
# CONFIG_DWMAC_SOCFPGA is not set
# CONFIG_DWMAC_STI is not set
+1
View File
@@ -1951,6 +1951,7 @@ CONFIG_DVB_MAX_ADAPTERS=16
# CONFIG_DWMAC_LPC18XX is not set
# CONFIG_DWMAC_MESON is not set
# CONFIG_DWMAC_MOTORCOMM is not set
# CONFIG_DWMAC_QCOM_ETHQOS is not set
# CONFIG_DWMAC_ROCKCHIP is not set
# CONFIG_DWMAC_SOCFPGA is not set
# CONFIG_DWMAC_STI is not set
@@ -15,9 +15,9 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
#include "gpiolib.h"
#include "gpiolib-of.h"
@@ -1198,3 +1200,73 @@ void of_gpiochip_remove(struct gpio_chip
{
of_node_put(dev_of_node(&chip->gpiodev->dev));
@@ -1205,3 +1207,73 @@ void of_gpiochip_remove(struct gpio_chip
of_node_put(np);
}
+
+#ifdef CONFIG_GPIO_SYSFS
@@ -15,7 +15,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
#include "gpiolib.h"
#include "gpiolib-of.h"
@@ -1295,3 +1297,73 @@ bool of_gpiochip_instance_match(struct g
@@ -1302,3 +1304,73 @@ bool of_gpiochip_instance_match(struct g
return false;
}
+2 -2
View File
@@ -1,2 +1,2 @@
LINUX_VERSION-6.12 = .87
LINUX_KERNEL_HASH-6.12.87 = cc12a7644b4cef9e06627b29de8753e22b3d076703a9b52be84263e05c8b9830
LINUX_VERSION-6.12 = .89
LINUX_KERNEL_HASH-6.12.89 = 585afd804a9d2853a353dba5e3ac05627a8186cb1274668f151c0b10250799a0
+2 -2
View File
@@ -1,2 +1,2 @@
LINUX_VERSION-6.18 = .28
LINUX_KERNEL_HASH-6.18.28 = f360789483586cf8a20b4ab2bffe76ead6b62c0db1eeb0d917294456c4d77b74
LINUX_VERSION-6.18 = .31
LINUX_KERNEL_HASH-6.18.31 = a0a0b86d485d409cfcc6be3fe85cdf23b8a5996b78d7a232c0e03d2a8bf258b6
@@ -161,7 +161,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
struct rtnl_link {
rtnl_doit_func doit;
@@ -5012,7 +5012,9 @@ int ndo_dflt_bridge_getlink(struct sk_bu
@@ -5013,7 +5013,9 @@ int ndo_dflt_bridge_getlink(struct sk_bu
brport_nla_put_flag(skb, flags, mask,
IFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD) ||
brport_nla_put_flag(skb, flags, mask,
@@ -202,7 +202,8 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+ */
+ } else if (test_bit(state->interface, pl->config->pcs_interfaces)) {
+ bool pcs_found = false;
+
- pcs_changed = pl->pcs != pcs;
+ list_for_each_entry(pcs, &pl->pcs_list, list) {
+ if (!phylink_validate_pcs_interface(pcs,
+ state->interface)) {
@@ -215,8 +216,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+ phylink_err(pl,
+ "couldn't find a PCS for %s\n",
+ phy_modes(state->interface));
- pcs_changed = pl->pcs != pcs;
+
+ pl->major_config_failed = true;
+ return;
+ }
@@ -245,28 +245,70 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
pl->pcs = pcs;
}
@@ -1931,8 +2006,9 @@ struct phylink *phylink_create(struct ph
@@ -1909,6 +1984,44 @@ int phylink_set_fixed_link(struct phylin
}
EXPORT_SYMBOL_GPL(phylink_set_fixed_link);
+static int phylink_fill_available_pcs(struct phylink *pl,
+ struct phylink_config *config)
+{
+ struct phylink_pcs **pcss;
+ int i, ret;
+
+ if (!config->num_available_pcs)
+ return 0;
+
+ if (!config->fill_available_pcs) {
+ dev_err(config->dev,
+ "phylink: error: num_available_pcs defined but no fill_available_pcs\n");
+ return -EINVAL;
+ }
+
+ pcss = kcalloc(config->num_available_pcs, sizeof(*pcss), GFP_KERNEL);
+ if (!pcss)
+ return -ENOMEM;
+
+ ret = config->fill_available_pcs(config, pcss, config->num_available_pcs);
+ if (ret)
+ goto out;
+
+ for (i = 0; i < config->num_available_pcs; i++) {
+ struct phylink_pcs *pcs = pcss[i];
+
+ if (!pcs)
+ continue;
+
+ list_add(&pcs->list, &pl->pcs_list);
+ }
+
+out:
+ kfree(pcss);
+
+ return ret;
+}
+
/**
* phylink_create() - create a phylink instance
* @config: a pointer to the target &struct phylink_config
@@ -1931,6 +2044,7 @@ struct phylink *phylink_create(struct ph
const struct phylink_mac_ops *mac_ops)
{
bool using_mac_select_pcs = false;
+ struct phylink_pcs *pcs;
struct phylink *pl;
- int ret;
+ int i, ret;
int ret;
/* Validate the supplied configuration */
if (phy_interface_empty(config->supported_interfaces)) {
@@ -1952,9 +2028,21 @@ struct phylink *phylink_create(struct ph
@@ -1952,9 +2066,21 @@ struct phylink *phylink_create(struct ph
mutex_init(&pl->state_mutex);
INIT_WORK(&pl->resolve, phylink_resolve);
+ INIT_LIST_HEAD(&pl->pcs_list);
+
+ /* Fill the PCS list with available PCS from phylink config */
+ for (i = 0; i < config->num_available_pcs; i++) {
+ pcs = config->available_pcs[i];
+
+ list_add(&pcs->list, &pl->pcs_list);
+ ret = phylink_fill_available_pcs(pl, config);
+ if (ret) {
+ kfree(pl);
+ return ERR_PTR(ret);
+ }
phy_interface_copy(pl->supported_interfaces,
@@ -278,7 +320,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
pl->config = config;
if (config->type == PHYLINK_NETDEV) {
@@ -2024,10 +2112,16 @@ EXPORT_SYMBOL_GPL(phylink_create);
@@ -2024,10 +2150,16 @@ EXPORT_SYMBOL_GPL(phylink_create);
*/
void phylink_destroy(struct phylink *pl)
{
@@ -295,7 +337,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
cancel_work_sync(&pl->resolve);
kfree(pl);
}
@@ -2472,6 +2566,7 @@ static irqreturn_t phylink_link_handler(
@@ -2472,6 +2604,7 @@ static irqreturn_t phylink_link_handler(
*/
void phylink_start(struct phylink *pl)
{
@@ -303,7 +345,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
bool poll = false;
ASSERT_RTNL();
@@ -2498,6 +2593,10 @@ void phylink_start(struct phylink *pl)
@@ -2498,6 +2631,10 @@ void phylink_start(struct phylink *pl)
pl->pcs_state = PCS_STATE_STARTED;
@@ -314,7 +356,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
phylink_enable_and_run_resolve(pl, PHYLINK_DISABLE_STOPPED);
if (pl->cfg_link_an_mode == MLO_AN_FIXED && pl->link_gpio) {
@@ -2542,6 +2641,8 @@ EXPORT_SYMBOL_GPL(phylink_start);
@@ -2542,6 +2679,8 @@ EXPORT_SYMBOL_GPL(phylink_start);
*/
void phylink_stop(struct phylink *pl)
{
@@ -323,7 +365,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
ASSERT_RTNL();
if (pl->sfp_bus)
@@ -2559,6 +2660,14 @@ void phylink_stop(struct phylink *pl)
@@ -2559,6 +2698,14 @@ void phylink_stop(struct phylink *pl)
pl->pcs_state = PCS_STATE_DOWN;
phylink_pcs_disable(pl->pcs);
@@ -340,31 +382,43 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -147,7 +147,11 @@ enum phylink_op_type {
@@ -10,6 +10,7 @@ struct ethtool_cmd;
struct fwnode_handle;
struct net_device;
struct phylink;
+struct phylink_pcs;
enum {
MLO_PAUSE_NONE,
@@ -147,7 +148,13 @@ enum phylink_op_type {
* if MAC link is at %MLO_AN_FIXED mode.
* @supported_interfaces: bitmap describing which PHY_INTERFACE_MODE_xxx
* are supported by the MAC/PCS.
+ * @pcs_interfaces: bitmap describing for which PHY_INTERFACE_MODE_xxx a
+ * dedicated PCS is required.
* @mac_capabilities: MAC pause/speed/duplex capabilities.
+ * @available_pcs: array of available phylink_pcs PCS
+ * @num_available_pcs: num of available phylink_pcs PCS
+ * @fill_available_pcs: callback to fill the available PCS in the passed
+ * array struct of phylink_pcs PCS available_pcs up to
+ * num_available_pcs.
*/
struct phylink_config {
struct device *dev;
@@ -159,7 +163,11 @@ struct phylink_config {
@@ -159,7 +166,13 @@ struct phylink_config {
void (*get_fixed_state)(struct phylink_config *config,
struct phylink_link_state *state);
DECLARE_PHY_INTERFACE_MASK(supported_interfaces);
+ DECLARE_PHY_INTERFACE_MASK(pcs_interfaces);
unsigned long mac_capabilities;
+
+ struct phylink_pcs **available_pcs;
+ unsigned int num_available_pcs;
+ int (*fill_available_pcs)(struct phylink_config *config,
+ struct phylink_pcs **available_pcs,
+ unsigned int num_available_pcs);
};
void phylink_limit_mac_speed(struct phylink_config *config, u32 max_speed);
@@ -417,6 +425,9 @@ struct phylink_pcs {
@@ -417,6 +430,9 @@ struct phylink_pcs {
bool neg_mode;
bool poll;
bool rxc_always_on;
@@ -123,7 +123,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
/* If configuration of the interface failed, force the link down
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -632,6 +632,8 @@ void phylink_disconnect_phy(struct phyli
@@ -637,6 +637,8 @@ void phylink_disconnect_phy(struct phyli
int phylink_set_fixed_link(struct phylink *,
const struct phylink_link_state *);
@@ -110,9 +110,9 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
/* What interface are supported by the current link.
* Can change on removal or addition of new PCS.
@@ -2039,6 +2041,51 @@ int phylink_set_fixed_link(struct phylin
@@ -2077,6 +2079,51 @@ out:
return ret;
}
EXPORT_SYMBOL_GPL(phylink_set_fixed_link);
+static int pcs_provider_notify(struct notifier_block *self,
+ unsigned long val, void *data)
@@ -162,7 +162,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
/**
* phylink_create() - create a phylink instance
* @config: a pointer to the target &struct phylink_config
@@ -2099,6 +2146,11 @@ struct phylink *phylink_create(struct ph
@@ -2137,6 +2184,11 @@ struct phylink *phylink_create(struct ph
pl->supported_interfaces,
pcs->supported_interfaces);
@@ -46,7 +46,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
phylink_info(pl, "Link is Down\n");
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -443,6 +443,7 @@ struct phylink_pcs {
@@ -448,6 +448,7 @@ struct phylink_pcs {
* @pcs_an_restart: restart 802.3z BaseX autonegotiation.
* @pcs_link_up: program the PCS for the resolved link configuration
* (where necessary).
@@ -54,7 +54,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
* @pcs_pre_init: configure PCS components necessary for MAC hardware
* initialization e.g. RX clock for stmmac.
*/
@@ -466,6 +467,7 @@ struct phylink_pcs_ops {
@@ -471,6 +472,7 @@ struct phylink_pcs_ops {
void (*pcs_an_restart)(struct phylink_pcs *pcs);
void (*pcs_link_up)(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface, int speed, int duplex);
@@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- a/Makefile
+++ b/Makefile
@@ -626,7 +626,7 @@ export RUSTC_BOOTSTRAP := 1
@@ -628,7 +628,7 @@ export RUSTC_BOOTSTRAP := 1
# Allows finding `.clippy.toml` in out-of-srctree builds.
export CLIPPY_CONF_DIR := $(srctree)
@@ -161,7 +161,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
struct rtnl_link {
rtnl_doit_func doit;
@@ -5331,7 +5331,9 @@ int ndo_dflt_bridge_getlink(struct sk_bu
@@ -5332,7 +5332,9 @@ int ndo_dflt_bridge_getlink(struct sk_bu
brport_nla_put_flag(skb, flags, mask,
IFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD) ||
brport_nla_put_flag(skb, flags, mask,
@@ -1,20 +1,28 @@
From d134e22b540226a7404cabb88c86a54857486b4f Mon Sep 17 00:00:00 2001
From 2606833af0ba47d4740b004afbcae2ad10f2efb5 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Mon, 31 Mar 2025 16:03:26 +0200
Subject: [PATCH 2/7] net: phylink: introduce internal phylink PCS handling
Subject: [PATCH 1/9] net: phylink: introduce internal phylink PCS handling
Introduce internal handling of PCS for phylink. This is an alternative
to .mac_select_pcs that moves the selection logic of the PCS entirely to
phylink with the usage of supported_interface value in the PCS struct.
way to .mac_select_pcs that moves the selection logic of the PCS entirely
to phylink with the usage of the supported_interface value in the PCS
struct.
MAC should now provide an array of available PCS in phylink_config in
.available_pcs and fill the .num_available_pcs with the number of
elements in the array. MAC should also define a new bitmap,
MAC should now provide a callback to fill the available PCS in
phylink_config in .fill_available_pcs and fill the .num_available_pcs with
the number of elements in the array. MAC should also define a new bitmap,
pcs_interfaces, in phylink_config to define for what interface mode a
dedicated PCS is required.
On phylink_create() this array is parsed and a linked list of PCS is
created based on the PCS passed in phylink_config.
On phylink_create(), an array of PCS pointer is allocated of size
.num_available_pcs from phylink_config and .fill_available_pcs from
phylink_config is called passing as args the just allocated array and
the numer of available element in it.
MAC will fill this passed array with all the available PCS.
This array is then parsed and a linked list of PCS is created based on
the allocated PCS array filled by MAC via .fill_available_pcs().
Also the supported_interface value in phylink struct is updated with the
new supported_interface from the provided PCS.
@@ -26,9 +34,6 @@ On phylink_stop(), every PCS in phylink PCS list is detached from the
phylink instance. This is done by setting the phylink value in
phylink_pcs struct to NULL.
On phylink_stop(), every PCS in phylink PCS list is removed from the
list.
phylink_validate_mac_and_pcs(), phylink_major_config() and
phylink_inband_caps() are updated to support this new implementation
with the PCS list stored in phylink.
@@ -37,14 +42,17 @@ They will make use of phylink_validate_pcs_interface() that will loop
for every PCS in the phylink PCS available list and find one that supports
the passed interface.
phylink_validate_pcs_interface() apply the same logic of .mac_select_pcs
phylink_validate_pcs_interface() applies the same logic of .mac_select_pcs
where if a supported_interface value is not set for the PCS struct, then
it's assumed every interface is supported.
It's required for a MAC that implement either a .mac_select_pcs or make
use of the PCS list implementation. Implementing both will result in a fail
A MAC is required to implement either a .mac_select_pcs or make use of
the PCS list implementation. Implementing both will result in a fail
on MAC/PCS validation.
A MAC defining .num_available_pcs in phylink_config MUST also define a
.fill_available_pcs or phylink_create() will fail with an negative error.
phylink value in phylink_pcs struct with this implementation is used to
track from PCS side when it's attached to a phylink instance. PCS driver
will make use of this information to correctly detach from a phylink
@@ -56,9 +64,9 @@ and remove .mac_select_pcs.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/net/phy/phylink.c | 149 +++++++++++++++++++++++++++++++++-----
include/linux/phylink.h | 11 +++
2 files changed, 141 insertions(+), 19 deletions(-)
drivers/net/phy/phylink.c | 185 ++++++++++++++++++++++++++++++++++----
include/linux/phylink.h | 16 ++++
2 files changed, 183 insertions(+), 18 deletions(-)
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -201,7 +209,8 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+ */
+ } else if (test_bit(state->interface, pl->config->pcs_interfaces)) {
+ bool pcs_found = false;
+
- pcs_changed = pl->pcs != pcs;
+ list_for_each_entry(pcs, &pl->pcs_list, list) {
+ if (!phylink_validate_pcs_interface(pcs,
+ state->interface)) {
@@ -214,8 +223,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+ phylink_err(pl,
+ "couldn't find a PCS for %s\n",
+ phy_modes(state->interface));
- pcs_changed = pl->pcs != pcs;
+
+ pl->major_config_failed = true;
+ return;
+ }
@@ -244,28 +252,70 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
pl->pcs = pcs;
}
@@ -1844,8 +1921,9 @@ struct phylink *phylink_create(struct ph
@@ -1823,6 +1900,44 @@ int phylink_set_fixed_link(struct phylin
}
EXPORT_SYMBOL_GPL(phylink_set_fixed_link);
+static int phylink_fill_available_pcs(struct phylink *pl,
+ struct phylink_config *config)
+{
+ struct phylink_pcs **pcss;
+ int i, ret;
+
+ if (!config->num_available_pcs)
+ return 0;
+
+ if (!config->fill_available_pcs) {
+ dev_err(config->dev,
+ "phylink: error: num_available_pcs defined but no fill_available_pcs\n");
+ return -EINVAL;
+ }
+
+ pcss = kcalloc(config->num_available_pcs, sizeof(*pcss), GFP_KERNEL);
+ if (!pcss)
+ return -ENOMEM;
+
+ ret = config->fill_available_pcs(config, pcss, config->num_available_pcs);
+ if (ret)
+ goto out;
+
+ for (i = 0; i < config->num_available_pcs; i++) {
+ struct phylink_pcs *pcs = pcss[i];
+
+ if (!pcs)
+ continue;
+
+ list_add(&pcs->list, &pl->pcs_list);
+ }
+
+out:
+ kfree(pcss);
+
+ return ret;
+}
+
/**
* phylink_create() - create a phylink instance
* @config: a pointer to the target &struct phylink_config
@@ -1844,6 +1959,7 @@ struct phylink *phylink_create(struct ph
phy_interface_t iface,
const struct phylink_mac_ops *mac_ops)
{
+ struct phylink_pcs *pcs;
struct phylink *pl;
- int ret;
+ int i, ret;
int ret;
/* Validate the supplied configuration */
if (phy_interface_empty(config->supported_interfaces)) {
@@ -1861,9 +1939,21 @@ struct phylink *phylink_create(struct ph
@@ -1861,9 +1977,21 @@ struct phylink *phylink_create(struct ph
mutex_init(&pl->phydev_mutex);
mutex_init(&pl->state_mutex);
INIT_WORK(&pl->resolve, phylink_resolve);
+ INIT_LIST_HEAD(&pl->pcs_list);
+
+ /* Fill the PCS list with available PCS from phylink config */
+ for (i = 0; i < config->num_available_pcs; i++) {
+ pcs = config->available_pcs[i];
+
+ list_add(&pcs->list, &pl->pcs_list);
+ ret = phylink_fill_available_pcs(pl, config);
+ if (ret) {
+ kfree(pl);
+ return ERR_PTR(ret);
+ }
phy_interface_copy(pl->supported_interfaces,
@@ -277,7 +327,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
pl->config = config;
if (config->type == PHYLINK_NETDEV) {
@@ -1942,10 +2032,16 @@ EXPORT_SYMBOL_GPL(phylink_create);
@@ -1942,10 +2070,16 @@ EXPORT_SYMBOL_GPL(phylink_create);
*/
void phylink_destroy(struct phylink *pl)
{
@@ -294,7 +344,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
cancel_work_sync(&pl->resolve);
kfree(pl);
}
@@ -2447,6 +2543,7 @@ static irqreturn_t phylink_link_handler(
@@ -2447,6 +2581,7 @@ static irqreturn_t phylink_link_handler(
*/
void phylink_start(struct phylink *pl)
{
@@ -302,7 +352,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
bool poll = false;
ASSERT_RTNL();
@@ -2473,6 +2570,10 @@ void phylink_start(struct phylink *pl)
@@ -2473,6 +2608,10 @@ void phylink_start(struct phylink *pl)
pl->pcs_state = PCS_STATE_STARTED;
@@ -313,7 +363,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
phylink_enable_and_run_resolve(pl, PHYLINK_DISABLE_STOPPED);
if (pl->cfg_link_an_mode == MLO_AN_FIXED && pl->link_gpio) {
@@ -2517,6 +2618,8 @@ EXPORT_SYMBOL_GPL(phylink_start);
@@ -2517,6 +2656,8 @@ EXPORT_SYMBOL_GPL(phylink_start);
*/
void phylink_stop(struct phylink *pl)
{
@@ -322,7 +372,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
ASSERT_RTNL();
if (pl->sfp_bus)
@@ -2534,6 +2637,14 @@ void phylink_stop(struct phylink *pl)
@@ -2534,6 +2675,14 @@ void phylink_stop(struct phylink *pl)
pl->pcs_state = PCS_STATE_DOWN;
phylink_pcs_disable(pl->pcs);
@@ -339,7 +389,15 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -150,12 +150,16 @@ enum phylink_op_type {
@@ -12,6 +12,7 @@ struct ethtool_cmd;
struct fwnode_handle;
struct net_device;
struct phylink;
+struct phylink_pcs;
enum {
MLO_PAUSE_NONE,
@@ -150,12 +151,18 @@ enum phylink_op_type {
* if MAC link is at %MLO_AN_FIXED mode.
* @supported_interfaces: bitmap describing which PHY_INTERFACE_MODE_xxx
* are supported by the MAC/PCS.
@@ -351,12 +409,14 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
* @lpi_capabilities: MAC speeds which can support LPI signalling
* @lpi_timer_default: Default EEE LPI timer setting.
* @eee_enabled_default: If set, EEE will be enabled by phylink at creation time
+ * @available_pcs: array of available phylink_pcs PCS
+ * @num_available_pcs: num of available phylink_pcs PCS
+ * @fill_available_pcs: callback to fill the available PCS in the passed
+ * array struct of phylink_pcs PCS available_pcs up to
+ * num_available_pcs.
*/
struct phylink_config {
struct device *dev;
@@ -168,11 +172,15 @@ struct phylink_config {
@@ -168,11 +175,17 @@ struct phylink_config {
void (*get_fixed_state)(struct phylink_config *config,
struct phylink_link_state *state);
DECLARE_PHY_INTERFACE_MASK(supported_interfaces);
@@ -367,12 +427,14 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
u32 lpi_timer_default;
bool eee_enabled_default;
+
+ struct phylink_pcs **available_pcs;
+ unsigned int num_available_pcs;
+ int (*fill_available_pcs)(struct phylink_config *config,
+ struct phylink_pcs **available_pcs,
+ unsigned int num_available_pcs);
};
void phylink_limit_mac_speed(struct phylink_config *config, u32 max_speed);
@@ -468,6 +476,9 @@ struct phylink_pcs {
@@ -468,6 +481,9 @@ struct phylink_pcs {
struct phylink *phylink;
bool poll;
bool rxc_always_on;
@@ -123,7 +123,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
/* If configuration of the interface failed, force the link down
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -717,6 +717,8 @@ void phylink_disconnect_phy(struct phyli
@@ -722,6 +722,8 @@ void phylink_disconnect_phy(struct phyli
int phylink_set_fixed_link(struct phylink *,
const struct phylink_link_state *);
@@ -110,9 +110,9 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
/* What interface are supported by the current link.
* Can change on removal or addition of new PCS.
@@ -1955,6 +1957,51 @@ int phylink_set_fixed_link(struct phylin
@@ -1993,6 +1995,51 @@ out:
return ret;
}
EXPORT_SYMBOL_GPL(phylink_set_fixed_link);
+static int pcs_provider_notify(struct notifier_block *self,
+ unsigned long val, void *data)
@@ -162,7 +162,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
/**
* phylink_create() - create a phylink instance
* @config: a pointer to the target &struct phylink_config
@@ -2010,6 +2057,11 @@ struct phylink *phylink_create(struct ph
@@ -2048,6 +2095,11 @@ struct phylink *phylink_create(struct ph
pl->supported_interfaces,
pcs->supported_interfaces);
@@ -46,7 +46,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
phylink_info(pl, "Link is Down\n");
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -494,6 +494,7 @@ struct phylink_pcs {
@@ -499,6 +499,7 @@ struct phylink_pcs {
* @pcs_an_restart: restart 802.3z BaseX autonegotiation.
* @pcs_link_up: program the PCS for the resolved link configuration
* (where necessary).
@@ -54,7 +54,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
* @pcs_disable_eee: optional notification to PCS that EEE has been disabled
* at the MAC.
* @pcs_enable_eee: optional notification to PCS that EEE will be enabled at
@@ -521,6 +522,7 @@ struct phylink_pcs_ops {
@@ -526,6 +527,7 @@ struct phylink_pcs_ops {
void (*pcs_an_restart)(struct phylink_pcs *pcs);
void (*pcs_link_up)(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface, int speed, int duplex);
@@ -275,25 +275,56 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
.mac_config = mtk_mac_config,
.mac_finish = mtk_mac_finish,
.mac_link_down = mtk_mac_link_down,
@@ -4991,7 +5024,8 @@ static int mtk_add_mac(struct mtk_eth *e
@@ -4985,13 +5018,38 @@ static const struct net_device_ops mtk_n
.ndo_select_queue = mtk_select_queue,
};
+static int mtk_fill_available_pcs(struct phylink_config *config,
+ struct phylink_pcs **available_pcs,
+ unsigned int num_available_pcs)
+{
+ struct mtk_mac *mac = container_of(config, struct mtk_mac,
+ phylink_config);
+ struct mtk_eth *eth = mac->hw;
+ unsigned int sid;
+
+ if (mtk_is_netsys_v3_or_greater(eth)) {
+ return fwnode_phylink_pcs_parse(of_fwnode_handle(mac->of_node),
+ available_pcs,
+ &num_available_pcs);
+ } else {
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII))
+ sid = 0;
+ else
+ sid = mac->id;
+
+ available_pcs[0] = eth->sgmii_pcs[sid];
+ }
+
+ return 0;
+}
+
static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
{
const __be32 *_id = of_get_property(np, "reg", NULL);
phy_interface_t phy_mode;
struct phylink *phylink;
struct mtk_mac *mac;
- int id, err;
+ int id, err, count;
+ unsigned int sid;
int txqs = 1;
u32 val;
@@ -5062,6 +5096,7 @@ static int mtk_add_mac(struct mtk_eth *e
@@ -5062,6 +5120,8 @@ static int mtk_add_mac(struct mtk_eth *e
mac->phylink_config.lpi_capabilities = MAC_100FD | MAC_1000FD |
MAC_2500FD;
mac->phylink_config.lpi_timer_default = 1000;
+ mac->phylink_config.num_available_pcs = 0;
+ mac->phylink_config.fill_available_pcs = mtk_fill_available_pcs;
/* MT7623 gmac0 is now missing its speed-specific PLL configuration
* in its .mac_config method (since state->speed is not valid there.
@@ -5092,13 +5127,62 @@ static int mtk_add_mac(struct mtk_eth *e
@@ -5092,13 +5152,53 @@ static int mtk_add_mac(struct mtk_eth *e
if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_SGMII)) {
__set_bit(PHY_INTERFACE_MODE_SGMII,
@@ -326,11 +357,6 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+ if (err)
+ goto free_netdev;
+
+ err = fwnode_phylink_pcs_parse(of_fwnode_handle(np), mac->available_pcs, &count);
+ if (err)
+ goto free_netdev;
+
+ mac->phylink_config.available_pcs = mac->available_pcs;
+ mac->phylink_config.num_available_pcs = count;
+ } else {
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) {
@@ -341,12 +367,8 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+ err = -EBUSY;
+ goto free_netdev;
+ }
+ sid = 0;
+ eth->shared_sgmii_used = true;
+ } else {
+ sid = id;
+ }
+ mac->phylink_config.available_pcs = &eth->sgmii_pcs[sid];
+ mac->phylink_config.num_available_pcs = 1;
+ }
+
@@ -359,7 +381,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
if (mtk_is_netsys_v3_or_greater(mac->hw) &&
MTK_HAS_CAPS(mac->hw->soc->caps, MTK_ESW) &&
id == MTK_GMAC1_ID) {
@@ -5108,18 +5192,16 @@ static int mtk_add_mac(struct mtk_eth *e
@@ -5108,18 +5208,16 @@ static int mtk_add_mac(struct mtk_eth *e
phy_interface_zero(mac->phylink_config.supported_interfaces);
__set_bit(PHY_INTERFACE_MODE_INTERNAL,
mac->phylink_config.supported_interfaces);
@@ -386,7 +408,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_2P5GPHY) &&
id == MTK_GMAC2_ID)
__set_bit(PHY_INTERFACE_MODE_INTERNAL,
@@ -5142,6 +5224,16 @@ static int mtk_add_mac(struct mtk_eth *e
@@ -5142,6 +5240,16 @@ static int mtk_add_mac(struct mtk_eth *e
eth->netdev[id]->irq = eth->irq[MTK_FE_IRQ_SHARED];
eth->netdev[id]->dev.of_node = np;
@@ -403,7 +425,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628))
eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH - MTK_RX_ETH_HLEN;
else
@@ -5335,7 +5427,8 @@ static int mtk_probe(struct platform_dev
@@ -5335,7 +5443,8 @@ static int mtk_probe(struct platform_dev
regmap_write(cci, 0, 3);
}
@@ -30,7 +30,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -5702,7 +5702,7 @@ static const struct mtk_soc_data mt2701_
@@ -5718,7 +5718,7 @@ static const struct mtk_soc_data mt2701_
DESC_SIZE(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
@@ -39,7 +39,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
},
@@ -5730,7 +5730,7 @@ static const struct mtk_soc_data mt7621_
@@ -5746,7 +5746,7 @@ static const struct mtk_soc_data mt7621_
DESC_SIZE(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
@@ -48,7 +48,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
},
@@ -5760,7 +5760,7 @@ static const struct mtk_soc_data mt7622_
@@ -5776,7 +5776,7 @@ static const struct mtk_soc_data mt7622_
DESC_SIZE(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
@@ -57,7 +57,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
},
@@ -5789,7 +5789,7 @@ static const struct mtk_soc_data mt7623_
@@ -5805,7 +5805,7 @@ static const struct mtk_soc_data mt7623_
DESC_SIZE(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
@@ -66,7 +66,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
},
@@ -5815,7 +5815,7 @@ static const struct mtk_soc_data mt7629_
@@ -5831,7 +5831,7 @@ static const struct mtk_soc_data mt7629_
DESC_SIZE(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
@@ -75,7 +75,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
},
@@ -5847,7 +5847,7 @@ static const struct mtk_soc_data mt7981_
@@ -5863,7 +5863,7 @@ static const struct mtk_soc_data mt7981_
.dma_l4_valid = RX_DMA_L4_VALID_V2,
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
@@ -84,7 +84,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
},
};
@@ -5877,7 +5877,7 @@ static const struct mtk_soc_data mt7986_
@@ -5893,7 +5893,7 @@ static const struct mtk_soc_data mt7986_
.dma_l4_valid = RX_DMA_L4_VALID_V2,
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
@@ -93,7 +93,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
},
};
@@ -5930,7 +5930,7 @@ static const struct mtk_soc_data rt5350_
@@ -5946,7 +5946,7 @@ static const struct mtk_soc_data rt5350_
.dma_l4_valid = RX_DMA_L4_VALID_PDMA,
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
@@ -98,7 +98,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
return NOTIFY_DONE;
if (mac->speed > 0 && mac->speed <= s.base.speed)
@@ -5048,7 +5052,7 @@ static int mtk_add_mac(struct mtk_eth *e
@@ -5072,7 +5076,7 @@ static int mtk_add_mac(struct mtk_eth *e
}
if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA))
@@ -107,7 +107,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
eth->netdev[id] = alloc_etherdev_mqs(sizeof(*mac), txqs, 1);
if (!eth->netdev[id]) {
@@ -5693,6 +5697,7 @@ static const struct mtk_soc_data mt2701_
@@ -5709,6 +5713,7 @@ static const struct mtk_soc_data mt2701_
.required_clks = MT7623_CLKS_BITMAP,
.required_pctl = true,
.version = 1,
@@ -115,7 +115,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
.tx = {
DESC_SIZE(struct mtk_tx_dma),
.dma_max_len = MTK_TX_DMA_BUF_LEN,
@@ -5720,6 +5725,7 @@ static const struct mtk_soc_data mt7621_
@@ -5736,6 +5741,7 @@ static const struct mtk_soc_data mt7621_
.offload_version = 1,
.ppe_num = 1,
.hash_offset = 2,
@@ -123,7 +123,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
.foe_entry_size = MTK_FOE_ENTRY_V1_SIZE,
.tx = {
DESC_SIZE(struct mtk_tx_dma),
@@ -5750,6 +5756,7 @@ static const struct mtk_soc_data mt7622_
@@ -5766,6 +5772,7 @@ static const struct mtk_soc_data mt7622_
.ppe_num = 1,
.hash_offset = 2,
.has_accounting = true,
@@ -131,7 +131,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
.foe_entry_size = MTK_FOE_ENTRY_V1_SIZE,
.tx = {
DESC_SIZE(struct mtk_tx_dma),
@@ -5778,6 +5785,7 @@ static const struct mtk_soc_data mt7623_
@@ -5794,6 +5801,7 @@ static const struct mtk_soc_data mt7623_
.offload_version = 1,
.ppe_num = 1,
.hash_offset = 2,
@@ -139,7 +139,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
.foe_entry_size = MTK_FOE_ENTRY_V1_SIZE,
.disable_pll_modes = true,
.tx = {
@@ -5806,6 +5814,7 @@ static const struct mtk_soc_data mt7629_
@@ -5822,6 +5830,7 @@ static const struct mtk_soc_data mt7629_
.required_pctl = false,
.has_accounting = true,
.version = 1,
@@ -147,7 +147,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
.tx = {
DESC_SIZE(struct mtk_tx_dma),
.dma_max_len = MTK_TX_DMA_BUF_LEN,
@@ -5835,6 +5844,7 @@ static const struct mtk_soc_data mt7981_
@@ -5851,6 +5860,7 @@ static const struct mtk_soc_data mt7981_
.ppe_num = 2,
.hash_offset = 4,
.has_accounting = true,
@@ -155,7 +155,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
.foe_entry_size = MTK_FOE_ENTRY_V2_SIZE,
.tx = {
DESC_SIZE(struct mtk_tx_dma_v2),
@@ -5865,6 +5875,7 @@ static const struct mtk_soc_data mt7986_
@@ -5881,6 +5891,7 @@ static const struct mtk_soc_data mt7986_
.ppe_num = 2,
.hash_offset = 4,
.has_accounting = true,
@@ -163,7 +163,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
.foe_entry_size = MTK_FOE_ENTRY_V2_SIZE,
.tx = {
DESC_SIZE(struct mtk_tx_dma_v2),
@@ -5895,6 +5906,7 @@ static const struct mtk_soc_data mt7988_
@@ -5911,6 +5922,7 @@ static const struct mtk_soc_data mt7988_
.ppe_num = 3,
.hash_offset = 4,
.has_accounting = true,
@@ -114,16 +114,16 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
if (__ethtool_get_link_ksettings(dev, &s))
return NOTIFY_DONE;
@@ -5030,7 +5074,7 @@ static int mtk_add_mac(struct mtk_eth *e
@@ -5055,7 +5099,7 @@ static int mtk_add_mac(struct mtk_eth *e
phy_interface_t phy_mode;
struct phylink *phylink;
struct mtk_mac *mac;
- int id, err, count;
+ int id, err, count, i;
unsigned int sid;
int txqs = 1;
u32 val;
@@ -5065,6 +5109,16 @@ static int mtk_add_mac(struct mtk_eth *e
@@ -5089,6 +5133,16 @@ static int mtk_add_mac(struct mtk_eth *e
mac->hw = eth;
mac->of_node = np;
+1
View File
@@ -300,6 +300,7 @@ CONFIG_MTD_SPLIT_UIMAGE_FW=y
CONFIG_MTD_UBI=y
CONFIG_MTD_UBI_BEB_LIMIT=20
CONFIG_MTD_UBI_BLOCK=y
CONFIG_MTD_UBI_NVMEM=y
CONFIG_MTD_UBI_WL_THRESHOLD=4096
CONFIG_MUTEX_SPIN_ON_OWNER=y
CONFIG_NEED_DMA_MAP_STATE=y
@@ -194,8 +194,14 @@
partition@36c0000 {
label = "ubi";
reg = <0x36c0000 0x46c0000>;
};
partition@7d80000 {
label = "art";
reg = <0x7d80000 0x200000>;
read-only;
volumes {
ubi-volume-art {
volname = "ART";
@@ -211,12 +217,6 @@
};
};
};
partition@7d80000 {
label = "art";
reg = <0x7d80000 0x200000>;
read-only;
};
};
};
};
@@ -0,0 +1,225 @@
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/dts-v1/;
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/leds/common.h>
#include "mt7981b.dtsi"
/ {
model = "COMFAST CF-XR186";
compatible = "comfast,cf-xr186", "mediatek,mt7981";
aliases {
label-mac-device = &gmac1;
serial0 = &uart0;
led-boot = &led_wifi_red;
led-failsafe = &led_wifi_red;
led-upgrade = &led_wifi_red;
led-running = &led_wifi_red;
};
chosen {
bootargs-override = "console=ttyS0,115200n8";
stdout-path = "serial0:115200n8";
};
memory@40000000 {
reg = <0 0x40000000 0 0x10000000>;
device_type = "memory";
};
gpio-keys {
compatible = "gpio-keys";
reset {
label = "reset";
linux,code = <KEY_RESTART>;
gpios = <&pio 1 GPIO_ACTIVE_LOW>;
};
};
leds {
compatible = "gpio-leds";
led_wifi_blue: wifi-blue {
color = <LED_COLOR_ID_BLUE>;
function = LED_FUNCTION_WLAN;
gpios = <&pio 6 GPIO_ACTIVE_LOW>;
};
led_wifi_green: wifi-green {
color = <LED_COLOR_ID_GREEN>;
function = LED_FUNCTION_WLAN;
gpios = <&pio 35 GPIO_ACTIVE_LOW>;
};
led_wifi_red: wifi-red {
color = <LED_COLOR_ID_RED>;
function = LED_FUNCTION_WLAN;
gpios = <&pio 34 GPIO_ACTIVE_LOW>;
};
led_lan: lan-blue {
color = <LED_COLOR_ID_BLUE>;
function = LED_FUNCTION_LAN;
gpios = <&pio 4 GPIO_ACTIVE_LOW>;
};
};
};
&crypto {
status = "okay";
};
&eth {
pinctrl-names = "default";
pinctrl-0 = <&mdio_pins>;
status = "okay";
gmac1: mac@1 {
compatible = "mediatek,eth-mac";
reg = <1>;
phy-mode = "gmii";
phy-handle = <&int_gbe_phy>;
nvmem-cells = <&macaddr_factory_e000 0>;
nvmem-cell-names = "mac-address";
};
};
&pio {
spi0_flash_pins: spi0-pins {
mux {
function = "spi";
groups = "spi0", "spi0_wp_hold";
};
conf-pu {
pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP";
drive-strength = <MTK_DRIVE_8mA>;
bias-pull-up = <MTK_PUPD_SET_R1R0_11>;
};
conf-pd {
pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO";
drive-strength = <MTK_DRIVE_8mA>;
bias-pull-down = <MTK_PUPD_SET_R1R0_11>;
};
};
};
&spi0 {
pinctrl-names = "default";
pinctrl-0 = <&spi0_flash_pins>;
status = "okay";
spi_nand: spi-nand@0 {
compatible = "spi-nand";
reg = <0>;
spi-max-frequency = <52000000>;
spi-cal-enable;
spi-cal-mode = "read-data";
spi-cal-datalen = <7>;
spi-cal-data = /bits/ 8 <0x53 0x50 0x49 0x4E 0x41 0x4E 0x44>;
spi-cal-addrlen = <5>;
spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>;
spi-tx-bus-width = <4>;
spi-rx-bus-width = <4>;
mediatek,nmbm;
mediatek,bmt-max-ratio = <1>;
mediatek,bmt-max-reserved-blocks = <64>;
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "BL2";
reg = <0x00000 0x0100000>;
read-only;
};
partition@100000 {
label = "u-boot-env";
reg = <0x0100000 0x0080000>;
read-only;
};
factory: partition@180000 {
label = "Factory";
reg = <0x180000 0x0200000>;
read-only;
nvmem-layout {
compatible = "fixed-layout";
#address-cells = <1>;
#size-cells = <1>;
eeprom_factory_0: eeprom@0 {
reg = <0x0 0x1000>;
};
macaddr_factory_4: macaddr@4 {
compatible = "mac-base";
reg = <0x4 0x6>;
#nvmem-cell-cells = <1>;
};
macaddr_factory_8000: macaddr@8000 {
compatible = "mac-base";
reg = <0x8000 0x6>;
#nvmem-cell-cells = <1>;
};
macaddr_factory_e000: macaddr@e000 {
compatible = "mac-base";
reg = <0xe000 0x6>;
#nvmem-cell-cells = <1>;
};
};
};
partition@380000 {
label = "FIP";
reg = <0x380000 0x0200000>;
read-only;
};
partition@580000 {
label = "ubi";
reg = <0x580000 0x4000000>;
compatible = "linux,ubi";
};
};
};
};
&uart0 {
status = "okay";
};
&watchdog {
status = "okay";
};
&wifi {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
nvmem-cells = <&eeprom_factory_0>;
nvmem-cell-names = "eeprom";
band@0 {
reg = <0>;
nvmem-cells = <&macaddr_factory_4 0>;
nvmem-cell-names = "mac-address";
};
band@1 {
reg = <1>;
nvmem-cells = <&macaddr_factory_8000 0>;
nvmem-cell-names = "mac-address";
};
};
@@ -0,0 +1,195 @@
// SPDX-License-Identifier: GPL-2.0-only OR MIT
/dts-v1/;
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/leds/common.h>
#include <dt-bindings/pinctrl/mt65xx.h>
#include "mt7981b.dtsi"
/ {
compatible = "tplink,f65-v1", "mediatek,mt7981";
model = "TP-Link F65 v1";
aliases {
serial0 = &uart0;
led-boot = &led_status;
led-failsafe = &led_status;
led-running = &led_status;
led-upgrade = &led_status;
};
chosen {
bootargs-append = " ubi.mtd=ubi root=/dev/ubiblock0_1";
stdout-path = "serial0:115200n8";
};
memory@40000000 {
reg = <0 0x40000000 0 0x20000000>;
device_type = "memory";
};
gpio-keys {
compatible = "gpio-keys";
reset {
label = "reset";
linux,code = <KEY_RESTART>;
gpios = <&pio 1 GPIO_ACTIVE_LOW>;
};
};
leds {
compatible = "gpio-leds";
led_status: led_status {
function = LED_FUNCTION_STATUS;
color = <LED_COLOR_ID_BLUE>;
gpios = <&pio 35 GPIO_ACTIVE_HIGH>;
};
};
};
&uart0 {
status = "okay";
};
&watchdog {
status = "okay";
};
&spi0 {
pinctrl-names = "default";
pinctrl-0 = <&spi0_flash_pins>;
status = "okay";
spi_nand@0 {
compatible = "spi-nand";
reg = <0>;
spi-max-frequency = <52000000>;
spi-tx-buswidth = <4>;
spi-rx-buswidth = <4>;
mediatek,nmbm;
mediatek,bmt-max-ratio = <1>;
mediatek,bmt-max-reserved-blocks = <64>;
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "bl2";
reg = <0x00000 0x100000>;
read-only;
};
partition@100000 {
label = "boot-config";
reg = <0x100000 0x100000>;
read-only;
};
partition@200000 {
label = "boot-config1";
reg = <0x200000 0x100000>;
read-only;
};
partition@300000 {
compatible = "u-boot,env";
label = "u-boot-env";
reg = <0x300000 0x100000>;
};
partition@400000 {
label = "fip0";
reg = <0x400000 0x200000>;
read-only;
};
partition@600000 {
label = "fip1";
reg = <0x600000 0x200000>;
read-only;
};
partition@800000 {
label = "oops";
reg = <0x800000 0x100000>;
read-only;
};
partition@900000 {
label = "ubi";
reg = <0x900000 0x2680000>;
};
partition@2F80000 {
label = "ubi_1";
reg = <0x2F80000 0x2680000>;
read-only;
};
partition@5600000 {
label = "factory";
reg = <0x5600000 0x800000>;
read-only;
};
partition@5E00000 {
label = "runtime_data";
reg = <0x5E00000 0xC00000>;
read-only;
};
partition@6A00000 {
label = "backup_data";
reg = <0x6A00000 0x800000>;
read-only;
};
partition@7200000 {
label = "runtime_backup";
reg = <0x7200000 0x800000>;
read-only;
};
};
};
};
&pio {
spi0_flash_pins: spi0-pins {
mux {
function = "spi";
groups = "spi0", "spi0_wp_hold";
};
conf-pu {
pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP";
drive-strength = <MTK_DRIVE_8mA>;
};
conf-pd {
pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO";
drive-strength = <MTK_DRIVE_8mA>;
};
};
};
&eth {
status = "okay";
gmac1: mac@1 {
compatible = "mediatek,eth-mac";
reg = <1>;
phy-mode = "gmii";
phy-handle = <&int_gbe_phy>;
};
};
&wifi {
status = "okay";
};
@@ -0,0 +1,77 @@
// SPDX-License-Identifier: GPL-2.0-only OR MIT
/dts-v1/;
#include "mt7981b-wavlink-wl-wnt100x3.dtsi"
/ {
model = "WAVLINK WL-WNT100X3 (OpenWrt U-Boot layout)";
compatible = "wavlink,wl-wnt100x3-ubootmod", "mediatek,mt7981b";
};
&chosen {
bootargs = "root=/dev/fit0 rootwait";
rootdisk = <&ubi_rootdisk>;
};
&spi_nand {
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "bl2";
reg = <0x0 0x100000>;
read-only;
};
partition@100000 {
label = "u-boot-env";
reg = <0x100000 0x80000>;
read-only;
};
partition@180000 {
label = "factory";
reg = <0x180000 0x200000>;
read-only;
nvmem-layout {
compatible = "fixed-layout";
#address-cells = <1>;
#size-cells = <1>;
eeprom_factory: eeprom@0 {
reg = <0x0 0x1000>;
};
macaddr_lan: macaddr@3fff4 {
reg = <0x3fff4 0x06>;
};
macaddr_wan: macaddr@3fffa {
reg = <0x3fffa 0x06>;
};
};
};
partition@380000 {
label = "fip";
reg = <0x380000 0x200000>;
read-only;
};
partition@580000 {
label = "ubi";
reg = <0x580000 0x7a80000>;
compatible = "linux,ubi";
volumes {
ubi_rootdisk: ubi-volume-fit {
volname = "fit";
};
};
};
};
};
@@ -0,0 +1,75 @@
// SPDX-License-Identifier: GPL-2.0-only OR MIT
/dts-v1/;
#include "mt7981b-wavlink-wl-wnt100x3.dtsi"
/ {
model = "WAVLINK WL-WNT100X3";
compatible = "wavlink,wl-wnt100x3", "mediatek,mt7981b";
};
&spi_nand {
mediatek,nmbm;
mediatek,bmt-max-ratio = <1>;
mediatek,bmt-max-reserved-blocks = <64>;
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "bl2";
reg = <0x0 0x100000>;
read-only;
};
partition@100000 {
label = "u-boot-env";
reg = <0x100000 0x80000>;
read-only;
};
partition@180000 {
label = "factory";
reg = <0x180000 0x200000>;
read-only;
nvmem-layout {
compatible = "fixed-layout";
#address-cells = <1>;
#size-cells = <1>;
eeprom_factory: eeprom@0 {
reg = <0x0 0x1000>;
};
macaddr_lan: macaddr@3fff4 {
reg = <0x3fff4 0x06>;
};
macaddr_wan: macaddr@3fffa {
reg = <0x3fffa 0x06>;
};
};
};
partition@380000 {
label = "fip";
reg = <0x380000 0x200000>;
read-only;
};
partition@580000 {
label = "ubi";
reg = <0x580000 0x5a00000>;
};
partition@5f80000 {
label = "hw";
reg = <0x5f80000 0x80000>;
read-only;
};
};
};
@@ -0,0 +1,167 @@
// SPDX-License-Identifier: GPL-2.0-only OR MIT
/dts-v1/;
#include "mt7981b.dtsi"
/ {
aliases {
label-mac-device = &wifi;
led-boot = &led_status_blue;
led-failsafe = &led_status_blue;
led-running = &led_status_blue;
led-upgrade = &led_status_blue;
serial0 = &uart0;
};
chosen: chosen {
stdout-path = "serial0:115200n8";
};
leds {
compatible = "gpio-leds";
led_status_blue: led-0 {
function = LED_FUNCTION_STATUS;
color = <LED_COLOR_ID_BLUE>;
gpios = <&pio 13 GPIO_ACTIVE_LOW>;
};
};
gpio-keys {
compatible = "gpio-keys";
button-0 {
label = "reset";
linux,code = <KEY_RESTART>;
gpios = <&pio 11 GPIO_ACTIVE_LOW>;
};
button-1 {
label = "mode";
linux,code = <BTN_0>;
linux,input-type = <EV_SW>;
gpios = <&pio 25 GPIO_ACTIVE_LOW>;
debounce-interval = <60>;
};
};
fan_5v: regulator-fan-5v {
compatible = "regulator-fixed";
regulator-name = "fan";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
gpios = <&pio 22 GPIO_ACTIVE_HIGH>;
enable-active-high;
regulator-boot-on;
};
};
&pwm {
pinctrl-names = "default";
pinctrl-0 = <&pwm_pins>;
status = "okay";
};
&fan {
pwms = <&pwm 0 40000 0>;
fan-supply = <&fan_5v>;
status = "okay";
};
&uart0 {
status = "okay";
};
&watchdog {
status = "okay";
};
&eth {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&mdio_pins>;
gmac0: mac@0 {
compatible = "mediatek,eth-mac";
reg = <0>;
phy-mode = "sgmii";
phy-handle = <&en8801sc>;
nvmem-cells = <&macaddr_lan>;
nvmem-cell-names = "mac-address";
managed = "in-band-status";
};
gmac1: mac@1 {
compatible = "mediatek,eth-mac";
reg = <1>;
phy-mode = "gmii";
phy-handle = <&int_gbe_phy>;
nvmem-cells = <&macaddr_wan>;
nvmem-cell-names = "mac-address";
};
};
&mdio_bus {
en8801sc: ethernet-phy@29 {
compatible = "ethernet-phy-id03a2.9471";
phy-mode = "sgmii";
reg = <29>;
reset-gpios = <&pio 39 GPIO_ACTIVE_LOW>;
reset-assert-us = <10000>;
reset-deassert-us = <20000>;
};
};
&spi0 {
pinctrl-names = "default";
pinctrl-0 = <&spi0_flash_pins>;
status = "okay";
spi_nand: flash@0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "spi-nand";
reg = <0>;
spi-max-frequency = <52000000>;
spi-tx-bus-width = <4>;
spi-rx-bus-width = <4>;
spi-cal-enable;
spi-cal-mode = "read-data";
spi-cal-datalen = <7>;
spi-cal-data = /bits/ 8 <0x53 0x50 0x49 0x4e 0x41 0x4e 0x44>;
spi-cal-addrlen = <5>;
spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>;
};
};
&pio {
pwm_pins: pwm0-pins {
mux {
function = "pwm";
groups = "pwm0_1";
};
};
spi0_flash_pins: spi0-pins {
mux {
function = "spi";
groups = "spi0", "spi0_wp_hold";
};
};
};
&usb_phy {
status = "okay";
};
&xhci {
status = "okay";
};
&wifi {
status = "okay";
nvmem-cells = <&eeprom_factory>;
nvmem-cell-names = "eeprom";
};
@@ -0,0 +1,53 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/dts-v1/;
#include "mt7986a-jiorouter-common.dtsi"
/ {
compatible = "jiorouter,ax6000-jidu6101", "mediatek,mt7986a";
model = "JioRouter AX6000 JIDU6101";
};
&switch {
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
label = "wan";
};
port@1 {
reg = <1>;
label = "lan2";
};
port@2 {
reg = <2>;
label = "lan3";
};
port@3 {
reg = <3>;
label = "lan4";
};
port@4 {
reg = <4>;
label = "lan1";
};
port@6 {
reg = <6>;
ethernet = <&gmac0>;
phy-mode = "2500base-x";
fixed-link {
speed = <2500>;
full-duplex;
pause;
};
};
};
};
@@ -0,0 +1,283 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
#include <dt-bindings/input/input.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/leds/common.h>
#include <dt-bindings/pinctrl/mt65xx.h>
#include "mt7986a.dtsi"
/ {
aliases {
serial0 = &uart0;
led-boot = &led_red;
led-failsafe = &led_red;
led-running = &led_red;
led-upgrade = &led_blue;
};
chosen {
stdout-path = "serial0:115200n8";
bootargs = "dm-mod.create=''";
};
keys {
compatible = "gpio-keys";
reset {
label = "reset";
gpios = <&pio 9 GPIO_ACTIVE_LOW>;
linux,code = <KEY_RESTART>;
};
};
leds {
compatible = "gpio-leds";
led_red: led-0 {
color = <LED_COLOR_ID_RED>;
function = LED_FUNCTION_STATUS;
gpios = <&pio 12 GPIO_ACTIVE_LOW>;
default-state = "on";
};
led_green: led-1 {
color = <LED_COLOR_ID_GREEN>;
function = LED_FUNCTION_STATUS;
gpios = <&pio 13 GPIO_ACTIVE_LOW>;
};
led_blue: led-2 {
color = <LED_COLOR_ID_BLUE>;
function = LED_FUNCTION_STATUS;
gpios = <&pio 14 GPIO_ACTIVE_LOW>;
};
};
memory@40000000 {
reg = <0 0x40000000 0 0x20000000>;
device_type = "memory";
};
reg_3p3v: regulator-3p3v {
compatible = "regulator-fixed";
regulator-name = "fixed-3.3V";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
regulator-always-on;
};
reg_5v: regulator-5v {
compatible = "regulator-fixed";
regulator-name = "fixed-5V";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
regulator-boot-on;
regulator-always-on;
};
};
&crypto {
status = "okay";
};
&eth {
status = "okay";
gmac0: mac@0 {
compatible = "mediatek,eth-mac";
reg = <0>;
phy-mode = "2500base-x";
fixed-link {
speed = <2500>;
full-duplex;
pause;
};
};
mdio: mdio-bus {
#address-cells = <1>;
#size-cells = <0>;
};
};
&mdio {
switch: switch@1f {
compatible = "mediatek,mt7531";
reg = <31>;
reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>;
interrupt-controller;
#interrupt-cells = <1>;
interrupt-parent = <&pio>;
interrupts = <66 IRQ_TYPE_LEVEL_HIGH>;
};
};
&pio {
spi_flash_pins: spi-flash-pins-33-to-38 {
mux {
function = "spi";
groups = "spi0", "spi0_wp_hold";
};
conf-pu {
pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP";
drive-strength = <MTK_DRIVE_8mA>;
bias-disable;
};
conf-pd {
pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO";
drive-strength = <MTK_DRIVE_8mA>;
bias-disable;
};
};
wf_2g_5g_pins: wf_2g_5g-pins {
mux {
function = "wifi";
groups = "wf_2g", "wf_5g";
};
conf {
pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4",
"WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6",
"WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10",
"WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1",
"WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0",
"WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8",
"WF1_TOP_CLK", "WF1_TOP_DATA";
drive-strength = <MTK_DRIVE_4mA>;
};
};
wf_dbdc_pins: wf_dbdc-pins {
mux {
function = "wifi";
groups = "wf_dbdc";
};
conf {
pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4",
"WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6",
"WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10",
"WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1",
"WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0",
"WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8",
"WF1_TOP_CLK", "WF1_TOP_DATA";
drive-strength = <MTK_DRIVE_4mA>;
};
};
};
&spi0 {
pinctrl-names = "default";
pinctrl-0 = <&spi_flash_pins>;
status = "okay";
spi_nand_flash: flash@0 {
compatible = "spi-nand";
reg = <0>;
#address-cells = <1>;
#size-cells = <1>;
spi-max-frequency = <52000000>;
spi-tx-bus-width = <4>;
spi-rx-bus-width = <4>;
mediatek,nmbm;
mediatek,bmt-max-ratio = <1>;
mediatek,bmt-max-reserved-blocks = <64>;
partitions: partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "BL2";
reg = <0x0 0x100000>;
read-only;
};
/* Only used for MAC address storage.
* The active U-Boot environment is stored in UBI.
*/
partition@100000 {
label = "u-boot-env";
reg = <0x100000 0x80000>;
read-only;
};
factory: partition@180000 {
label = "Factory";
reg = <0x180000 0x200000>;
read-only;
nvmem-layout {
compatible = "fixed-layout";
#address-cells = <1>;
#size-cells = <1>;
eeprom_factory_0: eeprom@0 {
reg = <0x0 0x1000>;
};
};
};
partition@380000 {
label = "FIP";
reg = <0x380000 0x200000>;
read-only;
};
partition@580000 {
label = "ubi";
reg = <0x580000 0x8c00000>;
};
partition@9180000 {
label = "ubi2";
reg = <0x9180000 0x5a00000>;
};
partition@eb80000 {
label = "MFG";
reg = <0xeb80000 0x200000>;
read-only;
};
partition@ed80000 {
label = "Reserved";
reg = <0xed80000 0x200000>;
read-only;
};
};
};
};
&ssusb {
vusb33-supply = <&reg_3p3v>;
vbus-supply = <&reg_5v>;
status = "okay";
};
&trng {
status = "okay";
};
&uart0 {
status = "okay";
};
&usb_phy {
status = "okay";
};
&watchdog {
status = "okay";
};
&wifi {
nvmem-cells = <&eeprom_factory_0>;
nvmem-cell-names = "eeprom";
pinctrl-names = "default", "dbdc";
pinctrl-0 = <&wf_2g_5g_pins>;
pinctrl-1 = <&wf_dbdc_pins>;
status = "okay";
};
@@ -62,6 +62,11 @@ bazis,ax3000wm)
ucidef_set_led_netdev "lanlink" "LANLINK" "green:lan" "eth1" "link"
ucidef_set_led_netdev "internet" "internet" "blue:wan-online" "wan" "link"
;;
comfast,cf-xr186)
ucidef_set_led_netdev "lan" "LAN" "blue:lan" "eth0" "link tx rx"
ucidef_set_led_netdev "wlan2g" "WLAN2G" "green:wlan" "phy0-ap0" "link tx rx"
ucidef_set_led_netdev "wlan5g" "WLAN5G" "blue:wlan" "phy1-ap0" "link tx rx"
;;
confiabits,mt7981)
ucidef_set_led_netdev "lan1" "lan1" "blue:lan-1" "lan1" "link tx rx"
ucidef_set_led_netdev "lan2" "lan2" "blue:lan-2" "lan2" "link tx rx"
@@ -118,6 +118,7 @@ mediatek_setup_interfaces()
cudy,ap3000wall-v1)
ucidef_set_interface_lan "lan1 lan2 lan3 lan4 lan5"
;;
comfast,cf-xr186|\
cudy,ap3000outdoor-v1|\
cudy,ap3000-v1|\
cudy,re3000-v1|\
@@ -127,6 +128,7 @@ mediatek_setup_interfaces()
netgear,eax17|\
netgear,wax220|\
openfi,6c|\
tplink,f65-v1|\
ubnt,unifi-6-plus|\
wavlink,wl-wn573hx3|\
widelantech,wap430x|\
@@ -138,7 +140,9 @@ mediatek_setup_interfaces()
edgecore,eap111|\
huasifei,wh3000-emmc|\
huasifei,wh3000-pro-emmc|\
huasifei,wh3000-pro-nand)
huasifei,wh3000-pro-nand|\
wavlink,wl-wnt100x3|\
wavlink,wl-wnt100x3-ubootmod)
ucidef_set_interfaces_lan_wan eth0 eth1
;;
bazis,ax3000wm|\
@@ -273,6 +277,11 @@ mediatek_setup_macs()
lan_mac=$(macaddr_add "$wan_mac" 1)
label_mac=$wan_mac
;;
jiorouter,ax6000-jidu6101)
label_mac=$(mtd_get_mac_ascii u-boot-env mac)
wan_mac=$label_mac
lan_mac=$(macaddr_add "$label_mac" 1)
;;
mercusys,mr80x-v3|\
mercusys,mr85x)
mac_dirty=$(cat "/tmp/tp_data/default-mac" | sed -n 's/^'"MAC"'://p')
@@ -301,7 +310,8 @@ mediatek_setup_macs()
wan_mac=$(macaddr_add "$lan_mac" 1)
label_mac=$wan_mac
;;
tplink,eap683-lr)
tplink,eap683-lr|\
tplink,f65-v1)
label_mac=$(get_mac_binary "/tmp/factory/default-mac" 0)
lan_mac=$label_mac
;;
@@ -14,6 +14,9 @@ case "$FIRMWARE" in
ln -sf /tmp/tp_data/MT7981_EEPROM.bin \
/lib/firmware/$FIRMWARE
;;
tplink,f65-v1)
ln -sf /tmp/factory/radio /lib/firmware/$FIRMWARE
;;
tplink,fr365-v1)
ln -sf /tmp/wlan/radio /lib/firmware/$FIRMWARE
;;
@@ -149,6 +149,11 @@ case "$board" in
jdcloud,re-cp-03)
[ "$PHYNBR" = "1" ] && mmc_get_mac_binary factory 0xa > /sys${DEVPATH}/macaddress
;;
jiorouter,ax6000-jidu6101)
addr=$(mtd_get_mac_ascii u-boot-env mac)
[ "$PHYNBR" = "0" ] && macaddr_add $addr 2 > /sys${DEVPATH}/macaddress
[ "$PHYNBR" = "1" ] && macaddr_add $addr 3 > /sys${DEVPATH}/macaddress
;;
keenetic,kap-630|\
keenetic,kn-3711|\
keenetic,kn-3811|\
@@ -205,7 +210,8 @@ case "$board" in
ruijie,rg-x60)
[ "$PHYNBR" = "1" ] && macaddr_setbit_la $(macaddr_add $(get_mac_label) 0xb00002) > /sys${DEVPATH}/macaddress
;;
tplink,eap683-lr)
tplink,eap683-lr|\
tplink,f65-v1)
addr=$(get_mac_label)
[ "$PHYNBR" = "0" ] && echo $addr > /sys${DEVPATH}/macaddress
[ "$PHYNBR" = "1" ] && macaddr_add $addr 1 > /sys${DEVPATH}/macaddress
@@ -22,7 +22,8 @@ preinit_mount_cfg_part() {
tplink,re6000xd)
mount_ubi_part "tp_data" "tp_data"
;;
tplink,eap683-lr)
tplink,eap683-lr|\
tplink,f65-v1)
mount_ubi_part "factory" "ubi_factory_data"
;;
tplink,fr365-v1)
@@ -24,6 +24,27 @@ buffalo_initial_setup()
ubiformat /dev/mtd$mtdnum -y
}
jiorouter_initial_setup()
{
[ "$(rootfs_type)" = "tmpfs" ] || return 0
local mtdnum="$( find_mtd_index ubi )"
if [ ! "$mtdnum" ]; then
echo "unable to find mtd partition ubi"
return 1
fi
ubidetach -m "$mtdnum" 2>/dev/null
ubiformat /dev/mtd$mtdnum -y
ubiattach -m "$mtdnum"
ubimkvol /dev/ubi0 -n 0 -N u-boot-env -s 0x80000
# Set boot arguments in freshly created U-Boot environment
fw_setenv bootcmd 'ubi read 46000000 kernel;fdt addr $(fdtcontroladdr);fdt rm /signature;bootm 0x46000000'
fw_setenv bootdelay 0
fw_setenv ipaddr ''
}
xiaomi_initial_setup()
{
# initialize UBI and setup uboot-env if it's running on initramfs
@@ -163,6 +184,7 @@ platform_do_upgrade() {
tplink,tl-xdr6086|\
tplink,tl-xdr6088|\
tplink,tl-xtr8488|\
wavlink,wl-wnt100x3-ubootmod|\
xiaomi,mi-router-ax3000t-ubootmod|\
xiaomi,redmi-router-ax6000-ubootmod|\
xiaomi,mi-router-wr30u-ubootmod|\
@@ -215,7 +237,8 @@ platform_do_upgrade() {
buffalo,wsr-6000ax8|\
cudy,wr3000h-v1|\
cudy,wr3000p-v1|\
huasifei,wh3000-pro-nand)
huasifei,wh3000-pro-nand|\
jiorouter,ax6000-jidu6101)
CI_UBIPART="ubi"
nand_do_upgrade "$1"
;;
@@ -224,6 +247,7 @@ platform_do_upgrade() {
kebidumei,ax3000-u22|\
totolink,x6000r|\
wavlink,wl-wn573hx3|\
wavlink,wl-wnt100x3|\
widelantech,wap430x|\
yuncore,ax835)
default_do_upgrade "$1"
@@ -370,6 +394,7 @@ platform_check_image() {
tplink,tl-xdr6086|\
tplink,tl-xdr6088|\
tplink,tl-xtr8488|\
wavlink,wl-wnt100x3-ubootmod|\
xiaomi,mi-router-ax3000t-ubootmod|\
xiaomi,redmi-router-ax6000-ubootmod|\
xiaomi,mi-router-wr30u-ubootmod|\
@@ -470,6 +495,9 @@ platform_pre_upgrade() {
[ -z "$delay" ] || [ "$delay" -eq "0" ] && \
fw_setenv bootmenu_delay 3
;;
jiorouter,ax6000-jidu6101)
jiorouter_initial_setup
;;
xiaomi,mi-router-ax3000t|\
xiaomi,mi-router-wr30u-stock|\
xiaomi,redmi-router-ax6000-stock)

Some files were not shown because too many files have changed in this diff Show More