From 4c5d910ef152886ea285f8c1ca50924af03fe55e Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 31 Jul 2023 01:12:24 +0100 Subject: [PATCH 01/23] arm-trusted-firmware-mediatek: fix PKG_MIRROR_HASH Instead of using the hash of the Github-generated tarball use the hash of the tarball generated by the OpenWrt build system (in this case they are different, unfortunately). Reported-by: Chen Minqiang Fixes: 07dbeb430e ("arm-trusted-firmware-mediatek: update to sources of 2023-07-24") Signed-off-by: Daniel Golle --- package/boot/arm-trusted-firmware-mediatek/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/boot/arm-trusted-firmware-mediatek/Makefile b/package/boot/arm-trusted-firmware-mediatek/Makefile index 0d1ad8e98a..853049cfb0 100644 --- a/package/boot/arm-trusted-firmware-mediatek/Makefile +++ b/package/boot/arm-trusted-firmware-mediatek/Makefile @@ -15,7 +15,7 @@ PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=https://github.com/mtk-openwrt/arm-trusted-firmware.git PKG_SOURCE_DATE:=2023-07-24 PKG_SOURCE_VERSION:=00ac6db375b76e57e1f5e9e9bffa033e907c3581 -PKG_MIRROR_HASH:=35e84b2160a7ddc083439e469d7366bb4e6098fc43b5616e68f001364eb05835 +PKG_MIRROR_HASH:=74fc18395532c4292f530da8d00fa1873ada4e05e600c0077a7b7f85ace0d913 PKG_MAINTAINER:=Daniel Golle From 5757b21db098cce0ddda1558df5430ca2e2df978 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Mon, 31 Jul 2023 12:08:34 +0200 Subject: [PATCH 02/23] qualcommax: ipq807x: fix Gen2 PCIe port Gen2 PCIe port recently got broken on IPQ807x during update to 6.1.39 as upstream backported: ("PCI: qcom: Remove PCIE20_ prefix from register definitions") [1] So, fix it by adding a pending upstream fix for it [2]. [1] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/drivers/pci/controller/dwc/pcie-qcom.c?h=v6.1.39&id=db962c7a711c3393a80a18219960cd54fb33c53d [2] https://patchwork.kernel.org/project/linux-arm-msm/patch/20230724063429.3980462-1-quic_srichara@quicinc.com/ Fixes: fec22f8375b4 ("kernel: bump 6.1 to 6.1.39") Signed-off-by: Robert Marko --- ...broken-pcie-enumeration-for-2_3_3-co.patch | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 target/linux/qualcommax/patches-6.1/0134-PCI-qcom-Fixing-broken-pcie-enumeration-for-2_3_3-co.patch diff --git a/target/linux/qualcommax/patches-6.1/0134-PCI-qcom-Fixing-broken-pcie-enumeration-for-2_3_3-co.patch b/target/linux/qualcommax/patches-6.1/0134-PCI-qcom-Fixing-broken-pcie-enumeration-for-2_3_3-co.patch new file mode 100644 index 0000000000..1b34cdda46 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0134-PCI-qcom-Fixing-broken-pcie-enumeration-for-2_3_3-co.patch @@ -0,0 +1,44 @@ +From f92c2f22197b7beed59b81f2aa179e16987c02e4 Mon Sep 17 00:00:00 2001 +From: Sricharan Ramabadhran +Date: Mon, 24 Jul 2023 12:04:29 +0530 +Subject: [PATCH] PCI: qcom: Fixing broken pcie enumeration for 2_3_3 configs + ops + +PARF_SLV_ADDR_SPACE_SIZE_2_3_3 macro is used for IPQ8074 2_3_3 post_init. +PCIe slave addr register offset is 0x358, but was wrongly changed to +0x168 as a part of commit 39171b33f652 ("PCI: qcom: Remove PCIE20_ prefix +from register definitions"). Fixing it, by using the right macro and remove +the unused PARF_SLV_ADDR_SPACE_SIZE_2_3_3. + +Without this access to the registers of slave addr space like iATU etc +are broken leading to pcie enumeration failure. + +Fixes: 39171b33f652 ("PCI: qcom: Remove PCIE20_ prefix from register definitions") +Cc: +Reviewed-by: Manivannan Sadhasivam +Reviewed-by: Konrad Dybcio +Signed-off-by: Sricharan Ramabadhran +--- + drivers/pci/controller/dwc/pcie-qcom.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/pci/controller/dwc/pcie-qcom.c ++++ b/drivers/pci/controller/dwc/pcie-qcom.c +@@ -40,7 +40,6 @@ + #define PARF_PHY_REFCLK 0x4c + #define PARF_CONFIG_BITS 0x50 + #define PARF_DBI_BASE_ADDR 0x168 +-#define PARF_SLV_ADDR_SPACE_SIZE_2_3_3 0x16c /* Register offset specific to IP ver 2.3.3 */ + #define PARF_MHI_CLOCK_RESET_CTRL 0x174 + #define PARF_AXI_MSTR_WR_ADDR_HALT 0x178 + #define PARF_AXI_MSTR_WR_ADDR_HALT_V2 0x1a8 +@@ -1148,8 +1147,7 @@ static int qcom_pcie_post_init_2_3_3(str + u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); + u32 val; + +- writel(SLV_ADDR_SPACE_SZ, +- pcie->parf + PARF_SLV_ADDR_SPACE_SIZE_2_3_3); ++ writel(SLV_ADDR_SPACE_SZ, pcie->parf + PARF_SLV_ADDR_SPACE_SIZE); + + val = readl(pcie->parf + PARF_PHY_CTRL); + val &= ~BIT(0); From 915fd357fd06139ac436f246800c2eb55202cba2 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 31 Jul 2023 17:46:22 +0100 Subject: [PATCH 03/23] uboot-mediatek: add missing 'memory' nodes to downstream boards Among the patches adding support for MT7988 also came the switch to use fdtdec_setup_mem_size_base() and no longer rely on CFG_SYS_SDRAM_BASE. Take care of our downstream boards which did not have a 'memory' node in their device trees. Fixes: 572ea68070 ("uboot-mediatek: add patches for MT7988 and builds for RFB") Signed-off-by: Daniel Golle --- .../uboot-mediatek/patches/412-add-ubnt-unifi-6-lr.patch | 7 ++++++- .../patches/431-add-xiaomi_redmi-ax6000.patch | 7 ++++++- .../uboot-mediatek/patches/432-add-tplink-xdr608x.patch | 7 ++++++- .../boot/uboot-mediatek/patches/433-add-qihoo_360t7.patch | 7 ++++++- .../patches/434-add-xiaomi_mi-router-wr30u.patch | 7 ++++++- .../patches/435-add-h3c_magic-nx30-pro.patch | 7 ++++++- 6 files changed, 36 insertions(+), 6 deletions(-) diff --git a/package/boot/uboot-mediatek/patches/412-add-ubnt-unifi-6-lr.patch b/package/boot/uboot-mediatek/patches/412-add-ubnt-unifi-6-lr.patch index b495f48d66..4bde061765 100644 --- a/package/boot/uboot-mediatek/patches/412-add-ubnt-unifi-6-lr.patch +++ b/package/boot/uboot-mediatek/patches/412-add-ubnt-unifi-6-lr.patch @@ -150,7 +150,7 @@ +CONFIG_SERVERIP="192.168.1.254" --- /dev/null +++ b/arch/arm/dts/mt7622-ubnt-unifi-6-lr.dts -@@ -0,0 +1,188 @@ +@@ -0,0 +1,193 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. @@ -173,6 +173,11 @@ + tick-timer = &timer0; + }; + ++ memory@40000000 { ++ device_type = "memory"; ++ reg = <0x40000000 0x20000000>; ++ }; ++ + aliases { + spi0 = &snor; + }; diff --git a/package/boot/uboot-mediatek/patches/431-add-xiaomi_redmi-ax6000.patch b/package/boot/uboot-mediatek/patches/431-add-xiaomi_redmi-ax6000.patch index 88e426366b..070456b2ee 100644 --- a/package/boot/uboot-mediatek/patches/431-add-xiaomi_redmi-ax6000.patch +++ b/package/boot/uboot-mediatek/patches/431-add-xiaomi_redmi-ax6000.patch @@ -182,7 +182,7 @@ +CONFIG_SERVERIP="192.168.1.254" --- /dev/null +++ b/arch/arm/dts/mt7986a-xiaomi_redmi-ax6000.dts -@@ -0,0 +1,156 @@ +@@ -0,0 +1,161 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2021 MediaTek Inc. @@ -205,6 +205,11 @@ + tick-timer = &timer0; + }; + ++ memory@40000000 { ++ device_type = "memory"; ++ reg = <0x40000000 0x20000000>; ++ }; ++ + keys { + compatible = "gpio-keys"; + factory { diff --git a/package/boot/uboot-mediatek/patches/432-add-tplink-xdr608x.patch b/package/boot/uboot-mediatek/patches/432-add-tplink-xdr608x.patch index b1c25ba791..365f280947 100644 --- a/package/boot/uboot-mediatek/patches/432-add-tplink-xdr608x.patch +++ b/package/boot/uboot-mediatek/patches/432-add-tplink-xdr608x.patch @@ -555,7 +555,7 @@ +CONFIG_SERVERIP="192.168.1.254" --- /dev/null +++ b/arch/arm/dts/mt7986a-tplink-tl-xdr608x.dts -@@ -0,0 +1,191 @@ +@@ -0,0 +1,196 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2021 MediaTek Inc. @@ -578,6 +578,11 @@ + tick-timer = &timer0; + }; + ++ memory@40000000 { ++ device_type = "memory"; ++ reg = <0x40000000 0x20000000>; ++ }; ++ + keys { + compatible = "gpio-keys"; + diff --git a/package/boot/uboot-mediatek/patches/433-add-qihoo_360t7.patch b/package/boot/uboot-mediatek/patches/433-add-qihoo_360t7.patch index aaaeaa4f8a..4f98c95893 100644 --- a/package/boot/uboot-mediatek/patches/433-add-qihoo_360t7.patch +++ b/package/boot/uboot-mediatek/patches/433-add-qihoo_360t7.patch @@ -178,7 +178,7 @@ +CONFIG_SERVERIP="192.168.1.254" --- /dev/null +++ b/arch/arm/dts/mt7981_qihoo-360t7.dts -@@ -0,0 +1,180 @@ +@@ -0,0 +1,185 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022 MediaTek Inc. @@ -201,6 +201,11 @@ + tick-timer = &timer0; + }; + ++ memory@40000000 { ++ device_type = "memory"; ++ reg = <0x40000000 0x10000000>; ++ }; ++ + keys { + compatible = "gpio-keys"; + diff --git a/package/boot/uboot-mediatek/patches/434-add-xiaomi_mi-router-wr30u.patch b/package/boot/uboot-mediatek/patches/434-add-xiaomi_mi-router-wr30u.patch index 6be64e5421..2bd1afe7a8 100644 --- a/package/boot/uboot-mediatek/patches/434-add-xiaomi_mi-router-wr30u.patch +++ b/package/boot/uboot-mediatek/patches/434-add-xiaomi_mi-router-wr30u.patch @@ -178,7 +178,7 @@ +CONFIG_SERVERIP="192.168.1.254" --- /dev/null +++ b/arch/arm/dts/mt7981_xiaomi_mi-router-wr30u.dts -@@ -0,0 +1,216 @@ +@@ -0,0 +1,221 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022 MediaTek Inc. @@ -206,6 +206,11 @@ + system_led = "yellow:system"; + }; + ++ memory@40000000 { ++ device_type = "memory"; ++ reg = <0x40000000 0x10000000>; ++ }; ++ + gpio-keys { + compatible = "gpio-keys"; + diff --git a/package/boot/uboot-mediatek/patches/435-add-h3c_magic-nx30-pro.patch b/package/boot/uboot-mediatek/patches/435-add-h3c_magic-nx30-pro.patch index 57181c73c0..d5a149b903 100644 --- a/package/boot/uboot-mediatek/patches/435-add-h3c_magic-nx30-pro.patch +++ b/package/boot/uboot-mediatek/patches/435-add-h3c_magic-nx30-pro.patch @@ -178,7 +178,7 @@ +CONFIG_SERVERIP="192.168.1.254" --- /dev/null +++ b/arch/arm/dts/mt7981_h3c_magic-nx30-pro.dts -@@ -0,0 +1,200 @@ +@@ -0,0 +1,205 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022 MediaTek Inc. @@ -201,6 +201,11 @@ + tick-timer = &timer0; + }; + ++ memory@40000000 { ++ device_type = "memory"; ++ reg = <0x40000000 0x10000000>; ++ }; ++ + keys { + compatible = "gpio-keys"; + From dc4aafb30939316a163c2eaede6811d871cace2f Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 31 Jul 2023 18:05:22 +0100 Subject: [PATCH 04/23] mediatek: filogic: enable driver for MediaTek XS-PHY Enable driver for MediaTek SuperSpeedPlus XS-PHY transceiver for the USB3.1 GEN2 controllers found in the MT7988 SoC. Signed-off-by: Daniel Golle --- target/linux/mediatek/filogic/config-5.15 | 2 +- target/linux/mediatek/filogic/config-6.1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/target/linux/mediatek/filogic/config-5.15 b/target/linux/mediatek/filogic/config-5.15 index 4cae8c50ac..2ffc466b7c 100644 --- a/target/linux/mediatek/filogic/config-5.15 +++ b/target/linux/mediatek/filogic/config-5.15 @@ -306,7 +306,7 @@ CONFIG_PHYLINK=y CONFIG_PHYS_ADDR_T_64BIT=y CONFIG_PHY_MTK_TPHY=y # CONFIG_PHY_MTK_UFS is not set -# CONFIG_PHY_MTK_XSPHY is not set +CONFIG_PHY_MTK_XSPHY=y CONFIG_PINCTRL=y # CONFIG_PINCTRL_MT2712 is not set # CONFIG_PINCTRL_MT6765 is not set diff --git a/target/linux/mediatek/filogic/config-6.1 b/target/linux/mediatek/filogic/config-6.1 index 96a7566735..334dfa8502 100644 --- a/target/linux/mediatek/filogic/config-6.1 +++ b/target/linux/mediatek/filogic/config-6.1 @@ -330,7 +330,7 @@ CONFIG_PHYS_ADDR_T_64BIT=y # CONFIG_PHY_MTK_PCIE is not set CONFIG_PHY_MTK_TPHY=y # CONFIG_PHY_MTK_UFS is not set -# CONFIG_PHY_MTK_XSPHY is not set +CONFIG_PHY_MTK_XSPHY=y CONFIG_PINCTRL=y # CONFIG_PINCTRL_MT2712 is not set # CONFIG_PINCTRL_MT6765 is not set From e3dd5ee02bb3acb2022405f67ed7ec854481f8cf Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 31 Jul 2023 19:47:54 +0100 Subject: [PATCH 05/23] uboot-mediatek: fix build for MT7629 Add patch to fix build failure caused by a missing header which had previously been implicitely included. Fixes: 6ddb5f5a65 ("uboot-mediatek: update to version 2023.07.02") Signed-off-by: Daniel Golle --- ...include-linux-sizes.h-for-SZ_-macros.patch | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 package/boot/uboot-mediatek/patches/102-ram-mediatek-include-linux-sizes.h-for-SZ_-macros.patch diff --git a/package/boot/uboot-mediatek/patches/102-ram-mediatek-include-linux-sizes.h-for-SZ_-macros.patch b/package/boot/uboot-mediatek/patches/102-ram-mediatek-include-linux-sizes.h-for-SZ_-macros.patch new file mode 100644 index 0000000000..3cfc684956 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/102-ram-mediatek-include-linux-sizes.h-for-SZ_-macros.patch @@ -0,0 +1,47 @@ +From 4bd66fd5b69eda41b4320fd6f8db50a7b7fa7bf7 Mon Sep 17 00:00:00 2001 +Message-ID: <4bd66fd5b69eda41b4320fd6f8db50a7b7fa7bf7.1690828424.git.daniel@makrotopia.org> +From: Daniel Golle +Date: Mon, 31 Jul 2023 19:25:04 +0100 +Subject: [PATCH] ram: mediatek: include for SZ_* macros +To: Ryder Lee , + Weijie Gao , + Chunfeng Yun , + GSS_MTK_Uboot_upstream , + u-boot@lists.denx.de + +Something between U-Boot 2023.04 and 2023.07.02 resulted in no longer +implicitely including in the DDR3 RAM driver for the +MT7929 SoC. The result is a build failure: +drivers/ram/mediatek/ddr3-mt7629.c: In function 'mtk_ddr3_get_info': +drivers/ram/mediatek/ddr3-mt7629.c:734:30: error: 'SZ_128M' undeclared (first use in this function) + 734 | info->size = SZ_128M; + | ^~~~~~~ +drivers/ram/mediatek/ddr3-mt7629.c:734:30: note: each undeclared identifier is reported only once for each function it appears in +drivers/ram/mediatek/ddr3-mt7629.c:737:30: error: 'SZ_256M' undeclared (first use in this function) + 737 | info->size = SZ_256M; + | ^~~~~~~ +drivers/ram/mediatek/ddr3-mt7629.c:740:30: error: 'SZ_512M' undeclared (first use in this function) + 740 | info->size = SZ_512M; + | ^~~~~~~ +drivers/ram/mediatek/ddr3-mt7629.c:743:30: error: 'SZ_1G' undeclared (first use in this function) + 743 | info->size = SZ_1G; + | ^~~~~ + +Include so SZ_* is defined. + +Reported-by: Tianling Shen +Signed-off-by: Daniel Golle +--- + drivers/ram/mediatek/ddr3-mt7629.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/ram/mediatek/ddr3-mt7629.c ++++ b/drivers/ram/mediatek/ddr3-mt7629.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + + /* EMI */ + #define EMI_CONA 0x000 From e6b72de70367044260a6077bba3a91da463feaab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kwiatek?= Date: Fri, 28 Jul 2023 15:59:44 +0200 Subject: [PATCH 06/23] ath11k-firmware: update to stable WLAN.HK.2.9.0.1-01862 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changelog from quic: Bug fixes, stability improvements from previous releases are present. There are no backward comatibility issues with this release. Reviewed-by: Robert Marko Tested-by: Michał Kwiatek # Xiaomi AX3600 Signed-off-by: Michał Kwiatek --- package/firmware/ath11k-firmware/Makefile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/package/firmware/ath11k-firmware/Makefile b/package/firmware/ath11k-firmware/Makefile index 7acc233b6f..41178b25ff 100644 --- a/package/firmware/ath11k-firmware/Makefile +++ b/package/firmware/ath11k-firmware/Makefile @@ -8,9 +8,9 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ath11k-firmware -PKG_SOURCE_DATE:=2023-07-06 -PKG_SOURCE_VERSION:=69f6b7346b64784188dba791a9cfb614eefa441f -PKG_MIRROR_HASH:=0f0203f755cb6713f6a1f41397dcd0f1a24e5cdbe75258af961343b927ebb3e9 +PKG_SOURCE_DATE:=2023-07-28 +PKG_SOURCE_VERSION:=006a4e2a23a6cf9e7a28d8349025a4418e39cb1d +PKG_MIRROR_HASH:=1043b8c01d28cad2a34e4586e4e6a3949bd1aed9f9afd5b71f527b6b23835e81 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git @@ -60,14 +60,14 @@ $(eval $(call Download,qcn9074-board)) define Package/ath11k-firmware-ipq8074/install $(INSTALL_DIR) $(1)/lib/firmware/IPQ8074 $(INSTALL_DATA) \ - $(PKG_BUILD_DIR)/ath11k-firmware/IPQ8074/hw2.0/2.9.0.1/WLAN.HK.2.9.0.1-01837-QCAHKSWPL_SILICONZ-1/* \ + $(PKG_BUILD_DIR)/ath11k-firmware/IPQ8074/hw2.0/2.9.0.1/WLAN.HK.2.9.0.1-01862-QCAHKSWPL_SILICONZ-1/* \ $(1)/lib/firmware/IPQ8074/ endef define Package/ath11k-firmware-qcn9074/install $(INSTALL_DIR) $(1)/lib/firmware/ath11k/QCN9074/hw1.0 $(INSTALL_DATA) \ - $(PKG_BUILD_DIR)/ath11k-firmware/QCN9074/hw1.0/2.9.0.1/WLAN.HK.2.9.0.1-01837-QCAHKSWPL_SILICONZ-1/* \ + $(PKG_BUILD_DIR)/ath11k-firmware/QCN9074/hw1.0/2.9.0.1/WLAN.HK.2.9.0.1-01862-QCAHKSWPL_SILICONZ-1/* \ $(1)/lib/firmware/ath11k/QCN9074/hw1.0/ $(INSTALL_BIN) \ $(DL_DIR)/$(QCN9074_BOARD_FILE) $(1)/lib/firmware/ath11k/QCN9074/hw1.0/board-2.bin From 57fbbf15cd3d1cceb5d10cdae8369421c2092223 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 16 Mar 2023 11:35:50 +0100 Subject: [PATCH 07/23] hostapd: add experimental radius server This can be used to run a standalone EAP server that can be used from other APs. It uses json as user database format and can automatically handle reload. Signed-off-by: Felix Fietkau --- package/network/services/hostapd/Makefile | 39 +- .../services/hostapd/files/radius.clients | 1 + .../services/hostapd/files/radius.config | 9 + .../services/hostapd/files/radius.init | 42 + .../services/hostapd/files/radius.users | 14 + .../hostapd/patches/770-radius_server.patch | 154 ++++ .../services/hostapd/src/hostapd/radius.c | 715 ++++++++++++++++++ 7 files changed, 969 insertions(+), 5 deletions(-) create mode 100644 package/network/services/hostapd/files/radius.clients create mode 100644 package/network/services/hostapd/files/radius.config create mode 100644 package/network/services/hostapd/files/radius.init create mode 100644 package/network/services/hostapd/files/radius.users create mode 100644 package/network/services/hostapd/patches/770-radius_server.patch create mode 100644 package/network/services/hostapd/src/hostapd/radius.c diff --git a/package/network/services/hostapd/Makefile b/package/network/services/hostapd/Makefile index 0fe53dc8d4..1d034a1752 100644 --- a/package/network/services/hostapd/Makefile +++ b/package/network/services/hostapd/Makefile @@ -148,7 +148,7 @@ define Package/hostapd/Default SUBMENU:=WirelessAPD TITLE:=IEEE 802.1x Authenticator URL:=http://hostap.epitest.fi/ - DEPENDS:=$(DRV_DEPENDS) +hostapd-common +libubus + DEPENDS:=$(DRV_DEPENDS) +hostapd-common +libubus +libblobmsg-json EXTRA_DEPENDS:=hostapd-common (=$(PKG_VERSION)-$(PKG_RELEASE)) USERID:=network=101:network=101 PROVIDES:=hostapd @@ -253,7 +253,7 @@ define Package/wpad/Default CATEGORY:=Network SUBMENU:=WirelessAPD TITLE:=IEEE 802.1x Auth/Supplicant - DEPENDS:=$(DRV_DEPENDS) +hostapd-common +libubus + DEPENDS:=$(DRV_DEPENDS) +hostapd-common +libubus +libblobmsg-json EXTRA_DEPENDS:=hostapd-common (=$(PKG_VERSION)-$(PKG_RELEASE)) USERID:=network=101:network=101 URL:=http://hostap.epitest.fi/ @@ -398,7 +398,7 @@ define Package/wpa-supplicant/Default SUBMENU:=WirelessAPD TITLE:=WPA Supplicant URL:=http://hostap.epitest.fi/wpa_supplicant/ - DEPENDS:=$(DRV_DEPENDS) +hostapd-common +libubus + DEPENDS:=$(DRV_DEPENDS) +hostapd-common +libubus +libblobmsg-json EXTRA_DEPENDS:=hostapd-common (=$(PKG_VERSION)-$(PKG_RELEASE)) USERID:=network=101:network=101 PROVIDES:=wpa-supplicant @@ -520,7 +520,7 @@ define Package/eapol-test/Default SECTION:=net SUBMENU:=WirelessAPD CATEGORY:=Network - DEPENDS:=$(DRV_DEPENDS) +libubus + DEPENDS:=$(DRV_DEPENDS) +libubus +libblobmsg-json endef define Package/eapol-test @@ -585,7 +585,7 @@ TARGET_CPPFLAGS := \ -D_GNU_SOURCE \ $(if $(CONFIG_WPA_MSG_MIN_PRIORITY),-DCONFIG_MSG_MIN_PRIORITY=$(CONFIG_WPA_MSG_MIN_PRIORITY)) -TARGET_LDFLAGS += -lubox -lubus +TARGET_LDFLAGS += -lubox -lubus -lblobmsg_json ifdef CONFIG_PACKAGE_kmod-cfg80211 TARGET_LDFLAGS += -lm -lnl-tiny @@ -674,8 +674,37 @@ define Build/Compile $(Build/Compile/$(BUILD_VARIANT)) endef +define Install/hostapd/full + $(INSTALL_DIR) $(1)/etc/init.d $(1)/etc/config $(1)/etc/radius + ln -sf hostapd $(1)/usr/sbin/hostapd-radius + $(INSTALL_BIN) ./files/radius.init $(1)/etc/init.d/radius + $(INSTALL_DATA) ./files/radius.config $(1)/etc/config/radius + $(INSTALL_DATA) ./files/radius.clients $(1)/etc/radius/clients + $(INSTALL_DATA) ./files/radius.users $(1)/etc/radius/users +endef + +define Package/hostapd-full/conffiles +/etc/config/radius +/etc/radius +endef + +ifeq ($(CONFIG_VARIANT),full) +Package/wpad-mesh-openssl/conffiles = $(Package/hostapd-full/conffiles) +Package/wpad-mesh-wolfssl/conffiles = $(Package/hostapd-full/conffiles) +Package/wpad-mesh-mbedtls/conffiles = $(Package/hostapd-full/conffiles) +Package/wpad/conffiles = $(Package/hostapd-full/conffiles) +Package/wpad-openssl/conffiles = $(Package/hostapd-full/conffiles) +Package/wpad-wolfssl/conffiles = $(Package/hostapd-full/conffiles) +Package/wpad-mbedtls/conffiles = $(Package/hostapd-full/conffiles) +Package/hostapd/conffiles = $(Package/hostapd-full/conffiles) +Package/hostapd-openssl/conffiles = $(Package/hostapd-full/conffiles) +Package/hostapd-wolfssl/conffiles = $(Package/hostapd-full/conffiles) +Package/hostapd-mbedtls/conffiles = $(Package/hostapd-full/conffiles) +endif + define Install/hostapd $(INSTALL_DIR) $(1)/usr/sbin + $(if $(findstring full,$(CONFIG_VARIANT)),$(Install/hostapd/full)) endef define Install/supplicant diff --git a/package/network/services/hostapd/files/radius.clients b/package/network/services/hostapd/files/radius.clients new file mode 100644 index 0000000000..3175dcfd04 --- /dev/null +++ b/package/network/services/hostapd/files/radius.clients @@ -0,0 +1 @@ +0.0.0.0/0 radius diff --git a/package/network/services/hostapd/files/radius.config b/package/network/services/hostapd/files/radius.config new file mode 100644 index 0000000000..ad8730748b --- /dev/null +++ b/package/network/services/hostapd/files/radius.config @@ -0,0 +1,9 @@ +config radius + option disabled '1' + option ca_cert '/etc/radius/ca.pem' + option cert '/etc/radius/cert.pem' + option key '/etc/radius/key.pem' + option users '/etc/radius/users' + option clients '/etc/radius/clients' + option auth_port '1812' + option acct_port '1813' diff --git a/package/network/services/hostapd/files/radius.init b/package/network/services/hostapd/files/radius.init new file mode 100644 index 0000000000..4c562c2473 --- /dev/null +++ b/package/network/services/hostapd/files/radius.init @@ -0,0 +1,42 @@ +#!/bin/sh /etc/rc.common + +START=30 + +USE_PROCD=1 +NAME=radius + +radius_start() { + local cfg="$1" + + config_get_bool disabled "$cfg" disabled 0 + + [ "$disabled" -gt 0 ] && return + + config_get ca "$cfg" ca_cert + config_get key "$cfg" key + config_get cert "$cfg" cert + config_get users "$cfg" users + config_get clients "$cfg" clients + config_get auth_port "$cfg" auth_port 1812 + config_get acct_port "$cfg" acct_port 1813 + config_get identity "$cfg" identity "$(cat /proc/sys/kernel/hostname)" + + procd_open_instance $cfg + procd_set_param command /usr/sbin/hostapd-radius \ + -C "$ca" \ + -c "$cert" -k "$key" \ + -s "$clients" -u "$users" \ + -p "$auth_port" -P "$acct_port" \ + -i "$identity" + procd_close_instance +} + +start_service() { + config_load radius + config_foreach radius_start radius +} + +service_triggers() +{ + procd_add_reload_trigger "radius" +} diff --git a/package/network/services/hostapd/files/radius.users b/package/network/services/hostapd/files/radius.users new file mode 100644 index 0000000000..03e2fc8fae --- /dev/null +++ b/package/network/services/hostapd/files/radius.users @@ -0,0 +1,14 @@ +{ + "phase1": { + "wildcard": [ + { + "name": "*", + "methods": [ "PEAP" ] + } + ] + }, + "phase2": { + "users": { + } + } +} diff --git a/package/network/services/hostapd/patches/770-radius_server.patch b/package/network/services/hostapd/patches/770-radius_server.patch new file mode 100644 index 0000000000..3f0f40c0f7 --- /dev/null +++ b/package/network/services/hostapd/patches/770-radius_server.patch @@ -0,0 +1,154 @@ +--- a/hostapd/Makefile ++++ b/hostapd/Makefile +@@ -63,6 +63,10 @@ endif + OBJS += main.o + OBJS += config_file.o + ++ifdef CONFIG_RADIUS_SERVER ++OBJS += radius.o ++endif ++ + OBJS += ../src/ap/hostapd.o + OBJS += ../src/ap/wpa_auth_glue.o + OBJS += ../src/ap/drv_callbacks.o +--- a/hostapd/main.c ++++ b/hostapd/main.c +@@ -42,6 +42,7 @@ static struct hapd_global global; + static int daemonize = 0; + static char *pid_file = NULL; + ++extern int radius_main(int argc, char **argv); + + #ifndef CONFIG_NO_HOSTAPD_LOGGER + static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module, +@@ -665,6 +666,11 @@ int main(int argc, char *argv[]) + if (os_program_init()) + return -1; + ++#ifdef RADIUS_SERVER ++ if (strstr(argv[0], "radius")) ++ return radius_main(argc, argv); ++#endif ++ + os_memset(&interfaces, 0, sizeof(interfaces)); + interfaces.reload_config = hostapd_reload_config; + interfaces.config_read_cb = hostapd_config_read; +--- a/src/radius/radius_server.c ++++ b/src/radius/radius_server.c +@@ -63,6 +63,12 @@ struct radius_server_counters { + u32 unknown_acct_types; + }; + ++struct radius_accept_attr { ++ u8 type; ++ u16 len; ++ void *data; ++}; ++ + /** + * struct radius_session - Internal RADIUS server data for a session + */ +@@ -90,7 +96,7 @@ struct radius_session { + unsigned int macacl:1; + unsigned int t_c_filtering:1; + +- struct hostapd_radius_attr *accept_attr; ++ struct radius_accept_attr *accept_attr; + + u32 t_c_timestamp; /* Last read T&C timestamp from user DB */ + }; +@@ -394,6 +400,7 @@ static void radius_server_session_free(s + radius_msg_free(sess->last_reply); + os_free(sess->username); + os_free(sess->nas_ip); ++ os_free(sess->accept_attr); + os_free(sess); + data->num_sess--; + } +@@ -554,6 +561,36 @@ radius_server_erp_find_key(struct radius + } + #endif /* CONFIG_ERP */ + ++static struct radius_accept_attr * ++radius_server_copy_attr(const struct hostapd_radius_attr *data) ++{ ++ const struct hostapd_radius_attr *attr; ++ struct radius_accept_attr *attr_new; ++ size_t data_size = 0; ++ void *data_buf; ++ int n_attr = 1; ++ ++ for (attr = data; attr; attr = attr->next) { ++ n_attr++; ++ data_size += wpabuf_len(attr->val); ++ } ++ ++ attr_new = os_zalloc(n_attr * sizeof(*attr) + data_size); ++ if (!attr_new) ++ return NULL; ++ ++ data_buf = &attr_new[n_attr]; ++ for (n_attr = 0, attr = data; attr; attr = attr->next) { ++ struct radius_accept_attr *cur = &attr_new[n_attr++]; ++ ++ cur->type = attr->type; ++ cur->len = wpabuf_len(attr->val); ++ cur->data = memcpy(data_buf, wpabuf_head(attr->val), cur->len); ++ data_buf += cur->len; ++ } ++ ++ return attr_new; ++} + + static struct radius_session * + radius_server_get_new_session(struct radius_server_data *data, +@@ -607,7 +644,7 @@ radius_server_get_new_session(struct rad + eap_user_free(tmp); + return NULL; + } +- sess->accept_attr = tmp->accept_attr; ++ sess->accept_attr = radius_server_copy_attr(tmp->accept_attr); + sess->macacl = tmp->macacl; + eap_user_free(tmp); + +@@ -1118,11 +1155,10 @@ radius_server_encapsulate_eap(struct rad + } + + if (code == RADIUS_CODE_ACCESS_ACCEPT) { +- struct hostapd_radius_attr *attr; +- for (attr = sess->accept_attr; attr; attr = attr->next) { +- if (!radius_msg_add_attr(msg, attr->type, +- wpabuf_head(attr->val), +- wpabuf_len(attr->val))) { ++ struct radius_accept_attr *attr; ++ for (attr = sess->accept_attr; attr->data; attr++) { ++ if (!radius_msg_add_attr(msg, attr->type, attr->data, ++ attr->len)) { + wpa_printf(MSG_ERROR, "Could not add RADIUS attribute"); + radius_msg_free(msg); + return NULL; +@@ -1211,11 +1247,10 @@ radius_server_macacl(struct radius_serve + } + + if (code == RADIUS_CODE_ACCESS_ACCEPT) { +- struct hostapd_radius_attr *attr; +- for (attr = sess->accept_attr; attr; attr = attr->next) { +- if (!radius_msg_add_attr(msg, attr->type, +- wpabuf_head(attr->val), +- wpabuf_len(attr->val))) { ++ struct radius_accept_attr *attr; ++ for (attr = sess->accept_attr; attr->data; attr++) { ++ if (!radius_msg_add_attr(msg, attr->type, attr->data, ++ attr->len)) { + wpa_printf(MSG_ERROR, "Could not add RADIUS attribute"); + radius_msg_free(msg); + return NULL; +@@ -2512,7 +2547,7 @@ static int radius_server_get_eap_user(vo + ret = data->get_eap_user(data->conf_ctx, identity, identity_len, + phase2, user); + if (ret == 0 && user) { +- sess->accept_attr = user->accept_attr; ++ sess->accept_attr = radius_server_copy_attr(user->accept_attr); + sess->remediation = user->remediation; + sess->macacl = user->macacl; + sess->t_c_timestamp = user->t_c_timestamp; diff --git a/package/network/services/hostapd/src/hostapd/radius.c b/package/network/services/hostapd/src/hostapd/radius.c new file mode 100644 index 0000000000..362a22c276 --- /dev/null +++ b/package/network/services/hostapd/src/hostapd/radius.c @@ -0,0 +1,715 @@ +#include "utils/includes.h" +#include "utils/common.h" +#include "utils/eloop.h" +#include "crypto/crypto.h" +#include "crypto/tls.h" + +#include "ap/ap_config.h" +#include "eap_server/eap.h" +#include "radius/radius.h" +#include "radius/radius_server.h" +#include "eap_register.h" + +#include +#include +#include +#include +#include + +#include +#include + +#define VENDOR_ID_WISPR 14122 +#define VENDOR_ATTR_SIZE 6 + +struct radius_parse_attr_data { + unsigned int vendor; + u8 type; + int size; + char format; + const char *data; +}; + +struct radius_parse_attr_state { + struct hostapd_radius_attr *prev; + struct hostapd_radius_attr *attr; + struct wpabuf *buf; + void *attrdata; +}; + +struct radius_user_state { + struct avl_node node; + struct eap_user data; +}; + +struct radius_user_data { + struct kvlist users; + struct avl_tree user_state; + struct blob_attr *wildcard; +}; + +struct radius_state { + struct radius_server_data *radius; + struct eap_config eap; + + struct radius_user_data phase1, phase2; + const char *user_file; + time_t user_file_ts; + + int n_attrs; + struct hostapd_radius_attr *attrs; +}; + +struct radius_config { + struct tls_connection_params tls; + struct radius_server_conf radius; +}; + +enum { + USER_ATTR_PASSWORD, + USER_ATTR_HASH, + USER_ATTR_SALT, + USER_ATTR_METHODS, + USER_ATTR_RADIUS, + USER_ATTR_VLAN, + USER_ATTR_MAX_RATE_UP, + USER_ATTR_MAX_RATE_DOWN, + __USER_ATTR_MAX +}; + +static void radius_tls_event(void *ctx, enum tls_event ev, + union tls_event_data *data) +{ + switch (ev) { + case TLS_CERT_CHAIN_SUCCESS: + wpa_printf(MSG_DEBUG, "radius: remote certificate verification success"); + break; + case TLS_CERT_CHAIN_FAILURE: + wpa_printf(MSG_INFO, "radius: certificate chain failure: reason=%d depth=%d subject='%s' err='%s'", + data->cert_fail.reason, + data->cert_fail.depth, + data->cert_fail.subject, + data->cert_fail.reason_txt); + break; + case TLS_PEER_CERTIFICATE: + wpa_printf(MSG_DEBUG, "radius: peer certificate: depth=%d serial_num=%s subject=%s", + data->peer_cert.depth, + data->peer_cert.serial_num ? data->peer_cert.serial_num : "N/A", + data->peer_cert.subject); + break; + case TLS_ALERT: + if (data->alert.is_local) + wpa_printf(MSG_DEBUG, "radius: local TLS alert: %s", + data->alert.description); + else + wpa_printf(MSG_DEBUG, "radius: remote TLS alert: %s", + data->alert.description); + break; + case TLS_UNSAFE_RENEGOTIATION_DISABLED: + /* Not applicable to TLS server */ + break; + } +} + +static void radius_userdata_init(struct radius_user_data *u) +{ + kvlist_init(&u->users, kvlist_blob_len); + avl_init(&u->user_state, avl_strcmp, false, NULL); +} + +static void radius_userdata_free(struct radius_user_data *u) +{ + struct radius_user_state *s, *tmp; + + kvlist_free(&u->users); + free(u->wildcard); + u->wildcard = NULL; + avl_remove_all_elements(&u->user_state, s, node, tmp) + free(s); +} + +static void +radius_userdata_load(struct radius_user_data *u, struct blob_attr *data) +{ + enum { + USERSTATE_USERS, + USERSTATE_WILDCARD, + __USERSTATE_MAX, + }; + static const struct blobmsg_policy policy[__USERSTATE_MAX] = { + [USERSTATE_USERS] = { "users", BLOBMSG_TYPE_TABLE }, + [USERSTATE_WILDCARD] = { "wildcard", BLOBMSG_TYPE_ARRAY }, + }; + struct blob_attr *tb[__USERSTATE_MAX], *cur; + int rem; + + if (!data) + return; + + blobmsg_parse(policy, __USERSTATE_MAX, tb, blobmsg_data(data), blobmsg_len(data)); + + blobmsg_for_each_attr(cur, tb[USERSTATE_USERS], rem) + kvlist_set(&u->users, blobmsg_name(cur), cur); + + if (tb[USERSTATE_WILDCARD]) + u->wildcard = blob_memdup(tb[USERSTATE_WILDCARD]); +} + +static void +load_userfile(struct radius_state *s) +{ + enum { + USERDATA_PHASE1, + USERDATA_PHASE2, + __USERDATA_MAX + }; + static const struct blobmsg_policy policy[__USERDATA_MAX] = { + [USERDATA_PHASE1] = { "phase1", BLOBMSG_TYPE_TABLE }, + [USERDATA_PHASE2] = { "phase2", BLOBMSG_TYPE_TABLE }, + }; + struct blob_attr *tb[__USERDATA_MAX], *cur; + static struct blob_buf b; + struct stat st; + int rem; + + if (stat(s->user_file, &st)) + return; + + if (s->user_file_ts == st.st_mtime) + return; + + s->user_file_ts = st.st_mtime; + radius_userdata_free(&s->phase1); + radius_userdata_free(&s->phase2); + + blob_buf_init(&b, 0); + blobmsg_add_json_from_file(&b, s->user_file); + blobmsg_parse(policy, __USERDATA_MAX, tb, blob_data(b.head), blob_len(b.head)); + radius_userdata_load(&s->phase1, tb[USERDATA_PHASE1]); + radius_userdata_load(&s->phase2, tb[USERDATA_PHASE2]); + + blob_buf_free(&b); +} + +static struct blob_attr * +radius_user_get(struct radius_user_data *s, const char *name) +{ + struct blob_attr *cur; + int rem; + + cur = kvlist_get(&s->users, name); + if (cur) + return cur; + + blobmsg_for_each_attr(cur, s->wildcard, rem) { + static const struct blobmsg_policy policy = { + "name", BLOBMSG_TYPE_STRING + }; + struct blob_attr *pattern; + + if (blobmsg_type(cur) != BLOBMSG_TYPE_TABLE) + continue; + + blobmsg_parse(&policy, 1, &pattern, blobmsg_data(cur), blobmsg_len(cur)); + if (!name) + continue; + + if (!fnmatch(blobmsg_get_string(pattern), name, 0)) + return cur; + } + + return NULL; +} + +static struct radius_parse_attr_data * +radius_parse_attr(struct blob_attr *attr) +{ + static const struct blobmsg_policy policy[4] = { + { .type = BLOBMSG_TYPE_INT32 }, + { .type = BLOBMSG_TYPE_INT32 }, + { .type = BLOBMSG_TYPE_STRING }, + { .type = BLOBMSG_TYPE_STRING }, + }; + static struct radius_parse_attr_data data; + struct blob_attr *tb[4]; + const char *format; + + blobmsg_parse_array(policy, ARRAY_SIZE(policy), tb, blobmsg_data(attr), blobmsg_len(attr)); + + if (!tb[0] || !tb[1] || !tb[2] || !tb[3]) + return NULL; + + format = blobmsg_get_string(tb[2]); + if (strlen(format) != 1) + return NULL; + + data.vendor = blobmsg_get_u32(tb[0]); + data.type = blobmsg_get_u32(tb[1]); + data.format = format[0]; + data.data = blobmsg_get_string(tb[3]); + data.size = strlen(data.data); + + switch (data.format) { + case 's': + break; + case 'x': + if (data.size & 1) + return NULL; + data.size /= 2; + break; + case 'd': + data.size = 4; + break; + default: + return NULL; + } + + return &data; +} + +static void +radius_count_attrs(struct blob_attr **tb, int *n_attr, size_t *attr_size) +{ + struct blob_attr *data = tb[USER_ATTR_RADIUS]; + struct blob_attr *cur; + int rem; + + blobmsg_for_each_attr(cur, data, rem) { + struct radius_parse_attr_data *data; + size_t prev = *attr_size; + + data = radius_parse_attr(cur); + if (!data) + continue; + + *attr_size += data->size; + if (data->vendor) + *attr_size += VENDOR_ATTR_SIZE; + + (*n_attr)++; + } + + *n_attr += !!tb[USER_ATTR_VLAN] * 3 + + !!tb[USER_ATTR_MAX_RATE_UP] + + !!tb[USER_ATTR_MAX_RATE_DOWN]; + *attr_size += !!tb[USER_ATTR_VLAN] * (4 + 4 + 5) + + !!tb[USER_ATTR_MAX_RATE_UP] * (4 + VENDOR_ATTR_SIZE) + + !!tb[USER_ATTR_MAX_RATE_DOWN] * (4 + VENDOR_ATTR_SIZE); +} + +static void * +radius_add_attr(struct radius_parse_attr_state *state, + u32 vendor, u8 type, u8 len) +{ + struct hostapd_radius_attr *attr; + struct wpabuf *buf; + void *val; + + val = state->attrdata; + + buf = state->buf++; + buf->buf = val; + + attr = state->attr++; + attr->val = buf; + attr->type = type; + + if (state->prev) + state->prev->next = attr; + state->prev = attr; + + if (vendor) { + u8 *vendor_hdr = val + 4; + + WPA_PUT_BE32(val, vendor); + vendor_hdr[0] = type; + vendor_hdr[1] = len + 2; + + len += VENDOR_ATTR_SIZE; + val += VENDOR_ATTR_SIZE; + attr->type = RADIUS_ATTR_VENDOR_SPECIFIC; + } + + buf->size = buf->used = len; + state->attrdata += len; + + return val; +} + +static void +radius_parse_attrs(struct blob_attr **tb, struct radius_parse_attr_state *state) +{ + struct blob_attr *data = tb[USER_ATTR_RADIUS]; + struct hostapd_radius_attr *prev = NULL; + struct blob_attr *cur; + int len, rem; + void *val; + + if ((cur = tb[USER_ATTR_VLAN]) != NULL && blobmsg_get_u32(cur) < 4096) { + char buf[5]; + + val = radius_add_attr(state, 0, RADIUS_ATTR_TUNNEL_TYPE, 4); + WPA_PUT_BE32(val, RADIUS_TUNNEL_TYPE_VLAN); + + val = radius_add_attr(state, 0, RADIUS_ATTR_TUNNEL_MEDIUM_TYPE, 4); + WPA_PUT_BE32(val, RADIUS_TUNNEL_MEDIUM_TYPE_802); + + len = snprintf(buf, sizeof(buf), "%d", blobmsg_get_u32(cur)); + val = radius_add_attr(state, 0, RADIUS_ATTR_TUNNEL_PRIVATE_GROUP_ID, len); + memcpy(val, buf, len); + } + + if ((cur = tb[USER_ATTR_MAX_RATE_UP]) != NULL) { + val = radius_add_attr(state, VENDOR_ID_WISPR, 7, 4); + WPA_PUT_BE32(val, blobmsg_get_u32(cur)); + } + + if ((cur = tb[USER_ATTR_MAX_RATE_DOWN]) != NULL) { + val = radius_add_attr(state, VENDOR_ID_WISPR, 8, 4); + WPA_PUT_BE32(val, blobmsg_get_u32(cur)); + } + + blobmsg_for_each_attr(cur, data, rem) { + struct radius_parse_attr_data *data; + void *val; + int size; + + data = radius_parse_attr(cur); + if (!data) + continue; + + val = radius_add_attr(state, data->vendor, data->type, data->size); + switch (data->format) { + case 's': + memcpy(val, data->data, data->size); + break; + case 'x': + hexstr2bin(data->data, val, data->size); + break; + case 'd': + WPA_PUT_BE32(val, atoi(data->data)); + break; + } + } +} + +static void +radius_user_parse_methods(struct eap_user *eap, struct blob_attr *data) +{ + struct blob_attr *cur; + int rem, n = 0; + + if (!data) + return; + + blobmsg_for_each_attr(cur, data, rem) { + const char *method; + + if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING) + continue; + + if (n == EAP_MAX_METHODS) + break; + + method = blobmsg_get_string(cur); + eap->methods[n].method = eap_server_get_type(method, &eap->methods[n].vendor); + if (eap->methods[n].vendor == EAP_VENDOR_IETF && + eap->methods[n].method == EAP_TYPE_NONE) { + if (!strcmp(method, "TTLS-PAP")) { + eap->ttls_auth |= EAP_TTLS_AUTH_PAP; + continue; + } + if (!strcmp(method, "TTLS-CHAP")) { + eap->ttls_auth |= EAP_TTLS_AUTH_CHAP; + continue; + } + if (!strcmp(method, "TTLS-MSCHAP")) { + eap->ttls_auth |= EAP_TTLS_AUTH_MSCHAP; + continue; + } + if (!strcmp(method, "TTLS-MSCHAPV2")) { + eap->ttls_auth |= EAP_TTLS_AUTH_MSCHAPV2; + continue; + } + } + n++; + } +} + +static struct eap_user * +radius_user_get_state(struct radius_user_data *u, struct blob_attr *data, + const char *id) +{ + static const struct blobmsg_policy policy[__USER_ATTR_MAX] = { + [USER_ATTR_PASSWORD] = { "password", BLOBMSG_TYPE_STRING }, + [USER_ATTR_HASH] = { "hash", BLOBMSG_TYPE_STRING }, + [USER_ATTR_SALT] = { "salt", BLOBMSG_TYPE_STRING }, + [USER_ATTR_METHODS] = { "methods", BLOBMSG_TYPE_ARRAY }, + [USER_ATTR_RADIUS] = { "radius", BLOBMSG_TYPE_ARRAY }, + [USER_ATTR_VLAN] = { "vlan-id", BLOBMSG_TYPE_INT32 }, + [USER_ATTR_MAX_RATE_UP] = { "max-rate-up", BLOBMSG_TYPE_INT32 }, + [USER_ATTR_MAX_RATE_DOWN] = { "max-rate-down", BLOBMSG_TYPE_INT32 }, + }; + struct blob_attr *tb[__USER_ATTR_MAX], *cur; + char *password_buf, *salt_buf, *name_buf; + struct radius_parse_attr_state astate = {}; + struct hostapd_radius_attr *attr; + struct radius_user_state *state; + int pw_len = 0, salt_len = 0; + struct eap_user *eap; + struct wpabuf *val; + size_t attrsize = 0; + void *attrdata; + int n_attr = 0; + + state = avl_find_element(&u->user_state, id, state, node); + if (state) + return &state->data; + + blobmsg_parse(policy, __USER_ATTR_MAX, tb, blobmsg_data(data), blobmsg_len(data)); + + if ((cur = tb[USER_ATTR_SALT]) != NULL) + salt_len = strlen(blobmsg_get_string(cur)) / 2; + if ((cur = tb[USER_ATTR_HASH]) != NULL) + pw_len = strlen(blobmsg_get_string(cur)) / 2; + else if ((cur = tb[USER_ATTR_PASSWORD]) != NULL) + pw_len = blobmsg_len(cur) - 1; + radius_count_attrs(tb, &n_attr, &attrsize); + + state = calloc_a(sizeof(*state), &name_buf, strlen(id) + 1, + &password_buf, pw_len, + &salt_buf, salt_len, + &astate.attr, n_attr * sizeof(*astate.attr), + &astate.buf, n_attr * sizeof(*astate.buf), + &astate.attrdata, attrsize); + eap = &state->data; + eap->salt = salt_len ? salt_buf : NULL; + eap->salt_len = salt_len; + eap->password = pw_len ? password_buf : NULL; + eap->password_len = pw_len; + eap->force_version = -1; + + if ((cur = tb[USER_ATTR_SALT]) != NULL) + hexstr2bin(blobmsg_get_string(cur), salt_buf, salt_len); + if ((cur = tb[USER_ATTR_PASSWORD]) != NULL) + memcpy(password_buf, blobmsg_get_string(cur), pw_len); + else if ((cur = tb[USER_ATTR_HASH]) != NULL) { + hexstr2bin(blobmsg_get_string(cur), password_buf, pw_len); + eap->password_hash = 1; + } + radius_user_parse_methods(eap, tb[USER_ATTR_METHODS]); + + if (n_attr > 0) { + cur = tb[USER_ATTR_RADIUS]; + eap->accept_attr = astate.attr; + radius_parse_attrs(tb, &astate); + } + + state->node.key = strcpy(name_buf, id); + avl_insert(&u->user_state, &state->node); + + return &state->data; + +free: + free(state); + return NULL; +} + +static int radius_get_eap_user(void *ctx, const u8 *identity, + size_t identity_len, int phase2, + struct eap_user *user) +{ + struct radius_state *s = ctx; + struct radius_user_data *u = phase2 ? &s->phase2 : &s->phase1; + struct blob_attr *entry; + struct eap_user *data; + char *id; + + if (identity_len > 512) + return -1; + + load_userfile(s); + + id = alloca(identity_len + 1); + memcpy(id, identity, identity_len); + id[identity_len] = 0; + + entry = radius_user_get(u, id); + if (!entry) + return -1; + + if (!user) + return 0; + + data = radius_user_get_state(u, entry, id); + if (!data) + return -1; + + *user = *data; + if (user->password_len > 0) + user->password = os_memdup(user->password, user->password_len); + if (user->salt_len > 0) + user->salt = os_memdup(user->salt, user->salt_len); + user->phase2 = phase2; + + return 0; +} + +static int radius_setup(struct radius_state *s, struct radius_config *c) +{ + struct eap_config *eap = &s->eap; + struct tls_config conf = { + .event_cb = radius_tls_event, + .tls_flags = TLS_CONN_DISABLE_TLSv1_3, + .cb_ctx = s, + }; + + eap->eap_server = 1; + eap->max_auth_rounds = 100; + eap->max_auth_rounds_short = 50; + eap->ssl_ctx = tls_init(&conf); + if (!eap->ssl_ctx) { + wpa_printf(MSG_INFO, "TLS init failed\n"); + return 1; + } + + if (tls_global_set_params(eap->ssl_ctx, &c->tls)) { + wpa_printf(MSG_INFO, "failed to set TLS parameters\n"); + return 1; + } + + c->radius.eap_cfg = eap; + c->radius.conf_ctx = s; + c->radius.get_eap_user = radius_get_eap_user; + s->radius = radius_server_init(&c->radius); + if (!s->radius) { + wpa_printf(MSG_INFO, "failed to initialize radius server\n"); + return 1; + } + + return 0; +} + +static int radius_init(struct radius_state *s) +{ + memset(s, 0, sizeof(*s)); + radius_userdata_init(&s->phase1); + radius_userdata_init(&s->phase2); +} + +static void radius_deinit(struct radius_state *s) +{ + if (s->radius) + radius_server_deinit(s->radius); + + if (s->eap.ssl_ctx) + tls_deinit(s->eap.ssl_ctx); + + radius_userdata_free(&s->phase1); + radius_userdata_free(&s->phase2); +} + +static int usage(const char *progname) +{ + fprintf(stderr, "Usage: %s \n", + progname); +} + +int radius_main(int argc, char **argv) +{ + static struct radius_state state = {}; + static struct radius_config config = {}; + const char *progname = argv[0]; + int ret = 0; + int ch; + + wpa_debug_setup_stdout(); + wpa_debug_level = 0; + + if (eloop_init()) { + wpa_printf(MSG_ERROR, "Failed to initialize event loop"); + return 1; + } + + eap_server_register_methods(); + radius_init(&state); + + while ((ch = getopt(argc, argv, "6C:c:d:i:k:K:p:P:s:u:")) != -1) { + switch (ch) { + case '6': + config.radius.ipv6 = 1; + break; + case 'C': + config.tls.ca_cert = optarg; + break; + case 'c': + if (config.tls.client_cert2) + return usage(progname); + + if (config.tls.client_cert) + config.tls.client_cert2 = optarg; + else + config.tls.client_cert = optarg; + break; + case 'd': + config.tls.dh_file = optarg; + break; + case 'i': + state.eap.server_id = optarg; + state.eap.server_id_len = strlen(optarg); + break; + case 'k': + if (config.tls.private_key2) + return usage(progname); + + if (config.tls.private_key) + config.tls.private_key2 = optarg; + else + config.tls.private_key = optarg; + break; + case 'K': + if (config.tls.private_key_passwd2) + return usage(progname); + + if (config.tls.private_key_passwd) + config.tls.private_key_passwd2 = optarg; + else + config.tls.private_key_passwd = optarg; + break; + case 'p': + config.radius.auth_port = atoi(optarg); + break; + case 'P': + config.radius.acct_port = atoi(optarg); + break; + case 's': + config.radius.client_file = optarg; + break; + case 'u': + state.user_file = optarg; + break; + default: + return usage(progname); + } + } + + if (!config.tls.client_cert || !config.tls.private_key || + !config.radius.client_file || !state.eap.server_id || + !state.user_file) { + wpa_printf(MSG_INFO, "missing options\n"); + goto out; + } + + ret = radius_setup(&state, &config); + if (ret) + goto out; + + load_userfile(&state); + eloop_run(); + +out: + radius_deinit(&state); + os_program_deinit(); + + return ret; +} From 9769655d1b298337694f564c36b22844b1ec500e Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 21 Jul 2023 13:05:23 +0200 Subject: [PATCH 08/23] hostapd: add support for querying assoc/probe IEs Signed-off-by: Felix Fietkau --- .../services/hostapd/src/src/ap/ubus.c | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/package/network/services/hostapd/src/src/ap/ubus.c b/package/network/services/hostapd/src/src/ap/ubus.c index ddd86447eb..077d40c268 100644 --- a/package/network/services/hostapd/src/src/ap/ubus.c +++ b/package/network/services/hostapd/src/src/ap/ubus.c @@ -1669,10 +1669,61 @@ hostapd_bss_update_airtime(struct ubus_context *ctx, struct ubus_object *obj, } #endif +#ifdef CONFIG_TAXONOMY +static const struct blobmsg_policy addr_policy[] = { + { "address", BLOBMSG_TYPE_STRING } +}; + +static bool +hostapd_add_b64_data(const char *name, const struct wpabuf *buf) +{ + char *str; + + if (!buf) + return false; + + str = blobmsg_alloc_string_buffer(&b, name, B64_ENCODE_LEN(wpabuf_len(buf))); + b64_encode(wpabuf_head(buf), wpabuf_len(buf), str, B64_ENCODE_LEN(wpabuf_len(buf))); + blobmsg_add_string_buffer(&b); + + return true; +} + +static int +hostapd_bss_get_sta_ies(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); + struct blob_attr *tb; + struct sta_info *sta; + u8 addr[ETH_ALEN]; + + blobmsg_parse(addr_policy, 1, &tb, blobmsg_data(msg), blobmsg_len(msg)); + + if (!tb || hwaddr_aton(blobmsg_data(tb), addr)) + return UBUS_STATUS_INVALID_ARGUMENT; + + sta = ap_get_sta(hapd, addr); + if (!sta || (!sta->probe_ie_taxonomy && !sta->assoc_ie_taxonomy)) + return UBUS_STATUS_NOT_FOUND; + + blob_buf_init(&b, 0); + hostapd_add_b64_data("probe_ie", sta->probe_ie_taxonomy); + hostapd_add_b64_data("assoc_ie", sta->assoc_ie_taxonomy); + ubus_send_reply(ctx, req, b.head); + + return 0; +} +#endif + static const struct ubus_method bss_methods[] = { UBUS_METHOD_NOARG("reload", hostapd_bss_reload), UBUS_METHOD_NOARG("get_clients", hostapd_bss_get_clients), +#ifdef CONFIG_TAXONOMY + UBUS_METHOD("get_sta_ies", hostapd_bss_get_sta_ies, addr_policy), +#endif UBUS_METHOD_NOARG("get_status", hostapd_bss_get_status), UBUS_METHOD("del_client", hostapd_bss_del_client, del_policy), #ifdef CONFIG_AIRTIME_POLICY From 33e4ad767e085f691bf5433d8808b20dfcf63222 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 24 May 2023 10:23:13 +0200 Subject: [PATCH 09/23] hostapd: switch to using uloop (integrated with built-in eloop) Preparation for pulling in more code that uses uloop Signed-off-by: Felix Fietkau --- .../hostapd/patches/600-ubus_support.patch | 156 +++++++++++++++++- .../services/hostapd/src/src/ap/ubus.c | 16 +- .../hostapd/src/wpa_supplicant/ubus.c | 16 +- 3 files changed, 165 insertions(+), 23 deletions(-) diff --git a/package/network/services/hostapd/patches/600-ubus_support.patch b/package/network/services/hostapd/patches/600-ubus_support.patch index f3936342a5..1be2b1fdf8 100644 --- a/package/network/services/hostapd/patches/600-ubus_support.patch +++ b/package/network/services/hostapd/patches/600-ubus_support.patch @@ -1,11 +1,12 @@ --- a/hostapd/Makefile +++ b/hostapd/Makefile -@@ -166,6 +166,11 @@ OBJS += ../src/common/hw_features_common +@@ -166,6 +166,12 @@ OBJS += ../src/common/hw_features_common OBJS += ../src/eapol_auth/eapol_auth_sm.o +ifdef CONFIG_UBUS +CFLAGS += -DUBUS_SUPPORT ++OBJS += ../src/utils/uloop.o +OBJS += ../src/ap/ubus.o +LIBS += -lubox -lubus +endif @@ -330,20 +331,21 @@ --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile -@@ -194,6 +194,12 @@ ifdef CONFIG_EAPOL_TEST +@@ -194,6 +194,13 @@ ifdef CONFIG_EAPOL_TEST CFLAGS += -Werror -DEAPOL_TEST endif +ifdef CONFIG_UBUS +CFLAGS += -DUBUS_SUPPORT +OBJS += ubus.o ++OBJS += ../src/utils/uloop.o +LIBS += -lubox -lubus +endif + ifdef CONFIG_CODE_COVERAGE CFLAGS += -O0 -fprofile-arcs -ftest-coverage LIBS += -lgcov -@@ -989,6 +995,9 @@ ifdef CONFIG_CTRL_IFACE_MIB +@@ -989,6 +996,9 @@ ifdef CONFIG_CTRL_IFACE_MIB CFLAGS += -DCONFIG_CTRL_IFACE_MIB endif OBJS += ../src/ap/ctrl_iface_ap.o @@ -623,3 +625,151 @@ wpa_hexdump(MSG_DEBUG, "WNM: BSS Transition Candidate List Entries", pos, end - pos); } +--- a/src/utils/eloop.c ++++ b/src/utils/eloop.c +@@ -77,6 +77,9 @@ struct eloop_sock_table { + struct eloop_data { + int max_sock; + ++ eloop_timeout_poll_handler timeout_poll_cb; ++ eloop_poll_handler poll_cb; ++ + size_t count; /* sum of all table counts */ + #ifdef CONFIG_ELOOP_POLL + size_t max_pollfd_map; /* number of pollfds_map currently allocated */ +@@ -1121,6 +1124,12 @@ void eloop_run(void) + os_reltime_sub(&timeout->time, &now, &tv); + else + tv.sec = tv.usec = 0; ++ } ++ ++ if (eloop.timeout_poll_cb && eloop.timeout_poll_cb(&tv, !!timeout)) ++ timeout = (void *)1; ++ ++ if (timeout) { + #if defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) + timeout_ms = tv.sec * 1000 + tv.usec / 1000; + #endif /* defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) */ +@@ -1190,7 +1199,8 @@ void eloop_run(void) + eloop.exceptions.changed = 0; + + eloop_process_pending_signals(); +- ++ if (eloop.poll_cb) ++ eloop.poll_cb(); + + /* check if some registered timeouts have occurred */ + timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, +@@ -1252,6 +1262,14 @@ out: + return; + } + ++int eloop_register_cb(eloop_poll_handler poll_cb, ++ eloop_timeout_poll_handler timeout_cb) ++{ ++ eloop.poll_cb = poll_cb; ++ eloop.timeout_poll_cb = timeout_cb; ++ ++ return 0; ++} + + void eloop_terminate(void) + { +--- a/src/utils/eloop.h ++++ b/src/utils/eloop.h +@@ -65,6 +65,9 @@ typedef void (*eloop_timeout_handler)(vo + */ + typedef void (*eloop_signal_handler)(int sig, void *signal_ctx); + ++typedef bool (*eloop_timeout_poll_handler)(struct os_reltime *tv, bool tv_set); ++typedef void (*eloop_poll_handler)(void); ++ + /** + * eloop_init() - Initialize global event loop data + * Returns: 0 on success, -1 on failure +@@ -73,6 +76,9 @@ typedef void (*eloop_signal_handler)(int + */ + int eloop_init(void); + ++int eloop_register_cb(eloop_poll_handler poll_cb, ++ eloop_timeout_poll_handler timeout_cb); ++ + /** + * eloop_register_read_sock - Register handler for read events + * @sock: File descriptor number for the socket +@@ -320,6 +326,8 @@ int eloop_register_signal_reconfig(eloop + */ + int eloop_sock_requeue(void); + ++void eloop_add_uloop(void); ++ + /** + * eloop_run - Start the event loop + * +--- /dev/null ++++ b/src/utils/uloop.c +@@ -0,0 +1,64 @@ ++#include ++#include "includes.h" ++#include "common.h" ++#include "eloop.h" ++ ++static void eloop_uloop_event_cb(int sock, void *eloop_ctx, void *sock_ctx) ++{ ++} ++ ++static void eloop_uloop_fd_cb(struct uloop_fd *fd, unsigned int events) ++{ ++ unsigned int changed = events ^ fd->flags; ++ ++ if (changed & ULOOP_READ) { ++ if (events & ULOOP_READ) ++ eloop_register_sock(fd->fd, EVENT_TYPE_READ, eloop_uloop_event_cb, fd, fd); ++ else ++ eloop_unregister_sock(fd->fd, EVENT_TYPE_READ); ++ } ++ ++ if (changed & ULOOP_WRITE) { ++ if (events & ULOOP_WRITE) ++ eloop_register_sock(fd->fd, EVENT_TYPE_WRITE, eloop_uloop_event_cb, fd, fd); ++ else ++ eloop_unregister_sock(fd->fd, EVENT_TYPE_WRITE); ++ } ++} ++ ++static bool uloop_timeout_poll_handler(struct os_reltime *tv, bool tv_set) ++{ ++ struct os_reltime tv_uloop; ++ int timeout_ms = uloop_get_next_timeout(); ++ ++ if (timeout_ms < 0) ++ return false; ++ ++ tv_uloop.sec = timeout_ms / 1000; ++ tv_uloop.usec = (timeout_ms % 1000) * 1000; ++ ++ if (!tv_set || os_reltime_before(&tv_uloop, tv)) { ++ *tv = tv_uloop; ++ return true; ++ } ++ ++ return false; ++} ++ ++static void uloop_poll_handler(void) ++{ ++ uloop_run_timeout(0); ++} ++ ++void eloop_add_uloop(void) ++{ ++ static bool init_done = false; ++ ++ if (!init_done) { ++ uloop_init(); ++ uloop_fd_set_cb = eloop_uloop_fd_cb; ++ init_done = true; ++ } ++ ++ eloop_register_cb(uloop_poll_handler, uloop_timeout_poll_handler); ++} diff --git a/package/network/services/hostapd/src/src/ap/ubus.c b/package/network/services/hostapd/src/src/ap/ubus.c index 077d40c268..a8a55f0493 100644 --- a/package/network/services/hostapd/src/src/ap/ubus.c +++ b/package/network/services/hostapd/src/src/ap/ubus.c @@ -44,12 +44,6 @@ struct ubus_banned_client { u8 addr[ETH_ALEN]; }; -static void ubus_receive(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct ubus_context *ctx = eloop_ctx; - ubus_handle_event(ctx); -} - static void ubus_reconnect_timeout(void *eloop_data, void *user_ctx) { if (ubus_reconnect(ctx, NULL)) { @@ -57,12 +51,12 @@ static void ubus_reconnect_timeout(void *eloop_data, void *user_ctx) return; } - eloop_register_read_sock(ctx->sock.fd, ubus_receive, ctx, NULL); + ubus_add_uloop(ctx); } static void hostapd_ubus_connection_lost(struct ubus_context *ctx) { - eloop_unregister_read_sock(ctx->sock.fd); + uloop_fd_delete(&ctx->sock); eloop_register_timeout(1, 0, ubus_reconnect_timeout, ctx, NULL); } @@ -71,12 +65,14 @@ static bool hostapd_ubus_init(void) if (ctx) return true; + eloop_add_uloop(); ctx = ubus_connect(NULL); if (!ctx) return false; ctx->connection_lost = hostapd_ubus_connection_lost; - eloop_register_read_sock(ctx->sock.fd, ubus_receive, ctx, NULL); + ubus_add_uloop(ctx); + return true; } @@ -94,7 +90,7 @@ static void hostapd_ubus_ref_dec(void) if (ctx_ref) return; - eloop_unregister_read_sock(ctx->sock.fd); + uloop_fd_delete(&ctx->sock); ubus_free(ctx); ctx = NULL; } diff --git a/package/network/services/hostapd/src/wpa_supplicant/ubus.c b/package/network/services/hostapd/src/wpa_supplicant/ubus.c index 16a68c5073..804d465941 100644 --- a/package/network/services/hostapd/src/wpa_supplicant/ubus.c +++ b/package/network/services/hostapd/src/wpa_supplicant/ubus.c @@ -30,12 +30,6 @@ static inline struct wpa_supplicant *get_wpas_from_object(struct ubus_object *ob return container_of(obj, struct wpa_supplicant, ubus.obj); } -static void ubus_receive(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct ubus_context *ctx = eloop_ctx; - ubus_handle_event(ctx); -} - static void ubus_reconnect_timeout(void *eloop_data, void *user_ctx) { if (ubus_reconnect(ctx, NULL)) { @@ -43,12 +37,12 @@ static void ubus_reconnect_timeout(void *eloop_data, void *user_ctx) return; } - eloop_register_read_sock(ctx->sock.fd, ubus_receive, ctx, NULL); + ubus_add_uloop(ctx); } static void wpas_ubus_connection_lost(struct ubus_context *ctx) { - eloop_unregister_read_sock(ctx->sock.fd); + uloop_fd_delete(&ctx->sock); eloop_register_timeout(1, 0, ubus_reconnect_timeout, ctx, NULL); } @@ -57,12 +51,14 @@ static bool wpas_ubus_init(void) if (ctx) return true; + eloop_add_uloop(); ctx = ubus_connect(NULL); if (!ctx) return false; ctx->connection_lost = wpas_ubus_connection_lost; - eloop_register_read_sock(ctx->sock.fd, ubus_receive, ctx, NULL); + ubus_add_uloop(ctx); + return true; } @@ -80,7 +76,7 @@ static void wpas_ubus_ref_dec(void) if (ctx_ref) return; - eloop_unregister_read_sock(ctx->sock.fd); + uloop_fd_delete(&ctx->sock); ubus_free(ctx); ctx = NULL; } From e56c5f7b276a17f4c9b9321e1e6fbef0bf8ca6c6 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 26 May 2023 10:23:59 +0200 Subject: [PATCH 10/23] hostapd: add ucode support, use ucode for the main ubus object This implements vastly improved dynamic configuration reload support. It can handle configuration changes on individual wifi interfaces, as well as adding/removing interfaces. Signed-off-by: Felix Fietkau --- .../files/lib/netifd/wireless/mac80211.sh | 555 +++++++----------- package/network/services/hostapd/Makefile | 25 +- .../network/services/hostapd/files/common.uc | 168 ++++++ .../network/services/hostapd/files/hostapd.sh | 23 - .../network/services/hostapd/files/hostapd.uc | 399 +++++++++++++ .../network/services/hostapd/files/wdev.uc | 153 +++++ .../services/hostapd/files/wpa_supplicant.uc | 161 +++++ .../hostapd/patches/600-ubus_support.patch | 27 - .../hostapd/patches/601-ucode_support.patch | 224 +++++++ .../hostapd/patches/700-wifi-reload.patch | 54 +- .../patches/701-reload_config_inline.patch | 33 ++ .../patches/720-iface_max_num_sta.patch | 2 +- ...750-qos_map_set_without_interworking.patch | 4 +- .../hostapd/patches/761-shared_das_port.patch | 2 +- .../hostapd/patches/770-radius_server.patch | 2 +- .../services/hostapd/src/src/ap/ubus.c | 148 +---- .../services/hostapd/src/src/ap/ucode.c | 394 +++++++++++++ .../services/hostapd/src/src/ap/ucode.h | 54 ++ .../services/hostapd/src/src/utils/ucode.c | 237 ++++++++ .../services/hostapd/src/src/utils/ucode.h | 28 + .../hostapd/src/wpa_supplicant/ubus.c | 146 ----- .../hostapd/src/wpa_supplicant/ubus.h | 11 - .../hostapd/src/wpa_supplicant/ucode.c | 177 ++++++ .../hostapd/src/wpa_supplicant/ucode.h | 38 ++ 24 files changed, 2360 insertions(+), 705 deletions(-) create mode 100644 package/network/services/hostapd/files/common.uc create mode 100644 package/network/services/hostapd/files/hostapd.uc create mode 100644 package/network/services/hostapd/files/wdev.uc create mode 100644 package/network/services/hostapd/files/wpa_supplicant.uc create mode 100644 package/network/services/hostapd/patches/601-ucode_support.patch create mode 100644 package/network/services/hostapd/patches/701-reload_config_inline.patch create mode 100644 package/network/services/hostapd/src/src/ap/ucode.c create mode 100644 package/network/services/hostapd/src/src/ap/ucode.h create mode 100644 package/network/services/hostapd/src/src/utils/ucode.c create mode 100644 package/network/services/hostapd/src/src/utils/ucode.h create mode 100644 package/network/services/hostapd/src/wpa_supplicant/ucode.c create mode 100644 package/network/services/hostapd/src/wpa_supplicant/ucode.h diff --git a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh index 5aaba9af26..a2a7bdba25 100644 --- a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh +++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh @@ -15,12 +15,9 @@ MP_CONFIG_INT="mesh_retry_timeout mesh_confirm_timeout mesh_holding_timeout mesh MP_CONFIG_BOOL="mesh_auto_open_plinks mesh_fwding" MP_CONFIG_STRING="mesh_power_mode" -NEWAPLIST= -OLDAPLIST= -NEWSPLIST= -OLDSPLIST= -NEWUMLIST= -OLDUMLIST= +wdev_tool() { + ucode /usr/share/hostap/wdev.uc "$@" +} drv_mac80211_init_device_config() { hostapd_common_add_device_config @@ -661,74 +658,6 @@ mac80211_check_ap() { has_ap=1 } -mac80211_iw_interface_add() { - local phy="$1" - local ifname="$2" - local type="$3" - local wdsflag="$4" - local rc - local oldifname - - iw phy "$phy" interface add "$ifname" type "$type" $wdsflag >/dev/null 2>&1 - rc="$?" - - [ "$rc" = 233 ] && { - # Device might have just been deleted, give the kernel some time to finish cleaning it up - sleep 1 - - iw phy "$phy" interface add "$ifname" type "$type" $wdsflag >/dev/null 2>&1 - rc="$?" - } - - [ "$rc" = 233 ] && { - # Keep matching pre-existing interface - [ -d "/sys/class/ieee80211/${phy}/device/net/${ifname}" ] && \ - case "$(iw dev $ifname info | grep "^\ttype" | cut -d' ' -f2- 2>/dev/null)" in - "AP") - [ "$type" = "__ap" ] && rc=0 - ;; - "IBSS") - [ "$type" = "adhoc" ] && rc=0 - ;; - "managed") - [ "$type" = "managed" ] && rc=0 - ;; - "mesh point") - [ "$type" = "mp" ] && rc=0 - ;; - "monitor") - [ "$type" = "monitor" ] && rc=0 - ;; - esac - } - - [ "$rc" = 233 ] && { - iw dev "$ifname" del >/dev/null 2>&1 - [ "$?" = 0 ] && { - sleep 1 - - iw phy "$phy" interface add "$ifname" type "$type" $wdsflag >/dev/null 2>&1 - rc="$?" - } - } - - [ "$rc" != 0 ] && { - # Device might not support virtual interfaces, so the interface never got deleted in the first place. - # Check if the interface already exists, and avoid failing in this case. - [ -d "/sys/class/ieee80211/${phy}/device/net/${ifname}" ] && rc=0 - } - - [ "$rc" != 0 ] && { - # Device doesn't support virtual interfaces and may have existing interface other than ifname. - oldifname="$(basename "/sys/class/ieee80211/${phy}/device/net"/* 2>/dev/null)" - [ "$oldifname" ] && ip link set "$oldifname" name "$ifname" 1>/dev/null 2>&1 - rc="$?" - } - - [ "$rc" != 0 ] && echo "Failed to create interface $ifname" - return $rc -} - mac80211_set_ifname() { local phy="$1" local prefix="$2" @@ -752,10 +681,10 @@ mac80211_prepare_vif() { mac80211_set_ifname "$phy" "$prefix" } + append active_ifnames "$ifname" set_default wds 0 set_default powersave 0 - - json_select .. + json_add_string _ifname "$ifname" if [ -z "$macaddr" ]; then macaddr="$(mac80211_generate_mac $phy)" @@ -763,10 +692,9 @@ mac80211_prepare_vif() { elif [ "$macaddr" = 'random' ]; then macaddr="$(macaddr_random)" fi + json_add_string _macaddr "$macaddr" + json_select .. - json_add_object data - json_add_string ifname "$ifname" - json_close_object [ "$mode" == "ap" ] && { [ -z "$wpa_psk_file" ] && hostapd_set_psk "$ifname" @@ -777,9 +705,6 @@ mac80211_prepare_vif() { # It is far easier to delete and create the desired interface case "$mode" in - adhoc) - mac80211_iw_interface_add "$phy" "$ifname" adhoc || return - ;; ap) # Hostapd will handle recreating the interface and # subsequent virtual APs belonging to the same PHY @@ -791,114 +716,16 @@ mac80211_prepare_vif() { mac80211_hostapd_setup_bss "$phy" "$ifname" "$macaddr" "$type" || return - NEWAPLIST="${NEWAPLIST}$ifname " [ -n "$hostapd_ctrl" ] || { ap_ifname="${ifname}" hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd/$ifname}" } ;; - mesh) - mac80211_iw_interface_add "$phy" "$ifname" mp || return - ;; - monitor) - mac80211_iw_interface_add "$phy" "$ifname" monitor || return - ;; - sta) - local wdsflag= - [ "$enable" = 0 ] || staidx="$(($staidx + 1))" - [ "$wds" -gt 0 ] && wdsflag="4addr on" - mac80211_iw_interface_add "$phy" "$ifname" managed "$wdsflag" || return - if [ "$wds" -gt 0 ]; then - iw "$ifname" set 4addr on - else - iw "$ifname" set 4addr off - fi - [ "$powersave" -gt 0 ] && powersave="on" || powersave="off" - iw "$ifname" set power_save "$powersave" - ;; esac - case "$mode" in - monitor|mesh) - [ "$auto_channel" -gt 0 ] || iw dev "$ifname" set channel "$channel" $iw_htmode - ;; - esac - - if [ "$mode" != "ap" ]; then - # ALL ap functionality will be passed to hostapd - # All interfaces must have unique mac addresses - # which can either be explicitly set in the device - # section, or automatically generated - ip link set dev "$ifname" address "$macaddr" - fi - json_select .. } -mac80211_setup_supplicant() { - local enable=$1 - local add_sp=0 - local spobj="$(ubus -S list | grep wpa_supplicant.${ifname})" - - [ "$enable" = 0 ] && { - ubus call wpa_supplicant.${phy} config_remove "{\"iface\":\"$ifname\"}" - ip link set dev "$ifname" down - iw dev "$ifname" del - return 0 - } - - wpa_supplicant_prepare_interface "$ifname" nl80211 || { - iw dev "$ifname" del - return 1 - } - if [ "$mode" = "sta" ]; then - wpa_supplicant_add_network "$ifname" - else - wpa_supplicant_add_network "$ifname" "$freq" "$htmode" "$noscan" - fi - - NEWSPLIST="${NEWSPLIST}$ifname " - - if [ "${NEWAPLIST%% *}" != "${OLDAPLIST%% *}" ]; then - [ "$spobj" ] && ubus call wpa_supplicant config_remove "{\"iface\":\"$ifname\"}" - add_sp=1 - fi - [ -z "$spobj" ] && add_sp=1 - - NEW_MD5_SP=$(test -e "${_config}" && md5sum ${_config}) - OLD_MD5_SP=$(uci -q -P /var/state get wireless._${phy}.md5_${ifname}) - if [ "$add_sp" = "1" ]; then - wpa_supplicant_run "$ifname" "$hostapd_ctrl" - else - [ "${NEW_MD5_SP}" == "${OLD_MD5_SP}" ] || ubus call $spobj reload - fi - uci -q -P /var/state set wireless._${phy}.md5_${ifname}="${NEW_MD5_SP}" - return 0 -} - -mac80211_setup_supplicant_noctl() { - local enable=$1 - local spobj="$(ubus -S list | grep wpa_supplicant.${ifname})" - wpa_supplicant_prepare_interface "$ifname" nl80211 || { - iw dev "$ifname" del - return 1 - } - - wpa_supplicant_add_network "$ifname" "$freq" "$htmode" "$noscan" - - NEWSPLIST="${NEWSPLIST}$ifname " - [ "$enable" = 0 ] && { - ubus call wpa_supplicant config_remove "{\"iface\":\"$ifname\"}" - ip link set dev "$ifname" down - return 0 - } - if [ -z "$spobj" ]; then - wpa_supplicant_run "$ifname" - else - ubus call $spobj reload - fi -} - mac80211_prepare_iw_htmode() { case "$htmode" in VHT20|HT20|HE20) iw_htmode=HT20;; @@ -936,6 +763,13 @@ mac80211_prepare_iw_htmode() { esac } +mac80211_add_mesh_params() { + for var in $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING; do + eval "mp_val=\"\$var\"" + [ -n "$mp_val" ] && json_add_string "$var" "$mp_val" + done +} + mac80211_setup_adhoc() { local enable=$1 json_get_vars bssid ssid key mcast_rate @@ -977,82 +811,216 @@ mac80211_setup_adhoc() { mcval= [ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate" - iw dev "$ifname" set type ibss - iw dev "$ifname" ibss join "$ssid" $freq $iw_htmode fixed-freq $bssid \ - beacon-interval $beacon_int \ - ${brstr:+basic-rates $brstr} \ - ${mcval:+mcast-rate $mcval} \ - ${keyspec:+keys $keyspec} + local prev + json_set_namespace wdev_uc prev + + json_add_object "$ifname" + json_add_string mode adhoc + json_add_string macaddr "$macaddr" + json_add_string ssid "$ssid" + json_add_string freq "$freq" + json_add_string htmode "$iw_htmode" + [ -n "$bssid" ] && json_add_string bssid "$bssid" + json_add_int beacon-interval "$beacon_int" + [ -n "$brstr" ] && json_add_string basic-rates "$brstr" + [ -n "$mcval" ] && json_add_string mcast-rate "$mcval" + [ -n "$keyspec" ] && json_add_string keys "$keyspec" + json_close_object + + json_set_namespace "$prev" } mac80211_setup_mesh() { - local enable=$1 json_get_vars ssid mesh_id mcast_rate - NEWUMLIST="${NEWUMLIST}$ifname " - - [ "$enable" = 0 ] && { - ip link set dev "$ifname" down - return 0 - } - mcval= [ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate" [ -n "$mesh_id" ] && ssid="$mesh_id" - iw dev "$ifname" mesh join "$ssid" freq $freq $iw_htmode \ - ${mcval:+mcast-rate $mcval} \ - beacon-interval $beacon_int + local prev + json_set_namespace wdev_uc prev + + json_add_object "$ifname" + json_add_string mode mesh + json_add_string macaddr "$macaddr" + json_add_string ssid "$ssid" + json_add_string freq "$freq" + json_add_string htmode "$iw_htmode" + [ -n "$mcval" ] && json_add_string mcast-rate "$mcval" + json_add_int beacon-interval "$beacon_int" + mac80211_add_mesh_params + + json_close_object + + json_set_namespace "$prev" +} + +mac80211_setup_monitor() { + local prev + json_set_namespace wdev_uc prev + + json_add_object "$ifname" + json_add_string mode monitor + [ -n "$freq" ] && json_add_string freq "$freq" + json_add_string htmode "$iw_htmode" + json_close_object + + json_set_namespace "$prev" +} + +mac80211_set_vif_txpower() { + local name="$1" + + json_select config + json_get_var ifname _ifname + json_get_vars vif_txpower + json_select .. + + [ -z "$vif_txpower" ] || iw dev "$ifname" set txpower fixed "${vif_txpower%%.*}00" +} + +wpa_supplicant_init_config() { + json_set_namespace wpa_supp prev + + json_init + json_add_array config + + json_set_namespace "$prev" +} + +wpa_supplicant_add_interface() { + local ifname="$1" + local mode="$2" + local hostapd_ctrl="$3" + local prev + + _wpa_supplicant_common "$ifname" + + json_set_namespace wpa_supp prev + + json_add_object + json_add_string ctrl "$_rpath" + json_add_string iface "$ifname" + json_add_string mode "$mode" + json_add_string config "$_config" + json_add_string macaddr "$macaddr" + [ -n "$network_bridge" ] && json_add_string bridge "$network_bridge" + [ -n "$hostapd_ctrl" ] && json_add_string hostapd_ctrl "$hostapd_ctrl" + [ -n "$wds" ] && json_add_boolean 4addr "$wds" + json_add_boolean powersave "$powersave" + [ "$mode" = "mesh" ] && mac80211_add_mesh_params + json_close_object + + json_set_namespace "$prev" + + wpa_supp_init=1 +} + +wpa_supplicant_set_config() { + local phy="$1" + local prev + + json_set_namespace wpa_supp prev + json_close_array + json_add_string phy "$phy" + json_add_boolean defer 1 + local data="$(json_dump)" + + json_cleanup + json_set_namespace "$prev" + + ubus -S -t 0 wait_for wpa_supplicant || { + [ -n "$wpa_supp_init" ] || return 0 + + ubus wait_for wpa_supplicant + } + + local supplicant_res="$(ubus call wpa_supplicant config_set "$data")" + ret="$?" + [ "$ret" != 0 -o -z "$supplicant_res" ] && wireless_setup_vif_failed WPA_SUPPLICANT_FAILED + + wireless_add_process "$(jsonfilter -s "$supplicant_res" -l 1 -e @.pid)" "/usr/sbin/wpa_supplicant" 1 1 + +} + +hostapd_set_config() { + [ -n "$hostapd_ctrl" ] || { + ubus call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"${hostapd_conf_file}.prev"'" }' > /dev/null + return 0; + } + + ubus wait_for hostapd + local hostapd_res="$(ubus call hostapd config_set "{ \"phy\": \"$phy\", \"config\":\"${hostapd_conf_file}\", \"prev_config\": \"${hostapd_conf_file}.prev\"}")" + ret="$?" + [ "$ret" != 0 -o -z "$hostapd_res" ] && { + wireless_setup_failed HOSTAPD_START_FAILED + return + } + wireless_add_process "$(jsonfilter -s "$hostapd_res" -l 1 -e @.pid)" "/usr/sbin/hostapd" 1 1 +} + + +wpa_supplicant_start() { + local phy="$1" + + [ -n "$wpa_supp_init" ] || return 0 + + ubus call wpa_supplicant config_set '{ "phy": "'"$phy"'" }' > /dev/null +} + +mac80211_setup_supplicant() { + local enable=$1 + local add_sp=0 + + wpa_supplicant_prepare_interface "$ifname" nl80211 || return 1 + + if [ "$mode" = "sta" ]; then + wpa_supplicant_add_network "$ifname" + else + wpa_supplicant_add_network "$ifname" "$freq" "$htmode" "$noscan" + fi + + wpa_supplicant_add_interface "$ifname" "$mode" "$hostapd_ctrl" + + return 0 } mac80211_setup_vif() { local name="$1" local failed - local action=up - - json_select data - json_get_vars ifname - json_select .. json_select config - json_get_vars mode - json_get_var vif_txpower - json_get_var vif_enable enable 1 + json_get_var ifname _ifname + json_get_var macaddr _macaddr + json_get_vars mode wds powersave - [ "$vif_enable" = 1 ] || action=down - if [ "$mode" != "ap" ] || [ "$ifname" = "$ap_ifname" ]; then - ip link set dev "$ifname" "$action" || { - wireless_setup_vif_failed IFUP_ERROR - json_select .. - return - } - [ -z "$vif_txpower" ] || iw dev "$ifname" set txpower fixed "${vif_txpower%%.*}00" - fi + set_default powersave 0 + set_default wds 0 case "$mode" in mesh) + json_get_vars $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING wireless_vif_parse_encryption [ -z "$htmode" ] && htmode="NOHT"; - if wpa_supplicant -vmesh || [ "$wpa" -gt 0 -o "$auto_channel" -gt 0 ] || chan_is_dfs "$phy" "$channel"; then - mac80211_setup_supplicant $vif_enable || failed=1 + if wpa_supplicant -vmesh; then + mac80211_setup_supplicant || failed=1 else - mac80211_setup_mesh $vif_enable + mac80211_setup_mesh fi - for var in $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING; do - json_get_var mp_val "$var" - [ -n "$mp_val" ] && iw dev "$ifname" set mesh_param "$var" "$mp_val" - done ;; adhoc) wireless_vif_parse_encryption if [ "$wpa" -gt 0 -o "$auto_channel" -gt 0 ]; then - mac80211_setup_supplicant_noctl $vif_enable || failed=1 + mac80211_setup_supplicant || failed=1 else - mac80211_setup_adhoc $vif_enable + mac80211_setup_adhoc fi ;; sta) - mac80211_setup_supplicant $vif_enable || failed=1 + mac80211_setup_supplicant || failed=1 + ;; + monitor) + mac80211_setup_monitor ;; esac @@ -1085,7 +1053,6 @@ band_match && $3 == "MHz" && $4 == channel { ' } - chan_is_dfs() { local phy="$1" local chan="$2" @@ -1093,27 +1060,6 @@ chan_is_dfs() { return $! } -mac80211_vap_cleanup() { - local service="$1" - local vaps="$2" - - for wdev in $vaps; do - [ "$service" != "none" ] && ubus call ${service} config_remove "{\"iface\":\"$wdev\"}" - ip link set dev "$wdev" down 2>/dev/null - iw dev "$wdev" del - done -} - -mac80211_interface_cleanup() { - local phy="$1" - local primary_ap=$(uci -q -P /var/state get wireless._${phy}.aplist) - primary_ap=${primary_ap%% *} - - mac80211_vap_cleanup hostapd "${primary_ap}" - mac80211_vap_cleanup wpa_supplicant "$(uci -q -P /var/state get wireless._${phy}.splist)" - mac80211_vap_cleanup none "$(uci -q -P /var/state get wireless._${phy}.umlist)" -} - mac80211_set_noscan() { hostapd_noscan=1 } @@ -1122,6 +1068,15 @@ drv_mac80211_cleanup() { hostapd_common_cleanup } +mac80211_reset_config() { + local phy="$1" + + hostapd_conf_file="/var/run/hostapd-$phy.conf" + ubus call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"$hostapd_conf_file"'" }' > /dev/null + ubus call wpa_supplicant config_set '{ "phy": "'"$phy"'", "config": [] }' > /dev/null + wdev_tool "$phy" '{}' +} + drv_mac80211_setup() { json_select config json_get_vars \ @@ -1141,30 +1096,11 @@ drv_mac80211_setup() { } wireless_set_data phy="$phy" - [ -z "$(uci -q -P /var/state show wireless._${phy})" ] && uci -q -P /var/state set wireless._${phy}=phy - - OLDAPLIST=$(uci -q -P /var/state get wireless._${phy}.aplist) - OLDSPLIST=$(uci -q -P /var/state get wireless._${phy}.splist) - OLDUMLIST=$(uci -q -P /var/state get wireless._${phy}.umlist) local wdev local cwdev local found - for wdev in $(list_phy_interfaces "$phy"); do - found=0 - for cwdev in $OLDAPLIST $OLDSPLIST $OLDUMLIST; do - if [ "$wdev" = "$cwdev" ]; then - found=1 - break - fi - done - if [ "$found" = "0" ]; then - ip link set dev "$wdev" down - iw dev "$wdev" del - fi - done - # convert channel to frequency [ "$auto_channel" -gt 0 ] || freq="$(get_freq "$phy" "$channel" "$band")" @@ -1177,7 +1113,6 @@ drv_mac80211_setup() { hostapd_conf_file="/var/run/hostapd-$phy.conf" - no_ap=1 macidx=0 staidx=0 @@ -1212,78 +1147,36 @@ drv_mac80211_setup() { hostapd_ctrl= ap_ifname= hostapd_noscan= + wpa_supp_init= for_each_interface "ap" mac80211_check_ap - rm -f "$hostapd_conf_file" + [ -f "$hostapd_conf_file" ] && mv "$hostapd_conf_file" "$hostapd_conf_file.prev" for_each_interface "sta adhoc mesh" mac80211_set_noscan [ -n "$has_ap" ] && mac80211_hostapd_setup_base "$phy" + local prev + json_set_namespace wdev_uc prev + json_init + json_set_namespace "$prev" + + wpa_supplicant_init_config + mac80211_prepare_iw_htmode - for_each_interface "sta adhoc mesh monitor" mac80211_prepare_vif - NEWAPLIST= - for_each_interface "ap" mac80211_prepare_vif - NEW_MD5=$(test -e "${hostapd_conf_file}" && md5sum ${hostapd_conf_file}) - OLD_MD5=$(uci -q -P /var/state get wireless._${phy}.md5) - if [ "${NEWAPLIST}" != "${OLDAPLIST}" ]; then - mac80211_vap_cleanup hostapd "${OLDAPLIST}" - fi - [ -n "${NEWAPLIST}" ] && mac80211_iw_interface_add "$phy" "${NEWAPLIST%% *}" __ap - local add_ap=0 - local primary_ap=${NEWAPLIST%% *} - [ -n "$hostapd_ctrl" ] && { - local no_reload=1 - if [ -n "$(ubus list | grep hostapd.$primary_ap)" ]; then - no_reload=0 - [ "${NEW_MD5}" = "${OLD_MD5}" ] || { - ubus call hostapd.$primary_ap reload - no_reload=$? - if [ "$no_reload" != "0" ]; then - mac80211_vap_cleanup hostapd "${OLDAPLIST}" - mac80211_vap_cleanup wpa_supplicant "$(uci -q -P /var/state get wireless._${phy}.splist)" - mac80211_vap_cleanup none "$(uci -q -P /var/state get wireless._${phy}.umlist)" - sleep 2 - mac80211_iw_interface_add "$phy" "${NEWAPLIST%% *}" __ap - for_each_interface "sta adhoc mesh monitor" mac80211_prepare_vif - fi - } - fi - if [ "$no_reload" != "0" ]; then - add_ap=1 - ubus wait_for hostapd - local hostapd_res="$(ubus call hostapd config_add "{\"iface\":\"$primary_ap\", \"config\":\"${hostapd_conf_file}\"}")" - ret="$?" - [ "$ret" != 0 -o -z "$hostapd_res" ] && { - wireless_setup_failed HOSTAPD_START_FAILED - return - } - wireless_add_process "$(jsonfilter -s "$hostapd_res" -l 1 -e @.pid)" "/usr/sbin/hostapd" 1 1 - fi - } - uci -q -P /var/state set wireless._${phy}.aplist="${NEWAPLIST}" - uci -q -P /var/state set wireless._${phy}.md5="${NEW_MD5}" + active_ifnames= + for_each_interface "ap sta adhoc mesh monitor" mac80211_prepare_vif + for_each_interface "ap sta adhoc mesh monitor" mac80211_setup_vif - [ "${add_ap}" = 1 ] && sleep 1 - for_each_interface "ap" mac80211_setup_vif + [ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_set_config "$phy" + [ -x /usr/sbin/hostapd ] && hostapd_set_config "$phy" - NEWSPLIST= - NEWUMLIST= + [ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_start "$phy" - for_each_interface "sta adhoc mesh monitor" mac80211_setup_vif + json_set_namespace wdev_uc prev + wdev_tool "$phy" "$(json_dump)" $active_ifnames + json_set_namespace "$prev" - uci -q -P /var/state set wireless._${phy}.splist="${NEWSPLIST}" - uci -q -P /var/state set wireless._${phy}.umlist="${NEWUMLIST}" - - local foundvap - local dropvap="" - for oldvap in $OLDSPLIST; do - foundvap=0 - for newvap in $NEWSPLIST; do - [ "$oldvap" = "$newvap" ] && foundvap=1 - done - [ "$foundvap" = "0" ] && dropvap="$dropvap $oldvap" - done - [ -n "$dropvap" ] && mac80211_vap_cleanup wpa_supplicant "$dropvap" + for_each_interface "ap sta adhoc mesh monitor" mac80211_set_vif_txpower wireless_set_up } @@ -1314,8 +1207,12 @@ drv_mac80211_teardown() { return 1 } - mac80211_interface_cleanup "$phy" - uci -q -P /var/state revert wireless._${phy} + mac80211_reset_config "$phy" + + for wdev in $(list_phy_interfaces "$phy"); do + ip link set dev "$wdev" down + iw dev "$wdev" del + done } add_driver mac80211 diff --git a/package/network/services/hostapd/Makefile b/package/network/services/hostapd/Makefile index 1d034a1752..f147c42ad8 100644 --- a/package/network/services/hostapd/Makefile +++ b/package/network/services/hostapd/Makefile @@ -81,12 +81,15 @@ ifneq ($(CONFIG_DRIVER_11AX_SUPPORT),) HOSTAPD_IEEE80211AX:=y endif +CORE_DEPENDS = +ucode +libubus +libucode +ucode-mod-fs +ucode-mod-nl80211 +ucode-mod-rtnl +ucode-mod-ubus +ucode-mod-uloop +libblobmsg-json + DRIVER_MAKEOPTS= \ CONFIG_ACS=$(CONFIG_PACKAGE_kmod-cfg80211) \ CONFIG_DRIVER_NL80211=$(CONFIG_PACKAGE_kmod-cfg80211) \ CONFIG_IEEE80211AC=$(HOSTAPD_IEEE80211AC) \ CONFIG_IEEE80211AX=$(HOSTAPD_IEEE80211AX) \ - CONFIG_MBO=$(CONFIG_WPA_MBO_SUPPORT) + CONFIG_MBO=$(CONFIG_WPA_MBO_SUPPORT) \ + CONFIG_UCODE=y ifeq ($(SSL_VARIANT),openssl) DRIVER_MAKEOPTS += CONFIG_TLS=openssl CONFIG_SAE=y @@ -148,7 +151,7 @@ define Package/hostapd/Default SUBMENU:=WirelessAPD TITLE:=IEEE 802.1x Authenticator URL:=http://hostap.epitest.fi/ - DEPENDS:=$(DRV_DEPENDS) +hostapd-common +libubus +libblobmsg-json + DEPENDS:=$(DRV_DEPENDS) +hostapd-common $(CORE_DEPENDS) EXTRA_DEPENDS:=hostapd-common (=$(PKG_VERSION)-$(PKG_RELEASE)) USERID:=network=101:network=101 PROVIDES:=hostapd @@ -253,7 +256,7 @@ define Package/wpad/Default CATEGORY:=Network SUBMENU:=WirelessAPD TITLE:=IEEE 802.1x Auth/Supplicant - DEPENDS:=$(DRV_DEPENDS) +hostapd-common +libubus +libblobmsg-json + DEPENDS:=$(DRV_DEPENDS) +hostapd-common $(CORE_DEPENDS) EXTRA_DEPENDS:=hostapd-common (=$(PKG_VERSION)-$(PKG_RELEASE)) USERID:=network=101:network=101 URL:=http://hostap.epitest.fi/ @@ -398,7 +401,7 @@ define Package/wpa-supplicant/Default SUBMENU:=WirelessAPD TITLE:=WPA Supplicant URL:=http://hostap.epitest.fi/wpa_supplicant/ - DEPENDS:=$(DRV_DEPENDS) +hostapd-common +libubus +libblobmsg-json + DEPENDS:=$(DRV_DEPENDS) +hostapd-common $(CORE_DEPENDS) EXTRA_DEPENDS:=hostapd-common (=$(PKG_VERSION)-$(PKG_RELEASE)) USERID:=network=101:network=101 PROVIDES:=wpa-supplicant @@ -520,7 +523,7 @@ define Package/eapol-test/Default SECTION:=net SUBMENU:=WirelessAPD CATEGORY:=Network - DEPENDS:=$(DRV_DEPENDS) +libubus +libblobmsg-json + DEPENDS:=$(DRV_DEPENDS) $(CORE_DEPENDS) endef define Package/eapol-test @@ -585,7 +588,7 @@ TARGET_CPPFLAGS := \ -D_GNU_SOURCE \ $(if $(CONFIG_WPA_MSG_MIN_PRIORITY),-DCONFIG_MSG_MIN_PRIORITY=$(CONFIG_WPA_MSG_MIN_PRIORITY)) -TARGET_LDFLAGS += -lubox -lubus -lblobmsg_json +TARGET_LDFLAGS += -lubox -lubus -lblobmsg_json -lucode ifdef CONFIG_PACKAGE_kmod-cfg80211 TARGET_LDFLAGS += -lm -lnl-tiny @@ -703,22 +706,26 @@ Package/hostapd-mbedtls/conffiles = $(Package/hostapd-full/conffiles) endif define Install/hostapd - $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/share/hostap + $(INSTALL_DATA) ./files/hostapd.uc $(1)/usr/share/hostap/ $(if $(findstring full,$(CONFIG_VARIANT)),$(Install/hostapd/full)) endef define Install/supplicant - $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/share/hostap + $(INSTALL_DATA) ./files/wpa_supplicant.uc $(1)/usr/share/hostap/ endef define Package/hostapd-common/install - $(INSTALL_DIR) $(1)/etc/capabilities $(1)/etc/rc.button $(1)/etc/hotplug.d/ieee80211 $(1)/etc/init.d $(1)/lib/netifd $(1)/usr/share/acl.d + $(INSTALL_DIR) $(1)/etc/capabilities $(1)/etc/rc.button $(1)/etc/hotplug.d/ieee80211 $(1)/etc/init.d $(1)/lib/netifd $(1)/usr/share/acl.d $(1)/usr/share/hostap $(INSTALL_BIN) ./files/dhcp-get-server.sh $(1)/lib/netifd/dhcp-get-server.sh $(INSTALL_DATA) ./files/hostapd.sh $(1)/lib/netifd/hostapd.sh $(INSTALL_BIN) ./files/wpad.init $(1)/etc/init.d/wpad $(INSTALL_BIN) ./files/wps-hotplug.sh $(1)/etc/rc.button/wps $(INSTALL_DATA) ./files/wpad_acl.json $(1)/usr/share/acl.d $(INSTALL_DATA) ./files/wpad.json $(1)/etc/capabilities + $(INSTALL_DATA) ./files/common.uc $(1)/usr/share/hostap/ + $(INSTALL_DATA) ./files/wdev.uc $(1)/usr/share/hostap/ endef define Package/hostapd/install diff --git a/package/network/services/hostapd/files/common.uc b/package/network/services/hostapd/files/common.uc new file mode 100644 index 0000000000..2002572cf1 --- /dev/null +++ b/package/network/services/hostapd/files/common.uc @@ -0,0 +1,168 @@ +import * as nl80211 from "nl80211"; +import * as rtnl from "rtnl"; +import { readfile } from "fs"; + +const iftypes = { + ap: nl80211.const.NL80211_IFTYPE_AP, + mesh: nl80211.const.NL80211_IFTYPE_MESH_POINT, + sta: nl80211.const.NL80211_IFTYPE_STATION, + adhoc: nl80211.const.NL80211_IFTYPE_ADHOC, + monitor: nl80211.const.NL80211_IFTYPE_MONITOR, +}; + +function wdev_remove(name) +{ + nl80211.request(nl80211.const.NL80211_CMD_DEL_INTERFACE, 0, { dev: name }); +} + +function __phy_is_fullmac(phyidx) +{ + let data = nl80211.request(nl80211.const.NL80211_CMD_GET_WIPHY, 0, { wiphy: phyidx }); + + return !data.software_iftypes.ap_vlan; +} + +function phy_is_fullmac(phy) +{ + let phyidx = int(trim(readfile(`/sys/class/ieee80211/${phy}/index`))); + + return __phy_is_fullmac(phyidx); +} + +function find_reusable_wdev(phyidx) +{ + if (!__phy_is_fullmac(phyidx)) + return null; + + data = nl80211.request( + nl80211.const.NL80211_CMD_GET_INTERFACE, + nl80211.const.NLM_F_DUMP, + { wiphy: phyidx }); + for (let res in data) + if (trim(readfile(`/sys/class/net/${res.ifname}/operstate`)) == "down") + return res.ifname; + return null; +} + +function wdev_create(phy, name, data) +{ + let phyidx = int(readfile(`/sys/class/ieee80211/${phy}/index`)); + + wdev_remove(name); + + if (!iftypes[data.mode]) + return `Invalid mode: ${data.mode}`; + + let req = { + wiphy: phyidx, + ifname: name, + iftype: iftypes[data.mode], + }; + + if (data["4addr"]) + req["4addr"] = data["4addr"]; + if (data.macaddr) + req.mac = data.macaddr; + + nl80211.error(); + + let reuse_ifname = find_reusable_wdev(phyidx); + if (reuse_ifname && + (reuse_ifname == name || + rtnl.request(rtnl.const.RTM_SETLINK, 0, { dev: reuse_ifname, ifname: name}) != false)) + nl80211.request( + nl80211.const.NL80211_CMD_SET_INTERFACE, 0, { + wiphy: phyidx, + dev: name, + iftype: iftypes[data.mode], + }); + else + nl80211.request( + nl80211.const.NL80211_CMD_NEW_INTERFACE, + nl80211.const.NLM_F_CREATE, + req); + + let error = nl80211.error(); + if (error) + return error; + + if (data.powersave != null) { + nl80211.request(nl80211.const.NL80211_CMD_SET_POWER_SAVE, 0, + { dev: name, ps_state: data.powersave ? 1 : 0}); + } + + return null; +} + +const vlist_proto = { + update: function(values, arg) { + let data = this.data; + let cb = this.cb; + let seq = { }; + let new_data = {}; + let old_data = {}; + + this.data = new_data; + + if (type(values) == "object") { + for (let key in values) { + old_data[key] = data[key]; + new_data[key] = values[key]; + delete data[key]; + } + } else { + for (let val in values) { + let cur_key = val[0]; + let cur_obj = val[1]; + + old_data[cur_key] = data[cur_key]; + new_data[cur_key] = val[1]; + delete data[cur_key]; + } + } + + for (let key in data) { + cb(null, data[key], arg); + delete data[key]; + } + for (let key in new_data) + cb(new_data[key], old_data[key], arg); + } +}; + +function is_equal(val1, val2) { + let t1 = type(val1); + + if (t1 != type(val2)) + return false; + + if (t1 == "array") { + if (length(val1) != length(val2)) + return false; + + for (let i = 0; i < length(val1); i++) + if (!is_equal(val1[i], val2[i])) + return false; + + return true; + } else if (t1 == "object") { + for (let key in val1) + if (!is_equal(val1[key], val2[key])) + return false; + for (let key in val2) + if (!val1[key]) + return false; + return true; + } else { + return val1 == val2; + } +} + +function vlist_new(cb) { + return proto({ + cb: cb, + data: {} + }, vlist_proto); +} + +export { wdev_remove, wdev_create, is_equal, vlist_new, phy_is_fullmac }; diff --git a/package/network/services/hostapd/files/hostapd.sh b/package/network/services/hostapd/files/hostapd.sh index bf3625c92d..49db03ed46 100644 --- a/package/network/services/hostapd/files/hostapd.sh +++ b/package/network/services/hostapd/files/hostapd.sh @@ -1591,29 +1591,6 @@ EOF return 0 } -wpa_supplicant_run() { - local ifname="$1" - local hostapd_ctrl="$2" - - _wpa_supplicant_common "$ifname" - - ubus wait_for wpa_supplicant - local supplicant_res="$(ubus call wpa_supplicant config_add "{ \ - \"driver\": \"${_w_driver:-wext}\", \"ctrl\": \"$_rpath\", \ - \"iface\": \"$ifname\", \"config\": \"$_config\" \ - ${network_bridge:+, \"bridge\": \"$network_bridge\"} \ - ${hostapd_ctrl:+, \"hostapd_ctrl\": \"$hostapd_ctrl\"} \ - }")" - - ret="$?" - - [ "$ret" != 0 -o -z "$supplicant_res" ] && wireless_setup_vif_failed WPA_SUPPLICANT_FAILED - - wireless_add_process "$(jsonfilter -s "$supplicant_res" -l 1 -e @.pid)" "/usr/sbin/wpa_supplicant" 1 1 - - return $ret -} - hostapd_common_cleanup() { killall meshd-nl80211 } diff --git a/package/network/services/hostapd/files/hostapd.uc b/package/network/services/hostapd/files/hostapd.uc new file mode 100644 index 0000000000..cc026cc853 --- /dev/null +++ b/package/network/services/hostapd/files/hostapd.uc @@ -0,0 +1,399 @@ +let libubus = require("ubus"); +import { open, readfile } from "fs"; +import { wdev_create, wdev_remove, is_equal, vlist_new, phy_is_fullmac } from "common"; + +let ubus = libubus.connect(); + +hostapd.data.config = {}; + +hostapd.data.file_fields = { + vlan_file: true, + wpa_psk_file: true, + accept_mac_file: true, + deny_mac_file: true, + eap_user_file: true, + ca_cert: true, + server_cert: true, + server_cert2: true, + private_key: true, + private_key2: true, + dh_file: true, + eap_sim_db: true, +}; + +function iface_remove(cfg) +{ + if (!cfg || !cfg.bss || !cfg.bss[0] || !cfg.bss[0].ifname) + return; + + hostapd.remove_iface(cfg.bss[0].ifname); + for (let bss in cfg.bss) + wdev_remove(bss.ifname); +} + +function iface_gen_config(phy, config) +{ + let str = `data: +${join("\n", config.radio.data)} +channel=${config.radio.channel} +`; + + for (let i = 0; i < length(config.bss); i++) { + let bss = config.bss[i]; + let type = i > 0 ? "bss" : "interface"; + + str += ` +${type}=${bss.ifname} +${join("\n", bss.data)} +`; + } + + return str; +} + +function iface_restart(phy, config, old_config) +{ + iface_remove(old_config); + iface_remove(config); + + if (!config.bss || !config.bss[0]) { + hostapd.printf(`No bss for phy ${phy}`); + return; + } + + let bss = config.bss[0]; + let err = wdev_create(phy, bss.ifname, { mode: "ap" }); + if (err) + hostapd.printf(`Failed to create ${bss.ifname} on phy ${phy}: ${err}`); + let config_inline = iface_gen_config(phy, config); + if (hostapd.add_iface(`bss_config=${bss.ifname}:${config_inline}`) < 0) { + hostapd.printf(`hostapd.add_iface failed for phy ${phy} ifname=${bss.ifname}`); + return; + } +} + +function array_to_obj(arr, key, start) +{ + let obj = {}; + + start ??= 0; + for (let i = start; i < length(arr); i++) { + let cur = arr[i]; + obj[cur[key]] = cur; + } + + return obj; +} + +function find_array_idx(arr, key, val) +{ + for (let i = 0; i < length(arr); i++) + if (arr[i][key] == val) + return i; + + return -1; +} + +function bss_reload_psk(bss, config, old_config) +{ + if (is_equal(old_config.hash.wpa_psk_file, config.hash.wpa_psk_file)) + return; + + old_config.hash.wpa_psk_file = config.hash.wpa_psk_file; + if (!is_equal(old_config, config)) + return; + + let ret = bss.ctrl("RELOAD_WPA_PSK"); + ret ??= "failed"; + + hostapd.printf(`Reload WPA PSK file for bss ${config.ifname}: ${ret}`); +} + +function iface_reload_config(phy, config, old_config) +{ + if (!old_config || !is_equal(old_config.radio, config.radio)) + return false; + + if (is_equal(old_config.bss, config.bss)) + return true; + + if (config.bss[0].ifname != old_config.bss[0].ifname) + return false; + + let iface = hostapd.interfaces[config.bss[0].ifname]; + if (!iface) + return false; + + let config_inline = iface_gen_config(phy, config); + + bss_reload_psk(iface.bss[0], config.bss[0], old_config.bss[0]); + if (!is_equal(config.bss[0], old_config.bss[0])) { + if (phy_is_fullmac(phy)) + return false; + + hostapd.printf(`Reload config for bss '${config.bss[0].ifname}' on phy '${phy}'`); + if (iface.bss[0].set_config(config_inline, 0) < 0) { + hostapd.printf(`Failed to set config`); + return false; + } + } + + let bss_list = array_to_obj(iface.bss, "name", 1); + let new_cfg = array_to_obj(config.bss, "ifname", 1); + let old_cfg = array_to_obj(old_config.bss, "ifname", 1); + + for (let name in old_cfg) { + let bss = bss_list[name]; + if (!bss) { + hostapd.printf(`bss '${name}' not found`); + return false; + } + + if (!new_cfg[name]) { + hostapd.printf(`Remove bss '${name}' on phy '${phy}'`); + bss.delete(); + wdev_remove(name); + continue; + } + + let new_cfg_data = new_cfg[name]; + delete new_cfg[name]; + + if (is_equal(old_cfg[name], new_cfg_data)) + continue; + + hostapd.printf(`Reload config for bss '${name}' on phy '${phy}'`); + let idx = find_array_idx(config.bss, "ifname", name); + if (idx < 0) { + hostapd.printf(`bss index not found`); + return false; + } + + if (bss.set_config(config_inline, idx) < 0) { + hostapd.printf(`Failed to set config`); + return false; + } + } + + for (let name in new_cfg) { + hostapd.printf(`Add bss '${name}' on phy '${phy}'`); + + let idx = find_array_idx(config.bss, "ifname", name); + if (idx < 0) { + hostapd.printf(`bss index not found`); + return false; + } + + if (iface.add_bss(config_inline, idx) < 0) { + hostapd.printf(`Failed to add bss`); + return false; + } + } + + return true; +} + +function iface_set_config(phy, config) +{ + let old_config = hostapd.data.config[phy]; + + hostapd.data.config[phy] = config; + + if (!config) + return iface_remove(old_config); + + let ret = iface_reload_config(phy, config, old_config); + if (ret) { + hostapd.printf(`Reloaded settings for phy ${phy}`); + return 0; + } + + hostapd.printf(`Restart interface for phy ${phy}`); + return iface_restart(phy, config, old_config); +} + +function config_add_bss(config, name) +{ + let bss = { + ifname: name, + data: [], + hash: {} + }; + + push(config.bss, bss); + + return bss; +} + +function iface_load_config(filename) +{ + let f = open(filename, "r"); + if (!f) + return null; + + let config = { + radio: { + data: [] + }, + bss: [], + orig_file: filename, + }; + + let bss; + let line; + while ((line = trim(f.read("line"))) != null) { + let val = split(line, "=", 2); + if (!val[0]) + continue; + + if (val[0] == "interface") { + bss = config_add_bss(config, val[1]); + break; + } + + if (val[0] == "channel") { + config.radio.channel = val[1]; + continue; + } + + push(config.radio.data, line); + } + + while ((line = trim(f.read("line"))) != null) { + let val = split(line, "=", 2); + if (!val[0]) + continue; + + if (val[0] == "bss") { + bss = config_add_bss(config, val[1]); + continue; + } + + if (hostapd.data.file_fields[val[0]]) + bss.hash[val[0]] = hostapd.sha1(readfile(val[1])); + + push(bss.data, line); + } + f.close(); + + return config; +} + + + +let main_obj = { + reload: { + args: { + phy: "", + }, + call: function(req) { + try { + let phy_list = req.args.phy ? [ req.args.phy ] : keys(hostapd.data.config); + for (let phy_name in phy_list) { + let phy = hostapd.data.config[phy_name]; + let config = iface_load_config(phy.orig_file); + iface_set_config(phy_name, config); + } + } catch(e) { + hostapd.printf(`Error reloading config: ${e}\n${e.stacktrace[0].context}`); + return libubus.STATUS_INVALID_ARGUMENT; + } + + return 0; + } + }, + config_set: { + args: { + phy: "", + config: "", + prev_config: "", + }, + call: function(req) { + let phy = req.args.phy; + let file = req.args.config; + let prev_file = req.args.prev_config; + + if (!phy) + return libubus.STATUS_INVALID_ARGUMENT; + + try { + if (prev_file && !hostapd.data.config[phy]) { + let config = iface_load_config(prev_file); + if (config) + config.radio.data = []; + hostapd.data.config[phy] = config; + } + + let config = iface_load_config(file); + + hostapd.printf(`Set new config for phy ${phy}: ${file}`); + iface_set_config(phy, config); + } catch(e) { + hostapd.printf(`Error loading config: ${e}\n${e.stacktrace[0].context}`); + return libubus.STATUS_INVALID_ARGUMENT; + } + + return { + pid: hostapd.getpid() + }; + } + }, + config_add: { + args: { + iface: "", + config: "", + }, + call: function(req) { + if (!req.args.iface || !req.args.config) + return libubus.STATUS_INVALID_ARGUMENT; + + if (hostapd.add_iface(`bss_config=${req.args.iface}:${req.args.config}`) < 0) + return libubus.STATUS_INVALID_ARGUMENT; + + return { + pid: hostapd.getpid() + }; + } + }, + config_remove: { + args: { + iface: "" + }, + call: function(req) { + if (!req.args.iface) + return libubus.STATUS_INVALID_ARGUMENT; + + hostapd.remove_iface(req.args.iface); + return 0; + } + }, +}; + +hostapd.data.ubus = ubus; +hostapd.data.obj = ubus.publish("hostapd", main_obj); + +function bss_event(type, name, data) { + let ubus = hostapd.data.ubus; + + data ??= {}; + data.name = name; + hostapd.data.obj.notify(`bss.${type}`, data, null, null, null, -1); + ubus.call("service", "event", { type: `hostapd.${name}.${type}`, data: {} }); +} + +return { + shutdown: function() { + for (let phy in hostapd.data.config) + iface_set_config(phy, null); + hostapd.ubus.disconnect(); + }, + bss_add: function(name, obj) { + bss_event("add", name); + }, + bss_reload: function(name, obj, reconf) { + bss_event("reload", name, { reconf: reconf != 0 }); + }, + bss_remove: function(name, obj) { + bss_event("remove", name); + } +}; diff --git a/package/network/services/hostapd/files/wdev.uc b/package/network/services/hostapd/files/wdev.uc new file mode 100644 index 0000000000..9701af125a --- /dev/null +++ b/package/network/services/hostapd/files/wdev.uc @@ -0,0 +1,153 @@ +#!/usr/bin/env ucode +'use strict'; +import { vlist_new, is_equal, wdev_create, wdev_remove } from "/usr/share/hostap/common.uc"; +import { readfile, writefile, basename, glob } from "fs"; + +let keep_devices = {}; +let phy = shift(ARGV); +let new_config = shift(ARGV); +const mesh_params = [ + "mesh_retry_timeout", "mesh_confirm_timeout", "mesh_holding_timeout", "mesh_max_peer_links", + "mesh_max_retries", "mesh_ttl", "mesh_element_ttl", "mesh_hwmp_max_preq_retries", + "mesh_path_refresh_time", "mesh_min_discovery_timeout", "mesh_hwmp_active_path_timeout", + "mesh_hwmp_preq_min_interval", "mesh_hwmp_net_diameter_traversal_time", "mesh_hwmp_rootmode", + "mesh_hwmp_rann_interval", "mesh_gate_announcements", "mesh_sync_offset_max_neighor", + "mesh_rssi_threshold", "mesh_hwmp_active_path_to_root_timeout", "mesh_hwmp_root_interval", + "mesh_hwmp_confirmation_interval", "mesh_awake_window", "mesh_plink_timeout", + "mesh_auto_open_plinks", "mesh_fwding", "mesh_power_mode" +]; + +function iface_stop(wdev) +{ + if (keep_devices[wdev.ifname]) + return; + + wdev_remove(wdev.ifname); +} + +function iface_start(wdev) +{ + let ifname = wdev.ifname; + + if (readfile(`/sys/class/net/${ifname}/ifindex`)) { + system([ "ip", "link", "set", "dev", ifname, "down" ]); + wdev_remove(ifname); + } + wdev_create(phy, ifname, wdev); + system([ "ip", "link", "set", "dev", ifname, "up" ]); + if (wdev.freq) + system(`iw dev ${ifname} set freq ${wdev.freq} ${wdev.htmode}`); + if (wdev.mode == "adhoc") { + let cmd = ["iw", "dev", ifname, "ibss", "join", wdev.ssid, wdev.freq, wdev.htmode, "fixed-freq" ]; + if (wdev.bssid) + push(cmd, wdev.bssid); + for (let key in [ "beacon-interval", "basic-rates", "mcast-rate", "keys" ]) + if (wdev[key]) + push(cmd, key, wdev[key]); + system(cmd); + } else if (wdev.mode == "mesh") { + let cmd = [ "iw", "dev", ifname, "mesh", "join", ssid, "freq", wdev.freq, wdev.htmode ]; + for (let key in [ "beacon-interval", "mcast-rate" ]) + if (wdev[key]) + push(cmd, key, wdev[key]); + system(cmd); + + cmd = ["iw", "dev", ifname, "set", "mesh_param" ]; + let len = length(cmd); + + for (let param in mesh_params) + if (wdev[param]) + push(cmd, param, wdev[param]); + + if (len == length(cmd)) + return; + + system(cmd); + } + +} + +function iface_cb(new_if, old_if) +{ + if (old_if && new_if && is_equal(old_if, new_if)) + return; + + if (old_if) + iface_stop(old_if); + if (new_if) + iface_start(new_if); +} + +function drop_inactive(config) +{ + for (let key in config) { + if (!readfile(`/sys/class/net/${key}/ifindex`)) + delete config[key]; + } +} + +function add_ifname(config) +{ + for (let key in config) + config[key].ifname = key; +} + +function delete_ifname(config) +{ + for (let key in config) + delete config[key].ifname; +} + +function add_existing(phy, config) +{ + let wdevs = glob(`/sys/class/ieee80211/${phy}/device/net/*`); + wdevs = map(wdevs, (arg) => basename(arg)); + for (let wdev in wdevs) { + if (config[wdev]) + continue; + + if (trim(readfile(`/sys/class/net/${wdev}/operstate`)) == "down") + config[wdev] = {}; + } +} + + +let statefile = `/var/run/wdev-${phy}.json`; + +for (let dev in ARGV) + keep_devices[dev] = true; + +if (!phy || !new_config) { + warn(`Usage: ${basename(sourcepath())} [conf->oce & OCE_STA_CFON) && \ -@@ -92,7 +93,7 @@ struct hapd_interfaces { - #ifdef CONFIG_CTRL_IFACE_UDP - unsigned char ctrl_iface_cookie[CTRL_IFACE_COOKIE_LEN]; - #endif /* CONFIG_CTRL_IFACE_UDP */ -- -+ struct ubus_object ubus; - }; - - enum hostapd_chan_status { @@ -184,6 +185,7 @@ struct hostapd_data { struct hostapd_iface *iface; struct hostapd_config *iconf; @@ -434,24 +425,6 @@ if (wpa_s->conf->wps_cred_processing == 1) return 0; ---- a/hostapd/main.c -+++ b/hostapd/main.c -@@ -991,6 +991,7 @@ int main(int argc, char *argv[]) - } - - hostapd_global_ctrl_iface_init(&interfaces); -+ hostapd_ubus_add(&interfaces); - - if (hostapd_global_run(&interfaces, daemonize, pid_file)) { - wpa_printf(MSG_ERROR, "Failed to start eloop"); -@@ -1000,6 +1001,7 @@ int main(int argc, char *argv[]) - ret = 0; - - out: -+ hostapd_ubus_free(&interfaces); - hostapd_global_ctrl_iface_deinit(&interfaces); - /* Deinitialize all interfaces */ - for (i = 0; i < interfaces.count; i++) { --- a/wpa_supplicant/main.c +++ b/wpa_supplicant/main.c @@ -204,7 +204,7 @@ int main(int argc, char *argv[]) diff --git a/package/network/services/hostapd/patches/601-ucode_support.patch b/package/network/services/hostapd/patches/601-ucode_support.patch new file mode 100644 index 0000000000..6cfc9b7d8d --- /dev/null +++ b/package/network/services/hostapd/patches/601-ucode_support.patch @@ -0,0 +1,224 @@ +--- a/hostapd/Makefile ++++ b/hostapd/Makefile +@@ -168,9 +168,21 @@ OBJS += ../src/eapol_auth/eapol_auth_sm. + + ifdef CONFIG_UBUS + CFLAGS += -DUBUS_SUPPORT +-OBJS += ../src/utils/uloop.o + OBJS += ../src/ap/ubus.o +-LIBS += -lubox -lubus ++LIBS += -lubus ++NEED_ULOOP:=y ++endif ++ ++ifdef CONFIG_UCODE ++CFLAGS += -DUCODE_SUPPORT ++OBJS += ../src/utils/ucode.o ++OBJS += ../src/ap/ucode.o ++NEED_ULOOP:=y ++endif ++ ++ifdef NEED_ULOOP ++OBJS += ../src/utils/uloop.o ++LIBS += -lubox + endif + + ifdef CONFIG_CODE_COVERAGE +--- a/hostapd/main.c ++++ b/hostapd/main.c +@@ -991,6 +991,7 @@ int main(int argc, char *argv[]) + } + + hostapd_global_ctrl_iface_init(&interfaces); ++ hostapd_ucode_init(&interfaces); + + if (hostapd_global_run(&interfaces, daemonize, pid_file)) { + wpa_printf(MSG_ERROR, "Failed to start eloop"); +@@ -1000,6 +1001,7 @@ int main(int argc, char *argv[]) + ret = 0; + + out: ++ hostapd_ucode_free(); + hostapd_global_ctrl_iface_deinit(&interfaces); + /* Deinitialize all interfaces */ + for (i = 0; i < interfaces.count; i++) { +--- a/src/ap/hostapd.h ++++ b/src/ap/hostapd.h +@@ -19,6 +19,7 @@ + #include "ap_config.h" + #include "drivers/driver.h" + #include "ubus.h" ++#include "ucode.h" + + #define OCE_STA_CFON_ENABLED(hapd) \ + ((hapd->conf->oce & OCE_STA_CFON) && \ +@@ -51,6 +52,10 @@ struct hapd_interfaces { + struct hostapd_config * (*config_read_cb)(const char *config_fname); + int (*ctrl_iface_init)(struct hostapd_data *hapd); + void (*ctrl_iface_deinit)(struct hostapd_data *hapd); ++ int (*ctrl_iface_recv)(struct hostapd_data *hapd, ++ char *buf, char *reply, int reply_size, ++ struct sockaddr_storage *from, ++ socklen_t fromlen); + int (*for_each_interface)(struct hapd_interfaces *interfaces, + int (*cb)(struct hostapd_iface *iface, + void *ctx), void *ctx); +@@ -186,6 +191,7 @@ struct hostapd_data { + struct hostapd_config *iconf; + struct hostapd_bss_config *conf; + struct hostapd_ubus_bss ubus; ++ struct hostapd_ucode_bss ucode; + int interface_added; /* virtual interface added for this BSS */ + unsigned int started:1; + unsigned int disabled:1; +@@ -506,6 +512,7 @@ struct hostapd_sta_info { + */ + struct hostapd_iface { + struct hapd_interfaces *interfaces; ++ struct hostapd_ucode_iface ucode; + void *owner; + char *config_fname; + struct hostapd_config *conf; +--- a/src/ap/hostapd.c ++++ b/src/ap/hostapd.c +@@ -276,6 +276,8 @@ int hostapd_reload_config(struct hostapd + size_t j; + int i; + ++ hostapd_ucode_reload_bss(hapd, reconf); ++ + if (iface->config_fname == NULL) { + /* Only in-memory config in use - assume it has been updated */ + hostapd_clear_old(iface); +@@ -455,6 +457,7 @@ void hostapd_free_hapd_data(struct hosta + hapd->beacon_set_done = 0; + + wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface); ++ hostapd_ucode_free_bss(hapd); + hostapd_ubus_free_bss(hapd); + accounting_deinit(hapd); + hostapd_deinit_wpa(hapd); +@@ -619,6 +622,7 @@ void hostapd_cleanup_iface_partial(struc + static void hostapd_cleanup_iface(struct hostapd_iface *iface) + { + wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface); ++ hostapd_ucode_free_iface(iface); + eloop_cancel_timeout(channel_list_update_timeout, iface, NULL); + eloop_cancel_timeout(hostapd_interface_setup_failure_handler, iface, + NULL); +@@ -1209,6 +1213,7 @@ static int hostapd_start_beacon(struct h + hapd->driver->set_operstate(hapd->drv_priv, 1); + + hostapd_ubus_add_bss(hapd); ++ hostapd_ucode_add_bss(hapd); + + return 0; + } +--- a/wpa_supplicant/Makefile ++++ b/wpa_supplicant/Makefile +@@ -197,8 +197,20 @@ endif + ifdef CONFIG_UBUS + CFLAGS += -DUBUS_SUPPORT + OBJS += ubus.o ++LIBS += -lubus ++NEED_ULOOP:=y ++endif ++ ++ifdef CONFIG_UCODE ++CFLAGS += -DUCODE_SUPPORT ++OBJS += ../src/utils/ucode.o ++OBJS += ucode.o ++NEED_ULOOP:=y ++endif ++ ++ifdef NEED_ULOOP + OBJS += ../src/utils/uloop.o +-LIBS += -lubox -lubus ++LIBS += -lubox + endif + + ifdef CONFIG_CODE_COVERAGE +--- a/wpa_supplicant/wpa_supplicant.c ++++ b/wpa_supplicant/wpa_supplicant.c +@@ -7636,6 +7636,7 @@ struct wpa_supplicant * wpa_supplicant_a + #endif /* CONFIG_P2P */ + + wpas_ubus_add_bss(wpa_s); ++ wpas_ucode_add_bss(wpa_s); + + return wpa_s; + } +@@ -7663,6 +7664,7 @@ int wpa_supplicant_remove_iface(struct w + struct wpa_supplicant *parent = wpa_s->parent; + #endif /* CONFIG_MESH */ + ++ wpas_ucode_free_bss(wpa_s); + wpas_ubus_free_bss(wpa_s); + + /* Remove interface from the global list of interfaces */ +@@ -7973,6 +7975,7 @@ struct wpa_global * wpa_supplicant_init( + + eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0, + wpas_periodic, global, NULL); ++ wpas_ucode_init(global); + + return global; + } +@@ -8011,12 +8014,8 @@ int wpa_supplicant_run(struct wpa_global + eloop_register_signal_terminate(wpa_supplicant_terminate, global); + eloop_register_signal_reconfig(wpa_supplicant_reconfig, global); + +- wpas_ubus_add(global); +- + eloop_run(); + +- wpas_ubus_free(global); +- + return 0; + } + +@@ -8049,6 +8048,8 @@ void wpa_supplicant_deinit(struct wpa_gl + + wpas_notify_supplicant_deinitialized(global); + ++ wpas_ucode_free(); ++ + eap_peer_unregister_methods(); + #ifdef CONFIG_AP + eap_server_unregister_methods(); +--- a/wpa_supplicant/wpa_supplicant_i.h ++++ b/wpa_supplicant/wpa_supplicant_i.h +@@ -22,6 +22,7 @@ + #include "wmm_ac.h" + #include "pasn/pasn_common.h" + #include "ubus.h" ++#include "ucode.h" + + extern const char *const wpa_supplicant_version; + extern const char *const wpa_supplicant_license; +@@ -659,6 +660,7 @@ struct wpa_supplicant { + unsigned char perm_addr[ETH_ALEN]; + char ifname[100]; + struct wpas_ubus_bss ubus; ++ struct wpas_ucode_bss ucode; + #ifdef CONFIG_MATCH_IFACE + int matched; + #endif /* CONFIG_MATCH_IFACE */ +--- a/hostapd/ctrl_iface.c ++++ b/hostapd/ctrl_iface.c +@@ -4921,6 +4921,7 @@ try_again: + return -1; + } + ++ interface->ctrl_iface_recv = hostapd_ctrl_iface_receive_process; + wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb); + + return 0; +@@ -5022,6 +5023,7 @@ fail: + os_free(fname); + + interface->global_ctrl_sock = s; ++ interface->ctrl_iface_recv = hostapd_ctrl_iface_receive_process; + eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive, + interface, NULL); + diff --git a/package/network/services/hostapd/patches/700-wifi-reload.patch b/package/network/services/hostapd/patches/700-wifi-reload.patch index 0c7627645f..c0e7e4d16e 100644 --- a/package/network/services/hostapd/patches/700-wifi-reload.patch +++ b/package/network/services/hostapd/patches/700-wifi-reload.patch @@ -40,6 +40,15 @@ int rts_threshold; --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c +@@ -127,7 +127,7 @@ void hostapd_reconfig_encryption(struct + } + + +-static void hostapd_reload_bss(struct hostapd_data *hapd) ++void hostapd_reload_bss(struct hostapd_data *hapd) + { + struct hostapd_ssid *ssid; + @@ -255,6 +255,10 @@ static int hostapd_iface_conf_changed(st { size_t i; @@ -60,7 +69,7 @@ { struct hapd_interfaces *interfaces = iface->interfaces; struct hostapd_data *hapd = iface->bss[0]; -@@ -296,6 +300,9 @@ int hostapd_reload_config(struct hostapd +@@ -298,6 +302,9 @@ int hostapd_reload_config(struct hostapd char *fname; int res; @@ -70,7 +79,7 @@ hostapd_clear_old(iface); wpa_printf(MSG_DEBUG, -@@ -322,6 +329,24 @@ int hostapd_reload_config(struct hostapd +@@ -324,6 +331,24 @@ int hostapd_reload_config(struct hostapd wpa_printf(MSG_ERROR, "Failed to enable interface on config reload"); return res; @@ -95,7 +104,7 @@ } iface->conf = newconf; -@@ -338,6 +363,12 @@ int hostapd_reload_config(struct hostapd +@@ -340,6 +365,12 @@ int hostapd_reload_config(struct hostapd for (j = 0; j < iface->num_bss; j++) { hapd = iface->bss[j]; @@ -108,7 +117,17 @@ if (!hapd->conf->config_id || !newconf->bss[j]->config_id || os_strcmp(hapd->conf->config_id, newconf->bss[j]->config_id) != 0) -@@ -2700,6 +2731,10 @@ hostapd_alloc_bss_data(struct hostapd_if +@@ -1236,8 +1267,7 @@ static int hostapd_start_beacon(struct h + * initialized. Most of the modules that are initialized here will be + * deinitialized in hostapd_cleanup(). + */ +-static int hostapd_setup_bss(struct hostapd_data *hapd, int first, +- bool start_beacon) ++int hostapd_setup_bss(struct hostapd_data *hapd, int first, bool start_beacon) + { + struct hostapd_bss_config *conf = hapd->conf; + u8 ssid[SSID_MAX_LEN + 1]; +@@ -2705,6 +2735,10 @@ hostapd_alloc_bss_data(struct hostapd_if hapd->iconf = conf; hapd->conf = bss; hapd->iface = hapd_iface; @@ -119,9 +138,18 @@ if (conf) hapd->driver = conf->driver; hapd->ctrl_sock = -1; +@@ -2723,7 +2757,7 @@ hostapd_alloc_bss_data(struct hostapd_if + } + + +-static void hostapd_bss_deinit(struct hostapd_data *hapd) ++void hostapd_bss_deinit(struct hostapd_data *hapd) + { + if (!hapd) + return; --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h -@@ -47,7 +47,7 @@ struct mesh_conf; +@@ -48,7 +48,7 @@ struct mesh_conf; struct hostapd_iface; struct hapd_interfaces { @@ -130,23 +158,33 @@ struct hostapd_config * (*config_read_cb)(const char *config_fname); int (*ctrl_iface_init)(struct hostapd_data *hapd); void (*ctrl_iface_deinit)(struct hostapd_data *hapd); -@@ -186,6 +186,7 @@ struct hostapd_data { - struct hostapd_config *iconf; +@@ -192,6 +192,7 @@ struct hostapd_data { struct hostapd_bss_config *conf; struct hostapd_ubus_bss ubus; + struct hostapd_ucode_bss ucode; + char *config_id; int interface_added; /* virtual interface added for this BSS */ unsigned int started:1; unsigned int disabled:1; -@@ -689,7 +690,7 @@ struct hostapd_iface { +@@ -696,7 +697,9 @@ struct hostapd_iface { int hostapd_for_each_interface(struct hapd_interfaces *interfaces, int (*cb)(struct hostapd_iface *iface, void *ctx), void *ctx); -int hostapd_reload_config(struct hostapd_iface *iface); +int hostapd_reload_config(struct hostapd_iface *iface, int reconf); ++void hostapd_reload_bss(struct hostapd_data *hapd); ++void hostapd_bss_deinit(struct hostapd_data *hapd); void hostapd_reconfig_encryption(struct hostapd_data *hapd); struct hostapd_data * hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface, +@@ -713,6 +716,7 @@ struct hostapd_iface * hostapd_init(stru + struct hostapd_iface * + hostapd_interface_init_bss(struct hapd_interfaces *interfaces, const char *phy, + const char *config_fname, int debug); ++int hostapd_setup_bss(struct hostapd_data *hapd, int first, bool start_beacon); + void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta, + int reassoc); + void hostapd_interface_deinit_free(struct hostapd_iface *iface); --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -5322,6 +5322,9 @@ static int wpa_driver_nl80211_set_ap(voi diff --git a/package/network/services/hostapd/patches/701-reload_config_inline.patch b/package/network/services/hostapd/patches/701-reload_config_inline.patch new file mode 100644 index 0000000000..071281eb5c --- /dev/null +++ b/package/network/services/hostapd/patches/701-reload_config_inline.patch @@ -0,0 +1,33 @@ +--- a/hostapd/config_file.c ++++ b/hostapd/config_file.c +@@ -4814,7 +4814,12 @@ struct hostapd_config * hostapd_config_r + int errors = 0; + size_t i; + +- f = fopen(fname, "r"); ++ if (!strncmp(fname, "data:", 5)) { ++ f = fmemopen((void *)(fname + 5), strlen(fname + 5), "r"); ++ fname = ""; ++ } else { ++ f = fopen(fname, "r"); ++ } + if (f == NULL) { + wpa_printf(MSG_ERROR, "Could not open configuration file '%s' " + "for reading.", fname); +--- a/wpa_supplicant/config_file.c ++++ b/wpa_supplicant/config_file.c +@@ -326,8 +326,13 @@ struct wpa_config * wpa_config_read(cons + while (cred_tail && cred_tail->next) + cred_tail = cred_tail->next; + ++ if (!strncmp(name, "data:", 5)) { ++ f = fmemopen((void *)(name + 5), strlen(name + 5), "r"); ++ name = ""; ++ } else { ++ f = fopen(name, "r"); ++ } + wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name); +- f = fopen(name, "r"); + if (f == NULL) { + wpa_printf(MSG_ERROR, "Failed to open config file '%s', " + "error: %s", name, strerror(errno)); diff --git a/package/network/services/hostapd/patches/720-iface_max_num_sta.patch b/package/network/services/hostapd/patches/720-iface_max_num_sta.patch index 0bb00f9555..5f40aabb5e 100644 --- a/package/network/services/hostapd/patches/720-iface_max_num_sta.patch +++ b/package/network/services/hostapd/patches/720-iface_max_num_sta.patch @@ -17,7 +17,7 @@ } else if (os_strcmp(buf, "extended_key_id") == 0) { --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h -@@ -734,6 +734,7 @@ void hostapd_cleanup_cs_params(struct ho +@@ -744,6 +744,7 @@ void hostapd_cleanup_cs_params(struct ho void hostapd_periodic_iface(struct hostapd_iface *iface); int hostapd_owe_trans_get_info(struct hostapd_data *hapd); void hostapd_ocv_check_csa_sa_query(void *eloop_ctx, void *timeout_ctx); diff --git a/package/network/services/hostapd/patches/750-qos_map_set_without_interworking.patch b/package/network/services/hostapd/patches/750-qos_map_set_without_interworking.patch index 124f5ea6ba..3e282b47a3 100644 --- a/package/network/services/hostapd/patches/750-qos_map_set_without_interworking.patch +++ b/package/network/services/hostapd/patches/750-qos_map_set_without_interworking.patch @@ -32,7 +32,7 @@ os_free(bss->dump_msk_file); --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c -@@ -1534,6 +1534,7 @@ static int hostapd_setup_bss(struct host +@@ -1538,6 +1538,7 @@ int hostapd_setup_bss(struct hostapd_dat wpa_printf(MSG_ERROR, "GAS server initialization failed"); return -1; } @@ -40,7 +40,7 @@ if (conf->qos_map_set_len && hostapd_drv_set_qos_map(hapd, conf->qos_map_set, -@@ -1541,7 +1542,6 @@ static int hostapd_setup_bss(struct host +@@ -1545,7 +1546,6 @@ int hostapd_setup_bss(struct hostapd_dat wpa_printf(MSG_ERROR, "Failed to initialize QoS Map"); return -1; } diff --git a/package/network/services/hostapd/patches/761-shared_das_port.patch b/package/network/services/hostapd/patches/761-shared_das_port.patch index dad7afddf1..d60764ac59 100644 --- a/package/network/services/hostapd/patches/761-shared_das_port.patch +++ b/package/network/services/hostapd/patches/761-shared_das_port.patch @@ -10,7 +10,7 @@ unsigned int time_window; --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c -@@ -1471,6 +1471,7 @@ static int hostapd_setup_bss(struct host +@@ -1475,6 +1475,7 @@ int hostapd_setup_bss(struct hostapd_dat os_memset(&das_conf, 0, sizeof(das_conf)); das_conf.port = conf->radius_das_port; diff --git a/package/network/services/hostapd/patches/770-radius_server.patch b/package/network/services/hostapd/patches/770-radius_server.patch index 3f0f40c0f7..6fca86d881 100644 --- a/package/network/services/hostapd/patches/770-radius_server.patch +++ b/package/network/services/hostapd/patches/770-radius_server.patch @@ -21,7 +21,7 @@ #ifndef CONFIG_NO_HOSTAPD_LOGGER static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module, -@@ -665,6 +666,11 @@ int main(int argc, char *argv[]) +@@ -755,6 +756,11 @@ int main(int argc, char *argv[]) if (os_program_init()) return -1; diff --git a/package/network/services/hostapd/src/src/ap/ubus.c b/package/network/services/hostapd/src/src/ap/ubus.c index a8a55f0493..a609eb1ef2 100644 --- a/package/network/services/hostapd/src/src/ap/ubus.c +++ b/package/network/services/hostapd/src/src/ap/ubus.c @@ -29,11 +29,6 @@ static struct ubus_context *ctx; static struct blob_buf b; static int ctx_ref; -static inline struct hapd_interfaces *get_hapd_interfaces_from_object(struct ubus_object *obj) -{ - return container_of(obj, struct hapd_interfaces, ubus); -} - static inline struct hostapd_data *get_hapd_from_object(struct ubus_object *obj) { return container_of(obj, struct hostapd_data, ubus.obj); @@ -123,38 +118,6 @@ static void hostapd_notify_ubus(struct ubus_object *obj, char *bssname, char *ev free(event_type); } -static void hostapd_send_procd_event(char *bssname, char *event) -{ - char *name, *s; - uint32_t id; - void *v; - - if (!ctx || ubus_lookup_id(ctx, "service", &id)) - return; - - if (asprintf(&name, "hostapd.%s.%s", bssname, event) < 0) - return; - - blob_buf_init(&b, 0); - - s = blobmsg_alloc_string_buffer(&b, "type", strlen(name) + 1); - sprintf(s, "%s", name); - blobmsg_add_string_buffer(&b); - - v = blobmsg_open_table(&b, "data"); - blobmsg_close_table(&b, v); - - ubus_invoke(ctx, id, "event", b.head, NULL, NULL, 1000); - - free(name); -} - -static void hostapd_send_shared_event(struct ubus_object *obj, char *bssname, char *event) -{ - hostapd_send_procd_event(bssname, event); - hostapd_notify_ubus(obj, bssname, event); -} - static void hostapd_bss_del_ban(void *eloop_data, void *user_ctx) { @@ -199,10 +162,8 @@ hostapd_bss_reload(struct ubus_context *ctx, struct ubus_object *obj, struct blob_attr *msg) { struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); - int ret = hostapd_reload_config(hapd->iface, 1); - hostapd_send_shared_event(&hapd->iface->interfaces->ubus, hapd->conf->iface, "reload"); - return ret; + return hostapd_reload_config(hapd->iface, 1); } @@ -683,68 +644,6 @@ enum { __CONFIG_MAX }; -static const struct blobmsg_policy config_add_policy[__CONFIG_MAX] = { - [CONFIG_IFACE] = { "iface", BLOBMSG_TYPE_STRING }, - [CONFIG_FILE] = { "config", BLOBMSG_TYPE_STRING }, -}; - -static int -hostapd_config_add(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) -{ - struct blob_attr *tb[__CONFIG_MAX]; - struct hapd_interfaces *interfaces = get_hapd_interfaces_from_object(obj); - char buf[128]; - - blobmsg_parse(config_add_policy, __CONFIG_MAX, tb, blob_data(msg), blob_len(msg)); - - if (!tb[CONFIG_FILE] || !tb[CONFIG_IFACE]) - return UBUS_STATUS_INVALID_ARGUMENT; - - snprintf(buf, sizeof(buf), "bss_config=%s:%s", - blobmsg_get_string(tb[CONFIG_IFACE]), - blobmsg_get_string(tb[CONFIG_FILE])); - - if (hostapd_add_iface(interfaces, buf)) - return UBUS_STATUS_INVALID_ARGUMENT; - - blob_buf_init(&b, 0); - blobmsg_add_u32(&b, "pid", getpid()); - ubus_send_reply(ctx, req, b.head); - - return UBUS_STATUS_OK; -} - -enum { - CONFIG_REM_IFACE, - __CONFIG_REM_MAX -}; - -static const struct blobmsg_policy config_remove_policy[__CONFIG_REM_MAX] = { - [CONFIG_REM_IFACE] = { "iface", BLOBMSG_TYPE_STRING }, -}; - -static int -hostapd_config_remove(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) -{ - struct blob_attr *tb[__CONFIG_REM_MAX]; - struct hapd_interfaces *interfaces = get_hapd_interfaces_from_object(obj); - char buf[128]; - - blobmsg_parse(config_remove_policy, __CONFIG_REM_MAX, tb, blob_data(msg), blob_len(msg)); - - if (!tb[CONFIG_REM_IFACE]) - return UBUS_STATUS_INVALID_ARGUMENT; - - if (hostapd_remove_iface(interfaces, blobmsg_get_string(tb[CONFIG_REM_IFACE]))) - return UBUS_STATUS_INVALID_ARGUMENT; - - return UBUS_STATUS_OK; -} - enum { CSA_FREQ, CSA_BCN_COUNT, @@ -1781,8 +1680,6 @@ void hostapd_ubus_add_bss(struct hostapd_data *hapd) obj->n_methods = bss_object_type.n_methods; ret = ubus_add_object(ctx, obj); hostapd_ubus_ref_inc(); - - hostapd_send_shared_event(&hapd->iface->interfaces->ubus, hapd->conf->iface, "add"); } void hostapd_ubus_free_bss(struct hostapd_data *hapd) @@ -1798,8 +1695,6 @@ void hostapd_ubus_free_bss(struct hostapd_data *hapd) if (!ctx) return; - hostapd_send_shared_event(&hapd->iface->interfaces->ubus, hapd->conf->iface, "remove"); - if (obj->id) { ubus_remove_object(ctx, obj); hostapd_ubus_ref_dec(); @@ -1845,47 +1740,6 @@ void hostapd_ubus_remove_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vl hostapd_ubus_vlan_action(hapd, vlan, "vlan_remove"); } -static const struct ubus_method daemon_methods[] = { - UBUS_METHOD("config_add", hostapd_config_add, config_add_policy), - UBUS_METHOD("config_remove", hostapd_config_remove, config_remove_policy), -}; - -static struct ubus_object_type daemon_object_type = - UBUS_OBJECT_TYPE("hostapd", daemon_methods); - -void hostapd_ubus_add(struct hapd_interfaces *interfaces) -{ - struct ubus_object *obj = &interfaces->ubus; - int ret; - - if (!hostapd_ubus_init()) - return; - - obj->name = strdup("hostapd"); - - obj->type = &daemon_object_type; - obj->methods = daemon_object_type.methods; - obj->n_methods = daemon_object_type.n_methods; - ret = ubus_add_object(ctx, obj); - hostapd_ubus_ref_inc(); -} - -void hostapd_ubus_free(struct hapd_interfaces *interfaces) -{ - struct ubus_object *obj = &interfaces->ubus; - char *name = (char *) obj->name; - - if (!ctx) - return; - - if (obj->id) { - ubus_remove_object(ctx, obj); - hostapd_ubus_ref_dec(); - } - - free(name); -} - struct ubus_event_req { struct ubus_notify_request nreq; int resp; diff --git a/package/network/services/hostapd/src/src/ap/ucode.c b/package/network/services/hostapd/src/src/ap/ucode.c new file mode 100644 index 0000000000..137cb81ab4 --- /dev/null +++ b/package/network/services/hostapd/src/src/ap/ucode.c @@ -0,0 +1,394 @@ +#include + +#include "utils/includes.h" +#include "utils/common.h" +#include "utils/ucode.h" +#include "hostapd.h" +#include "ap_drv_ops.h" +#include + +static uc_resource_type_t *global_type, *bss_type, *iface_type; +static struct hapd_interfaces *interfaces; +static uc_value_t *global, *bss_registry, *iface_registry; +static uc_vm_t *vm; + +static uc_value_t * +hostapd_ucode_bss_get_uval(struct hostapd_data *hapd) +{ + uc_value_t *val; + + if (hapd->ucode.idx) + return wpa_ucode_registry_get(bss_registry, hapd->ucode.idx); + + val = uc_resource_new(bss_type, hapd); + wpa_ucode_registry_add(bss_registry, val, &hapd->ucode.idx); + + return val; +} + +static uc_value_t * +hostapd_ucode_iface_get_uval(struct hostapd_iface *hapd) +{ + uc_value_t *val; + + if (hapd->ucode.idx) + return wpa_ucode_registry_get(iface_registry, hapd->ucode.idx); + + val = uc_resource_new(iface_type, hapd); + wpa_ucode_registry_add(iface_registry, val, &hapd->ucode.idx); + + return val; +} + +static void +hostapd_ucode_update_bss_list(struct hostapd_iface *iface) +{ + uc_value_t *ifval, *list; + int i; + + list = ucv_array_new(vm); + for (i = 0; i < iface->num_bss; i++) { + struct hostapd_data *hapd = iface->bss[i]; + uc_value_t *val = hostapd_ucode_bss_get_uval(hapd); + uc_value_t *proto = ucv_prototype_get(val); + + ucv_object_add(proto, "name", ucv_get(ucv_string_new(hapd->conf->iface))); + ucv_object_add(proto, "index", ucv_int64_new(i)); + ucv_array_set(list, i, ucv_get(val)); + } + + ifval = hostapd_ucode_iface_get_uval(iface); + ucv_object_add(ucv_prototype_get(ifval), "bss", ucv_get(list)); +} + +static void +hostapd_ucode_update_interfaces(void) +{ + uc_value_t *ifs = ucv_object_new(vm); + int i; + + for (i = 0; i < interfaces->count; i++) { + struct hostapd_iface *iface = interfaces->iface[i]; + + ucv_object_add(ifs, iface->phy, ucv_get(hostapd_ucode_iface_get_uval(iface))); + hostapd_ucode_update_bss_list(iface); + } + + ucv_object_add(ucv_prototype_get(global), "interfaces", ucv_get(ifs)); + ucv_gc(vm); +} + +static uc_value_t * +uc_hostapd_add_iface(uc_vm_t *vm, size_t nargs) +{ + uc_value_t *iface = uc_fn_arg(0); + int ret; + + if (ucv_type(iface) != UC_STRING) + return ucv_int64_new(-1); + + ret = hostapd_add_iface(interfaces, ucv_string_get(iface)); + hostapd_ucode_update_interfaces(); + + return ucv_int64_new(ret); +} + +static uc_value_t * +uc_hostapd_remove_iface(uc_vm_t *vm, size_t nargs) +{ + uc_value_t *iface = uc_fn_arg(0); + + if (ucv_type(iface) != UC_STRING) + return NULL; + + hostapd_remove_iface(interfaces, ucv_string_get(iface)); + hostapd_ucode_update_interfaces(); + + return NULL; +} + +static uc_value_t * +uc_hostapd_bss_set_config(uc_vm_t *vm, size_t nargs) +{ + struct hostapd_data *hapd = uc_fn_thisval("hostapd.bss"); + struct hostapd_bss_config *old_bss; + struct hostapd_iface *iface; + struct hostapd_config *conf; + uc_value_t *file = uc_fn_arg(0); + uc_value_t *index = uc_fn_arg(1); + unsigned int i, idx = 0; + int ret = -1; + + if (!hapd || ucv_type(file) != UC_STRING) + goto out; + + if (ucv_type(index) == UC_INTEGER) + idx = ucv_int64_get(index); + + iface = hapd->iface; + conf = interfaces->config_read_cb(ucv_string_get(file)); + if (!conf || idx > conf->num_bss || !conf->bss[idx]) + goto out; + + hostapd_bss_deinit_no_free(hapd); + hostapd_drv_stop_ap(hapd); + hostapd_free_hapd_data(hapd); + + old_bss = hapd->conf; + for (i = 0; i < iface->conf->num_bss; i++) + if (iface->conf->bss[i] == hapd->conf) + iface->conf->bss[i] = conf->bss[idx]; + hapd->conf = conf->bss[idx]; + conf->bss[idx] = old_bss; + hostapd_config_free(conf); + + hostapd_setup_bss(hapd, hapd == iface->bss[0], !iface->conf->mbssid); + + ret = 0; + +out: + return ucv_int64_new(ret); +} + +static void +hostapd_remove_iface_bss_conf(struct hostapd_config *iconf, + struct hostapd_bss_config *conf) +{ + int i; + + for (i = 0; i < iconf->num_bss; i++) + if (iconf->bss[i] == conf) + break; + + if (i == iconf->num_bss) + return; + + for (i++; i < iconf->num_bss; i++) + iconf->bss[i - 1] = iconf->bss[i]; + iconf->num_bss--; +} + + +static uc_value_t * +uc_hostapd_bss_delete(uc_vm_t *vm, size_t nargs) +{ + struct hostapd_data *hapd = uc_fn_thisval("hostapd.bss"); + struct hostapd_iface *iface; + int i, idx; + + if (!hapd || hapd == hapd->iface->bss[0]) + return NULL; + + iface = hapd->iface; + for (idx = 0; idx < iface->num_bss; idx++) + if (iface->bss[idx] == hapd) + break; + + if (idx == iface->num_bss) + return NULL; + + for (i = idx + 1; i < iface->num_bss; i++) + iface->bss[i - 1] = iface->bss[i]; + iface->num_bss--; + + hostapd_drv_stop_ap(hapd); + hostapd_bss_deinit(hapd); + hostapd_remove_iface_bss_conf(iface->conf, hapd->conf); + hostapd_config_free_bss(hapd->conf); + os_free(hapd); + + hostapd_ucode_update_bss_list(iface); + ucv_gc(vm); + + return NULL; +} + +static uc_value_t * +uc_hostapd_iface_add_bss(uc_vm_t *vm, size_t nargs) +{ + struct hostapd_iface *iface = uc_fn_thisval("hostapd.iface"); + struct hostapd_bss_config *bss; + struct hostapd_config *conf; + struct hostapd_data *hapd; + uc_value_t *file = uc_fn_arg(0); + uc_value_t *index = uc_fn_arg(1); + unsigned int idx = 0; + uc_value_t *ret = NULL; + + if (!iface || ucv_type(file) != UC_STRING) + goto out; + + if (ucv_type(index) == UC_INTEGER) + idx = ucv_int64_get(index); + + conf = interfaces->config_read_cb(ucv_string_get(file)); + if (!conf || idx > conf->num_bss || !conf->bss[idx]) + goto out; + + bss = conf->bss[idx]; + hapd = hostapd_alloc_bss_data(iface, iface->conf, bss); + if (!hapd) + goto out; + + hapd->driver = iface->bss[0]->driver; + hapd->drv_priv = iface->bss[0]->drv_priv; + if (interfaces->ctrl_iface_init && + interfaces->ctrl_iface_init(hapd) < 0) + goto free_hapd; + + if (iface->state == HAPD_IFACE_ENABLED && + hostapd_setup_bss(hapd, -1, true)) + goto deinit_ctrl; + + iface->bss = os_realloc_array(iface->bss, iface->num_bss + 1, + sizeof(*iface->bss)); + iface->bss[iface->num_bss++] = hapd; + + iface->conf->bss = os_realloc_array(iface->conf->bss, + iface->conf->num_bss + 1, + sizeof(*iface->conf->bss)); + iface->conf->bss[iface->conf->num_bss] = bss; + conf->bss[idx] = NULL; + ret = hostapd_ucode_bss_get_uval(hapd); + hostapd_ucode_update_bss_list(iface); + goto out; + +deinit_ctrl: + if (interfaces->ctrl_iface_deinit) + interfaces->ctrl_iface_deinit(hapd); +free_hapd: + hostapd_free_hapd_data(hapd); + os_free(hapd); +out: + hostapd_config_free(conf); + return ret; +} + +static uc_value_t * +uc_hostapd_bss_ctrl(uc_vm_t *vm, size_t nargs) +{ + struct hostapd_data *hapd = uc_fn_thisval("hostapd.bss"); + uc_value_t *arg = uc_fn_arg(0); + struct sockaddr_storage from = {}; + static char reply[4096]; + int reply_len; + + if (!hapd || !interfaces->ctrl_iface_recv || + ucv_type(arg) != UC_STRING) + return NULL; + + reply_len = interfaces->ctrl_iface_recv(hapd, ucv_string_get(arg), + reply, sizeof(reply), + &from, sizeof(from)); + if (reply_len < 0) + return NULL; + + if (reply_len && reply[reply_len - 1] == '\n') + reply_len--; + + return ucv_string_new_length(reply, reply_len); +} + +int hostapd_ucode_init(struct hapd_interfaces *ifaces) +{ + static const uc_function_list_t global_fns[] = { + { "printf", uc_wpa_printf }, + { "getpid", uc_wpa_getpid }, + { "sha1", uc_wpa_sha1 }, + { "add_iface", uc_hostapd_add_iface }, + { "remove_iface", uc_hostapd_remove_iface }, + }; + static const uc_function_list_t bss_fns[] = { + { "ctrl", uc_hostapd_bss_ctrl }, + { "set_config", uc_hostapd_bss_set_config }, + { "delete", uc_hostapd_bss_delete }, + }; + static const uc_function_list_t iface_fns[] = { + { "add_bss", uc_hostapd_iface_add_bss } + }; + uc_value_t *data, *proto; + + interfaces = ifaces; + vm = wpa_ucode_create_vm(); + + global_type = uc_type_declare(vm, "hostapd.global", global_fns, NULL); + bss_type = uc_type_declare(vm, "hostapd.bss", bss_fns, NULL); + iface_type = uc_type_declare(vm, "hostapd.iface", iface_fns, NULL); + + bss_registry = ucv_array_new(vm); + uc_vm_registry_set(vm, "hostap.bss_registry", bss_registry); + + iface_registry = ucv_array_new(vm); + uc_vm_registry_set(vm, "hostap.iface_registry", iface_registry); + + global = wpa_ucode_global_init("hostapd", global_type); + + if (wpa_ucode_run(HOSTAPD_UC_PATH "hostapd.uc")) + goto free_vm; + ucv_gc(vm); + + return 0; + +free_vm: + wpa_ucode_free_vm(); + return -1; +} + +void hostapd_ucode_free(void) +{ + if (wpa_ucode_call_prepare("shutdown") == 0) + ucv_put(wpa_ucode_call(0)); + wpa_ucode_free_vm(); +} + +void hostapd_ucode_free_iface(struct hostapd_iface *iface) +{ + wpa_ucode_registry_remove(iface_registry, iface->ucode.idx); +} + +void hostapd_ucode_add_bss(struct hostapd_data *hapd) +{ + uc_value_t *val; + + if (wpa_ucode_call_prepare("bss_add")) + return; + + val = hostapd_ucode_bss_get_uval(hapd); + uc_value_push(ucv_get(ucv_string_new(hapd->conf->iface))); + uc_value_push(ucv_get(val)); + ucv_put(wpa_ucode_call(2)); + ucv_gc(vm); +} + +void hostapd_ucode_reload_bss(struct hostapd_data *hapd, int reconf) +{ + uc_value_t *val; + + if (wpa_ucode_call_prepare("bss_reload")) + return; + + val = hostapd_ucode_bss_get_uval(hapd); + uc_value_push(ucv_get(ucv_string_new(hapd->conf->iface))); + uc_value_push(ucv_get(val)); + uc_value_push(ucv_int64_new(reconf)); + ucv_put(wpa_ucode_call(3)); + ucv_gc(vm); +} + +void hostapd_ucode_free_bss(struct hostapd_data *hapd) +{ + uc_value_t *val; + + val = wpa_ucode_registry_remove(bss_registry, hapd->ucode.idx); + if (!val) + return; + + hapd->ucode.idx = 0; + if (wpa_ucode_call_prepare("bss_remove")) + return; + + uc_value_push(ucv_string_new(hapd->conf->iface)); + uc_value_push(ucv_get(val)); + ucv_put(wpa_ucode_call(2)); + ucv_gc(vm); +} diff --git a/package/network/services/hostapd/src/src/ap/ucode.h b/package/network/services/hostapd/src/src/ap/ucode.h new file mode 100644 index 0000000000..dbc49e6eac --- /dev/null +++ b/package/network/services/hostapd/src/src/ap/ucode.h @@ -0,0 +1,54 @@ +#ifndef __HOSTAPD_AP_UCODE_H +#define __HOSTAPD_AP_UCODE_H + +#include "utils/ucode.h" + +struct hostapd_data; + +struct hostapd_ucode_bss { +#ifdef UCODE_SUPPORT + int idx; +#endif +}; + +struct hostapd_ucode_iface { +#ifdef UCODE_SUPPORT + int idx; +#endif +}; + +#ifdef UCODE_SUPPORT + +int hostapd_ucode_init(struct hapd_interfaces *ifaces); + +void hostapd_ucode_free(void); +void hostapd_ucode_free_iface(struct hostapd_iface *iface); +void hostapd_ucode_add_bss(struct hostapd_data *hapd); +void hostapd_ucode_free_bss(struct hostapd_data *hapd); +void hostapd_ucode_reload_bss(struct hostapd_data *hapd, int reconf); + +#else + +static inline int hostapd_ucode_init(struct hapd_interfaces *ifaces) +{ + return -EINVAL; +} +static inline void hostapd_ucode_free(void) +{ +} +static inline void hostapd_ucode_free_iface(struct hostapd_iface *iface) +{ +} +static inline void hostapd_ucode_reload_bss(struct hostapd_data *hapd, int reconf) +{ +} +static inline void hostapd_ucode_add_bss(struct hostapd_data *hapd) +{ +} +static inline void hostapd_ucode_free_bss(struct hostapd_data *hapd) +{ +} + +#endif + +#endif diff --git a/package/network/services/hostapd/src/src/utils/ucode.c b/package/network/services/hostapd/src/src/utils/ucode.c new file mode 100644 index 0000000000..fabf58a5e8 --- /dev/null +++ b/package/network/services/hostapd/src/src/utils/ucode.c @@ -0,0 +1,237 @@ +#include +#include "ucode.h" +#include "utils/eloop.h" +#include "crypto/crypto.h" +#include "crypto/sha1.h" +#include +#include + +static uc_value_t *registry; +static uc_vm_t vm; +static struct uloop_timeout gc_timer; + +static void uc_gc_timer(struct uloop_timeout *timeout) +{ + ucv_gc(&vm); +} + +uc_value_t *uc_wpa_printf(uc_vm_t *vm, size_t nargs) +{ + uc_value_t *level = uc_fn_arg(0); + uc_value_t *ret, **args; + uc_cfn_ptr_t _sprintf; + int l = MSG_INFO; + int i, start = 0; + + _sprintf = uc_stdlib_function("sprintf"); + if (!sprintf) + return NULL; + + if (ucv_type(level) == UC_INTEGER) { + l = ucv_int64_get(level); + start++; + } + + if (nargs <= start) + return NULL; + + ret = _sprintf(vm, nargs - start); + if (ucv_type(ret) != UC_STRING) + return NULL; + + wpa_printf(l, "%s", ucv_string_get(ret)); + ucv_put(ret); + + return NULL; +} + +uc_value_t *uc_wpa_getpid(uc_vm_t *vm, size_t nargs) +{ + return ucv_int64_new(getpid()); +} + +uc_value_t *uc_wpa_sha1(uc_vm_t *vm, size_t nargs) +{ + u8 hash[SHA1_MAC_LEN]; + char hash_hex[2 * ARRAY_SIZE(hash) + 1]; + uc_value_t *val; + size_t *lens; + const u8 **args; + int i; + + if (!nargs) + return NULL; + + args = alloca(nargs * sizeof(*args)); + lens = alloca(nargs * sizeof(*lens)); + for (i = 0; i < nargs; i++) { + val = uc_fn_arg(i); + if (ucv_type(val) != UC_STRING) + return NULL; + + args[i] = ucv_string_get(val); + lens[i] = ucv_string_length(val); + } + + if (sha1_vector(nargs, args, lens, hash)) + return NULL; + + for (i = 0; i < ARRAY_SIZE(hash); i++) + sprintf(hash_hex + 2 * i, "%02x", hash[i]); + + return ucv_string_new_length(hash_hex, 2 * ARRAY_SIZE(hash)); +} + +uc_vm_t *wpa_ucode_create_vm(void) +{ + static uc_parse_config_t config = { + .strict_declarations = true, + .lstrip_blocks = true, + .trim_blocks = true, + .raw_mode = true + }; + + uc_search_path_init(&config.module_search_path); + uc_search_path_add(&config.module_search_path, HOSTAPD_UC_PATH "*.so"); + uc_search_path_add(&config.module_search_path, HOSTAPD_UC_PATH "*.uc"); + + uc_vm_init(&vm, &config); + + uc_stdlib_load(uc_vm_scope_get(&vm)); + eloop_add_uloop(); + gc_timer.cb = uc_gc_timer; + + return &vm; +} + +int wpa_ucode_run(const char *script) +{ + uc_source_t *source; + uc_program_t *prog; + uc_value_t *ops; + char *err; + int ret; + + source = uc_source_new_file(script); + if (!source) + return -1; + + prog = uc_compile(vm.config, source, &err); + uc_source_put(source); + if (!prog) { + wpa_printf(MSG_ERROR, "Error loading ucode: %s\n", err); + return -1; + } + + ret = uc_vm_execute(&vm, prog, &ops); + uc_program_put(prog); + if (ret || !ops) + return -1; + + registry = ucv_array_new(&vm); + uc_vm_registry_set(&vm, "hostap.registry", registry); + ucv_array_set(registry, 0, ucv_get(ops)); + + return 0; +} + +int wpa_ucode_call_prepare(const char *fname) +{ + uc_value_t *obj, *func; + + if (!registry) + return -1; + + obj = ucv_array_get(registry, 0); + if (!obj) + return -1; + + func = ucv_object_get(obj, fname, NULL); + if (!ucv_is_callable(func)) + return -1; + + uc_vm_stack_push(&vm, ucv_get(obj)); + uc_vm_stack_push(&vm, ucv_get(func)); + + return 0; +} + +uc_value_t *wpa_ucode_global_init(const char *name, uc_resource_type_t *global_type) +{ + uc_value_t *global = uc_resource_new(global_type, NULL); + uc_value_t *proto; + + uc_vm_registry_set(&vm, "hostap.global", global); + proto = ucv_prototype_get(global); + ucv_object_add(proto, "data", ucv_get(ucv_object_new(&vm))); + +#define ADD_CONST(x) ucv_object_add(proto, #x, ucv_int64_new(x)) + ADD_CONST(MSG_EXCESSIVE); + ADD_CONST(MSG_MSGDUMP); + ADD_CONST(MSG_DEBUG); + ADD_CONST(MSG_INFO); + ADD_CONST(MSG_WARNING); + ADD_CONST(MSG_ERROR); +#undef ADD_CONST + + ucv_object_add(uc_vm_scope_get(&vm), name, ucv_get(global)); + + return global; +} + +void wpa_ucode_registry_add(uc_value_t *reg, uc_value_t *val, int *idx) +{ + uc_value_t *data; + int i = 0; + + while (ucv_array_get(reg, i)) + i++; + + ucv_array_set(reg, i, ucv_get(val)); + + data = ucv_object_new(&vm); + ucv_object_add(ucv_prototype_get(val), "data", ucv_get(data)); + + *idx = i + 1; +} + +uc_value_t *wpa_ucode_registry_get(uc_value_t *reg, int idx) +{ + if (!idx) + return NULL; + + return ucv_array_get(reg, idx - 1); +} + +uc_value_t *wpa_ucode_registry_remove(uc_value_t *reg, int idx) +{ + uc_value_t *val = wpa_ucode_registry_get(reg, idx); + + if (val) + ucv_array_set(reg, idx - 1, NULL); + + return val; +} + + +uc_value_t *wpa_ucode_call(size_t nargs) +{ + if (uc_vm_call(&vm, true, nargs) != EXCEPTION_NONE) + return NULL; + + if (!gc_timer.pending) + uloop_timeout_set(&gc_timer, 10); + + return uc_vm_stack_pop(&vm); +} + +void wpa_ucode_free_vm(void) +{ + if (!vm.config) + return; + + uc_search_path_free(&vm.config->module_search_path); + uc_vm_free(&vm); + registry = NULL; + vm = (uc_vm_t){}; +} diff --git a/package/network/services/hostapd/src/src/utils/ucode.h b/package/network/services/hostapd/src/src/utils/ucode.h new file mode 100644 index 0000000000..4caf8ada5a --- /dev/null +++ b/package/network/services/hostapd/src/src/utils/ucode.h @@ -0,0 +1,28 @@ +#ifndef __HOSTAPD_UTILS_UCODE_H +#define __HOSTAPD_UTILS_UCODE_H + +#include "utils/includes.h" +#include "utils/common.h" +#include +#include + +#define HOSTAPD_UC_PATH "/usr/share/hostap/" + +extern uc_value_t *uc_registry; +uc_vm_t *wpa_ucode_create_vm(void); +int wpa_ucode_run(const char *script); +int wpa_ucode_call_prepare(const char *fname); +uc_value_t *wpa_ucode_call(size_t nargs); +void wpa_ucode_free_vm(void); + +uc_value_t *wpa_ucode_global_init(const char *name, uc_resource_type_t *global_type); + +void wpa_ucode_registry_add(uc_value_t *reg, uc_value_t *val, int *idx); +uc_value_t *wpa_ucode_registry_get(uc_value_t *reg, int idx); +uc_value_t *wpa_ucode_registry_remove(uc_value_t *reg, int idx); + +uc_value_t *uc_wpa_printf(uc_vm_t *vm, size_t nargs); +uc_value_t *uc_wpa_getpid(uc_vm_t *vm, size_t nargs); +uc_value_t *uc_wpa_sha1(uc_vm_t *vm, size_t nargs); + +#endif diff --git a/package/network/services/hostapd/src/wpa_supplicant/ubus.c b/package/network/services/hostapd/src/wpa_supplicant/ubus.c index 804d465941..1c477f0c0c 100644 --- a/package/network/services/hostapd/src/wpa_supplicant/ubus.c +++ b/package/network/services/hostapd/src/wpa_supplicant/ubus.c @@ -207,152 +207,6 @@ void wpas_ubus_free_bss(struct wpa_supplicant *wpa_s) free(name); } -enum { - WPAS_CONFIG_DRIVER, - WPAS_CONFIG_IFACE, - WPAS_CONFIG_BRIDGE, - WPAS_CONFIG_HOSTAPD_CTRL, - WPAS_CONFIG_CTRL, - WPAS_CONFIG_FILE, - __WPAS_CONFIG_MAX -}; - -static const struct blobmsg_policy wpas_config_add_policy[__WPAS_CONFIG_MAX] = { - [WPAS_CONFIG_DRIVER] = { "driver", BLOBMSG_TYPE_STRING }, - [WPAS_CONFIG_IFACE] = { "iface", BLOBMSG_TYPE_STRING }, - [WPAS_CONFIG_BRIDGE] = { "bridge", BLOBMSG_TYPE_STRING }, - [WPAS_CONFIG_HOSTAPD_CTRL] = { "hostapd_ctrl", BLOBMSG_TYPE_STRING }, - [WPAS_CONFIG_CTRL] = { "ctrl", BLOBMSG_TYPE_STRING }, - [WPAS_CONFIG_FILE] = { "config", BLOBMSG_TYPE_STRING }, -}; - -static int -wpas_config_add(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) -{ - struct blob_attr *tb[__WPAS_CONFIG_MAX]; - struct wpa_global *global = get_wpa_global_from_object(obj); - struct wpa_interface *iface; - - blobmsg_parse(wpas_config_add_policy, __WPAS_CONFIG_MAX, tb, blob_data(msg), blob_len(msg)); - - if (!tb[WPAS_CONFIG_FILE] || !tb[WPAS_CONFIG_IFACE] || !tb[WPAS_CONFIG_DRIVER]) - return UBUS_STATUS_INVALID_ARGUMENT; - - iface = os_zalloc(sizeof(struct wpa_interface)); - if (iface == NULL) - return UBUS_STATUS_UNKNOWN_ERROR; - - iface->driver = blobmsg_get_string(tb[WPAS_CONFIG_DRIVER]); - iface->ifname = blobmsg_get_string(tb[WPAS_CONFIG_IFACE]); - iface->confname = blobmsg_get_string(tb[WPAS_CONFIG_FILE]); - - if (tb[WPAS_CONFIG_BRIDGE]) - iface->bridge_ifname = blobmsg_get_string(tb[WPAS_CONFIG_BRIDGE]); - - if (tb[WPAS_CONFIG_CTRL]) - iface->ctrl_interface = blobmsg_get_string(tb[WPAS_CONFIG_CTRL]); - - if (tb[WPAS_CONFIG_HOSTAPD_CTRL]) - iface->hostapd_ctrl = blobmsg_get_string(tb[WPAS_CONFIG_HOSTAPD_CTRL]); - - if (!wpa_supplicant_add_iface(global, iface, NULL)) - return UBUS_STATUS_INVALID_ARGUMENT; - - blob_buf_init(&b, 0); - blobmsg_add_u32(&b, "pid", getpid()); - ubus_send_reply(ctx, req, b.head); - - return UBUS_STATUS_OK; -} - -enum { - WPAS_CONFIG_REM_IFACE, - __WPAS_CONFIG_REM_MAX -}; - -static const struct blobmsg_policy wpas_config_remove_policy[__WPAS_CONFIG_REM_MAX] = { - [WPAS_CONFIG_REM_IFACE] = { "iface", BLOBMSG_TYPE_STRING }, -}; - -static int -wpas_config_remove(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) -{ - struct blob_attr *tb[__WPAS_CONFIG_REM_MAX]; - struct wpa_global *global = get_wpa_global_from_object(obj); - struct wpa_supplicant *wpa_s = NULL; - unsigned int found = 0; - - blobmsg_parse(wpas_config_remove_policy, __WPAS_CONFIG_REM_MAX, tb, blob_data(msg), blob_len(msg)); - - if (!tb[WPAS_CONFIG_REM_IFACE]) - return UBUS_STATUS_INVALID_ARGUMENT; - - /* find wpa_s object for to-be-removed interface */ - for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { - if (!strncmp(wpa_s->ifname, - blobmsg_get_string(tb[WPAS_CONFIG_REM_IFACE]), - sizeof(wpa_s->ifname))) - { - found = 1; - break; - } - } - - if (!found) - return UBUS_STATUS_INVALID_ARGUMENT; - - if (wpa_supplicant_remove_iface(global, wpa_s, 0)) - return UBUS_STATUS_INVALID_ARGUMENT; - - return UBUS_STATUS_OK; -} - -static const struct ubus_method wpas_daemon_methods[] = { - UBUS_METHOD("config_add", wpas_config_add, wpas_config_add_policy), - UBUS_METHOD("config_remove", wpas_config_remove, wpas_config_remove_policy), -}; - -static struct ubus_object_type wpas_daemon_object_type = - UBUS_OBJECT_TYPE("wpa_supplicant", wpas_daemon_methods); - -void wpas_ubus_add(struct wpa_global *global) -{ - struct ubus_object *obj = &global->ubus_global; - int ret; - - if (!wpas_ubus_init()) - return; - - obj->name = strdup("wpa_supplicant"); - - obj->type = &wpas_daemon_object_type; - obj->methods = wpas_daemon_object_type.methods; - obj->n_methods = wpas_daemon_object_type.n_methods; - ret = ubus_add_object(ctx, obj); - wpas_ubus_ref_inc(); -} - -void wpas_ubus_free(struct wpa_global *global) -{ - struct ubus_object *obj = &global->ubus_global; - char *name = (char *) obj->name; - - if (!ctx) - return; - - if (obj->id) { - ubus_remove_object(ctx, obj); - wpas_ubus_ref_dec(); - } - - free(name); -} - - #ifdef CONFIG_WPS void wpas_ubus_notify(struct wpa_supplicant *wpa_s, const struct wps_credential *cred) { diff --git a/package/network/services/hostapd/src/wpa_supplicant/ubus.h b/package/network/services/hostapd/src/wpa_supplicant/ubus.h index bf92b98c01..f6681cb26d 100644 --- a/package/network/services/hostapd/src/wpa_supplicant/ubus.h +++ b/package/network/services/hostapd/src/wpa_supplicant/ubus.h @@ -24,9 +24,6 @@ struct wpas_ubus_bss { void wpas_ubus_add_bss(struct wpa_supplicant *wpa_s); void wpas_ubus_free_bss(struct wpa_supplicant *wpa_s); -void wpas_ubus_add(struct wpa_global *global); -void wpas_ubus_free(struct wpa_global *global); - #ifdef CONFIG_WPS void wpas_ubus_notify(struct wpa_supplicant *wpa_s, const struct wps_credential *cred); #endif @@ -34,14 +31,6 @@ void wpas_ubus_notify(struct wpa_supplicant *wpa_s, const struct wps_credential #else struct wpas_ubus_bss {}; -static inline void wpas_ubus_add_iface(struct wpa_supplicant *wpa_s) -{ -} - -static inline void wpas_ubus_free_iface(struct wpa_supplicant *wpa_s) -{ -} - static inline void wpas_ubus_add_bss(struct wpa_supplicant *wpa_s) { } diff --git a/package/network/services/hostapd/src/wpa_supplicant/ucode.c b/package/network/services/hostapd/src/wpa_supplicant/ucode.c new file mode 100644 index 0000000000..660357a43d --- /dev/null +++ b/package/network/services/hostapd/src/wpa_supplicant/ucode.c @@ -0,0 +1,177 @@ +#include "utils/includes.h" +#include "utils/common.h" +#include "utils/ucode.h" +#include "wpa_supplicant_i.h" +#include "wps_supplicant.h" +#include "ucode.h" + +static struct wpa_global *wpa_global; +static uc_resource_type_t *global_type, *iface_type; +static uc_value_t *global, *iface_registry; +static uc_vm_t *vm; + +static uc_value_t * +wpas_ucode_iface_get_uval(struct wpa_supplicant *wpa_s) +{ + uc_value_t *val; + + if (wpa_s->ucode.idx) + return wpa_ucode_registry_get(iface_registry, wpa_s->ucode.idx); + + val = uc_resource_new(iface_type, wpa_s); + wpa_ucode_registry_add(iface_registry, val, &wpa_s->ucode.idx); + + return val; +} + +static void +wpas_ucode_update_interfaces(void) +{ + uc_value_t *ifs = ucv_object_new(vm); + struct wpa_supplicant *wpa_s; + int i; + + for (wpa_s = wpa_global->ifaces; wpa_s; wpa_s = wpa_s->next) + ucv_object_add(ifs, wpa_s->ifname, ucv_get(wpas_ucode_iface_get_uval(wpa_s))); + + ucv_object_add(ucv_prototype_get(global), "interfaces", ucv_get(ifs)); + ucv_gc(vm); +} + +void wpas_ucode_add_bss(struct wpa_supplicant *wpa_s) +{ + uc_value_t *val; + + if (wpa_ucode_call_prepare("iface_add")) + return; + + uc_value_push(ucv_get(ucv_string_new(wpa_s->ifname))); + uc_value_push(ucv_get(wpas_ucode_iface_get_uval(wpa_s))); + ucv_put(wpa_ucode_call(2)); + ucv_gc(vm); +} + +void wpas_ucode_free_bss(struct wpa_supplicant *wpa_s) +{ + uc_value_t *val; + + val = wpa_ucode_registry_remove(iface_registry, wpa_s->ucode.idx); + if (!val) + return; + + wpa_s->ucode.idx = 0; + if (wpa_ucode_call_prepare("iface_remove")) + return; + + uc_value_push(ucv_string_new(wpa_s->ifname)); + uc_value_push(ucv_get(val)); + ucv_put(wpa_ucode_call(2)); + ucv_gc(vm); +} + +static const char *obj_stringval(uc_value_t *obj, const char *name) +{ + uc_value_t *val = ucv_object_get(obj, name, NULL); + + return ucv_string_get(val); +} + +static uc_value_t * +uc_wpas_add_iface(uc_vm_t *vm, size_t nargs) +{ + uc_value_t *info = uc_fn_arg(0); + uc_value_t *ifname = ucv_object_get(info, "iface", NULL); + uc_value_t *bridge = ucv_object_get(info, "bridge", NULL); + uc_value_t *config = ucv_object_get(info, "config", NULL); + uc_value_t *ctrl = ucv_object_get(info, "ctrl", NULL); + uc_value_t *hapd_ctrl = ucv_object_get(info, "hostapd_ctrl", NULL); + struct wpa_interface iface; + int ret = -1; + + if (ucv_type(info) != UC_OBJECT) + goto out; + + iface = (struct wpa_interface){ + .driver = "nl80211", + .ifname = ucv_string_get(ifname), + .bridge_ifname = ucv_string_get(bridge), + .confname = ucv_string_get(config), + .ctrl_interface = ucv_string_get(ctrl), + .hostapd_ctrl = ucv_string_get(hapd_ctrl), + }; + + if (!iface.ifname || !iface.confname) + goto out; + + ret = wpa_supplicant_add_iface(wpa_global, &iface, 0) ? 0 : -1; + wpas_ucode_update_interfaces(); + +out: + return ucv_int64_new(ret); +} + +static uc_value_t * +uc_wpas_remove_iface(uc_vm_t *vm, size_t nargs) +{ + struct wpa_supplicant *wpa_s = NULL; + uc_value_t *ifname_arg = uc_fn_arg(0); + const char *ifname = ucv_string_get(ifname_arg); + int ret = -1; + + if (!ifname) + goto out; + + for (wpa_s = wpa_global->ifaces; wpa_s; wpa_s = wpa_s->next) + if (!strcmp(wpa_s->ifname, ifname)) + break; + + if (!wpa_s) + goto out; + + ret = wpa_supplicant_remove_iface(wpa_global, wpa_s, 0); + wpas_ucode_update_interfaces(); + +out: + return ucv_int64_new(ret); +} + +int wpas_ucode_init(struct wpa_global *gl) +{ + static const uc_function_list_t global_fns[] = { + { "printf", uc_wpa_printf }, + { "getpid", uc_wpa_getpid }, + { "add_iface", uc_wpas_add_iface }, + { "remove_iface", uc_wpas_remove_iface }, + }; + static const uc_function_list_t iface_fns[] = { + }; + uc_value_t *data, *proto; + + wpa_global = gl; + vm = wpa_ucode_create_vm(); + + global_type = uc_type_declare(vm, "wpas.global", global_fns, NULL); + iface_type = uc_type_declare(vm, "hostapd.iface", iface_fns, NULL); + + iface_registry = ucv_array_new(vm); + uc_vm_registry_set(vm, "hostap.iface_registry", iface_registry); + + global = wpa_ucode_global_init("wpas", global_type); + + if (wpa_ucode_run(HOSTAPD_UC_PATH "wpa_supplicant.uc")) + goto free_vm; + + ucv_gc(vm); + return 0; + +free_vm: + wpa_ucode_free_vm(); + return -1; +} + +void wpas_ucode_free(void) +{ + if (wpa_ucode_call_prepare("shutdown") == 0) + ucv_put(wpa_ucode_call(0)); + wpa_ucode_free_vm(); +} diff --git a/package/network/services/hostapd/src/wpa_supplicant/ucode.h b/package/network/services/hostapd/src/wpa_supplicant/ucode.h new file mode 100644 index 0000000000..fcd231357b --- /dev/null +++ b/package/network/services/hostapd/src/wpa_supplicant/ucode.h @@ -0,0 +1,38 @@ +#ifndef __WPAS_UCODE_H +#define __WPAS_UCODE_H + +#include "utils/ucode.h" + +struct wpa_global; +struct wpa_supplicant; + +struct wpas_ucode_bss { +#ifdef UCODE_SUPPORT + unsigned int idx; +#endif +}; + +#ifdef UCODE_SUPPORT +int wpas_ucode_init(struct wpa_global *gl); +void wpas_ucode_free(void); +void wpas_ucode_add_bss(struct wpa_supplicant *wpa_s); +void wpas_ucode_free_bss(struct wpa_supplicant *wpa_s); +#else +static inline int wpas_ucode_init(struct wpa_global *gl) +{ + return -EINVAL; +} +static inline void wpas_ucode_free(void) +{ +} +static inline void wpas_ucode_add_bss(struct wpa_supplicant *wpa_s) +{ +} + +static inline void wpas_ucode_free_bss(struct wpa_supplicant *wpa_s) +{ +} + +#endif + +#endif From 11bf820124e3155ef6b1762cd3ca533b9a7d577d Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 5 Jul 2023 14:51:19 +0200 Subject: [PATCH 11/23] netifd: update to the latest version 8c2758b4fbbb wireless: add support for replacing data blobs at runtime 0ff22a6a68ce wireless: enable dynamic reconfiguration by default Signed-off-by: Felix Fietkau --- package/network/config/netifd/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/network/config/netifd/Makefile b/package/network/config/netifd/Makefile index a660f27bdf..94d2bfddec 100644 --- a/package/network/config/netifd/Makefile +++ b/package/network/config/netifd/Makefile @@ -5,9 +5,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/netifd.git -PKG_SOURCE_DATE:=2023-07-03 -PKG_SOURCE_VERSION:=e94f7a81a03992805aa443156b73721228e6e2d1 -PKG_MIRROR_HASH:=4cf3199c2ebb96bcee183a2c9a750541afca16a16942008e865b4313c14a01bd +PKG_SOURCE_DATE:=2023-07-17 +PKG_SOURCE_VERSION:=0ff22a6a68ce942d4c9e7d58355d128dd3793b06 +PKG_MIRROR_HASH:=4cc81829fa6eb571d67f6879c78d2f514b757a34cc963b7627d55a7a8deffb75 PKG_MAINTAINER:=Felix Fietkau PKG_LICENSE:=GPL-2.0 From 4ca450deaca133b14a7798ab1803129c3f26353a Mon Sep 17 00:00:00 2001 From: Nick Hainke Date: Wed, 19 Jul 2023 15:45:10 +0200 Subject: [PATCH 12/23] tools/7z: update to 23.01 Release Notes: https://sourceforge.net/p/sevenzip/discussion/45797/thread/3f550826d8/#e950 Manually adjust: - 7-zip-flags.patch Automatically refresh: - 7-zip-musl.patch Signed-off-by: Nick Hainke --- tools/7z/Makefile | 6 +++--- tools/7z/patches/7-zip-flags.patch | 15 ++++----------- tools/7z/patches/7-zip-musl.patch | 8 ++++---- 3 files changed, 11 insertions(+), 18 deletions(-) diff --git a/tools/7z/Makefile b/tools/7z/Makefile index 90362e7977..351ae527ff 100644 --- a/tools/7z/Makefile +++ b/tools/7z/Makefile @@ -1,12 +1,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=7z -PKG_VERSION:=22.01 -PKG_SOURCE_VERSION:=2201 +PKG_VERSION:=23.01 +PKG_SOURCE_VERSION:=2301 PKG_SOURCE:=$(PKG_NAME)$(PKG_SOURCE_VERSION)-src.tar.xz PKG_SOURCE_URL:=https://7-zip.org/a/ -PKG_HASH:=393098730c70042392af808917e765945dc2437dee7aae3cfcc4966eb920fbc5 +PKG_HASH:=356071007360e5a1824d9904993e8b2480b51b570e8c9faf7c0f58ebe4bf9f74 # This builds the 7zr variant which supports only 7z, so no non-LGPL code should be included PKG_LICENSE:=LGPL-2.1-or-later diff --git a/tools/7z/patches/7-zip-flags.patch b/tools/7z/patches/7-zip-flags.patch index ed5b508401..b9b2152f22 100644 --- a/tools/7z/patches/7-zip-flags.patch +++ b/tools/7z/patches/7-zip-flags.patch @@ -1,14 +1,16 @@ --- a/CPP/7zip/7zip_gcc.mak +++ b/CPP/7zip/7zip_gcc.mak -@@ -18,13 +18,13 @@ PROGPATH_STATIC = $(O)/$(PROG)s +@@ -24,7 +24,7 @@ PROGPATH_STATIC = $(O)/$(PROG)s ifneq ($(CC), xlc) --CFLAGS_WARN_WALL = -Wall -Werror -Wextra +-CFLAGS_WARN_WALL = -Werror -Wall -Wextra +CFLAGS_WARN_WALL = -Wall -Wextra endif # for object file +@@ -32,7 +32,7 @@ endif + # -save-temps CFLAGS_BASE_LIST = -c # CFLAGS_BASE_LIST = -S -CFLAGS_BASE = -O2 $(CFLAGS_BASE_LIST) $(CFLAGS_WARN_WALL) $(CFLAGS_WARN) \ @@ -16,12 +18,3 @@ -DNDEBUG -D_REENTRANT -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \ -fPIC -@@ -192,7 +192,7 @@ all: $(O) $(PROGPATH) $(STATIC_TARGET) - $(O): - $(MY_MKDIR) $(O) - --LFLAGS_ALL = -s $(MY_ARCH_2) $(LDFLAGS) $(LD_arch) $(OBJS) $(MY_LIBS) $(LIB2) -+LFLAGS_ALL = $(MY_ARCH_2) $(LDFLAGS) $(LD_arch) $(OBJS) $(MY_LIBS) $(LIB2) - $(PROGPATH): $(OBJS) - $(CXX) -o $(PROGPATH) $(LFLAGS_ALL) - diff --git a/tools/7z/patches/7-zip-musl.patch b/tools/7z/patches/7-zip-musl.patch index cf3386e4de..e066cc8ec9 100644 --- a/tools/7z/patches/7-zip-musl.patch +++ b/tools/7z/patches/7-zip-musl.patch @@ -1,6 +1,6 @@ --- a/C/CpuArch.c +++ b/C/CpuArch.c -@@ -421,8 +421,6 @@ BoolInt CPU_IsSupported_AES (void) { ret +@@ -766,8 +766,6 @@ BoolInt CPU_IsSupported_AES (void) { ret #ifdef USE_HWCAP @@ -11,7 +11,7 @@ --- a/C/Threads.c +++ b/C/Threads.c -@@ -257,7 +257,7 @@ WRes Thread_Create_With_CpuSet(CThread * +@@ -265,7 +265,7 @@ WRes Thread_Create_With_CpuSet(CThread * */ // ret2 = @@ -20,7 +20,7 @@ // if (ret2) ret = ret2; #endif } -@@ -267,14 +267,12 @@ WRes Thread_Create_With_CpuSet(CThread * +@@ -275,14 +275,12 @@ WRes Thread_Create_With_CpuSet(CThread * if (!ret) { p->_created = 1; @@ -37,7 +37,7 @@ // ret2 = --- a/C/Threads.h +++ b/C/Threads.h -@@ -19,6 +19,7 @@ +@@ -20,6 +20,7 @@ #endif #include From 85efbbcf06ea305aef1cb3c4cdc7d59f92407343 Mon Sep 17 00:00:00 2001 From: Nick Hainke Date: Thu, 20 Jul 2023 18:27:04 +0200 Subject: [PATCH 13/23] libtraceevent: update to 1.7.3 ChangeLog: dd14818 libtraceevent: version 1.7.3 0b9a34e libtraceevent: Handle printf '%+d" case eba4a41 libtraceevent: Add initial support for meson 1d8ddb9 libtraceevent: Handle %c Signed-off-by: Nick Hainke --- package/libs/libtraceevent/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/libs/libtraceevent/Makefile b/package/libs/libtraceevent/Makefile index 5d8740faab..bcba7eaf43 100644 --- a/package/libs/libtraceevent/Makefile +++ b/package/libs/libtraceevent/Makefile @@ -1,12 +1,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libtraceevent -PKG_VERSION:=1.7.2 +PKG_VERSION:=1.7.3 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/snapshot/ -PKG_HASH:=a8b4bf8f05c06d1d6405f6d0038467a87e7ab218f0d8b0608d08bca5d1fc112a +PKG_HASH:=097b72e0d907f3107825fb2edf0188324bf70dc9da360f6efa68dc484ffde541 PKG_MAINTAINER:=Nick Hainke From a8c84b550be10462f870688b2adf50cabb8dd2d2 Mon Sep 17 00:00:00 2001 From: Nick Hainke Date: Thu, 20 Jul 2023 18:29:27 +0200 Subject: [PATCH 14/23] libtracefs: update to 1.7.0 ChangeLog: aebab37 libtracefs: version 1.7 a3237c3 libtracefs: Add initial support for meson b25019f libtarcefs doc: Add tracefs_kprobe_destroy() to index man page 4c2194f libtracefs doc: State that tracefs_dynevent_create() is needed for tracefs_kprobe_alloc() df53d43 libtracefs Documentation: Add missing prototypes in top level man page 9a2df4a libtracefs: Update version to 1.7.dev 18ede68 libtracefs: Add tracefs_kprobe_destory() API 309b1ba libtracefs tests: Add helper function to destroy dynamic events 53dce80 tracefs: Add tracefs_time_conversion() API 5ea4128 libtracefs: Add tracefs_find_cid_pid() API 857dd3e libtracefs/utest: Fix crashing of synth test when synths exist 6332309 libtracefs/utest: Do not use synth for test_synth element 25cd206 libtracefs: Clarify the tracefs_synth_create() man page 6b6d43f libtracefs: Do not allow tracefs_synth_set_instance() on created synth c860f93 libtracefs: Documentation for tracefs_synth_set_instance 0039173 libtracefs: New API to set synthetic event instance e97c311 libtracefs: Do not segfault in tests if synthetic events are not configured 185019c libtracefs: Add tracefs_instance_tracers() API 6775d23 libtracefs: Do not use hwlat tracer and fdb_delete event for tests 5a1a01e libtracefs: Add stacktrace to tracefs_sql() b1b234e libtracefs: Unit test for tracefs_instance_reset() dd620f4 libtracefs: Documentation for tracefs_instance_reset() 789e82d libtracefs: New API to reset ftrace instance Signed-off-by: Nick Hainke --- package/libs/libtracefs/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/libs/libtracefs/Makefile b/package/libs/libtracefs/Makefile index b97922f460..eb879ee66d 100644 --- a/package/libs/libtracefs/Makefile +++ b/package/libs/libtracefs/Makefile @@ -1,12 +1,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libtracefs -PKG_VERSION:=1.6.4 +PKG_VERSION:=1.7.0 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/snapshot/ -PKG_HASH:=52ce793dbb35a3e59bddce31de09a5d92cedd4d0702e64d0916f1ccdb00526c9 +PKG_HASH:=411fcbf3434ecbaefa6c2b1bf092266293a672e2d7ee46fdd6b402753cb8bd16 PKG_MAINTAINER:=Nick Hainke From 6f8c79e00c70f08f234dc55fa4811f02d851c5d2 Mon Sep 17 00:00:00 2001 From: Nick Hainke Date: Thu, 20 Jul 2023 18:32:13 +0200 Subject: [PATCH 15/23] tracecmd: update to v3.2 ChangeLog: 46952ef trace-cmd: Version 3.2 f5871a1 libtracecmd: Version 1.4.0 d498af1 trace-cmd build: Add trace-attach.c to meson build 736df06 trace-cmd: Add initial support for meson e183566 libtracecmd: Add initial support for meson c508713 trace-cmd test: Quiet valgrind from reporting forked children 8ec026f trace-cmd test: Close handle after opening 4c179a6 trace-cmd library: Fix memory leaks of followers aa21520 trace-cmd: Add Makefile target for memory test 925e15f trace-cmd and library: Update the version to the development 4fa31c0 trace-cmd attach: Add new command "attach" 7e721ef trace-cmd library: Add tracecmd_get_tsc2nsec() API 8908555 tracecmd library: Unlock records in tracecmd_iterate_events() 2668b13 trace-cmd agent: Add "IP" to -N argument in help message 22ad81e trace-cmd record: Remove redundant check of instance in allocate_instance() d7ce897 libtracecmd: Free buf_from in error path of tracecmd_compress_copy_from() 6776d7a trace-cmd: Update v7 trace.dat documentation to clarify the strings section 9d6f3ba trace-cmd record/extract: Do not destroy existing instances 9c9d5ed trace-cmd extract: Do not extract top level unless told to 4b92132 libtracecmd: Fix tracecmd_compress_copy_from() write size return f30abfd documentation: trace-cmd-report: Document filter scope 7a390c5 trace-cmd-report: Support global filters 04ad2c6 trace-cmd report: Ensure filter is applied to single input file edf9424 trace-cmd: Open code execvp routine to avoid multiple execve syscalls Signed-off-by: Nick Hainke --- package/devel/trace-cmd/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/devel/trace-cmd/Makefile b/package/devel/trace-cmd/Makefile index 687907acaa..c1a24dc171 100644 --- a/package/devel/trace-cmd/Makefile +++ b/package/devel/trace-cmd/Makefile @@ -1,12 +1,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=trace-cmd -PKG_VERSION:=v3.1.6 +PKG_VERSION:=v3.2 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/snapshot/ -PKG_HASH:=f9198ea306deee9cda3b262342b03b6029e82c1b9c671ba521739a9703e115b9 +PKG_HASH:=62af2c6062eeb434925921bb5936774b0a0e17a5f86671fa2ea2f40704a080cd PKG_LICENSE:=GPL-2.0-only PKG_LICENSE_FILES:=COPYING From 4a4e0c636fa3e1feb4e2d7af77ff23b097d9d33a Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 1 Aug 2023 13:43:07 +0200 Subject: [PATCH 16/23] hostapd: fix mesh supplicant build error Include AP ucode source file Fixes: e56c5f7b276a ("hostapd: add ucode support, use ucode for the main ubus object") Signed-off-by: Felix Fietkau --- .../services/hostapd/patches/601-ucode_support.patch | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/package/network/services/hostapd/patches/601-ucode_support.patch b/package/network/services/hostapd/patches/601-ucode_support.patch index 6cfc9b7d8d..ff1a9ddc0d 100644 --- a/package/network/services/hostapd/patches/601-ucode_support.patch +++ b/package/network/services/hostapd/patches/601-ucode_support.patch @@ -138,6 +138,16 @@ endif ifdef CONFIG_CODE_COVERAGE +@@ -999,6 +1011,9 @@ OBJS += ../src/ap/ctrl_iface_ap.o + ifdef CONFIG_UBUS + OBJS += ../src/ap/ubus.o + endif ++ifdef CONFIG_UCODE ++OBJS += ../src/ap/ucode.o ++endif + endif + + CFLAGS += -DEAP_SERVER -DEAP_SERVER_IDENTITY --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -7636,6 +7636,7 @@ struct wpa_supplicant * wpa_supplicant_a From 150e6d28f2659b0614e87cc7822e93f488e11ede Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 2 Aug 2023 13:18:03 +0200 Subject: [PATCH 17/23] hostapd: fix undeclared variable in common.uc Fixes: https://github.com/openwrt/openwrt/issues/13210 Signed-off-by: Felix Fietkau --- package/network/services/hostapd/files/common.uc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/network/services/hostapd/files/common.uc b/package/network/services/hostapd/files/common.uc index 2002572cf1..9ece3b1af2 100644 --- a/package/network/services/hostapd/files/common.uc +++ b/package/network/services/hostapd/files/common.uc @@ -34,7 +34,7 @@ function find_reusable_wdev(phyidx) if (!__phy_is_fullmac(phyidx)) return null; - data = nl80211.request( + let data = nl80211.request( nl80211.const.NL80211_CMD_GET_INTERFACE, nl80211.const.NLM_F_DUMP, { wiphy: phyidx }); From 1874a7cfb0589862614aff74d4fd49d499da641f Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Tue, 1 Aug 2023 17:56:00 -0700 Subject: [PATCH 18/23] tools/cmake: update to 3.27.1 Fix zstd linking again. Signed-off-by: Rosen Penev --- tools/cmake/Makefile | 4 ++-- tools/cmake/patches/100-no-testing.patch | 8 ++++---- .../120-curl-fix-libressl-linking.patch | 2 +- .../130-bootstrap_parallel_make_flag.patch | 2 +- tools/cmake/patches/150-zstd-libarchive.patch | 19 ++++++------------- 5 files changed, 14 insertions(+), 21 deletions(-) diff --git a/tools/cmake/Makefile b/tools/cmake/Makefile index 0c96b017e3..2a0d06d7a7 100644 --- a/tools/cmake/Makefile +++ b/tools/cmake/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=cmake -PKG_VERSION:=3.26.4 +PKG_VERSION:=3.27.1 PKG_VERSION_MAJOR:=$(word 1,$(subst ., ,$(PKG_VERSION))).$(word 2,$(subst ., ,$(PKG_VERSION))) PKG_RELEASE:=1 PKG_CPE_ID:=cpe:/a:kitware:cmake @@ -15,7 +15,7 @@ PKG_CPE_ID:=cpe:/a:kitware:cmake PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/Kitware/CMake/releases/download/v$(PKG_VERSION)/ \ https://cmake.org/files/v$(PKG_VERSION_MAJOR)/ -PKG_HASH:=313b6880c291bd4fe31c0aa51d6e62659282a521e695f30d5cc0d25abbd5c208 +PKG_HASH:=b1a6b0135fa11b94476e90f5b32c4c8fad480bf91cf22d0ded98ce22c5132004 HOST_BUILD_PARALLEL:=1 HOST_CONFIGURE_PARALLEL:=1 diff --git a/tools/cmake/patches/100-no-testing.patch b/tools/cmake/patches/100-no-testing.patch index 44452ce39e..736a365e87 100644 --- a/tools/cmake/patches/100-no-testing.patch +++ b/tools/cmake/patches/100-no-testing.patch @@ -11,15 +11,15 @@ # like vs9 or vs10 --- a/Modules/Dart.cmake +++ b/Modules/Dart.cmake -@@ -33,7 +33,7 @@ whether testing support should be enable - # - # +@@ -47,7 +47,7 @@ if(cmp0145 STREQUAL "") + message(AUTHOR_WARNING "${_cmp0145_warning}") + endif() -option(BUILD_TESTING "Build the testing tree." ON) +option(BUILD_TESTING "Build the testing tree." OFF) if(BUILD_TESTING) - find_package(Dart QUIET) + # We only get here if a project already ran include(Dart), --- a/Tests/Contracts/VTK/Dashboard.cmake.in +++ b/Tests/Contracts/VTK/Dashboard.cmake.in @@ -25,7 +25,7 @@ ctest_empty_binary_directory(${CTEST_BIN diff --git a/tools/cmake/patches/120-curl-fix-libressl-linking.patch b/tools/cmake/patches/120-curl-fix-libressl-linking.patch index 1744fe5b04..b899d1d7ef 100644 --- a/tools/cmake/patches/120-curl-fix-libressl-linking.patch +++ b/tools/cmake/patches/120-curl-fix-libressl-linking.patch @@ -20,7 +20,7 @@ Signed-off-by: Jo-Philipp Wich --- --- a/Utilities/cmcurl/CMakeLists.txt +++ b/Utilities/cmcurl/CMakeLists.txt -@@ -611,6 +611,14 @@ if(CURL_USE_OPENSSL) +@@ -590,6 +590,14 @@ if(CURL_USE_OPENSSL) endif() set(SSL_ENABLED ON) set(USE_OPENSSL ON) diff --git a/tools/cmake/patches/130-bootstrap_parallel_make_flag.patch b/tools/cmake/patches/130-bootstrap_parallel_make_flag.patch index 70d122c9d9..983f376254 100644 --- a/tools/cmake/patches/130-bootstrap_parallel_make_flag.patch +++ b/tools/cmake/patches/130-bootstrap_parallel_make_flag.patch @@ -1,6 +1,6 @@ --- a/bootstrap +++ b/bootstrap -@@ -1449,7 +1449,10 @@ int main(){ printf("1%c", (char)0x0a); r +@@ -1486,7 +1486,10 @@ int main(){ printf("1%c", (char)0x0a); r ' > "test.c" cmake_original_make_flags="${cmake_make_flags}" if test "x${cmake_parallel_make}" != "x"; then diff --git a/tools/cmake/patches/150-zstd-libarchive.patch b/tools/cmake/patches/150-zstd-libarchive.patch index 34f7240fe4..4ed099fbfe 100644 --- a/tools/cmake/patches/150-zstd-libarchive.patch +++ b/tools/cmake/patches/150-zstd-libarchive.patch @@ -1,18 +1,11 @@ --- a/Utilities/cmlibarchive/CMakeLists.txt +++ b/Utilities/cmlibarchive/CMakeLists.txt -@@ -632,8 +632,13 @@ IF(ENABLE_ZSTD) +@@ -636,7 +636,7 @@ IF(ENABLE_ZSTD) SET(ZSTD_FIND_QUIETLY TRUE) ENDIF (ZSTD_INCLUDE_DIR) -- FIND_PATH(ZSTD_INCLUDE_DIR zstd.h) -- FIND_LIBRARY(ZSTD_LIBRARY NAMES zstd libzstd) -+ IF(UNIX) -+ FIND_PACKAGE(PkgConfig QUIET) -+ PKG_SEARCH_MODULE(PC_ZSTD libzstd) -+ ENDIF() -+ -+ FIND_PATH(ZSTD_INCLUDE_DIR zstd.h HINTS ${PC_ZSTD_INCLUDEDIR} ${PC_ZSTD_INCLUDE_DIRS}) -+ FIND_LIBRARY(ZSTD_LIBRARY NAMES zstd HINTS ${PC_ZSTD_LIBDIR} ${PC_ZSTD_LIBRARY_DIRS}) - INCLUDE(FindPackageHandleStandardArgs) - FIND_PACKAGE_HANDLE_STANDARD_ARGS(ZSTD DEFAULT_MSG ZSTD_LIBRARY ZSTD_INCLUDE_DIR) - ELSE(ENABLE_ZSTD) +- IF(0) # CMake does not let pkg-config override its search paths. ++ IF(1) # CMake does not let pkg-config override its search paths. + IF(UNIX) + FIND_PACKAGE(PkgConfig QUIET) + PKG_SEARCH_MODULE(PC_ZSTD libzstd) From 04f6d674f633398e56141097e9e7fa7c53bf461a Mon Sep 17 00:00:00 2001 From: Stefan Kalscheuer Date: Sun, 18 Jun 2023 16:55:50 +0200 Subject: [PATCH 19/23] mvebu: copy 5.15 patches to 6.1 To start migration to Kernel 6.1 we copy all existing patches from 5.15. Signed-off-by: Stefan Kalscheuer --- ...mnia-configure-LED-0-pin-function-to.patch | 38 + .../100-aardvark-workaround-PCIe.patch | 81 ++ ...ris-omnia-enable-LED-controller-node.patch | 48 + ...a-support-HW-controlled-mode-via-pri.patch | 118 ++ ...a-initialize-multi-intensity-to-full.patch | 33 + ...a-change-max-brightness-from-255-to-.patch | 31 + ...set-linkstation-poweroff-add-ls220de.patch | 15 + ...Mangle-bootloader-s-kernel-arguments.patch | 279 +++++ ...-mvebu-armada-38x-enable-libata-leds.patch | 10 + .../patches-6.1/302-add_powertables.patch | 770 ++++++++++++ .../patches-6.1/304-revert_i2c_delay.patch | 15 + .../305-armada-385-rd-mtd-partitions.patch | 19 + .../306-ARM-mvebu-385-ap-Add-partitions.patch | 35 + ...-armada-xp-linksys-mamba-broken-idle.patch | 10 + .../308-armada-xp-linksys-mamba-wan.patch | 11 + .../patches-6.1/309-linksys-status-led.patch | 50 + .../310-linksys-use-eth0-as-cpu-port.patch | 25 + .../311-adjust-compatible-for-linksys.patch | 68 ++ ...da388-clearfog-emmc-on-clearfog-base.patch | 87 ++ .../313-helios4-dts-status-led-alias.patch | 28 + ...rmada-xp-linksys-mamba-resize-kernel.patch | 37 + ...316-armada-370-dts-fix-crypto-engine.patch | 29 + .../patches-6.1/400-find_active_root.patch | 60 + .../700-mvneta-tx-queue-workaround.patch | 38 + ...ethernet-marvell-mvnetaMQPrioOffload.patch | 66 ++ ...xt-ethernet-marvell-mvnetaMQPrioFlag.patch | 30 + ...t-ethernet-marvell-mvnetaMQPrioQueue.patch | 97 ++ ...hernet-marvell-mvnetaMQPrioTCOffload.patch | 182 +++ ...mvebu-a3700-comphy-Reset-COMPHY-regi.patch | 50 + ...dicate-failure-to-enter-deeper-sleep.patch | 40 + ...-pci-mvebu-time-out-reset-on-link-up.patch | 60 + ...IEI-vendor-prefix-and-IEI-WT61P803-P.patch | 218 ++++ ...a-driver-for-IEI-WT61P803-PUZZLE-MCU.patch | 1034 +++++++++++++++++ ...d-the-IEI-WT61P803-PUZZLE-HWMON-driv.patch | 501 ++++++++ ...d-the-IEI-WT61P803-PUZZLE-LED-driver.patch | 207 ++++ ...I-Add-iei-wt61p803-puzzle-driver-sys.patch | 82 ++ ...mon-Add-iei-wt61p803-puzzle-hwmon-dr.patch | 74 ++ ...an-entry-for-the-IEI-WT61P803-PUZZLE.patch | 41 + ...rs-leds-wt61p803-puzzle-improvements.patch | 271 +++++ ...ivers-leds-wt61p803-puzzle-mcu-retry.patch | 63 + 40 files changed, 4951 insertions(+) create mode 100644 target/linux/mvebu/patches-6.1/100-ARM-dts-turris-omnia-configure-LED-0-pin-function-to.patch create mode 100644 target/linux/mvebu/patches-6.1/100-aardvark-workaround-PCIe.patch create mode 100644 target/linux/mvebu/patches-6.1/101-ARM-dts-turris-omnia-enable-LED-controller-node.patch create mode 100644 target/linux/mvebu/patches-6.1/102-leds-turris-omnia-support-HW-controlled-mode-via-pri.patch create mode 100644 target/linux/mvebu/patches-6.1/103-leds-turris-omnia-initialize-multi-intensity-to-full.patch create mode 100644 target/linux/mvebu/patches-6.1/104-leds-turris-omnia-change-max-brightness-from-255-to-.patch create mode 100644 target/linux/mvebu/patches-6.1/105-power-reset-linkstation-poweroff-add-ls220de.patch create mode 100644 target/linux/mvebu/patches-6.1/300-mvebu-Mangle-bootloader-s-kernel-arguments.patch create mode 100644 target/linux/mvebu/patches-6.1/301-mvebu-armada-38x-enable-libata-leds.patch create mode 100644 target/linux/mvebu/patches-6.1/302-add_powertables.patch create mode 100644 target/linux/mvebu/patches-6.1/304-revert_i2c_delay.patch create mode 100644 target/linux/mvebu/patches-6.1/305-armada-385-rd-mtd-partitions.patch create mode 100644 target/linux/mvebu/patches-6.1/306-ARM-mvebu-385-ap-Add-partitions.patch create mode 100644 target/linux/mvebu/patches-6.1/307-armada-xp-linksys-mamba-broken-idle.patch create mode 100644 target/linux/mvebu/patches-6.1/308-armada-xp-linksys-mamba-wan.patch create mode 100644 target/linux/mvebu/patches-6.1/309-linksys-status-led.patch create mode 100644 target/linux/mvebu/patches-6.1/310-linksys-use-eth0-as-cpu-port.patch create mode 100644 target/linux/mvebu/patches-6.1/311-adjust-compatible-for-linksys.patch create mode 100644 target/linux/mvebu/patches-6.1/312-ARM-dts-armada388-clearfog-emmc-on-clearfog-base.patch create mode 100644 target/linux/mvebu/patches-6.1/313-helios4-dts-status-led-alias.patch create mode 100644 target/linux/mvebu/patches-6.1/315-armada-xp-linksys-mamba-resize-kernel.patch create mode 100644 target/linux/mvebu/patches-6.1/316-armada-370-dts-fix-crypto-engine.patch create mode 100644 target/linux/mvebu/patches-6.1/400-find_active_root.patch create mode 100644 target/linux/mvebu/patches-6.1/700-mvneta-tx-queue-workaround.patch create mode 100644 target/linux/mvebu/patches-6.1/702-net-next-ethernet-marvell-mvnetaMQPrioOffload.patch create mode 100644 target/linux/mvebu/patches-6.1/703-net-next-ethernet-marvell-mvnetaMQPrioFlag.patch create mode 100644 target/linux/mvebu/patches-6.1/704-net-next-ethernet-marvell-mvnetaMQPrioQueue.patch create mode 100644 target/linux/mvebu/patches-6.1/705-net-next-ethernet-marvell-mvnetaMQPrioTCOffload.patch create mode 100644 target/linux/mvebu/patches-6.1/710-v6.2-phy-marvell-phy-mvebu-a3700-comphy-Reset-COMPHY-regi.patch create mode 100644 target/linux/mvebu/patches-6.1/800-cpuidle-mvebu-indicate-failure-to-enter-deeper-sleep.patch create mode 100644 target/linux/mvebu/patches-6.1/801-pci-mvebu-time-out-reset-on-link-up.patch create mode 100644 target/linux/mvebu/patches-6.1/901-dt-bindings-Add-IEI-vendor-prefix-and-IEI-WT61P803-P.patch create mode 100644 target/linux/mvebu/patches-6.1/902-drivers-mfd-Add-a-driver-for-IEI-WT61P803-PUZZLE-MCU.patch create mode 100644 target/linux/mvebu/patches-6.1/903-drivers-hwmon-Add-the-IEI-WT61P803-PUZZLE-HWMON-driv.patch create mode 100644 target/linux/mvebu/patches-6.1/904-drivers-leds-Add-the-IEI-WT61P803-PUZZLE-LED-driver.patch create mode 100644 target/linux/mvebu/patches-6.1/905-Documentation-ABI-Add-iei-wt61p803-puzzle-driver-sys.patch create mode 100644 target/linux/mvebu/patches-6.1/906-Documentation-hwmon-Add-iei-wt61p803-puzzle-hwmon-dr.patch create mode 100644 target/linux/mvebu/patches-6.1/907-MAINTAINERS-Add-an-entry-for-the-IEI-WT61P803-PUZZLE.patch create mode 100644 target/linux/mvebu/patches-6.1/910-drivers-leds-wt61p803-puzzle-improvements.patch create mode 100644 target/linux/mvebu/patches-6.1/911-drivers-leds-wt61p803-puzzle-mcu-retry.patch diff --git a/target/linux/mvebu/patches-6.1/100-ARM-dts-turris-omnia-configure-LED-0-pin-function-to.patch b/target/linux/mvebu/patches-6.1/100-ARM-dts-turris-omnia-configure-LED-0-pin-function-to.patch new file mode 100644 index 0000000000..67beb06541 --- /dev/null +++ b/target/linux/mvebu/patches-6.1/100-ARM-dts-turris-omnia-configure-LED-0-pin-function-to.patch @@ -0,0 +1,38 @@ +From 81c0004a6433ff90fa6129418802c3c367e453c2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 4 Jul 2022 13:36:21 +0200 +Subject: [PATCH 1/5] ARM: dts: turris-omnia: configure LED[0] pin function to + link/activity +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The marvell PHY driver changes the LED[0] pin function to "On - 1000 +Mbps Link, Off - Else". + +Turris Omnia expects that the function is "On - Link, Blink - Activity, +Off - No link". + +Use the `marvell,reg-init` DT property to change the function. + +In the future, once netdev trigger will support HW offloading, we will +be able to have this configured via the combination of PHY driver and +leds-turris-omnia driver. + +Signed-off-by: Marek Behún +--- + arch/arm/boot/dts/armada-385-turris-omnia.dts | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/armada-385-turris-omnia.dts ++++ b/arch/arm/boot/dts/armada-385-turris-omnia.dts +@@ -396,7 +396,8 @@ + phy1: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; +- marvell,reg-init = <3 18 0 0x4985>; ++ marvell,reg-init = <3 18 0 0x4985>, ++ <3 16 0xfff0 0x0001>; + + /* irq is connected to &pcawan pin 7 */ + }; diff --git a/target/linux/mvebu/patches-6.1/100-aardvark-workaround-PCIe.patch b/target/linux/mvebu/patches-6.1/100-aardvark-workaround-PCIe.patch new file mode 100644 index 0000000000..975eadb80e --- /dev/null +++ b/target/linux/mvebu/patches-6.1/100-aardvark-workaround-PCIe.patch @@ -0,0 +1,81 @@ +Subject: [PATCH v2] PCI: aardvark: Implement workaround for PCIe Completion Timeout +Date: Tue, 2 Aug 2022 14:38:16 +0200 +Message-Id: <20220802123816.21817-1-pali@kernel.org> +X-Mailer: git-send-email 2.20.1 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Precedence: bulk +List-ID: +X-Mailing-List: linux-pci@vger.kernel.org + +Marvell Armada 3700 Functional Errata, Guidelines, and Restrictions +document describes in erratum 3.12 PCIe Completion Timeout (Ref #: 251), +that PCIe IP does not support a strong-ordered model for inbound posted vs. +outbound completion. + +As a workaround for this erratum, DIS_ORD_CHK flag in Debug Mux Control +register must be set. It disables the ordering check in the core between +Completions and Posted requests received from the link. + +Marvell also suggests to do full memory barrier at the beginning of +aardvark summary interrupt handler before calling interrupt handlers of +endpoint drivers in order to minimize the risk for the race condition +documented in the Erratum between the DMA done status reading and the +completion of writing to the host memory. + +More details about this issue and suggested workarounds are in discussion: +https://lore.kernel.org/linux-pci/BN9PR18MB425154FE5019DCAF2028A1D5DB8D9@BN9PR18MB4251.namprd18.prod.outlook.com/t/#u + +It was reported that enabling this workaround fixes instability issues and +"Unhandled fault" errors when using 60 GHz WiFi 802.11ad card with Qualcomm +QCA6335 chip under significant load which were caused by interrupt status +stuck in the outbound CMPLT queue traced back to this erratum. + +This workaround fixes also kernel panic triggered after some minutes of +usage 5 GHz WiFi 802.11ax card with Mediatek MT7915 chip: + + Internal error: synchronous external abort: 96000210 [#1] SMP + Kernel panic - not syncing: Fatal exception in interrupt + +Signed-off-by: Thomas Petazzoni +Signed-off-by: Pali Rohár +Fixes: 8c39d710363c ("PCI: aardvark: Add Aardvark PCI host controller driver") +Cc: stable@vger.kernel.org +--- + drivers/pci/controller/pci-aardvark.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -210,6 +210,8 @@ enum { + }; + + #define VENDOR_ID_REG (LMI_BASE_ADDR + 0x44) ++#define DEBUG_MUX_CTRL_REG (LMI_BASE_ADDR + 0x208) ++#define DIS_ORD_CHK BIT(30) + + /* PCIe core controller registers */ + #define CTRL_CORE_BASE_ADDR 0x18000 +@@ -558,6 +560,11 @@ static void advk_pcie_setup_hw(struct ad + PCIE_CORE_CTRL2_TD_ENABLE; + advk_writel(pcie, reg, PCIE_CORE_CTRL2_REG); + ++ /* Disable ordering checks, workaround for erratum 3.12 "PCIe completion timeout" */ ++ reg = advk_readl(pcie, DEBUG_MUX_CTRL_REG); ++ reg |= DIS_ORD_CHK; ++ advk_writel(pcie, reg, DEBUG_MUX_CTRL_REG); ++ + /* Set lane X1 */ + reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG); + reg &= ~LANE_CNT_MSK; +@@ -1580,6 +1587,9 @@ static irqreturn_t advk_pcie_irq_handler + struct advk_pcie *pcie = arg; + u32 status; + ++ /* Full memory barrier (ARM dsb sy), workaround for erratum 3.12 "PCIe completion timeout" */ ++ mb(); ++ + status = advk_readl(pcie, HOST_CTRL_INT_STATUS_REG); + if (!(status & PCIE_IRQ_CORE_INT)) + return IRQ_NONE; diff --git a/target/linux/mvebu/patches-6.1/101-ARM-dts-turris-omnia-enable-LED-controller-node.patch b/target/linux/mvebu/patches-6.1/101-ARM-dts-turris-omnia-enable-LED-controller-node.patch new file mode 100644 index 0000000000..ecfb43553f --- /dev/null +++ b/target/linux/mvebu/patches-6.1/101-ARM-dts-turris-omnia-enable-LED-controller-node.patch @@ -0,0 +1,48 @@ +From fed7cef5e4f2df8c6a79bebf5da1fdd3783ff6f3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 4 Jul 2022 13:36:22 +0200 +Subject: [PATCH] ARM: dts: turris-omnia: enable LED controller node +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The LED controller node is disabled because the leds-turris-omnia driver +does not support setting the LED blinking to be controlled by the MCU. + +The patches for that have now been sent [1], so let's enable the node. + +[1] https://lore.kernel.org/linux-leds/20220704105955.15474-1-kabel@kernel.org/T/ + +Signed-off-by: Marek Behún +--- + arch/arm/boot/dts/armada-385-turris-omnia.dts | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +--- a/arch/arm/boot/dts/armada-385-turris-omnia.dts ++++ b/arch/arm/boot/dts/armada-385-turris-omnia.dts +@@ -194,15 +194,13 @@ + reg = <0x2b>; + #address-cells = <1>; + #size-cells = <0>; ++ status = "okay"; + + /* + * LEDs are controlled by MCU (STM32F0) at + * address 0x2b. + * +- * The driver does not support HW control mode +- * for the LEDs yet. Disable the LEDs for now. +- * +- * Also LED functions are not stable yet: ++ * LED functions are not stable yet: + * - there are 3 LEDs connected via MCU to PCIe + * ports. One of these ports supports mSATA. + * There is no mSATA nor PCIe function. +@@ -213,7 +211,6 @@ + * B. Again there is no such function defined. + * For now we use LED_FUNCTION_INDICATOR + */ +- status = "disabled"; + + multi-led@0 { + reg = <0x0>; diff --git a/target/linux/mvebu/patches-6.1/102-leds-turris-omnia-support-HW-controlled-mode-via-pri.patch b/target/linux/mvebu/patches-6.1/102-leds-turris-omnia-support-HW-controlled-mode-via-pri.patch new file mode 100644 index 0000000000..c14469460a --- /dev/null +++ b/target/linux/mvebu/patches-6.1/102-leds-turris-omnia-support-HW-controlled-mode-via-pri.patch @@ -0,0 +1,118 @@ +From 80e643510cb14f116f687e992210c0008a09d869 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 4 Jul 2022 12:59:53 +0200 +Subject: [PATCH] leds: turris-omnia: support HW controlled mode via + private trigger +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add support for enabling MCU controlled mode of the Turris Omnia LEDs +via a LED private trigger called "omnia-mcu". + +When in MCU controlled mode, the user can still set LED color, but the +blinking is done by MCU, which does different things for various LEDs: +- WAN LED is blinked according to the LED[0] pin of the WAN PHY +- LAN LEDs are blinked according to the LED[0] output of corresponding + port of the LAN switch +- PCIe LEDs are blinked according to the logical OR of the MiniPCIe port + LED pins + +For a long time I wanted to actually do this differently: I wanted to +make the netdev trigger to transparently offload the blinking to the HW +if user set compatible settings for the netdev trigger. +There was some work on this, and hopefully we will be able to complete +it sometime, but since there are various complications, it will probably +not be soon. + +In the meantime let's support HW controlled mode via this private LED +trigger. If, in the future, we manage to complete the netdev trigger +offloading, we can still keep this private trigger for backwards +compatiblity, if needed. + +We also set "omnia-mcu" to cdev->default_trigger, so that the MCU keeps +control until the user first wants to take over it. If a different +default trigger is specified in device-tree via the +`linux,default-trigger` property, LED class will overwrite +cdev->default_trigger, and so the DT property will be respected. + +Signed-off-by: Marek Behún +--- + drivers/leds/Kconfig | 1 + + drivers/leds/leds-turris-omnia.c | 41 ++++++++++++++++++++++++++++++++ + 2 files changed, 42 insertions(+) + +--- a/drivers/leds/Kconfig ++++ b/drivers/leds/Kconfig +@@ -163,6 +163,7 @@ config LEDS_TURRIS_OMNIA + depends on I2C + depends on MACH_ARMADA_38X || COMPILE_TEST + depends on OF ++ select LEDS_TRIGGERS + help + This option enables basic support for the LEDs found on the front + side of CZ.NIC's Turris Omnia router. There are 12 RGB LEDs on the +--- a/drivers/leds/leds-turris-omnia.c ++++ b/drivers/leds/leds-turris-omnia.c +@@ -41,6 +41,39 @@ struct omnia_leds { + struct omnia_led leds[]; + }; + ++static struct led_hw_trigger_type omnia_hw_trigger_type; ++ ++static int omnia_hwtrig_activate(struct led_classdev *cdev) ++{ ++ struct omnia_leds *leds = dev_get_drvdata(cdev->dev->parent); ++ struct omnia_led *led = to_omnia_led(lcdev_to_mccdev(cdev)); ++ ++ /* put the LED into MCU controlled mode */ ++ return i2c_smbus_write_byte_data(leds->client, CMD_LED_MODE, ++ CMD_LED_MODE_LED(led->reg)); ++} ++ ++static void omnia_hwtrig_deactivate(struct led_classdev *cdev) ++{ ++ struct omnia_leds *leds = dev_get_drvdata(cdev->dev->parent); ++ struct omnia_led *led = to_omnia_led(lcdev_to_mccdev(cdev)); ++ int ret; ++ ++ /* put the LED into software mode */ ++ ret = i2c_smbus_write_byte_data(leds->client, CMD_LED_MODE, ++ CMD_LED_MODE_LED(led->reg) | ++ CMD_LED_MODE_USER); ++ if (ret < 0) ++ dev_err(cdev->dev, "Cannot put to software mode: %i\n", ret); ++} ++ ++static struct led_trigger omnia_hw_trigger = { ++ .name = "omnia-mcu", ++ .activate = omnia_hwtrig_activate, ++ .deactivate = omnia_hwtrig_deactivate, ++ .trigger_type = &omnia_hw_trigger_type, ++}; ++ + static int omnia_led_brightness_set_blocking(struct led_classdev *cdev, + enum led_brightness brightness) + { +@@ -112,6 +145,8 @@ static int omnia_led_register(struct i2c + cdev = &led->mc_cdev.led_cdev; + cdev->max_brightness = 255; + cdev->brightness_set_blocking = omnia_led_brightness_set_blocking; ++ cdev->trigger_type = &omnia_hw_trigger_type; ++ cdev->default_trigger = omnia_hw_trigger.name; + + /* put the LED into software mode */ + ret = i2c_smbus_write_byte_data(client, CMD_LED_MODE, +@@ -228,6 +263,12 @@ static int omnia_leds_probe(struct i2c_c + + mutex_init(&leds->lock); + ++ ret = devm_led_trigger_register(dev, &omnia_hw_trigger); ++ if (ret < 0) { ++ dev_err(dev, "Cannot register private LED trigger: %d\n", ret); ++ return ret; ++ } ++ + led = &leds->leds[0]; + for_each_available_child_of_node(np, child) { + ret = omnia_led_register(client, led, child); diff --git a/target/linux/mvebu/patches-6.1/103-leds-turris-omnia-initialize-multi-intensity-to-full.patch b/target/linux/mvebu/patches-6.1/103-leds-turris-omnia-initialize-multi-intensity-to-full.patch new file mode 100644 index 0000000000..1fe76b8f2c --- /dev/null +++ b/target/linux/mvebu/patches-6.1/103-leds-turris-omnia-initialize-multi-intensity-to-full.patch @@ -0,0 +1,33 @@ +From bda176cceb735b9b46c1900658b6486c34e13ae6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 4 Jul 2022 12:59:54 +0200 +Subject: [PATCH] leds: turris-omnia: initialize multi-intensity to full +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The default color of each LED before driver probe (255, 255, 255). +Initialize multi_intensity to this value, so that it corresponds to the +reality. + +Signed-off-by: Marek Behún +--- + drivers/leds/leds-turris-omnia.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/leds/leds-turris-omnia.c ++++ b/drivers/leds/leds-turris-omnia.c +@@ -131,10 +131,13 @@ static int omnia_led_register(struct i2c + } + + led->subled_info[0].color_index = LED_COLOR_ID_RED; ++ led->subled_info[0].intensity = 255; + led->subled_info[0].channel = 0; + led->subled_info[1].color_index = LED_COLOR_ID_GREEN; ++ led->subled_info[1].intensity = 255; + led->subled_info[1].channel = 1; + led->subled_info[2].color_index = LED_COLOR_ID_BLUE; ++ led->subled_info[2].intensity = 255; + led->subled_info[2].channel = 2; + + led->mc_cdev.subled_info = led->subled_info; diff --git a/target/linux/mvebu/patches-6.1/104-leds-turris-omnia-change-max-brightness-from-255-to-.patch b/target/linux/mvebu/patches-6.1/104-leds-turris-omnia-change-max-brightness-from-255-to-.patch new file mode 100644 index 0000000000..fb8864dfd1 --- /dev/null +++ b/target/linux/mvebu/patches-6.1/104-leds-turris-omnia-change-max-brightness-from-255-to-.patch @@ -0,0 +1,31 @@ +From 349cbe949b9622cc05b148ecfa6268cbbae35b45 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 4 Jul 2022 12:59:55 +0200 +Subject: [PATCH] leds: turris-omnia: change max brightness from 255 to 1 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Using binary brightness makes more sense for this controller, because +internally in the MCU it works that way: the LED has a color, and a +state whether it is ON or OFF. + +The resulting brightness computation with led_mc_calc_color_components() +will now always result in either (0, 0, 0) or the multi_intensity value. + +Signed-off-by: Marek Behún +--- + drivers/leds/leds-turris-omnia.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/leds/leds-turris-omnia.c ++++ b/drivers/leds/leds-turris-omnia.c +@@ -146,7 +146,7 @@ static int omnia_led_register(struct i2c + init_data.fwnode = &np->fwnode; + + cdev = &led->mc_cdev.led_cdev; +- cdev->max_brightness = 255; ++ cdev->max_brightness = 1; + cdev->brightness_set_blocking = omnia_led_brightness_set_blocking; + cdev->trigger_type = &omnia_hw_trigger_type; + cdev->default_trigger = omnia_hw_trigger.name; diff --git a/target/linux/mvebu/patches-6.1/105-power-reset-linkstation-poweroff-add-ls220de.patch b/target/linux/mvebu/patches-6.1/105-power-reset-linkstation-poweroff-add-ls220de.patch new file mode 100644 index 0000000000..3223861234 --- /dev/null +++ b/target/linux/mvebu/patches-6.1/105-power-reset-linkstation-poweroff-add-ls220de.patch @@ -0,0 +1,15 @@ +--- a/drivers/power/reset/linkstation-poweroff.c ++++ b/drivers/power/reset/linkstation-poweroff.c +@@ -142,6 +142,12 @@ static void linkstation_poweroff(void) + } + + static const struct of_device_id ls_poweroff_of_match[] = { ++ { .compatible = "buffalo,ls220d", ++ .data = &linkstation_power_off_cfg, ++ }, ++ { .compatible = "buffalo,ls220de", ++ .data = &linkstation_power_off_cfg, ++ }, + { .compatible = "buffalo,ls421d", + .data = &linkstation_power_off_cfg, + }, diff --git a/target/linux/mvebu/patches-6.1/300-mvebu-Mangle-bootloader-s-kernel-arguments.patch b/target/linux/mvebu/patches-6.1/300-mvebu-Mangle-bootloader-s-kernel-arguments.patch new file mode 100644 index 0000000000..9069de1614 --- /dev/null +++ b/target/linux/mvebu/patches-6.1/300-mvebu-Mangle-bootloader-s-kernel-arguments.patch @@ -0,0 +1,279 @@ +From 71270226b14733a4b1f2cde58ea9265caa50b38d Mon Sep 17 00:00:00 2001 +From: Adrian Panella +Date: Thu, 9 Mar 2017 09:37:17 +0100 +Subject: [PATCH 67/69] generic: Mangle bootloader's kernel arguments + +The command-line arguments provided by the boot loader will be +appended to a new device tree property: bootloader-args. +If there is a property "append-rootblock" in DT under /chosen +and a root= option in bootloaders command line it will be parsed +and added to DT bootargs with the form: XX. +Only command line ATAG will be processed, the rest of the ATAGs +sent by bootloader will be ignored. +This is usefull in dual boot systems, to get the current root partition +without afecting the rest of the system. + +Signed-off-by: Adrian Panella + +This patch has been modified to be mvebu specific. The original patch +did not pass the bootloader cmdline on if no append-rootblock stanza +was found, resulting in blank cmdline and failure to boot. + +Signed-off-by: Michael Gray +--- + arch/arm/Kconfig | 11 ++++ + arch/arm/boot/compressed/atags_to_fdt.c | 85 ++++++++++++++++++++++++- + init/main.c | 16 +++++ + 3 files changed, 111 insertions(+), 1 deletion(-) + +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -1727,6 +1727,17 @@ config ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEN + The command-line arguments provided by the boot loader will be + appended to the the device tree bootargs property. + ++config ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE ++ bool "Append rootblock parsing bootloader's kernel arguments" ++ help ++ The command-line arguments provided by the boot loader will be ++ appended to a new device tree property: bootloader-args. ++ If there is a property "append-rootblock" in DT under /chosen ++ and a root= option in bootloaders command line it will be parsed ++ and added to DT bootargs with the form: XX. ++ Only command line ATAG will be processed, the rest of the ATAGs ++ sent by bootloader will be ignored. ++ + endchoice + + config CMDLINE +--- a/arch/arm/boot/compressed/atags_to_fdt.c ++++ b/arch/arm/boot/compressed/atags_to_fdt.c +@@ -5,6 +5,8 @@ + + #if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND) + #define do_extend_cmdline 1 ++#elif defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) ++#define do_extend_cmdline 1 + #else + #define do_extend_cmdline 0 + #endif +@@ -20,6 +22,7 @@ static int node_offset(void *fdt, const + return offset; + } + ++#ifndef CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE + static int setprop(void *fdt, const char *node_path, const char *property, + void *val_array, int size) + { +@@ -28,6 +31,7 @@ static int setprop(void *fdt, const char + return offset; + return fdt_setprop(fdt, offset, property, val_array, size); + } ++#endif + + static int setprop_string(void *fdt, const char *node_path, + const char *property, const char *string) +@@ -38,6 +42,7 @@ static int setprop_string(void *fdt, con + return fdt_setprop_string(fdt, offset, property, string); + } + ++#ifndef CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE + static int setprop_cell(void *fdt, const char *node_path, + const char *property, uint32_t val) + { +@@ -46,6 +51,7 @@ static int setprop_cell(void *fdt, const + return offset; + return fdt_setprop_cell(fdt, offset, property, val); + } ++#endif + + static const void *getprop(const void *fdt, const char *node_path, + const char *property, int *len) +@@ -58,6 +64,7 @@ static const void *getprop(const void *f + return fdt_getprop(fdt, offset, property, len); + } + ++#ifndef CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE + static uint32_t get_cell_size(const void *fdt) + { + int len; +@@ -69,6 +76,74 @@ static uint32_t get_cell_size(const void + return cell_size; + } + ++#endif ++ ++#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) ++ ++static char *append_rootblock(char *dest, const char *str, int len, void *fdt) ++{ ++ const char *ptr, *end; ++ const char *root="root="; ++ int i, l; ++ const char *rootblock; ++ ++ //ARM doesn't have __HAVE_ARCH_STRSTR, so search manually ++ ptr = str - 1; ++ ++ do { ++ //first find an 'r' at the begining or after a space ++ do { ++ ptr++; ++ ptr = strchr(ptr, 'r'); ++ if (!ptr) ++ goto no_append; ++ ++ } while (ptr != str && *(ptr-1) != ' '); ++ ++ //then check for the rest ++ for(i = 1; i <= 4; i++) ++ if(*(ptr+i) != *(root+i)) break; ++ ++ } while (i != 5); ++ ++ end = strchr(ptr, ' '); ++ end = end ? (end - 1) : (strchr(ptr, 0) - 1); ++ ++ //find partition number (assumes format root=/dev/mtdXX | /dev/mtdblockXX | yy:XX ) ++ for( i = 0; end >= ptr && *end >= '0' && *end <= '9'; end--, i++); ++ ptr = end + 1; ++ ++ /* if append-rootblock property is set use it to append to command line */ ++ rootblock = getprop(fdt, "/chosen", "append-rootblock", &l); ++ if (rootblock == NULL) ++ goto no_append; ++ ++ if (*dest != ' ') { ++ *dest = ' '; ++ dest++; ++ len++; ++ } ++ ++ if (len + l + i <= COMMAND_LINE_SIZE) { ++ memcpy(dest, rootblock, l); ++ dest += l - 1; ++ memcpy(dest, ptr, i); ++ dest += i; ++ } ++ ++ return dest; ++ ++no_append: ++ len = strlen(str); ++ if (len + 1 < COMMAND_LINE_SIZE) { ++ memcpy(dest, str, len); ++ dest += len; ++ } ++ ++ return dest; ++} ++#endif ++ + static void merge_fdt_bootargs(void *fdt, const char *fdt_cmdline) + { + char cmdline[COMMAND_LINE_SIZE]; +@@ -88,18 +163,28 @@ static void merge_fdt_bootargs(void *fdt + + /* and append the ATAG_CMDLINE */ + if (fdt_cmdline) { ++ ++#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) ++ //save original bootloader args ++ //and append ubi.mtd with root partition number to current cmdline ++ setprop_string(fdt, "/chosen", "bootloader-args", fdt_cmdline); ++ ptr = append_rootblock(ptr, fdt_cmdline, len, fdt); ++ ++#else + len = strlen(fdt_cmdline); + if (ptr - cmdline + len + 2 < COMMAND_LINE_SIZE) { + *ptr++ = ' '; + memcpy(ptr, fdt_cmdline, len); + ptr += len; + } ++#endif + } + *ptr = '\0'; + + setprop_string(fdt, "/chosen", "bootargs", cmdline); + } + ++#ifndef CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE + static void hex_str(char *out, uint32_t value) + { + uint32_t digit; +@@ -117,6 +202,7 @@ static void hex_str(char *out, uint32_t + } + *out = '\0'; + } ++#endif + + /* + * Convert and fold provided ATAGs into the provided FDT. +@@ -131,9 +217,11 @@ int atags_to_fdt(void *atag_list, void * + struct tag *atag = atag_list; + /* In the case of 64 bits memory size, need to reserve 2 cells for + * address and size for each bank */ ++#ifndef CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE + __be32 mem_reg_property[2 * 2 * NR_BANKS]; +- int memcount = 0; +- int ret, memsize; ++ int memsize, memcount = 0; ++#endif ++ int ret; + + /* make sure we've got an aligned pointer */ + if ((u32)atag_list & 0x3) +@@ -168,7 +256,9 @@ int atags_to_fdt(void *atag_list, void * + else + setprop_string(fdt, "/chosen", "bootargs", + atag->u.cmdline.cmdline); +- } else if (atag->hdr.tag == ATAG_MEM) { ++ } ++#ifndef CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE ++ else if (atag->hdr.tag == ATAG_MEM) { + if (memcount >= sizeof(mem_reg_property)/4) + continue; + if (!atag->u.mem.size) +@@ -212,6 +302,10 @@ int atags_to_fdt(void *atag_list, void * + setprop(fdt, "/memory", "reg", mem_reg_property, + 4 * memcount * memsize); + } ++#else ++ ++ } ++#endif + + return fdt_pack(fdt); + } +--- a/init/main.c ++++ b/init/main.c +@@ -114,6 +114,10 @@ + + #include + ++#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) ++#include ++#endif ++ + static int kernel_init(void *); + + extern void init_IRQ(void); +@@ -991,6 +995,18 @@ asmlinkage __visible void __init __no_sa + page_alloc_init(); + + pr_notice("Kernel command line: %s\n", saved_command_line); ++ ++#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) ++ //Show bootloader's original command line for reference ++ if(of_chosen) { ++ const char *prop = of_get_property(of_chosen, "bootloader-args", NULL); ++ if(prop) ++ pr_notice("Bootloader command line (ignored): %s\n", prop); ++ else ++ pr_notice("Bootloader command line not present\n"); ++ } ++#endif ++ + /* parameters may set static keys */ + jump_label_init(); + parse_early_param(); diff --git a/target/linux/mvebu/patches-6.1/301-mvebu-armada-38x-enable-libata-leds.patch b/target/linux/mvebu/patches-6.1/301-mvebu-armada-38x-enable-libata-leds.patch new file mode 100644 index 0000000000..615caac24f --- /dev/null +++ b/target/linux/mvebu/patches-6.1/301-mvebu-armada-38x-enable-libata-leds.patch @@ -0,0 +1,10 @@ +--- a/arch/arm/mach-mvebu/Kconfig ++++ b/arch/arm/mach-mvebu/Kconfig +@@ -67,6 +67,7 @@ config MACH_ARMADA_38X + select HAVE_ARM_TWD if SMP + select MACH_MVEBU_V7 + select PINCTRL_ARMADA_38X ++ select ARCH_WANT_LIBATA_LEDS + help + Say 'Y' here if you want your kernel to support boards based + on the Marvell Armada 380/385 SoC with device tree. diff --git a/target/linux/mvebu/patches-6.1/302-add_powertables.patch b/target/linux/mvebu/patches-6.1/302-add_powertables.patch new file mode 100644 index 0000000000..93ad5de2cc --- /dev/null +++ b/target/linux/mvebu/patches-6.1/302-add_powertables.patch @@ -0,0 +1,770 @@ +--- a/arch/arm/boot/dts/armada-385-linksys.dtsi ++++ b/arch/arm/boot/dts/armada-385-linksys.dtsi +@@ -214,11 +214,19 @@ + &pcie1 { + /* Marvell 88W8864, 5GHz-only */ + status = "okay"; ++ ++ mwlwifi { ++ marvell,2ghz = <0>; ++ }; + }; + + &pcie2 { + /* Marvell 88W8864, 2GHz-only */ + status = "okay"; ++ ++ mwlwifi { ++ marvell,5ghz = <0>; ++ }; + }; + + &pinctrl { +--- a/arch/arm/boot/dts/armada-385-linksys-caiman.dts ++++ b/arch/arm/boot/dts/armada-385-linksys-caiman.dts +@@ -142,3 +142,205 @@ + }; + }; + }; ++ ++&pcie1 { ++ mwlwifi { ++ marvell,chainmask = <2 2>; ++ marvell,powertable { ++ AU = ++ <36 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <40 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <44 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <48 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <52 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <56 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <60 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <64 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <100 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <104 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <108 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <112 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <116 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <120 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <124 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <128 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <132 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <136 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <140 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <149 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x1a 0x1a 0x17 0x14 0 0xf>, ++ <153 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x1a 0x1a 0x17 0x14 0 0xf>, ++ <157 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x1a 0x1a 0x17 0x14 0 0xf>, ++ <161 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x1a 0x1a 0x17 0x14 0 0xf>, ++ <165 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x1a 0x1a 0x17 0x14 0 0xf>; ++ CA = ++ <36 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0 0xf>, ++ <40 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0 0xf>, ++ <44 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0 0xf>, ++ <48 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0 0xf>, ++ <52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <149 0 0x1a 0x1a 0x18 0x17 0x19 0x19 0x17 0x15 0x18 0x18 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, ++ <153 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, ++ <157 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, ++ <161 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, ++ <165 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>; ++ CN = ++ <36 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <40 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <44 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <48 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <52 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <56 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <60 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <64 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <100 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <104 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <108 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <112 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <116 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <120 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <124 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <128 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <132 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <136 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <140 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <149 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x11 0x11 0x11 0x11 0 0xf>, ++ <153 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0 0xf>, ++ <157 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0 0xf>, ++ <161 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0 0xf>, ++ <165 0 0x15 0x15 0x15 0x15 0x16 0x16 0x16 0x15 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0 0xf>; ++ ETSI = ++ <36 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <40 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <44 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <48 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <52 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <56 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <60 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <64 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <100 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <104 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <108 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <112 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <116 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <120 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <124 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <128 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <132 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <136 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <140 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <149 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>; ++ FCC = ++ <36 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <40 0 0x19 0x19 0x18 0x17 0x19 0x19 0x17 0x15 0x17 0x17 0x17 0x14 0x10 0x10 0x10 0x10 0 0xf>, ++ <44 0 0x19 0x19 0x18 0x17 0x19 0x19 0x17 0x15 0x17 0x17 0x17 0x14 0x10 0x10 0x10 0x10 0 0xf>, ++ <48 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x17 0x17 0x17 0x14 0x10 0x10 0x10 0x10 0 0xf>, ++ <52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <149 0 0x1a 0x1a 0x18 0x17 0x19 0x19 0x17 0x15 0x18 0x18 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, ++ <153 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, ++ <157 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, ++ <161 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, ++ <165 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>; ++ }; ++ }; ++}; ++ ++&pcie2 { ++ mwlwifi { ++ marvell,chainmask = <2 2>; ++ marvell,powertable { ++ AU = ++ <1 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>; ++ CA = ++ <1 0 0x19 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x10 0x10 0x10 0x10 0x00 0x00 0x00 0x00 0 0xf>, ++ <2 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, ++ <3 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, ++ <4 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, ++ <5 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, ++ <6 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, ++ <7 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, ++ <8 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, ++ <9 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, ++ <10 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, ++ <11 0 0x19 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x00 0x00 0x00 0x00 0 0xf>; ++ CN = ++ <1 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <12 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <13 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <14 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>; ++ ETSI = ++ <1 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <12 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <13 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>; ++ FCC = ++ <1 0 0x19 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0x19 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x0 0x0 0x0 0x0 0 0xf>; ++ }; ++ }; ++}; +--- a/arch/arm/boot/dts/armada-385-linksys-cobra.dts ++++ b/arch/arm/boot/dts/armada-385-linksys-cobra.dts +@@ -142,3 +142,205 @@ + }; + }; + }; ++ ++&pcie1 { ++ mwlwifi { ++ marvell,chainmask = <4 4>; ++ marvell,powertable { ++ AU = ++ <36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <100 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <104 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <108 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <112 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <116 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <120 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <124 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <128 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <132 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <136 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <140 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <149 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, ++ <153 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, ++ <157 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, ++ <161 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, ++ <165 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>; ++ CA = ++ <36 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <40 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <44 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <48 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <149 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <165 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>; ++ CN = ++ <36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <100 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <104 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <108 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <112 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <116 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <120 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <124 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <128 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <132 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <136 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <140 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <149 0 0x14 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, ++ <157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, ++ <161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, ++ <165 0 0x13 0x13 0x13 0x13 0x13 0x13 0x13 0x13 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>; ++ ETSI = ++ <36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <100 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <104 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <108 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <112 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <116 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <120 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <124 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <128 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <132 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <136 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <140 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <149 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>; ++ FCC = ++ <36 0 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0 0xf>, ++ <40 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, ++ <44 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, ++ <48 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, ++ <52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <149 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <165 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>; ++ }; ++ }; ++}; ++ ++&pcie2 { ++ mwlwifi { ++ marvell,chainmask = <4 4>; ++ marvell,powertable { ++ AU = ++ <1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; ++ CA = ++ <1 0 0x17 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0xe 0xe 0xe 0xe 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0x17 0x12 0x12 0x12 0x13 0x13 0x13 0x13 0xf 0xf 0xf 0xf 0x0 0x0 0x0 0x0 0 0xf>; ++ CN = ++ <1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <12 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <13 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <14 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; ++ ETSI = ++ <1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <12 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <13 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; ++ FCC = ++ <1 0 0x17 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0xe 0xe 0xe 0xe 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0x17 0x12 0x12 0x12 0x13 0x13 0x13 0x13 0xf 0xf 0xf 0xf 0x0 0x0 0x0 0x0 0 0xf>; ++ }; ++ }; ++}; +--- a/arch/arm/boot/dts/armada-385-linksys-shelby.dts ++++ b/arch/arm/boot/dts/armada-385-linksys-shelby.dts +@@ -142,3 +142,205 @@ + }; + }; + }; ++ ++&pcie1 { ++ mwlwifi { ++ marvell,chainmask = <4 4>; ++ marvell,powertable { ++ AU = ++ <36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <100 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <104 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <108 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <112 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <116 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <120 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <124 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <128 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <132 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <136 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <140 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <149 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, ++ <153 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, ++ <157 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, ++ <161 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, ++ <165 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>; ++ CA = ++ <36 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <40 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <44 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <48 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <149 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <165 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>; ++ CN = ++ <36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <100 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <104 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <108 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <112 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <116 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <120 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <124 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <128 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <132 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <136 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <140 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <149 0 0x14 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, ++ <157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, ++ <161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, ++ <165 0 0x13 0x13 0x13 0x13 0x13 0x13 0x13 0x13 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>; ++ ETSI = ++ <36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <100 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <104 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <108 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <112 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <116 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <120 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <124 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <128 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <132 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <136 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <140 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <149 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>; ++ FCC = ++ <36 0 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0 0xf>, ++ <40 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, ++ <44 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, ++ <48 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, ++ <52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <149 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <165 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>; ++ }; ++ }; ++}; ++ ++&pcie2 { ++ mwlwifi { ++ marvell,chainmask = <4 4>; ++ marvell,powertable { ++ AU = ++ <1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; ++ CA = ++ <1 0 0x17 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0xe 0xe 0xe 0xe 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0x17 0x12 0x12 0x12 0x13 0x13 0x13 0x13 0xf 0xf 0xf 0xf 0x0 0x0 0x0 0x0 0 0xf>; ++ CN = ++ <1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <12 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <13 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <14 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; ++ ETSI = ++ <1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <12 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <13 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; ++ FCC = ++ <1 0 0x17 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0xe 0xe 0xe 0xe 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0x17 0x12 0x12 0x12 0x13 0x13 0x13 0x13 0xf 0xf 0xf 0xf 0x0 0x0 0x0 0x0 0 0xf>; ++ }; ++ }; ++}; +--- a/arch/arm/boot/dts/armada-385-linksys-rango.dts ++++ b/arch/arm/boot/dts/armada-385-linksys-rango.dts +@@ -157,6 +157,18 @@ + }; + }; + ++&pcie1 { ++ mwlwifi { ++ marvell,chainmask = <4 4>; ++ }; ++}; ++ ++&pcie2 { ++ mwlwifi { ++ marvell,chainmask = <4 4>; ++ }; ++}; ++ + &sdhci { + pinctrl-names = "default"; + pinctrl-0 = <&sdhci_pins>; +--- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts ++++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts +@@ -225,12 +225,100 @@ + pcie@2,0 { + /* Port 0, Lane 1 */ + status = "okay"; ++ ++ mwlwifi { ++ marvell,5ghz = <0>; ++ marvell,chainmask = <4 4>; ++ marvell,powertable { ++ FCC = ++ <1 0 0x17 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0x17 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>; ++ ++ ETSI = ++ <1 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <12 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <13 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>; ++ }; ++ }; + }; + + /* Second mini-PCIe port */ + pcie@3,0 { + /* Port 0, Lane 3 */ + status = "okay"; ++ ++ mwlwifi { ++ marvell,2ghz = <0>; ++ marvell,chainmask = <4 4>; ++ marvell,powertable { ++ FCC = ++ <36 0 0x8 0x8 0x8 0x8 0x8 0x8 0x8 0x8 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <40 0 0x8 0x8 0x8 0x8 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <44 0 0x8 0x8 0x8 0x8 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <48 0 0x8 0x8 0x8 0x8 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <52 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0 0xf>, ++ <56 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0 0xf>, ++ <60 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0 0xf>, ++ <64 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0 0xf>, ++ <100 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <104 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <108 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <112 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <116 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <120 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <124 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <128 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <132 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <136 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <140 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <149 0 0x16 0x16 0x16 0x16 0x14 0x14 0x14 0x14 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0 0xf>, ++ <153 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0 0xf>, ++ <157 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0 0xf>, ++ <161 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0 0xf>, ++ <165 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0 0xf>; ++ ++ ETSI = ++ <36 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <40 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <44 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <48 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <52 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <56 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <60 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <64 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <100 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <104 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <108 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <112 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <116 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <120 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <124 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <128 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <132 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <136 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <140 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <149 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>; ++ }; ++ }; + }; + }; + diff --git a/target/linux/mvebu/patches-6.1/304-revert_i2c_delay.patch b/target/linux/mvebu/patches-6.1/304-revert_i2c_delay.patch new file mode 100644 index 0000000000..930c0f9494 --- /dev/null +++ b/target/linux/mvebu/patches-6.1/304-revert_i2c_delay.patch @@ -0,0 +1,15 @@ +--- a/arch/arm/boot/dts/armada-xp.dtsi ++++ b/arch/arm/boot/dts/armada-xp.dtsi +@@ -237,12 +237,10 @@ + }; + + &i2c0 { +- compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c"; + reg = <0x11000 0x100>; + }; + + &i2c1 { +- compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c"; + reg = <0x11100 0x100>; + }; + diff --git a/target/linux/mvebu/patches-6.1/305-armada-385-rd-mtd-partitions.patch b/target/linux/mvebu/patches-6.1/305-armada-385-rd-mtd-partitions.patch new file mode 100644 index 0000000000..31bd53b1f3 --- /dev/null +++ b/target/linux/mvebu/patches-6.1/305-armada-385-rd-mtd-partitions.patch @@ -0,0 +1,19 @@ +--- a/arch/arm/boot/dts/armada-388-rd.dts ++++ b/arch/arm/boot/dts/armada-388-rd.dts +@@ -103,6 +103,16 @@ + compatible = "st,m25p128", "jedec,spi-nor"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <108000000>; ++ ++ partition@0 { ++ label = "uboot"; ++ reg = <0 0x400000>; ++ }; ++ ++ partition@1 { ++ label = "firmware"; ++ reg = <0x400000 0xc00000>; ++ }; + }; + }; + diff --git a/target/linux/mvebu/patches-6.1/306-ARM-mvebu-385-ap-Add-partitions.patch b/target/linux/mvebu/patches-6.1/306-ARM-mvebu-385-ap-Add-partitions.patch new file mode 100644 index 0000000000..2057e31c7e --- /dev/null +++ b/target/linux/mvebu/patches-6.1/306-ARM-mvebu-385-ap-Add-partitions.patch @@ -0,0 +1,35 @@ +From 9861f93a59142a3131870df2521eb2deb73026d7 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Tue, 13 Jan 2015 11:14:09 +0100 +Subject: [PATCH 2/2] ARM: mvebu: 385-ap: Add partitions + +Signed-off-by: Maxime Ripard +--- + arch/arm/boot/dts/armada-385-db-ap.dts | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/arch/arm/boot/dts/armada-385-db-ap.dts ++++ b/arch/arm/boot/dts/armada-385-db-ap.dts +@@ -218,19 +218,19 @@ + #size-cells = <1>; + + partition@0 { +- label = "U-Boot"; ++ label = "u-boot"; + reg = <0x00000000 0x00800000>; + read-only; + }; + + partition@800000 { +- label = "uImage"; ++ label = "kernel"; + reg = <0x00800000 0x00400000>; + read-only; + }; + + partition@c00000 { +- label = "Root"; ++ label = "ubi"; + reg = <0x00c00000 0x3f400000>; + }; + }; diff --git a/target/linux/mvebu/patches-6.1/307-armada-xp-linksys-mamba-broken-idle.patch b/target/linux/mvebu/patches-6.1/307-armada-xp-linksys-mamba-broken-idle.patch new file mode 100644 index 0000000000..16112d53fc --- /dev/null +++ b/target/linux/mvebu/patches-6.1/307-armada-xp-linksys-mamba-broken-idle.patch @@ -0,0 +1,10 @@ +--- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts ++++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts +@@ -485,3 +485,7 @@ + }; + }; + }; ++ ++&coherencyfab { ++ broken-idle; ++}; diff --git a/target/linux/mvebu/patches-6.1/308-armada-xp-linksys-mamba-wan.patch b/target/linux/mvebu/patches-6.1/308-armada-xp-linksys-mamba-wan.patch new file mode 100644 index 0000000000..4315abc7d2 --- /dev/null +++ b/target/linux/mvebu/patches-6.1/308-armada-xp-linksys-mamba-wan.patch @@ -0,0 +1,11 @@ +--- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts ++++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts +@@ -387,7 +387,7 @@ + + port@4 { + reg = <4>; +- label = "internet"; ++ label = "wan"; + }; + + port@5 { diff --git a/target/linux/mvebu/patches-6.1/309-linksys-status-led.patch b/target/linux/mvebu/patches-6.1/309-linksys-status-led.patch new file mode 100644 index 0000000000..e5e83572c9 --- /dev/null +++ b/target/linux/mvebu/patches-6.1/309-linksys-status-led.patch @@ -0,0 +1,50 @@ +--- a/arch/arm/boot/dts/armada-385-linksys.dtsi ++++ b/arch/arm/boot/dts/armada-385-linksys.dtsi +@@ -14,6 +14,13 @@ + compatible = "linksys,armada385", "marvell,armada385", + "marvell,armada380"; + ++ aliases { ++ led-boot = &led_power; ++ led-failsafe = &led_power; ++ led-running = &led_power; ++ led-upgrade = &led_power; ++ }; ++ + chosen { + stdout-path = "serial0:115200n8"; + }; +@@ -71,7 +78,7 @@ + pinctrl-0 = <&gpio_leds_pins>; + pinctrl-names = "default"; + +- power { ++ led_power: power { + gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; +--- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts ++++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts +@@ -26,6 +26,13 @@ + compatible = "linksys,mamba", "marvell,armadaxp-mv78230", + "marvell,armadaxp", "marvell,armada-370-xp"; + ++ aliases { ++ led-boot = &led_power; ++ led-failsafe = &led_power; ++ led-running = &led_power; ++ led-upgrade = &led_power; ++ }; ++ + chosen { + bootargs = "console=ttyS0,115200"; + stdout-path = &uart0; +@@ -197,7 +204,7 @@ + pinctrl-0 = <&power_led_pin>; + pinctrl-names = "default"; + +- power { ++ led_power: power { + label = "mamba:white:power"; + gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>; + default-state = "on"; diff --git a/target/linux/mvebu/patches-6.1/310-linksys-use-eth0-as-cpu-port.patch b/target/linux/mvebu/patches-6.1/310-linksys-use-eth0-as-cpu-port.patch new file mode 100644 index 0000000000..84d49a004b --- /dev/null +++ b/target/linux/mvebu/patches-6.1/310-linksys-use-eth0-as-cpu-port.patch @@ -0,0 +1,25 @@ +--- a/arch/arm/boot/dts/armada-385-linksys.dtsi ++++ b/arch/arm/boot/dts/armada-385-linksys.dtsi +@@ -116,7 +116,7 @@ + }; + + ð2 { +- status = "okay"; ++ status = "disabled"; + phy-mode = "sgmii"; + buffer-manager = <&bm>; + bm,pool-long = <2>; +@@ -200,10 +200,10 @@ + label = "wan"; + }; + +- port@5 { +- reg = <5>; ++ port@6 { ++ reg = <6>; + label = "cpu"; +- ethernet = <ð2>; ++ ethernet = <ð0>; + + fixed-link { + speed = <1000>; diff --git a/target/linux/mvebu/patches-6.1/311-adjust-compatible-for-linksys.patch b/target/linux/mvebu/patches-6.1/311-adjust-compatible-for-linksys.patch new file mode 100644 index 0000000000..a5d3e63810 --- /dev/null +++ b/target/linux/mvebu/patches-6.1/311-adjust-compatible-for-linksys.patch @@ -0,0 +1,68 @@ +--- a/arch/arm/boot/dts/armada-385-linksys-rango.dts ++++ b/arch/arm/boot/dts/armada-385-linksys-rango.dts +@@ -12,8 +12,8 @@ + + / { + model = "Linksys WRT3200ACM"; +- compatible = "linksys,rango", "linksys,armada385", "marvell,armada385", +- "marvell,armada380"; ++ compatible = "linksys,wrt3200acm", "linksys,rango", "linksys,armada385", ++ "marvell,armada385", "marvell,armada380"; + }; + + &expander0 { +--- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts ++++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts +@@ -22,9 +22,10 @@ + #include "armada-xp-mv78230.dtsi" + + / { +- model = "Linksys WRT1900AC"; +- compatible = "linksys,mamba", "marvell,armadaxp-mv78230", +- "marvell,armadaxp", "marvell,armada-370-xp"; ++ model = "Linksys WRT1900AC v1"; ++ compatible = "linksys,wrt1900ac-v1", "linksys,mamba", ++ "marvell,armadaxp-mv78230", "marvell,armadaxp", ++ "marvell,armada-370-xp"; + + aliases { + led-boot = &led_power; +--- a/arch/arm/boot/dts/armada-385-linksys-cobra.dts ++++ b/arch/arm/boot/dts/armada-385-linksys-cobra.dts +@@ -9,8 +9,9 @@ + #include "armada-385-linksys.dtsi" + + / { +- model = "Linksys WRT1900ACv2"; +- compatible = "linksys,cobra", "linksys,armada385", "marvell,armada385", ++ model = "Linksys WRT1900AC v2"; ++ compatible = "linksys,wrt1900ac-v2", "linksys,cobra", ++ "linksys,armada385", "marvell,armada385", + "marvell,armada380"; + }; + +--- a/arch/arm/boot/dts/armada-385-linksys-caiman.dts ++++ b/arch/arm/boot/dts/armada-385-linksys-caiman.dts +@@ -10,8 +10,8 @@ + + / { + model = "Linksys WRT1200AC"; +- compatible = "linksys,caiman", "linksys,armada385", "marvell,armada385", +- "marvell,armada380"; ++ compatible = "linksys,wrt1200ac", "linksys,caiman", "linksys,armada385", ++ "marvell,armada385", "marvell,armada380"; + }; + + &expander0 { +--- a/arch/arm/boot/dts/armada-385-linksys-shelby.dts ++++ b/arch/arm/boot/dts/armada-385-linksys-shelby.dts +@@ -10,7 +10,8 @@ + + / { + model = "Linksys WRT1900ACS"; +- compatible = "linksys,shelby", "linksys,armada385", "marvell,armada385", ++ compatible = "linksys,wrt1900acs", "linksys,shelby", ++ "linksys,armada385", "marvell,armada385", + "marvell,armada380"; + }; + diff --git a/target/linux/mvebu/patches-6.1/312-ARM-dts-armada388-clearfog-emmc-on-clearfog-base.patch b/target/linux/mvebu/patches-6.1/312-ARM-dts-armada388-clearfog-emmc-on-clearfog-base.patch new file mode 100644 index 0000000000..dd2bef7f63 --- /dev/null +++ b/target/linux/mvebu/patches-6.1/312-ARM-dts-armada388-clearfog-emmc-on-clearfog-base.patch @@ -0,0 +1,87 @@ +From 8137da20701c776ad3481115305a5e8e410871ba Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Tue, 29 Nov 2016 10:15:45 +0000 +Subject: ARM: dts: armada388-clearfog: emmc on clearfog base + +Signed-off-by: Russell King +--- + arch/arm/boot/dts/armada-388-clearfog-base.dts | 1 + + .../dts/armada-38x-solidrun-microsom-emmc.dtsi | 62 ++++++++++++++++++++++ + 2 files changed, 63 insertions(+) + create mode 100644 arch/arm/boot/dts/armada-38x-solidrun-microsom-emmc.dtsi + +--- a/arch/arm/boot/dts/armada-388-clearfog-base.dts ++++ b/arch/arm/boot/dts/armada-388-clearfog-base.dts +@@ -7,6 +7,7 @@ + + /dts-v1/; + #include "armada-388-clearfog.dtsi" ++#include "armada-38x-solidrun-microsom-emmc.dtsi" + + / { + model = "SolidRun Clearfog Base A1"; +--- /dev/null ++++ b/arch/arm/boot/dts/armada-38x-solidrun-microsom-emmc.dtsi +@@ -0,0 +1,62 @@ ++/* ++ * Device Tree file for SolidRun Armada 38x Microsom add-on for eMMC ++ * ++ * Copyright (C) 2015 Russell King ++ * ++ * This board is in development; the contents of this file work with ++ * the A1 rev 2.0 of the board, which does not represent final ++ * production board. Things will change, don't expect this file to ++ * remain compatible info the future. ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPL or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This file is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Or, alternatively ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++/ { ++ soc { ++ internal-regs { ++ sdhci@d8000 { ++ bus-width = <4>; ++ no-1-8-v; ++ non-removable; ++ pinctrl-0 = <µsom_sdhci_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ wp-inverted; ++ }; ++ }; ++ }; ++}; diff --git a/target/linux/mvebu/patches-6.1/313-helios4-dts-status-led-alias.patch b/target/linux/mvebu/patches-6.1/313-helios4-dts-status-led-alias.patch new file mode 100644 index 0000000000..607f436297 --- /dev/null +++ b/target/linux/mvebu/patches-6.1/313-helios4-dts-status-led-alias.patch @@ -0,0 +1,28 @@ +--- a/arch/arm/boot/dts/armada-388-helios4.dts ++++ b/arch/arm/boot/dts/armada-388-helios4.dts +@@ -15,6 +15,13 @@ + model = "Helios4"; + compatible = "kobol,helios4", "marvell,armada388", + "marvell,armada385", "marvell,armada380"; ++ ++ aliases { ++ led-boot = &led_status; ++ led-failsafe = &led_status; ++ led-running = &led_status; ++ led-upgrade = &led_status; ++ }; + + memory { + device_type = "memory"; +@@ -73,10 +80,9 @@ + pinctrl-names = "default"; + pinctrl-0 = <&helios_system_led_pins>; + +- status-led { ++ led_status: status-led { + label = "helios4:green:status"; + gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; +- linux,default-trigger = "heartbeat"; + default-state = "on"; + }; + diff --git a/target/linux/mvebu/patches-6.1/315-armada-xp-linksys-mamba-resize-kernel.patch b/target/linux/mvebu/patches-6.1/315-armada-xp-linksys-mamba-resize-kernel.patch new file mode 100644 index 0000000000..f1fddceff4 --- /dev/null +++ b/target/linux/mvebu/patches-6.1/315-armada-xp-linksys-mamba-resize-kernel.patch @@ -0,0 +1,37 @@ +From 258233f00bcd013050efee00c5d9128ef8cd62dd Mon Sep 17 00:00:00 2001 +From: Tad +Date: Fri, 5 Feb 2021 22:32:11 -0500 +Subject: [PATCH] ARM: dts: armada-xp-linksys-mamba: Increase kernel + partition to 4MB + +Signed-off-by: Tad Davanzo +--- + arch/arm/boot/dts/armada-xp-linksys-mamba.dts | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts ++++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts +@@ -456,9 +456,9 @@ + reg = <0xa00000 0x2800000>; /* 40MB */ + }; + +- partition@d00000 { ++ partition@e00000 { + label = "rootfs1"; +- reg = <0xd00000 0x2500000>; /* 37MB */ ++ reg = <0xe00000 0x2400000>; /* 36MB */ + }; + + /* kernel2 overlaps with rootfs2 by design */ +@@ -467,9 +467,9 @@ + reg = <0x3200000 0x2800000>; /* 40MB */ + }; + +- partition@3500000 { ++ partition@3600000 { + label = "rootfs2"; +- reg = <0x3500000 0x2500000>; /* 37MB */ ++ reg = <0x3600000 0x2400000>; /* 36MB */ + }; + + /* diff --git a/target/linux/mvebu/patches-6.1/316-armada-370-dts-fix-crypto-engine.patch b/target/linux/mvebu/patches-6.1/316-armada-370-dts-fix-crypto-engine.patch new file mode 100644 index 0000000000..19378870ef --- /dev/null +++ b/target/linux/mvebu/patches-6.1/316-armada-370-dts-fix-crypto-engine.patch @@ -0,0 +1,29 @@ +--- a/arch/arm/boot/dts/armada-370.dtsi ++++ b/arch/arm/boot/dts/armada-370.dtsi +@@ -234,7 +234,7 @@ + clocks = <&gateclk 23>; + clock-names = "cesa0"; + marvell,crypto-srams = <&crypto_sram>; +- marvell,crypto-sram-size = <0x7e0>; ++ marvell,crypto-sram-size = <0x800>; + }; + }; + +@@ -255,12 +255,17 @@ + * cpuidle workaround. + */ + idle-sram@0 { ++ status = "disabled"; + reg = <0x0 0x20>; + }; + }; + }; + }; + ++&coherencyfab { ++ broken-idle; ++}; ++ + /* + * Default UART pinctrl setting without RTS/CTS, can be overwritten on + * board level if a different configuration is used. diff --git a/target/linux/mvebu/patches-6.1/400-find_active_root.patch b/target/linux/mvebu/patches-6.1/400-find_active_root.patch new file mode 100644 index 0000000000..5582d20c68 --- /dev/null +++ b/target/linux/mvebu/patches-6.1/400-find_active_root.patch @@ -0,0 +1,60 @@ +The WRT1900AC among other Linksys routers uses a dual-firmware layout. +Dynamically rename the active partition to "ubi". + +Signed-off-by: Imre Kaloz + +--- a/drivers/mtd/parsers/ofpart_core.c ++++ b/drivers/mtd/parsers/ofpart_core.c +@@ -38,6 +38,8 @@ static bool node_has_compatible(struct d + return of_get_property(pp, "compatible", NULL); + } + ++static int mangled_rootblock; ++ + static int parse_fixed_partitions(struct mtd_info *master, + const struct mtd_partition **pparts, + struct mtd_part_parser_data *data) +@@ -48,6 +50,7 @@ static int parse_fixed_partitions(struct + struct device_node *mtd_node; + struct device_node *ofpart_node; + const char *partname; ++ const char *owrtpart = "ubi"; + struct device_node *pp; + int nr_parts, i, ret = 0; + bool dedicated = true; +@@ -133,9 +136,13 @@ static int parse_fixed_partitions(struct + parts[i].size = of_read_number(reg + a_cells, s_cells); + parts[i].of_node = pp; + +- partname = of_get_property(pp, "label", &len); +- if (!partname) +- partname = of_get_property(pp, "name", &len); ++ if (mangled_rootblock && (i == mangled_rootblock)) { ++ partname = owrtpart; ++ } else { ++ partname = of_get_property(pp, "label", &len); ++ if (!partname) ++ partname = of_get_property(pp, "name", &len); ++ } + parts[i].name = partname; + + if (of_get_property(pp, "read-only", &len)) +@@ -252,6 +259,18 @@ static int __init ofpart_parser_init(voi + return 0; + } + ++static int __init active_root(char *str) ++{ ++ get_option(&str, &mangled_rootblock); ++ ++ if (!mangled_rootblock) ++ return 1; ++ ++ return 1; ++} ++ ++__setup("mangled_rootblock=", active_root); ++ + static void __exit ofpart_parser_exit(void) + { + deregister_mtd_parser(&ofpart_parser); diff --git a/target/linux/mvebu/patches-6.1/700-mvneta-tx-queue-workaround.patch b/target/linux/mvebu/patches-6.1/700-mvneta-tx-queue-workaround.patch new file mode 100644 index 0000000000..32e8ef4b7d --- /dev/null +++ b/target/linux/mvebu/patches-6.1/700-mvneta-tx-queue-workaround.patch @@ -0,0 +1,38 @@ +The hardware queue scheduling is apparently configured with fixed +priorities, which creates a nasty fairness issue where traffic from one +CPU can starve traffic from all other CPUs. + +Work around this issue by forcing all tx packets to go through one CPU, +until this issue is fixed properly. + +Signed-off-by: Felix Fietkau +--- +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -5006,6 +5006,16 @@ static int mvneta_setup_tc(struct net_de + } + } + ++#ifndef CONFIG_ARM64 ++static u16 mvneta_select_queue(struct net_device *dev, struct sk_buff *skb, ++ struct net_device *sb_dev) ++{ ++ /* XXX: hardware queue scheduling is broken, ++ * use only one queue until it is fixed */ ++ return 0; ++} ++#endif ++ + static const struct net_device_ops mvneta_netdev_ops = { + .ndo_open = mvneta_open, + .ndo_stop = mvneta_stop, +@@ -5016,6 +5026,9 @@ static const struct net_device_ops mvnet + .ndo_fix_features = mvneta_fix_features, + .ndo_get_stats64 = mvneta_get_stats64, + .ndo_eth_ioctl = mvneta_ioctl, ++#ifndef CONFIG_ARM64 ++ .ndo_select_queue = mvneta_select_queue, ++#endif + .ndo_bpf = mvneta_xdp, + .ndo_xdp_xmit = mvneta_xdp_xmit, + .ndo_setup_tc = mvneta_setup_tc, diff --git a/target/linux/mvebu/patches-6.1/702-net-next-ethernet-marvell-mvnetaMQPrioOffload.patch b/target/linux/mvebu/patches-6.1/702-net-next-ethernet-marvell-mvnetaMQPrioOffload.patch new file mode 100644 index 0000000000..019b9528c3 --- /dev/null +++ b/target/linux/mvebu/patches-6.1/702-net-next-ethernet-marvell-mvnetaMQPrioOffload.patch @@ -0,0 +1,66 @@ +From 75fa71e3acadbb4ab5eda18505277eb9a1f69b23 Mon Sep 17 00:00:00 2001 +From: Maxime Chevallier +Date: Fri, 26 Nov 2021 12:20:53 +0100 +Subject: net: mvneta: Use struct tc_mqprio_qopt_offload for MQPrio + configuration + +The struct tc_mqprio_qopt_offload is a container for struct tc_mqprio_qopt, +that allows passing extra parameters, such as traffic shaping. This commit +converts the current mqprio code to that new struct. + +Signed-off-by: Maxime Chevallier +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/marvell/mvneta.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +(limited to 'drivers/net/ethernet/marvell/mvneta.c') + +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + #include + + /* Registers */ +@@ -4966,14 +4967,14 @@ static void mvneta_setup_rx_prio_map(str + } + + static int mvneta_setup_mqprio(struct net_device *dev, +- struct tc_mqprio_qopt *qopt) ++ struct tc_mqprio_qopt_offload *mqprio) + { + struct mvneta_port *pp = netdev_priv(dev); + u8 num_tc; + int i; + +- qopt->hw = TC_MQPRIO_HW_OFFLOAD_TCS; +- num_tc = qopt->num_tc; ++ mqprio->qopt.hw = TC_MQPRIO_HW_OFFLOAD_TCS; ++ num_tc = mqprio->qopt.num_tc; + + if (num_tc > rxq_number) + return -EINVAL; +@@ -4984,13 +4985,15 @@ static int mvneta_setup_mqprio(struct ne + return 0; + } + +- memcpy(pp->prio_tc_map, qopt->prio_tc_map, sizeof(pp->prio_tc_map)); ++ memcpy(pp->prio_tc_map, mqprio->qopt.prio_tc_map, ++ sizeof(pp->prio_tc_map)); + + mvneta_setup_rx_prio_map(pp); + +- netdev_set_num_tc(dev, qopt->num_tc); +- for (i = 0; i < qopt->num_tc; i++) +- netdev_set_tc_queue(dev, i, qopt->count[i], qopt->offset[i]); ++ netdev_set_num_tc(dev, mqprio->qopt.num_tc); ++ for (i = 0; i < mqprio->qopt.num_tc; i++) ++ netdev_set_tc_queue(dev, i, mqprio->qopt.count[i], ++ mqprio->qopt.offset[i]); + + return 0; + } diff --git a/target/linux/mvebu/patches-6.1/703-net-next-ethernet-marvell-mvnetaMQPrioFlag.patch b/target/linux/mvebu/patches-6.1/703-net-next-ethernet-marvell-mvnetaMQPrioFlag.patch new file mode 100644 index 0000000000..c878a28843 --- /dev/null +++ b/target/linux/mvebu/patches-6.1/703-net-next-ethernet-marvell-mvnetaMQPrioFlag.patch @@ -0,0 +1,30 @@ +From e7ca75fe6662f78bfeb0112671c812e4c7b8e214 Mon Sep 17 00:00:00 2001 +From: Maxime Chevallier +Date: Fri, 26 Nov 2021 12:20:54 +0100 +Subject: net: mvneta: Don't force-set the offloading flag + +The qopt->hw flag is set by the TC code according to the offloading mode +asked by user. Don't force-set it in the driver, but instead read it to +make sure we do what's asked. + +Signed-off-by: Maxime Chevallier +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/marvell/mvneta.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +(limited to 'drivers/net/ethernet/marvell/mvneta.c') + +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -4973,7 +4973,9 @@ static int mvneta_setup_mqprio(struct ne + u8 num_tc; + int i; + +- mqprio->qopt.hw = TC_MQPRIO_HW_OFFLOAD_TCS; ++ if (mqprio->qopt.hw != TC_MQPRIO_HW_OFFLOAD_TCS) ++ return 0; ++ + num_tc = mqprio->qopt.num_tc; + + if (num_tc > rxq_number) diff --git a/target/linux/mvebu/patches-6.1/704-net-next-ethernet-marvell-mvnetaMQPrioQueue.patch b/target/linux/mvebu/patches-6.1/704-net-next-ethernet-marvell-mvnetaMQPrioQueue.patch new file mode 100644 index 0000000000..546a8486ef --- /dev/null +++ b/target/linux/mvebu/patches-6.1/704-net-next-ethernet-marvell-mvnetaMQPrioQueue.patch @@ -0,0 +1,97 @@ +From e9f7099d0730341b24c057acbf545dd019581db6 Mon Sep 17 00:00:00 2001 +From: Maxime Chevallier +Date: Fri, 26 Nov 2021 12:20:55 +0100 +Subject: net: mvneta: Allow having more than one queue per TC + +The current mqprio implementation assumed that we are only using one +queue per TC. Use the offset and count parameters to allow using +multiple queues per TC. In that case, the controller will use a standard +round-robin algorithm to pick queues assigned to the same TC, with the +same priority. + +This only applies to VLAN priorities in ingress traffic, each TC +corresponding to a vlan priority. + +Signed-off-by: Maxime Chevallier +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/marvell/mvneta.c | 35 ++++++++++++++++++++--------------- + 1 file changed, 20 insertions(+), 15 deletions(-) + +(limited to 'drivers/net/ethernet/marvell/mvneta.c') + +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -498,7 +498,6 @@ struct mvneta_port { + u8 mcast_count[256]; + u16 tx_ring_size; + u16 rx_ring_size; +- u8 prio_tc_map[8]; + + phy_interface_t phy_interface; + struct device_node *dn; +@@ -4955,13 +4954,12 @@ static void mvneta_clear_rx_prio_map(str + mvreg_write(pp, MVNETA_VLAN_PRIO_TO_RXQ, 0); + } + +-static void mvneta_setup_rx_prio_map(struct mvneta_port *pp) ++static void mvneta_map_vlan_prio_to_rxq(struct mvneta_port *pp, u8 pri, u8 rxq) + { +- u32 val = 0; +- int i; ++ u32 val = mvreg_read(pp, MVNETA_VLAN_PRIO_TO_RXQ); + +- for (i = 0; i < rxq_number; i++) +- val |= MVNETA_VLAN_PRIO_RXQ_MAP(i, pp->prio_tc_map[i]); ++ val &= ~MVNETA_VLAN_PRIO_RXQ_MAP(pri, 0x7); ++ val |= MVNETA_VLAN_PRIO_RXQ_MAP(pri, rxq); + + mvreg_write(pp, MVNETA_VLAN_PRIO_TO_RXQ, val); + } +@@ -4970,8 +4968,8 @@ static int mvneta_setup_mqprio(struct ne + struct tc_mqprio_qopt_offload *mqprio) + { + struct mvneta_port *pp = netdev_priv(dev); ++ int rxq, tc; + u8 num_tc; +- int i; + + if (mqprio->qopt.hw != TC_MQPRIO_HW_OFFLOAD_TCS) + return 0; +@@ -4981,21 +4979,28 @@ static int mvneta_setup_mqprio(struct ne + if (num_tc > rxq_number) + return -EINVAL; + ++ mvneta_clear_rx_prio_map(pp); ++ + if (!num_tc) { +- mvneta_clear_rx_prio_map(pp); + netdev_reset_tc(dev); + return 0; + } + +- memcpy(pp->prio_tc_map, mqprio->qopt.prio_tc_map, +- sizeof(pp->prio_tc_map)); ++ netdev_set_num_tc(dev, mqprio->qopt.num_tc); + +- mvneta_setup_rx_prio_map(pp); ++ for (tc = 0; tc < mqprio->qopt.num_tc; tc++) { ++ netdev_set_tc_queue(dev, tc, mqprio->qopt.count[tc], ++ mqprio->qopt.offset[tc]); ++ ++ for (rxq = mqprio->qopt.offset[tc]; ++ rxq < mqprio->qopt.count[tc] + mqprio->qopt.offset[tc]; ++ rxq++) { ++ if (rxq >= rxq_number) ++ return -EINVAL; + +- netdev_set_num_tc(dev, mqprio->qopt.num_tc); +- for (i = 0; i < mqprio->qopt.num_tc; i++) +- netdev_set_tc_queue(dev, i, mqprio->qopt.count[i], +- mqprio->qopt.offset[i]); ++ mvneta_map_vlan_prio_to_rxq(pp, tc, rxq); ++ } ++ } + + return 0; + } diff --git a/target/linux/mvebu/patches-6.1/705-net-next-ethernet-marvell-mvnetaMQPrioTCOffload.patch b/target/linux/mvebu/patches-6.1/705-net-next-ethernet-marvell-mvnetaMQPrioTCOffload.patch new file mode 100644 index 0000000000..1d4a055a71 --- /dev/null +++ b/target/linux/mvebu/patches-6.1/705-net-next-ethernet-marvell-mvnetaMQPrioTCOffload.patch @@ -0,0 +1,182 @@ +From 2551dc9e398c37a15e52122d385c29a8b06be45f Mon Sep 17 00:00:00 2001 +From: Maxime Chevallier +Date: Fri, 26 Nov 2021 12:20:56 +0100 +Subject: net: mvneta: Add TC traffic shaping offload + +The mvneta controller is able to do some tocken-bucket per-queue traffic +shaping. This commit adds support for setting these using the TC mqprio +interface. + +The token-bucket parameters are customisable, but the current +implementation configures them to have a 10kbps resolution for the +rate limitation, since it allows to cover the whole range of max_rate +values from 10kbps to 5Gbps with 10kbps increments. + +Signed-off-by: Maxime Chevallier +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/marvell/mvneta.c | 120 +++++++++++++++++++++++++++++++++- + 1 file changed, 119 insertions(+), 1 deletion(-) + +(limited to 'drivers/net/ethernet/marvell/mvneta.c') + +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -248,12 +248,39 @@ + #define MVNETA_TXQ_SENT_DESC_MASK 0x3fff0000 + #define MVNETA_PORT_TX_RESET 0x3cf0 + #define MVNETA_PORT_TX_DMA_RESET BIT(0) ++#define MVNETA_TXQ_CMD1_REG 0x3e00 ++#define MVNETA_TXQ_CMD1_BW_LIM_SEL_V1 BIT(3) ++#define MVNETA_TXQ_CMD1_BW_LIM_EN BIT(0) ++#define MVNETA_REFILL_NUM_CLK_REG 0x3e08 ++#define MVNETA_REFILL_MAX_NUM_CLK 0x0000ffff + #define MVNETA_TX_MTU 0x3e0c + #define MVNETA_TX_TOKEN_SIZE 0x3e14 + #define MVNETA_TX_TOKEN_SIZE_MAX 0xffffffff ++#define MVNETA_TXQ_BUCKET_REFILL_REG(q) (0x3e20 + ((q) << 2)) ++#define MVNETA_TXQ_BUCKET_REFILL_PERIOD_MASK 0x3ff00000 ++#define MVNETA_TXQ_BUCKET_REFILL_PERIOD_SHIFT 20 ++#define MVNETA_TXQ_BUCKET_REFILL_VALUE_MAX 0x0007ffff + #define MVNETA_TXQ_TOKEN_SIZE_REG(q) (0x3e40 + ((q) << 2)) + #define MVNETA_TXQ_TOKEN_SIZE_MAX 0x7fffffff + ++/* The values of the bucket refill base period and refill period are taken from ++ * the reference manual, and adds up to a base resolution of 10Kbps. This allows ++ * to cover all rate-limit values from 10Kbps up to 5Gbps ++ */ ++ ++/* Base period for the rate limit algorithm */ ++#define MVNETA_TXQ_BUCKET_REFILL_BASE_PERIOD_NS 100 ++ ++/* Number of Base Period to wait between each bucket refill */ ++#define MVNETA_TXQ_BUCKET_REFILL_PERIOD 1000 ++ ++/* The base resolution for rate limiting, in bps. Any max_rate value should be ++ * a multiple of that value. ++ */ ++#define MVNETA_TXQ_RATE_LIMIT_RESOLUTION (NSEC_PER_SEC / \ ++ (MVNETA_TXQ_BUCKET_REFILL_BASE_PERIOD_NS * \ ++ MVNETA_TXQ_BUCKET_REFILL_PERIOD)) ++ + #define MVNETA_LPI_CTRL_0 0x2cc0 + #define MVNETA_LPI_CTRL_1 0x2cc4 + #define MVNETA_LPI_REQUEST_ENABLE BIT(0) +@@ -4964,11 +4991,74 @@ static void mvneta_map_vlan_prio_to_rxq( + mvreg_write(pp, MVNETA_VLAN_PRIO_TO_RXQ, val); + } + ++static int mvneta_enable_per_queue_rate_limit(struct mvneta_port *pp) ++{ ++ unsigned long core_clk_rate; ++ u32 refill_cycles; ++ u32 val; ++ ++ core_clk_rate = clk_get_rate(pp->clk); ++ if (!core_clk_rate) ++ return -EINVAL; ++ ++ refill_cycles = MVNETA_TXQ_BUCKET_REFILL_BASE_PERIOD_NS / ++ (NSEC_PER_SEC / core_clk_rate); ++ ++ if (refill_cycles > MVNETA_REFILL_MAX_NUM_CLK) ++ return -EINVAL; ++ ++ /* Enable bw limit algorithm version 3 */ ++ val = mvreg_read(pp, MVNETA_TXQ_CMD1_REG); ++ val &= ~(MVNETA_TXQ_CMD1_BW_LIM_SEL_V1 | MVNETA_TXQ_CMD1_BW_LIM_EN); ++ mvreg_write(pp, MVNETA_TXQ_CMD1_REG, val); ++ ++ /* Set the base refill rate */ ++ mvreg_write(pp, MVNETA_REFILL_NUM_CLK_REG, refill_cycles); ++ ++ return 0; ++} ++ ++static void mvneta_disable_per_queue_rate_limit(struct mvneta_port *pp) ++{ ++ u32 val = mvreg_read(pp, MVNETA_TXQ_CMD1_REG); ++ ++ val |= (MVNETA_TXQ_CMD1_BW_LIM_SEL_V1 | MVNETA_TXQ_CMD1_BW_LIM_EN); ++ mvreg_write(pp, MVNETA_TXQ_CMD1_REG, val); ++} ++ ++static int mvneta_setup_queue_rates(struct mvneta_port *pp, int queue, ++ u64 min_rate, u64 max_rate) ++{ ++ u32 refill_val, rem; ++ u32 val = 0; ++ ++ /* Convert to from Bps to bps */ ++ max_rate *= 8; ++ ++ if (min_rate) ++ return -EINVAL; ++ ++ refill_val = div_u64_rem(max_rate, MVNETA_TXQ_RATE_LIMIT_RESOLUTION, ++ &rem); ++ ++ if (rem || !refill_val || ++ refill_val > MVNETA_TXQ_BUCKET_REFILL_VALUE_MAX) ++ return -EINVAL; ++ ++ val = refill_val; ++ val |= (MVNETA_TXQ_BUCKET_REFILL_PERIOD << ++ MVNETA_TXQ_BUCKET_REFILL_PERIOD_SHIFT); ++ ++ mvreg_write(pp, MVNETA_TXQ_BUCKET_REFILL_REG(queue), val); ++ ++ return 0; ++} ++ + static int mvneta_setup_mqprio(struct net_device *dev, + struct tc_mqprio_qopt_offload *mqprio) + { + struct mvneta_port *pp = netdev_priv(dev); +- int rxq, tc; ++ int rxq, txq, tc, ret; + u8 num_tc; + + if (mqprio->qopt.hw != TC_MQPRIO_HW_OFFLOAD_TCS) +@@ -4982,6 +5072,7 @@ static int mvneta_setup_mqprio(struct ne + mvneta_clear_rx_prio_map(pp); + + if (!num_tc) { ++ mvneta_disable_per_queue_rate_limit(pp); + netdev_reset_tc(dev); + return 0; + } +@@ -5002,6 +5093,33 @@ static int mvneta_setup_mqprio(struct ne + } + } + ++ if (mqprio->shaper != TC_MQPRIO_SHAPER_BW_RATE) { ++ mvneta_disable_per_queue_rate_limit(pp); ++ return 0; ++ } ++ ++ if (mqprio->qopt.num_tc > txq_number) ++ return -EINVAL; ++ ++ ret = mvneta_enable_per_queue_rate_limit(pp); ++ if (ret) ++ return ret; ++ ++ for (tc = 0; tc < mqprio->qopt.num_tc; tc++) { ++ for (txq = mqprio->qopt.offset[tc]; ++ txq < mqprio->qopt.count[tc] + mqprio->qopt.offset[tc]; ++ txq++) { ++ if (txq >= txq_number) ++ return -EINVAL; ++ ++ ret = mvneta_setup_queue_rates(pp, txq, ++ mqprio->min_rate[tc], ++ mqprio->max_rate[tc]); ++ if (ret) ++ return ret; ++ } ++ } ++ + return 0; + } + diff --git a/target/linux/mvebu/patches-6.1/710-v6.2-phy-marvell-phy-mvebu-a3700-comphy-Reset-COMPHY-regi.patch b/target/linux/mvebu/patches-6.1/710-v6.2-phy-marvell-phy-mvebu-a3700-comphy-Reset-COMPHY-regi.patch new file mode 100644 index 0000000000..a852dc1fc1 --- /dev/null +++ b/target/linux/mvebu/patches-6.1/710-v6.2-phy-marvell-phy-mvebu-a3700-comphy-Reset-COMPHY-regi.patch @@ -0,0 +1,50 @@ +From b01d622d76134e9401970ffd3fbbb9a7051f976a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Tue, 20 Sep 2022 14:11:54 +0200 +Subject: [PATCH] phy: marvell: phy-mvebu-a3700-comphy: Reset COMPHY registers + before USB 3.0 power on +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Turris MOX board with older ARM Trusted Firmware version v1.5 is not able +to detect any USB 3.0 device connected to USB-A port on Mox-A module after +commit 0a6fc70d76bd ("phy: marvell: phy-mvebu-a3700-comphy: Remove broken +reset support"). On the other hand USB 2.0 devices connected to the same +USB-A port are working fine. + +It looks as if the older firmware configures COMPHY registers for USB 3.0 +somehow incompatibly for kernel driver. Experiments show that resetting +COMPHY registers via setting SFT_RST auto-clearing bit in COMPHY_SFT_RESET +register fixes this issue. + +Reset the COMPHY in mvebu_a3700_comphy_usb3_power_on() function as a first +step after selecting COMPHY lane and USB 3.0 function. With this change +Turris MOX board can successfully detect USB 3.0 devices again. + +Before the above mentioned commit this reset was implemented in PHY reset +method, so this is the reason why there was no issue with older firmware +version then. + +Fixes: 0a6fc70d76bd ("phy: marvell: phy-mvebu-a3700-comphy: Remove broken reset support") +Reported-by: Marek Behún +Signed-off-by: Pali Rohár +Tested-by: Shin'ichiro Kawasaki +Link: https://lore.kernel.org/r/20220920121154.30115-1-pali@kernel.org +Signed-off-by: Vinod Koul +--- + drivers/phy/marvell/phy-mvebu-a3700-comphy.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/phy/marvell/phy-mvebu-a3700-comphy.c ++++ b/drivers/phy/marvell/phy-mvebu-a3700-comphy.c +@@ -826,6 +826,9 @@ mvebu_a3700_comphy_usb3_power_on(struct + if (ret) + return ret; + ++ /* COMPHY register reset (cleared automatically) */ ++ comphy_lane_reg_set(lane, COMPHY_SFT_RESET, SFT_RST, SFT_RST); ++ + /* + * 0. Set PHY OTG Control(0x5d034), bit 4, Power up OTG module The + * register belong to UTMI module, so it is set in UTMI phy driver. diff --git a/target/linux/mvebu/patches-6.1/800-cpuidle-mvebu-indicate-failure-to-enter-deeper-sleep.patch b/target/linux/mvebu/patches-6.1/800-cpuidle-mvebu-indicate-failure-to-enter-deeper-sleep.patch new file mode 100644 index 0000000000..29f36be460 --- /dev/null +++ b/target/linux/mvebu/patches-6.1/800-cpuidle-mvebu-indicate-failure-to-enter-deeper-sleep.patch @@ -0,0 +1,40 @@ +From c28b2d367da8a471482e6a4aa8337ab6369a80c2 Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Sat, 3 Oct 2015 09:13:05 +0100 +Subject: cpuidle: mvebu: indicate failure to enter deeper sleep states + +The cpuidle ->enter method expects the return value to be the sleep +state we entered. Returning negative numbers or other codes is not +permissible since coupled CPU idle was merged. + +At least some of the mvebu_v7_cpu_suspend() implementations return the +value from cpu_suspend(), which returns zero if the CPU vectors back +into the kernel via cpu_resume() (the success case), or the non-zero +return value of the suspend actor, or one (failure cases). + +We do not want to be returning the failure case value back to CPU idle +as that indicates that we successfully entered one of the deeper idle +states. Always return zero instead, indicating that we slept for the +shortest amount of time. + +Signed-off-by: Russell King +--- + drivers/cpuidle/cpuidle-mvebu-v7.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/cpuidle/cpuidle-mvebu-v7.c ++++ b/drivers/cpuidle/cpuidle-mvebu-v7.c +@@ -39,8 +39,12 @@ static int mvebu_v7_enter_idle(struct cp + ret = mvebu_v7_cpu_suspend(deepidle); + cpu_pm_exit(); + ++ /* ++ * If we failed to enter the desired state, indicate that we ++ * slept lightly. ++ */ + if (ret) +- return ret; ++ return 0; + + return index; + } diff --git a/target/linux/mvebu/patches-6.1/801-pci-mvebu-time-out-reset-on-link-up.patch b/target/linux/mvebu/patches-6.1/801-pci-mvebu-time-out-reset-on-link-up.patch new file mode 100644 index 0000000000..dba1253699 --- /dev/null +++ b/target/linux/mvebu/patches-6.1/801-pci-mvebu-time-out-reset-on-link-up.patch @@ -0,0 +1,60 @@ +From 287b9df160b6159f8d385424904f8bac501280c1 Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Sat, 9 Jul 2016 10:58:16 +0100 +Subject: pci: mvebu: time out reset on link up + +If the port reports that the link is up while we are resetting, there's +little point in waiting for the full duration. + +Signed-off-by: Russell King +--- + drivers/pci/controller/pci-mvebu.c | 20 ++++++++++++++------ + 1 file changed, 14 insertions(+), 6 deletions(-) + +--- a/drivers/pci/controller/pci-mvebu.c ++++ b/drivers/pci/controller/pci-mvebu.c +@@ -1023,6 +1023,7 @@ static int mvebu_pcie_powerup(struct mve + + if (port->reset_gpio) { + u32 reset_udelay = PCI_PM_D3COLD_WAIT * 1000; ++ unsigned int i; + + of_property_read_u32(port->dn, "reset-delay-us", + &reset_udelay); +@@ -1030,7 +1031,13 @@ static int mvebu_pcie_powerup(struct mve + udelay(100); + + gpiod_set_value_cansleep(port->reset_gpio, 0); +- msleep(reset_udelay / 1000); ++ for (i = 0; i < reset_udelay; i += 1000) { ++ if (mvebu_pcie_link_up(port)) ++ break; ++ msleep(1); ++ } ++ ++ printk("%s: reset completed in %dus\n", port->name, i); + } + + return 0; +@@ -1190,15 +1197,16 @@ static int mvebu_pcie_probe(struct platf + if (!child) + continue; + +- ret = mvebu_pcie_powerup(port); +- if (ret < 0) +- continue; +- + port->base = mvebu_pcie_map_registers(pdev, child, port); + if (IS_ERR(port->base)) { + dev_err(dev, "%s: cannot map registers\n", port->name); + port->base = NULL; +- mvebu_pcie_powerdown(port); ++ continue; ++ } ++ ++ ret = mvebu_pcie_powerup(port); ++ if (ret < 0) { ++ port->base = NULL; + continue; + } + diff --git a/target/linux/mvebu/patches-6.1/901-dt-bindings-Add-IEI-vendor-prefix-and-IEI-WT61P803-P.patch b/target/linux/mvebu/patches-6.1/901-dt-bindings-Add-IEI-vendor-prefix-and-IEI-WT61P803-P.patch new file mode 100644 index 0000000000..3446086cad --- /dev/null +++ b/target/linux/mvebu/patches-6.1/901-dt-bindings-Add-IEI-vendor-prefix-and-IEI-WT61P803-P.patch @@ -0,0 +1,218 @@ +From aa4a0ccc41997f2da172165c92803abace43bd1c Mon Sep 17 00:00:00 2001 +From: Luka Kovacic +Date: Tue, 24 Aug 2021 12:44:32 +0000 +Subject: [PATCH 1/7] dt-bindings: Add IEI vendor prefix and IEI WT61P803 + PUZZLE driver bindings + +Add the IEI WT61P803 PUZZLE Device Tree bindings for MFD, HWMON and LED +drivers. A new vendor prefix is also added accordingly for +IEI Integration Corp. + +Signed-off-by: Luka Kovacic +Signed-off-by: Pavo Banicevic +Cc: Luka Perkov +Cc: Robert Marko +--- + .../hwmon/iei,wt61p803-puzzle-hwmon.yaml | 53 ++++++++++++ + .../leds/iei,wt61p803-puzzle-leds.yaml | 39 +++++++++ + .../bindings/mfd/iei,wt61p803-puzzle.yaml | 82 +++++++++++++++++++ + .../devicetree/bindings/vendor-prefixes.yaml | 2 + + 4 files changed, 176 insertions(+) + create mode 100644 Documentation/devicetree/bindings/hwmon/iei,wt61p803-puzzle-hwmon.yaml + create mode 100644 Documentation/devicetree/bindings/leds/iei,wt61p803-puzzle-leds.yaml + create mode 100644 Documentation/devicetree/bindings/mfd/iei,wt61p803-puzzle.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/hwmon/iei,wt61p803-puzzle-hwmon.yaml +@@ -0,0 +1,53 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/hwmon/iei,wt61p803-puzzle-hwmon.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: IEI WT61P803 PUZZLE MCU HWMON module from IEI Integration Corp. ++ ++maintainers: ++ - Luka Kovacic ++ ++description: | ++ This module is a part of the IEI WT61P803 PUZZLE MFD device. For more details ++ see Documentation/devicetree/bindings/mfd/iei,wt61p803-puzzle.yaml. ++ ++ The HWMON module is a sub-node of the MCU node in the Device Tree. ++ ++properties: ++ compatible: ++ const: iei,wt61p803-puzzle-hwmon ++ ++ "#address-cells": ++ const: 1 ++ ++ "#size-cells": ++ const: 0 ++ ++patternProperties: ++ "^fan-group@[0-1]$": ++ type: object ++ properties: ++ reg: ++ minimum: 0 ++ maximum: 1 ++ description: ++ Fan group ID ++ ++ cooling-levels: ++ minItems: 1 ++ maxItems: 255 ++ description: ++ Cooling levels for the fans (PWM value mapping) ++ description: | ++ Properties for each fan group. ++ required: ++ - reg ++ ++required: ++ - compatible ++ - "#address-cells" ++ - "#size-cells" ++ ++additionalProperties: false +--- /dev/null ++++ b/Documentation/devicetree/bindings/leds/iei,wt61p803-puzzle-leds.yaml +@@ -0,0 +1,39 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/leds/iei,wt61p803-puzzle-leds.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: IEI WT61P803 PUZZLE MCU LED module from IEI Integration Corp. ++ ++maintainers: ++ - Luka Kovacic ++ ++description: | ++ This module is a part of the IEI WT61P803 PUZZLE MFD device. For more details ++ see Documentation/devicetree/bindings/mfd/iei,wt61p803-puzzle.yaml. ++ ++ The LED module is a sub-node of the MCU node in the Device Tree. ++ ++properties: ++ compatible: ++ const: iei,wt61p803-puzzle-leds ++ ++ "#address-cells": ++ const: 1 ++ ++ "#size-cells": ++ const: 0 ++ ++ led@0: ++ type: object ++ $ref: common.yaml ++ description: | ++ Properties for a single LED. ++ ++required: ++ - compatible ++ - "#address-cells" ++ - "#size-cells" ++ ++additionalProperties: false +--- /dev/null ++++ b/Documentation/devicetree/bindings/mfd/iei,wt61p803-puzzle.yaml +@@ -0,0 +1,82 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/mfd/iei,wt61p803-puzzle.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: IEI WT61P803 PUZZLE MCU from IEI Integration Corp. ++ ++maintainers: ++ - Luka Kovacic ++ ++description: | ++ IEI WT61P803 PUZZLE MCU is embedded in some IEI Puzzle series boards. ++ It's used for controlling system power states, fans, LEDs and temperature ++ sensors. ++ ++ For Device Tree bindings of other sub-modules (HWMON, LEDs) refer to the ++ binding documents under the respective subsystem directories. ++ ++properties: ++ compatible: ++ const: iei,wt61p803-puzzle ++ ++ current-speed: ++ description: ++ Serial bus speed in bps ++ maxItems: 1 ++ ++ enable-beep: true ++ ++ hwmon: ++ $ref: /schemas/hwmon/iei,wt61p803-puzzle-hwmon.yaml ++ ++ leds: ++ $ref: /schemas/leds/iei,wt61p803-puzzle-leds.yaml ++ ++required: ++ - compatible ++ - current-speed ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ serial { ++ mcu { ++ compatible = "iei,wt61p803-puzzle"; ++ current-speed = <115200>; ++ enable-beep; ++ ++ leds { ++ compatible = "iei,wt61p803-puzzle-leds"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ led@0 { ++ reg = <0>; ++ function = LED_FUNCTION_POWER; ++ color = ; ++ }; ++ }; ++ ++ hwmon { ++ compatible = "iei,wt61p803-puzzle-hwmon"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ fan-group@0 { ++ #cooling-cells = <2>; ++ reg = <0x00>; ++ cooling-levels = <64 102 170 230 250>; ++ }; ++ ++ fan-group@1 { ++ #cooling-cells = <2>; ++ reg = <0x01>; ++ cooling-levels = <64 102 170 230 250>; ++ }; ++ }; ++ }; ++ }; +--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml ++++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml +@@ -519,6 +519,8 @@ patternProperties: + description: IC Plus Corp. + "^idt,.*": + description: Integrated Device Technologies, Inc. ++ "^iei,.*": ++ description: IEI Integration Corp. + "^ifi,.*": + description: Ingenieurburo Fur Ic-Technologie (I/F/I) + "^ilitek,.*": diff --git a/target/linux/mvebu/patches-6.1/902-drivers-mfd-Add-a-driver-for-IEI-WT61P803-PUZZLE-MCU.patch b/target/linux/mvebu/patches-6.1/902-drivers-mfd-Add-a-driver-for-IEI-WT61P803-PUZZLE-MCU.patch new file mode 100644 index 0000000000..0e546b426e --- /dev/null +++ b/target/linux/mvebu/patches-6.1/902-drivers-mfd-Add-a-driver-for-IEI-WT61P803-PUZZLE-MCU.patch @@ -0,0 +1,1034 @@ +From 692cfa85272dd12995b427c0a7a585ced5d54f32 Mon Sep 17 00:00:00 2001 +From: Luka Kovacic +Date: Tue, 24 Aug 2021 12:44:33 +0000 +Subject: [PATCH 2/7] drivers: mfd: Add a driver for IEI WT61P803 PUZZLE MCU + +Add a driver for the IEI WT61P803 PUZZLE microcontroller, used in some +IEI Puzzle series devices. The microcontroller controls system power, +temperature sensors, fans and LEDs. + +This driver implements the core functionality for device communication +over the system serial (serdev bus). It handles MCU messages and the +internal MCU properties. Some properties can be managed over sysfs. + +Signed-off-by: Luka Kovacic +Signed-off-by: Pavo Banicevic +Cc: Luka Perkov +Cc: Robert Marko +--- + drivers/mfd/Kconfig | 8 + + drivers/mfd/Makefile | 1 + + drivers/mfd/iei-wt61p803-puzzle.c | 908 ++++++++++++++++++++++++ + include/linux/mfd/iei-wt61p803-puzzle.h | 66 ++ + 4 files changed, 983 insertions(+) + create mode 100644 drivers/mfd/iei-wt61p803-puzzle.c + create mode 100644 include/linux/mfd/iei-wt61p803-puzzle.h + +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -2189,6 +2189,15 @@ config SGI_MFD_IOC3 + If you have an SGI Origin, Octane, or a PCI IOC3 card, + then say Y. Otherwise say N. + ++config MFD_IEI_WT61P803_PUZZLE ++ tristate "IEI WT61P803 PUZZLE MCU driver" ++ depends on SERIAL_DEV_BUS ++ select MFD_CORE ++ help ++ IEI WT61P803 PUZZLE is a system power management microcontroller ++ used for fan control, temperature sensor reading, LED control ++ and system identification. ++ + config MFD_INTEL_M10_BMC + tristate "Intel MAX 10 Board Management Controller" + depends on SPI_MASTER +--- a/drivers/mfd/Makefile ++++ b/drivers/mfd/Makefile +@@ -237,6 +237,7 @@ obj-$(CONFIG_MFD_DLN2) += dln2.o + obj-$(CONFIG_MFD_RT4831) += rt4831.o + obj-$(CONFIG_MFD_RT5033) += rt5033.o + obj-$(CONFIG_MFD_SKY81452) += sky81452.o ++obj-$(CONFIG_MFD_IEI_WT61P803_PUZZLE) += iei-wt61p803-puzzle.o + + intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o + obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o +--- /dev/null ++++ b/drivers/mfd/iei-wt61p803-puzzle.c +@@ -0,0 +1,908 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* IEI WT61P803 PUZZLE MCU Driver ++ * System management microcontroller for fan control, temperature sensor reading, ++ * LED control and system identification on IEI Puzzle series ARM-based appliances. ++ * ++ * Copyright (C) 2020 Sartura Ltd. ++ * Author: Luka Kovacic ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* start, payload and XOR checksum at end */ ++#define IEI_WT61P803_PUZZLE_MAX_COMMAND_LENGTH (1 + 20 + 1) ++#define IEI_WT61P803_PUZZLE_RESP_BUF_SIZE 512 ++ ++#define IEI_WT61P803_PUZZLE_MAC_LENGTH 17 ++#define IEI_WT61P803_PUZZLE_SN_LENGTH 36 ++#define IEI_WT61P803_PUZZLE_VERSION_LENGTH 6 ++#define IEI_WT61P803_PUZZLE_BUILD_INFO_LENGTH 16 ++#define IEI_WT61P803_PUZZLE_PROTOCOL_VERSION_LENGTH 8 ++#define IEI_WT61P803_PUZZLE_NB_MAC 8 ++ ++/* Use HZ as a timeout value throughout the driver */ ++#define IEI_WT61P803_PUZZLE_GENERAL_TIMEOUT HZ ++ ++enum iei_wt61p803_puzzle_attribute_type { ++ IEI_WT61P803_PUZZLE_VERSION, ++ IEI_WT61P803_PUZZLE_BUILD_INFO, ++ IEI_WT61P803_PUZZLE_BOOTLOADER_MODE, ++ IEI_WT61P803_PUZZLE_PROTOCOL_VERSION, ++ IEI_WT61P803_PUZZLE_SERIAL_NUMBER, ++ IEI_WT61P803_PUZZLE_MAC_ADDRESS, ++ IEI_WT61P803_PUZZLE_AC_RECOVERY_STATUS, ++ IEI_WT61P803_PUZZLE_POWER_LOSS_RECOVERY, ++ IEI_WT61P803_PUZZLE_POWER_STATUS, ++}; ++ ++struct iei_wt61p803_puzzle_device_attribute { ++ struct device_attribute dev_attr; ++ enum iei_wt61p803_puzzle_attribute_type type; ++ u8 index; ++}; ++ ++/** ++ * struct iei_wt61p803_puzzle_mcu_status - MCU flags state ++ * @ac_recovery_status_flag: AC Recovery Status Flag ++ * @power_loss_recovery: System recovery after power loss ++ * @power_status: System Power-on Method ++ */ ++struct iei_wt61p803_puzzle_mcu_status { ++ u8 ac_recovery_status_flag; ++ u8 power_loss_recovery; ++ u8 power_status; ++}; ++ ++/** ++ * struct iei_wt61p803_puzzle_reply - MCU reply ++ * @size: Size of the MCU reply ++ * @data: Full MCU reply buffer ++ * @state: Current state of the packet ++ * @received: Was the response fullfilled ++ */ ++struct iei_wt61p803_puzzle_reply { ++ size_t size; ++ unsigned char data[IEI_WT61P803_PUZZLE_RESP_BUF_SIZE]; ++ struct completion received; ++}; ++ ++/** ++ * struct iei_wt61p803_puzzle_mcu_version - MCU version status ++ * @version: Primary firmware version ++ * @build_info: Build date and time ++ * @bootloader_mode: Status of the MCU operation ++ * @protocol_version: MCU communication protocol version ++ * @serial_number: Device factory serial number ++ * @mac_address: Device factory MAC addresses ++ * ++ * Last element of arrays is reserved for '\0'. ++ */ ++struct iei_wt61p803_puzzle_mcu_version { ++ char version[IEI_WT61P803_PUZZLE_VERSION_LENGTH + 1]; ++ char build_info[IEI_WT61P803_PUZZLE_BUILD_INFO_LENGTH + 1]; ++ bool bootloader_mode; ++ char protocol_version[IEI_WT61P803_PUZZLE_PROTOCOL_VERSION_LENGTH + 1]; ++ char serial_number[IEI_WT61P803_PUZZLE_SN_LENGTH + 1]; ++ char mac_address[IEI_WT61P803_PUZZLE_NB_MAC][IEI_WT61P803_PUZZLE_MAC_LENGTH + 1]; ++}; ++ ++/** ++ * struct iei_wt61p803_puzzle - IEI WT61P803 PUZZLE MCU Driver ++ * @serdev: Pointer to underlying serdev device ++ * @dev: Pointer to underlying dev device ++ * @reply_lock: Reply mutex lock ++ * @reply: Pointer to the iei_wt61p803_puzzle_reply struct ++ * @version: MCU version related data ++ * @status: MCU status related data ++ * @response_buffer Command response buffer allocation ++ * @lock General member mutex lock ++ */ ++struct iei_wt61p803_puzzle { ++ struct serdev_device *serdev; ++ struct device *dev; ++ struct mutex reply_lock; /* lock to prevent multiple firmware calls */ ++ struct iei_wt61p803_puzzle_reply *reply; ++ struct iei_wt61p803_puzzle_mcu_version version; ++ struct iei_wt61p803_puzzle_mcu_status status; ++ unsigned char response_buffer[IEI_WT61P803_PUZZLE_BUF_SIZE]; ++ struct mutex lock; /* lock to protect response buffer */ ++}; ++ ++static unsigned char iei_wt61p803_puzzle_checksum(unsigned char *buf, size_t len) ++{ ++ unsigned char checksum = 0; ++ size_t i; ++ ++ for (i = 0; i < len; i++) ++ checksum ^= buf[i]; ++ return checksum; ++} ++ ++static int iei_wt61p803_puzzle_process_resp(struct iei_wt61p803_puzzle *mcu, ++ const unsigned char *raw_resp_data, size_t size) ++{ ++ unsigned char checksum; ++ ++ /* Check the incoming frame header */ ++ if (!(raw_resp_data[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START || ++ raw_resp_data[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START_OTHER || ++ (raw_resp_data[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_EEPROM && ++ raw_resp_data[1] == IEI_WT61P803_PUZZLE_CMD_EEPROM_READ))) { ++ if (mcu->reply->size + size >= sizeof(mcu->reply->data)) ++ return -EIO; ++ ++ /* Append the frame to existing data */ ++ memcpy(mcu->reply->data + mcu->reply->size, raw_resp_data, size); ++ mcu->reply->size += size; ++ } else { ++ if (size >= sizeof(mcu->reply->data)) ++ return -EIO; ++ ++ /* Start processing a new frame */ ++ memcpy(mcu->reply->data, raw_resp_data, size); ++ mcu->reply->size = size; ++ } ++ ++ checksum = iei_wt61p803_puzzle_checksum(mcu->reply->data, mcu->reply->size - 1); ++ if (checksum != mcu->reply->data[mcu->reply->size - 1]) { ++ /* The checksum isn't matched yet, wait for new frames */ ++ return size; ++ } ++ ++ /* Received all the data */ ++ complete(&mcu->reply->received); ++ ++ return size; ++} ++ ++static int iei_wt61p803_puzzle_recv_buf(struct serdev_device *serdev, ++ const unsigned char *data, size_t size) ++{ ++ struct iei_wt61p803_puzzle *mcu = serdev_device_get_drvdata(serdev); ++ int ret; ++ ++ ret = iei_wt61p803_puzzle_process_resp(mcu, data, size); ++ /* Return the number of processed bytes if function returns error, ++ * discard the remaining incoming data, since the frame this data ++ * belongs to is broken anyway ++ */ ++ if (ret < 0) ++ return size; ++ ++ return ret; ++} ++ ++static const struct serdev_device_ops iei_wt61p803_puzzle_serdev_device_ops = { ++ .receive_buf = iei_wt61p803_puzzle_recv_buf, ++ .write_wakeup = serdev_device_write_wakeup, ++}; ++ ++/** ++ * iei_wt61p803_puzzle_write_command_watchdog() - Watchdog of the normal cmd ++ * @mcu: Pointer to the iei_wt61p803_puzzle core MFD struct ++ * @cmd: Pointer to the char array to send (size should be content + 1 (xor)) ++ * @size: Size of the cmd char array ++ * @reply_data: Pointer to the reply/response data array (should be allocated) ++ * @reply_size: Pointer to size_t (size of reply_data) ++ * @retry_count: Number of times to retry sending the command to the MCU ++ */ ++int iei_wt61p803_puzzle_write_command_watchdog(struct iei_wt61p803_puzzle *mcu, ++ unsigned char *cmd, size_t size, ++ unsigned char *reply_data, ++ size_t *reply_size, int retry_count) ++{ ++ struct device *dev = &mcu->serdev->dev; ++ int ret, i; ++ ++ for (i = 0; i < retry_count; i++) { ++ ret = iei_wt61p803_puzzle_write_command(mcu, cmd, size, ++ reply_data, reply_size); ++ if (ret != -ETIMEDOUT) ++ return ret; ++ } ++ ++ dev_err(dev, "Command response timed out. Retries: %d\n", retry_count); ++ ++ return -ETIMEDOUT; ++} ++EXPORT_SYMBOL_GPL(iei_wt61p803_puzzle_write_command_watchdog); ++ ++/** ++ * iei_wt61p803_puzzle_write_command() - Send a structured command to the MCU ++ * @mcu: Pointer to the iei_wt61p803_puzzle core MFD struct ++ * @cmd: Pointer to the char array to send (size should be content + 1 (xor)) ++ * @size: Size of the cmd char array ++ * @reply_data: Pointer to the reply/response data array (should be allocated) ++ * ++ * Sends a structured command to the MCU. ++ */ ++int iei_wt61p803_puzzle_write_command(struct iei_wt61p803_puzzle *mcu, ++ unsigned char *cmd, size_t size, ++ unsigned char *reply_data, ++ size_t *reply_size) ++{ ++ struct device *dev = &mcu->serdev->dev; ++ int ret; ++ ++ if (size <= 1 || size > IEI_WT61P803_PUZZLE_MAX_COMMAND_LENGTH) ++ return -EINVAL; ++ ++ mutex_lock(&mcu->reply_lock); ++ ++ cmd[size - 1] = iei_wt61p803_puzzle_checksum(cmd, size - 1); ++ ++ /* Initialize reply struct */ ++ reinit_completion(&mcu->reply->received); ++ mcu->reply->size = 0; ++ usleep_range(2000, 10000); ++ serdev_device_write_flush(mcu->serdev); ++ ret = serdev_device_write_buf(mcu->serdev, cmd, size); ++ if (ret < 0) ++ goto exit; ++ ++ serdev_device_wait_until_sent(mcu->serdev, IEI_WT61P803_PUZZLE_GENERAL_TIMEOUT); ++ ret = wait_for_completion_timeout(&mcu->reply->received, ++ IEI_WT61P803_PUZZLE_GENERAL_TIMEOUT); ++ if (ret == 0) { ++ dev_err(dev, "Command reply receive timeout\n"); ++ ret = -ETIMEDOUT; ++ goto exit; ++ } ++ ++ *reply_size = mcu->reply->size; ++ /* Copy the received data, as it will not be available after a new frame is received */ ++ memcpy(reply_data, mcu->reply->data, mcu->reply->size); ++ ret = 0; ++exit: ++ mutex_unlock(&mcu->reply_lock); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(iei_wt61p803_puzzle_write_command); ++ ++static int iei_wt61p803_puzzle_buzzer(struct iei_wt61p803_puzzle *mcu, bool long_beep) ++{ ++ unsigned char *resp_buf = mcu->response_buffer; ++ unsigned char buzzer_cmd[4] = {}; ++ size_t reply_size; ++ int ret; ++ ++ buzzer_cmd[0] = IEI_WT61P803_PUZZLE_CMD_HEADER_START; ++ buzzer_cmd[1] = IEI_WT61P803_PUZZLE_CMD_FUNCTION_SINGLE; ++ buzzer_cmd[2] = long_beep ? '3' : '2'; /* Buzzer 1.5 / 0.5 second beep */ ++ ++ mutex_lock(&mcu->lock); ++ ret = iei_wt61p803_puzzle_write_command(mcu, buzzer_cmd, sizeof(buzzer_cmd), ++ resp_buf, &reply_size); ++ if (ret) ++ goto exit; ++ ++ if (reply_size != 3) { ++ ret = -EIO; ++ goto exit; ++ } ++ ++ if (!(resp_buf[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START && ++ resp_buf[1] == IEI_WT61P803_PUZZLE_CMD_RESPONSE_OK && ++ resp_buf[2] == IEI_WT61P803_PUZZLE_CHECKSUM_RESPONSE_OK)) { ++ ret = -EPROTO; ++ goto exit; ++ } ++exit: ++ mutex_unlock(&mcu->lock); ++ return ret; ++} ++ ++static int iei_wt61p803_puzzle_get_version(struct iei_wt61p803_puzzle *mcu) ++{ ++ unsigned char version_cmd[3] = { ++ IEI_WT61P803_PUZZLE_CMD_HEADER_START_OTHER, ++ IEI_WT61P803_PUZZLE_CMD_OTHER_VERSION, ++ }; ++ unsigned char build_info_cmd[3] = { ++ IEI_WT61P803_PUZZLE_CMD_HEADER_START_OTHER, ++ IEI_WT61P803_PUZZLE_CMD_OTHER_BUILD, ++ }; ++ unsigned char bootloader_mode_cmd[3] = { ++ IEI_WT61P803_PUZZLE_CMD_HEADER_START_OTHER, ++ IEI_WT61P803_PUZZLE_CMD_OTHER_BOOTLOADER_MODE, ++ }; ++ unsigned char protocol_version_cmd[3] = { ++ IEI_WT61P803_PUZZLE_CMD_HEADER_START_OTHER, ++ IEI_WT61P803_PUZZLE_CMD_OTHER_PROTOCOL_VERSION, ++ }; ++ unsigned char *rb = mcu->response_buffer; ++ size_t reply_size; ++ int ret; ++ ++ mutex_lock(&mcu->lock); ++ ++ ret = iei_wt61p803_puzzle_write_command(mcu, version_cmd, sizeof(version_cmd), ++ rb, &reply_size); ++ if (ret) ++ goto err; ++ if (reply_size < 7) { ++ ret = -EIO; ++ goto err; ++ } ++ sprintf(mcu->version.version, "v%c.%.3s", rb[2], &rb[3]); ++ ++ ret = iei_wt61p803_puzzle_write_command(mcu, build_info_cmd, ++ sizeof(build_info_cmd), rb, ++ &reply_size); ++ if (ret) ++ goto err; ++ if (reply_size < 15) { ++ ret = -EIO; ++ goto err; ++ } ++ sprintf(mcu->version.build_info, "%c%c/%c%c/%.4s %c%c:%c%c", ++ rb[8], rb[9], rb[6], rb[7], &rb[2], rb[10], rb[11], ++ rb[12], rb[13]); ++ ++ ret = iei_wt61p803_puzzle_write_command(mcu, bootloader_mode_cmd, ++ sizeof(bootloader_mode_cmd), rb, ++ &reply_size); ++ if (ret) ++ goto err; ++ if (reply_size < 4) { ++ ret = -EIO; ++ goto err; ++ } ++ if (rb[2] == IEI_WT61P803_PUZZLE_CMD_OTHER_MODE_APPS) ++ mcu->version.bootloader_mode = false; ++ else if (rb[2] == IEI_WT61P803_PUZZLE_CMD_OTHER_MODE_BOOTLOADER) ++ mcu->version.bootloader_mode = true; ++ ++ ret = iei_wt61p803_puzzle_write_command(mcu, protocol_version_cmd, ++ sizeof(protocol_version_cmd), rb, ++ &reply_size); ++ if (ret) ++ goto err; ++ if (reply_size < 9) { ++ ret = -EIO; ++ goto err; ++ } ++ sprintf(mcu->version.protocol_version, "v%c.%c%c%c%c%c", ++ rb[7], rb[6], rb[5], rb[4], rb[3], rb[2]); ++err: ++ mutex_unlock(&mcu->lock); ++ return ret; ++} ++ ++static int iei_wt61p803_puzzle_get_mcu_status(struct iei_wt61p803_puzzle *mcu) ++{ ++ unsigned char mcu_status_cmd[5] = { ++ IEI_WT61P803_PUZZLE_CMD_HEADER_START, ++ IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER, ++ IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_STATUS, ++ IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_STATUS, ++ }; ++ unsigned char *resp_buf = mcu->response_buffer; ++ size_t reply_size; ++ int ret; ++ ++ mutex_lock(&mcu->lock); ++ ret = iei_wt61p803_puzzle_write_command(mcu, mcu_status_cmd, sizeof(mcu_status_cmd), ++ resp_buf, &reply_size); ++ if (ret) ++ goto exit; ++ if (reply_size < 20) { ++ ret = -EIO; ++ goto exit; ++ } ++ ++ /* Response format: ++ * (IDX RESPONSE) ++ * 0 @ ++ * 1 O ++ * 2 S ++ * 3 S ++ * ... ++ * 5 AC Recovery Status Flag ++ * ... ++ * 10 Power Loss Recovery ++ * ... ++ * 19 Power Status (system power on method) ++ * 20 XOR checksum ++ */ ++ if (resp_buf[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START && ++ resp_buf[1] == IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER && ++ resp_buf[2] == IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_STATUS && ++ resp_buf[3] == IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_STATUS) { ++ mcu->status.ac_recovery_status_flag = resp_buf[5]; ++ mcu->status.power_loss_recovery = resp_buf[10]; ++ mcu->status.power_status = resp_buf[19]; ++ } ++exit: ++ mutex_unlock(&mcu->lock); ++ return ret; ++} ++ ++static int iei_wt61p803_puzzle_get_serial_number(struct iei_wt61p803_puzzle *mcu) ++{ ++ unsigned char *resp_buf = mcu->response_buffer; ++ unsigned char serial_number_cmd[5] = { ++ IEI_WT61P803_PUZZLE_CMD_HEADER_EEPROM, ++ IEI_WT61P803_PUZZLE_CMD_EEPROM_READ, ++ 0x00, /* EEPROM read address */ ++ 0x24, /* Data length */ ++ }; ++ size_t reply_size; ++ int ret; ++ ++ mutex_lock(&mcu->lock); ++ ret = iei_wt61p803_puzzle_write_command(mcu, serial_number_cmd, ++ sizeof(serial_number_cmd), ++ resp_buf, &reply_size); ++ if (ret) ++ goto err; ++ ++ if (reply_size < IEI_WT61P803_PUZZLE_SN_LENGTH + 4) { ++ ret = -EIO; ++ goto err; ++ } ++ ++ sprintf(mcu->version.serial_number, "%.*s", ++ IEI_WT61P803_PUZZLE_SN_LENGTH, resp_buf + 4); ++err: ++ mutex_unlock(&mcu->lock); ++ return ret; ++} ++ ++static int iei_wt61p803_puzzle_write_serial_number(struct iei_wt61p803_puzzle *mcu, ++ unsigned char serial_number[36]) ++{ ++ unsigned char *resp_buf = mcu->response_buffer; ++ unsigned char serial_number_header[4] = { ++ IEI_WT61P803_PUZZLE_CMD_HEADER_EEPROM, ++ IEI_WT61P803_PUZZLE_CMD_EEPROM_WRITE, ++ 0x00, /* EEPROM write address */ ++ 0xC, /* Data length */ ++ }; ++ unsigned char serial_number_cmd[4 + 12 + 1]; /* header, serial number, XOR checksum */ ++ int ret, sn_counter; ++ size_t reply_size; ++ ++ /* The MCU can only handle 22 byte messages, send the S/N in 12 byte chunks */ ++ mutex_lock(&mcu->lock); ++ for (sn_counter = 0; sn_counter < 3; sn_counter++) { ++ serial_number_header[2] = 0x0 + 0xC * sn_counter; ++ ++ memcpy(serial_number_cmd, serial_number_header, sizeof(serial_number_header)); ++ memcpy(serial_number_cmd + sizeof(serial_number_header), ++ serial_number + 0xC * sn_counter, 0xC); ++ ++ ret = iei_wt61p803_puzzle_write_command(mcu, serial_number_cmd, ++ sizeof(serial_number_cmd), ++ resp_buf, &reply_size); ++ if (ret) ++ goto err; ++ if (reply_size != 3) { ++ ret = -EIO; ++ goto err; ++ } ++ if (!(resp_buf[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START && ++ resp_buf[1] == IEI_WT61P803_PUZZLE_CMD_RESPONSE_OK && ++ resp_buf[2] == IEI_WT61P803_PUZZLE_CHECKSUM_RESPONSE_OK)) { ++ ret = -EPROTO; ++ goto err; ++ } ++ } ++ ++ sprintf(mcu->version.serial_number, "%.*s", ++ IEI_WT61P803_PUZZLE_SN_LENGTH, serial_number); ++err: ++ mutex_unlock(&mcu->lock); ++ return ret; ++} ++ ++static int iei_wt61p803_puzzle_get_mac_address(struct iei_wt61p803_puzzle *mcu, int index) ++{ ++ unsigned char *resp_buf = mcu->response_buffer; ++ unsigned char mac_address_cmd[5] = { ++ IEI_WT61P803_PUZZLE_CMD_HEADER_EEPROM, ++ IEI_WT61P803_PUZZLE_CMD_EEPROM_READ, ++ 0x00, /* EEPROM read address */ ++ 0x11, /* Data length */ ++ }; ++ size_t reply_size; ++ int ret; ++ ++ mutex_lock(&mcu->lock); ++ mac_address_cmd[2] = 0x24 + 0x11 * index; ++ ++ ret = iei_wt61p803_puzzle_write_command(mcu, mac_address_cmd, ++ sizeof(mac_address_cmd), ++ resp_buf, &reply_size); ++ if (ret) ++ goto err; ++ ++ if (reply_size < 22) { ++ ret = -EIO; ++ goto err; ++ } ++ ++ sprintf(mcu->version.mac_address[index], "%.*s", ++ IEI_WT61P803_PUZZLE_MAC_LENGTH, resp_buf + 4); ++err: ++ mutex_unlock(&mcu->lock); ++ return ret; ++} ++ ++static int ++iei_wt61p803_puzzle_write_mac_address(struct iei_wt61p803_puzzle *mcu, ++ unsigned char mac_address[IEI_WT61P803_PUZZLE_MAC_LENGTH], ++ int mac_address_idx) ++{ ++ unsigned char mac_address_cmd[4 + IEI_WT61P803_PUZZLE_MAC_LENGTH + 1]; ++ unsigned char *resp_buf = mcu->response_buffer; ++ unsigned char mac_address_header[4] = { ++ IEI_WT61P803_PUZZLE_CMD_HEADER_EEPROM, ++ IEI_WT61P803_PUZZLE_CMD_EEPROM_WRITE, ++ 0x00, /* EEPROM write address */ ++ 0x11, /* Data length */ ++ }; ++ size_t reply_size; ++ int ret; ++ ++ if (mac_address_idx < 0 || mac_address_idx >= IEI_WT61P803_PUZZLE_NB_MAC) ++ return -EINVAL; ++ ++ mac_address_header[2] = 0x24 + 0x11 * mac_address_idx; ++ ++ /* Concat mac_address_header, mac_address to mac_address_cmd */ ++ memcpy(mac_address_cmd, mac_address_header, sizeof(mac_address_header)); ++ memcpy(mac_address_cmd + sizeof(mac_address_header), mac_address, ++ IEI_WT61P803_PUZZLE_MAC_LENGTH); ++ ++ mutex_lock(&mcu->lock); ++ ret = iei_wt61p803_puzzle_write_command(mcu, mac_address_cmd, ++ sizeof(mac_address_cmd), ++ resp_buf, &reply_size); ++ if (ret) ++ goto err; ++ if (reply_size != 3) { ++ ret = -EIO; ++ goto err; ++ } ++ if (!(resp_buf[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START && ++ resp_buf[1] == IEI_WT61P803_PUZZLE_CMD_RESPONSE_OK && ++ resp_buf[2] == IEI_WT61P803_PUZZLE_CHECKSUM_RESPONSE_OK)) { ++ ret = -EPROTO; ++ goto err; ++ } ++ ++ sprintf(mcu->version.mac_address[mac_address_idx], "%.*s", ++ IEI_WT61P803_PUZZLE_MAC_LENGTH, mac_address); ++err: ++ mutex_unlock(&mcu->lock); ++ return ret; ++} ++ ++static int iei_wt61p803_puzzle_write_power_loss_recovery(struct iei_wt61p803_puzzle *mcu, ++ int power_loss_recovery_action) ++{ ++ unsigned char *resp_buf = mcu->response_buffer; ++ unsigned char power_loss_recovery_cmd[5] = {}; ++ size_t reply_size; ++ int ret; ++ ++ if (power_loss_recovery_action < 0 || power_loss_recovery_action > 4) ++ return -EINVAL; ++ ++ power_loss_recovery_cmd[0] = IEI_WT61P803_PUZZLE_CMD_HEADER_START; ++ power_loss_recovery_cmd[1] = IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER; ++ power_loss_recovery_cmd[2] = IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_POWER_LOSS; ++ power_loss_recovery_cmd[3] = hex_asc[power_loss_recovery_action]; ++ ++ mutex_lock(&mcu->lock); ++ ret = iei_wt61p803_puzzle_write_command(mcu, power_loss_recovery_cmd, ++ sizeof(power_loss_recovery_cmd), ++ resp_buf, &reply_size); ++ if (ret) ++ goto exit; ++ mcu->status.power_loss_recovery = power_loss_recovery_action; ++exit: ++ mutex_unlock(&mcu->lock); ++ return ret; ++} ++ ++#define to_puzzle_dev_attr(_attr) \ ++ container_of(_attr, struct iei_wt61p803_puzzle_device_attribute, dev_attr) ++ ++static ssize_t show_output(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev); ++ struct iei_wt61p803_puzzle_device_attribute *pattr = to_puzzle_dev_attr(attr); ++ int ret; ++ ++ switch (pattr->type) { ++ case IEI_WT61P803_PUZZLE_VERSION: ++ return scnprintf(buf, PAGE_SIZE, "%s\n", mcu->version.version); ++ case IEI_WT61P803_PUZZLE_BUILD_INFO: ++ return scnprintf(buf, PAGE_SIZE, "%s\n", mcu->version.build_info); ++ case IEI_WT61P803_PUZZLE_BOOTLOADER_MODE: ++ return scnprintf(buf, PAGE_SIZE, "%d\n", mcu->version.bootloader_mode); ++ case IEI_WT61P803_PUZZLE_PROTOCOL_VERSION: ++ return scnprintf(buf, PAGE_SIZE, "%s\n", mcu->version.protocol_version); ++ case IEI_WT61P803_PUZZLE_SERIAL_NUMBER: ++ ret = iei_wt61p803_puzzle_get_serial_number(mcu); ++ if (!ret) ++ ret = scnprintf(buf, PAGE_SIZE, "%s\n", mcu->version.serial_number); ++ else ++ ret = 0; ++ return ret; ++ case IEI_WT61P803_PUZZLE_MAC_ADDRESS: ++ ret = iei_wt61p803_puzzle_get_mac_address(mcu, pattr->index); ++ if (!ret) ++ ret = scnprintf(buf, PAGE_SIZE, "%s\n", ++ mcu->version.mac_address[pattr->index]); ++ else ++ ret = 0; ++ return ret; ++ case IEI_WT61P803_PUZZLE_AC_RECOVERY_STATUS: ++ case IEI_WT61P803_PUZZLE_POWER_LOSS_RECOVERY: ++ case IEI_WT61P803_PUZZLE_POWER_STATUS: ++ ret = iei_wt61p803_puzzle_get_mcu_status(mcu); ++ if (ret) ++ return ret; ++ ++ mutex_lock(&mcu->lock); ++ switch (pattr->type) { ++ case IEI_WT61P803_PUZZLE_AC_RECOVERY_STATUS: ++ ret = scnprintf(buf, PAGE_SIZE, "%x\n", ++ mcu->status.ac_recovery_status_flag); ++ break; ++ case IEI_WT61P803_PUZZLE_POWER_LOSS_RECOVERY: ++ ret = scnprintf(buf, PAGE_SIZE, "%x\n", mcu->status.power_loss_recovery); ++ break; ++ case IEI_WT61P803_PUZZLE_POWER_STATUS: ++ ret = scnprintf(buf, PAGE_SIZE, "%x\n", mcu->status.power_status); ++ break; ++ default: ++ ret = 0; ++ break; ++ } ++ mutex_unlock(&mcu->lock); ++ return ret; ++ default: ++ return 0; ++ } ++ ++ return 0; ++} ++ ++static ssize_t store_output(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t len) ++{ ++ unsigned char serial_number[IEI_WT61P803_PUZZLE_SN_LENGTH]; ++ unsigned char mac_address[IEI_WT61P803_PUZZLE_MAC_LENGTH]; ++ struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev); ++ struct iei_wt61p803_puzzle_device_attribute *pattr = to_puzzle_dev_attr(attr); ++ int power_loss_recovery_action = 0; ++ int ret; ++ ++ switch (pattr->type) { ++ case IEI_WT61P803_PUZZLE_SERIAL_NUMBER: ++ if (len != (size_t)(IEI_WT61P803_PUZZLE_SN_LENGTH + 1)) ++ return -EINVAL; ++ memcpy(serial_number, buf, sizeof(serial_number)); ++ ret = iei_wt61p803_puzzle_write_serial_number(mcu, serial_number); ++ if (ret) ++ return ret; ++ return len; ++ case IEI_WT61P803_PUZZLE_MAC_ADDRESS: ++ if (len != (size_t)(IEI_WT61P803_PUZZLE_MAC_LENGTH + 1)) ++ return -EINVAL; ++ ++ memcpy(mac_address, buf, sizeof(mac_address)); ++ ++ if (strlen(attr->attr.name) != 13) ++ return -EIO; ++ ++ ret = iei_wt61p803_puzzle_write_mac_address(mcu, mac_address, pattr->index); ++ if (ret) ++ return ret; ++ return len; ++ case IEI_WT61P803_PUZZLE_POWER_LOSS_RECOVERY: ++ ret = kstrtoint(buf, 10, &power_loss_recovery_action); ++ if (ret) ++ return ret; ++ ret = iei_wt61p803_puzzle_write_power_loss_recovery(mcu, ++ power_loss_recovery_action); ++ if (ret) ++ return ret; ++ return len; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++#define IEI_WT61P803_PUZZLE_ATTR(_name, _mode, _show, _store, _type, _index) \ ++ struct iei_wt61p803_puzzle_device_attribute dev_attr_##_name = \ ++ { .dev_attr = __ATTR(_name, _mode, _show, _store), \ ++ .type = _type, \ ++ .index = _index } ++ ++#define IEI_WT61P803_PUZZLE_ATTR_RO(_name, _type, _id) \ ++ IEI_WT61P803_PUZZLE_ATTR(_name, 0444, show_output, NULL, _type, _id) ++ ++#define IEI_WT61P803_PUZZLE_ATTR_RW(_name, _type, _id) \ ++ IEI_WT61P803_PUZZLE_ATTR(_name, 0644, show_output, store_output, _type, _id) ++ ++static IEI_WT61P803_PUZZLE_ATTR_RO(version, IEI_WT61P803_PUZZLE_VERSION, 0); ++static IEI_WT61P803_PUZZLE_ATTR_RO(build_info, IEI_WT61P803_PUZZLE_BUILD_INFO, 0); ++static IEI_WT61P803_PUZZLE_ATTR_RO(bootloader_mode, IEI_WT61P803_PUZZLE_BOOTLOADER_MODE, 0); ++static IEI_WT61P803_PUZZLE_ATTR_RO(protocol_version, IEI_WT61P803_PUZZLE_PROTOCOL_VERSION, 0); ++static IEI_WT61P803_PUZZLE_ATTR_RW(serial_number, IEI_WT61P803_PUZZLE_SERIAL_NUMBER, 0); ++static IEI_WT61P803_PUZZLE_ATTR_RW(mac_address_0, IEI_WT61P803_PUZZLE_MAC_ADDRESS, 0); ++static IEI_WT61P803_PUZZLE_ATTR_RW(mac_address_1, IEI_WT61P803_PUZZLE_MAC_ADDRESS, 1); ++static IEI_WT61P803_PUZZLE_ATTR_RW(mac_address_2, IEI_WT61P803_PUZZLE_MAC_ADDRESS, 2); ++static IEI_WT61P803_PUZZLE_ATTR_RW(mac_address_3, IEI_WT61P803_PUZZLE_MAC_ADDRESS, 3); ++static IEI_WT61P803_PUZZLE_ATTR_RW(mac_address_4, IEI_WT61P803_PUZZLE_MAC_ADDRESS, 4); ++static IEI_WT61P803_PUZZLE_ATTR_RW(mac_address_5, IEI_WT61P803_PUZZLE_MAC_ADDRESS, 5); ++static IEI_WT61P803_PUZZLE_ATTR_RW(mac_address_6, IEI_WT61P803_PUZZLE_MAC_ADDRESS, 6); ++static IEI_WT61P803_PUZZLE_ATTR_RW(mac_address_7, IEI_WT61P803_PUZZLE_MAC_ADDRESS, 7); ++static IEI_WT61P803_PUZZLE_ATTR_RO(ac_recovery_status, IEI_WT61P803_PUZZLE_AC_RECOVERY_STATUS, 0); ++static IEI_WT61P803_PUZZLE_ATTR_RW(power_loss_recovery, IEI_WT61P803_PUZZLE_POWER_LOSS_RECOVERY, 0); ++static IEI_WT61P803_PUZZLE_ATTR_RO(power_status, IEI_WT61P803_PUZZLE_POWER_STATUS, 0); ++ ++static struct attribute *iei_wt61p803_puzzle_attrs[] = { ++ &dev_attr_version.dev_attr.attr, ++ &dev_attr_build_info.dev_attr.attr, ++ &dev_attr_bootloader_mode.dev_attr.attr, ++ &dev_attr_protocol_version.dev_attr.attr, ++ &dev_attr_serial_number.dev_attr.attr, ++ &dev_attr_mac_address_0.dev_attr.attr, ++ &dev_attr_mac_address_1.dev_attr.attr, ++ &dev_attr_mac_address_2.dev_attr.attr, ++ &dev_attr_mac_address_3.dev_attr.attr, ++ &dev_attr_mac_address_4.dev_attr.attr, ++ &dev_attr_mac_address_5.dev_attr.attr, ++ &dev_attr_mac_address_6.dev_attr.attr, ++ &dev_attr_mac_address_7.dev_attr.attr, ++ &dev_attr_ac_recovery_status.dev_attr.attr, ++ &dev_attr_power_loss_recovery.dev_attr.attr, ++ &dev_attr_power_status.dev_attr.attr, ++ NULL ++}; ++ATTRIBUTE_GROUPS(iei_wt61p803_puzzle); ++ ++static int iei_wt61p803_puzzle_sysfs_create(struct device *dev, ++ struct iei_wt61p803_puzzle *mcu) ++{ ++ int ret; ++ ++ ret = sysfs_create_groups(&mcu->dev->kobj, iei_wt61p803_puzzle_groups); ++ if (ret) ++ mfd_remove_devices(mcu->dev); ++ ++ return ret; ++} ++ ++static int iei_wt61p803_puzzle_sysfs_remove(struct device *dev, ++ struct iei_wt61p803_puzzle *mcu) ++{ ++ /* Remove sysfs groups */ ++ sysfs_remove_groups(&mcu->dev->kobj, iei_wt61p803_puzzle_groups); ++ mfd_remove_devices(mcu->dev); ++ ++ return 0; ++} ++ ++static int iei_wt61p803_puzzle_probe(struct serdev_device *serdev) ++{ ++ struct device *dev = &serdev->dev; ++ struct iei_wt61p803_puzzle *mcu; ++ u32 baud; ++ int ret; ++ ++ /* Read the baud rate from 'current-speed', because the MCU supports different rates */ ++ if (device_property_read_u32(dev, "current-speed", &baud)) { ++ dev_err(dev, ++ "'current-speed' is not specified in device node\n"); ++ return -EINVAL; ++ } ++ dev_dbg(dev, "Driver baud rate: %d\n", baud); ++ ++ /* Allocate the memory */ ++ mcu = devm_kzalloc(dev, sizeof(*mcu), GFP_KERNEL); ++ if (!mcu) ++ return -ENOMEM; ++ ++ mcu->reply = devm_kzalloc(dev, sizeof(*mcu->reply), GFP_KERNEL); ++ if (!mcu->reply) ++ return -ENOMEM; ++ ++ /* Initialize device struct data */ ++ mcu->serdev = serdev; ++ mcu->dev = dev; ++ init_completion(&mcu->reply->received); ++ mutex_init(&mcu->reply_lock); ++ mutex_init(&mcu->lock); ++ ++ /* Setup UART interface */ ++ serdev_device_set_drvdata(serdev, mcu); ++ serdev_device_set_client_ops(serdev, &iei_wt61p803_puzzle_serdev_device_ops); ++ ret = devm_serdev_device_open(dev, serdev); ++ if (ret) ++ return ret; ++ serdev_device_set_baudrate(serdev, baud); ++ serdev_device_set_flow_control(serdev, false); ++ ret = serdev_device_set_parity(serdev, SERDEV_PARITY_NONE); ++ if (ret) { ++ dev_err(dev, "Failed to set parity\n"); ++ return ret; ++ } ++ ++ ret = iei_wt61p803_puzzle_get_version(mcu); ++ if (ret) ++ return ret; ++ ++ dev_dbg(dev, "MCU version: %s\n", mcu->version.version); ++ dev_dbg(dev, "MCU firmware build info: %s\n", mcu->version.build_info); ++ dev_dbg(dev, "MCU in bootloader mode: %s\n", ++ mcu->version.bootloader_mode ? "true" : "false"); ++ dev_dbg(dev, "MCU protocol version: %s\n", mcu->version.protocol_version); ++ ++ if (device_property_read_bool(dev, "enable-beep")) { ++ ret = iei_wt61p803_puzzle_buzzer(mcu, false); ++ if (ret) ++ return ret; ++ } ++ ++ ret = iei_wt61p803_puzzle_sysfs_create(dev, mcu); ++ if (ret) ++ return ret; ++ ++ return devm_of_platform_populate(dev); ++} ++ ++static void iei_wt61p803_puzzle_remove(struct serdev_device *serdev) ++{ ++ struct device *dev = &serdev->dev; ++ struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev); ++ ++ iei_wt61p803_puzzle_sysfs_remove(dev, mcu); ++} ++ ++static const struct of_device_id iei_wt61p803_puzzle_dt_ids[] = { ++ { .compatible = "iei,wt61p803-puzzle" }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(of, iei_wt61p803_puzzle_dt_ids); ++ ++static struct serdev_device_driver iei_wt61p803_puzzle_drv = { ++ .probe = iei_wt61p803_puzzle_probe, ++ .remove = iei_wt61p803_puzzle_remove, ++ .driver = { ++ .name = "iei-wt61p803-puzzle", ++ .of_match_table = iei_wt61p803_puzzle_dt_ids, ++ }, ++}; ++ ++module_serdev_device_driver(iei_wt61p803_puzzle_drv); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Luka Kovacic "); ++MODULE_DESCRIPTION("IEI WT61P803 PUZZLE MCU Driver"); +--- /dev/null ++++ b/include/linux/mfd/iei-wt61p803-puzzle.h +@@ -0,0 +1,66 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* IEI WT61P803 PUZZLE MCU Driver ++ * System management microcontroller for fan control, temperature sensor reading, ++ * LED control and system identification on IEI Puzzle series ARM-based appliances. ++ * ++ * Copyright (C) 2020 Sartura Ltd. ++ * Author: Luka Kovacic ++ */ ++ ++#ifndef _MFD_IEI_WT61P803_PUZZLE_H_ ++#define _MFD_IEI_WT61P803_PUZZLE_H_ ++ ++#define IEI_WT61P803_PUZZLE_BUF_SIZE 512 ++ ++/* Command magic numbers */ ++#define IEI_WT61P803_PUZZLE_CMD_HEADER_START 0x40 /* @ */ ++#define IEI_WT61P803_PUZZLE_CMD_HEADER_START_OTHER 0x25 /* % */ ++#define IEI_WT61P803_PUZZLE_CMD_HEADER_EEPROM 0xF7 ++ ++#define IEI_WT61P803_PUZZLE_CMD_RESPONSE_OK 0x30 /* 0 */ ++#define IEI_WT61P803_PUZZLE_CHECKSUM_RESPONSE_OK 0x70 ++ ++#define IEI_WT61P803_PUZZLE_CMD_EEPROM_READ 0xA1 ++#define IEI_WT61P803_PUZZLE_CMD_EEPROM_WRITE 0xA0 ++ ++#define IEI_WT61P803_PUZZLE_CMD_OTHER_VERSION 0x56 /* V */ ++#define IEI_WT61P803_PUZZLE_CMD_OTHER_BUILD 0x42 /* B */ ++#define IEI_WT61P803_PUZZLE_CMD_OTHER_BOOTLOADER_MODE 0x4D /* M */ ++#define IEI_WT61P803_PUZZLE_CMD_OTHER_MODE_BOOTLOADER 0x30 ++#define IEI_WT61P803_PUZZLE_CMD_OTHER_MODE_APPS 0x31 ++#define IEI_WT61P803_PUZZLE_CMD_OTHER_PROTOCOL_VERSION 0x50 /* P */ ++ ++#define IEI_WT61P803_PUZZLE_CMD_FUNCTION_SINGLE 0x43 /* C */ ++#define IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER 0x4F /* O */ ++#define IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_STATUS 0x53 /* S */ ++#define IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_POWER_LOSS 0x41 /* A */ ++ ++#define IEI_WT61P803_PUZZLE_CMD_LED 0x52 /* R */ ++#define IEI_WT61P803_PUZZLE_CMD_LED_POWER 0x31 /* 1 */ ++ ++#define IEI_WT61P803_PUZZLE_CMD_TEMP 0x54 /* T */ ++#define IEI_WT61P803_PUZZLE_CMD_TEMP_ALL 0x41 /* A */ ++ ++#define IEI_WT61P803_PUZZLE_CMD_FAN 0x46 /* F */ ++#define IEI_WT61P803_PUZZLE_CMD_FAN_PWM_READ 0x5A /* Z */ ++#define IEI_WT61P803_PUZZLE_CMD_FAN_PWM_WRITE 0x57 /* W */ ++#define IEI_WT61P803_PUZZLE_CMD_FAN_PWM_BASE 0x30 ++#define IEI_WT61P803_PUZZLE_CMD_FAN_RPM_BASE 0x41 /* A */ ++ ++#define IEI_WT61P803_PUZZLE_CMD_FAN_PWM(x) (IEI_WT61P803_PUZZLE_CMD_FAN_PWM_BASE + (x)) /* 0 - 1 */ ++#define IEI_WT61P803_PUZZLE_CMD_FAN_RPM(x) (IEI_WT61P803_PUZZLE_CMD_FAN_RPM_BASE + (x)) /* 0 - 5 */ ++ ++struct iei_wt61p803_puzzle_mcu_version; ++struct iei_wt61p803_puzzle_reply; ++struct iei_wt61p803_puzzle; ++ ++int iei_wt61p803_puzzle_write_command_watchdog(struct iei_wt61p803_puzzle *mcu, ++ unsigned char *cmd, size_t size, ++ unsigned char *reply_data, size_t *reply_size, ++ int retry_count); ++ ++int iei_wt61p803_puzzle_write_command(struct iei_wt61p803_puzzle *mcu, ++ unsigned char *cmd, size_t size, ++ unsigned char *reply_data, size_t *reply_size); ++ ++#endif /* _MFD_IEI_WT61P803_PUZZLE_H_ */ diff --git a/target/linux/mvebu/patches-6.1/903-drivers-hwmon-Add-the-IEI-WT61P803-PUZZLE-HWMON-driv.patch b/target/linux/mvebu/patches-6.1/903-drivers-hwmon-Add-the-IEI-WT61P803-PUZZLE-HWMON-driv.patch new file mode 100644 index 0000000000..023495373b --- /dev/null +++ b/target/linux/mvebu/patches-6.1/903-drivers-hwmon-Add-the-IEI-WT61P803-PUZZLE-HWMON-driv.patch @@ -0,0 +1,501 @@ +From e3310a638cd310bfd93dbbc6d2732ab6aea18dd2 Mon Sep 17 00:00:00 2001 +From: Luka Kovacic +Date: Tue, 24 Aug 2021 12:44:34 +0000 +Subject: [PATCH 3/7] drivers: hwmon: Add the IEI WT61P803 PUZZLE HWMON driver + +Add the IEI WT61P803 PUZZLE HWMON driver, that handles the fan speed +control via PWM, reading fan speed and reading on-board temperature +sensors. + +The driver registers a HWMON device and a simple thermal cooling device to +enable in-kernel fan management. + +This driver depends on the IEI WT61P803 PUZZLE MFD driver. + +Signed-off-by: Luka Kovacic +Signed-off-by: Pavo Banicevic +Acked-by: Guenter Roeck +Cc: Luka Perkov +Cc: Robert Marko +--- + drivers/hwmon/Kconfig | 8 + + drivers/hwmon/Makefile | 1 + + drivers/hwmon/iei-wt61p803-puzzle-hwmon.c | 413 ++++++++++++++++++++++ + 3 files changed, 422 insertions(+) + create mode 100644 drivers/hwmon/iei-wt61p803-puzzle-hwmon.c + +--- a/drivers/hwmon/Kconfig ++++ b/drivers/hwmon/Kconfig +@@ -732,6 +732,14 @@ config SENSORS_IBMPOWERNV + This driver can also be built as a module. If so, the module + will be called ibmpowernv. + ++config SENSORS_IEI_WT61P803_PUZZLE_HWMON ++ tristate "IEI WT61P803 PUZZLE MFD HWMON Driver" ++ depends on MFD_IEI_WT61P803_PUZZLE ++ help ++ The IEI WT61P803 PUZZLE MFD HWMON Driver handles reading fan speed ++ and writing fan PWM values. It also supports reading on-board ++ temperature sensors. ++ + config SENSORS_IIO_HWMON + tristate "Hwmon driver that uses channels specified via iio maps" + depends on IIO +--- a/drivers/hwmon/Makefile ++++ b/drivers/hwmon/Makefile +@@ -84,6 +84,7 @@ obj-$(CONFIG_SENSORS_HIH6130) += hih6130 + obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o + obj-$(CONFIG_SENSORS_I5500) += i5500_temp.o + obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o ++obj-$(CONFIG_SENSORS_IEI_WT61P803_PUZZLE_HWMON) += iei-wt61p803-puzzle-hwmon.o + obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o + obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o + obj-$(CONFIG_SENSORS_IBMPOWERNV)+= ibmpowernv.o +--- /dev/null ++++ b/drivers/hwmon/iei-wt61p803-puzzle-hwmon.c +@@ -0,0 +1,445 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* IEI WT61P803 PUZZLE MCU HWMON Driver ++ * ++ * Copyright (C) 2020 Sartura Ltd. ++ * Author: Luka Kovacic ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define IEI_WT61P803_PUZZLE_HWMON_MAX_PWM 2 ++#define IEI_WT61P803_PUZZLE_HWMON_MAX_PWM_VAL 255 ++ ++/** ++ * struct iei_wt61p803_puzzle_thermal_cooling_device - Thermal cooling device instance ++ * @mcu_hwmon: Parent driver struct pointer ++ * @tcdev: Thermal cooling device pointer ++ * @name: Thermal cooling device name ++ * @pwm_channel: Controlled PWM channel (0 or 1) ++ * @cooling_levels: Thermal cooling device cooling levels (DT) ++ * @cur_level: Current cooling level ++ * @num_levels: Number of cooling levels ++ */ ++struct iei_wt61p803_puzzle_thermal_cooling_device { ++ struct iei_wt61p803_puzzle_hwmon *mcu_hwmon; ++ struct thermal_cooling_device *tcdev; ++ char name[THERMAL_NAME_LENGTH]; ++ int pwm_channel; ++ u32 *cooling_levels; ++ int cur_level; ++ u8 num_levels; ++}; ++ ++/** ++ * struct iei_wt61p803_puzzle_hwmon - MCU HWMON Driver ++ * @mcu: MCU struct pointer ++ * @response_buffer Global MCU response buffer ++ * @thermal_cooling_dev_present: Per-channel thermal cooling device control indicator ++ * @cdev: Per-channel thermal cooling device private structure ++ */ ++struct iei_wt61p803_puzzle_hwmon { ++ struct iei_wt61p803_puzzle *mcu; ++ unsigned char response_buffer[IEI_WT61P803_PUZZLE_BUF_SIZE]; ++ bool thermal_cooling_dev_present[IEI_WT61P803_PUZZLE_HWMON_MAX_PWM]; ++ struct iei_wt61p803_puzzle_thermal_cooling_device ++ *cdev[IEI_WT61P803_PUZZLE_HWMON_MAX_PWM]; ++ struct mutex lock; /* mutex to protect response_buffer array */ ++}; ++ ++#define raw_temp_to_milidegree_celsius(x) (((x) - 0x80) * 1000) ++static int iei_wt61p803_puzzle_read_temp_sensor(struct iei_wt61p803_puzzle_hwmon *mcu_hwmon, ++ int channel, long *value) ++{ ++ unsigned char *resp_buf = mcu_hwmon->response_buffer; ++ unsigned char temp_sensor_ntc_cmd[4] = { ++ IEI_WT61P803_PUZZLE_CMD_HEADER_START, ++ IEI_WT61P803_PUZZLE_CMD_TEMP, ++ IEI_WT61P803_PUZZLE_CMD_TEMP_ALL, ++ }; ++ size_t reply_size; ++ int ret; ++ ++ mutex_lock(&mcu_hwmon->lock); ++ ret = iei_wt61p803_puzzle_write_command(mcu_hwmon->mcu, temp_sensor_ntc_cmd, ++ sizeof(temp_sensor_ntc_cmd), resp_buf, ++ &reply_size); ++ if (ret) ++ goto exit; ++ ++ if (reply_size != 7) { ++ ret = -EIO; ++ goto exit; ++ } ++ ++ /* Check the number of NTC values */ ++ if (resp_buf[3] != '2') { ++ ret = -EIO; ++ goto exit; ++ } ++ ++ *value = raw_temp_to_milidegree_celsius(resp_buf[4 + channel]); ++exit: ++ mutex_unlock(&mcu_hwmon->lock); ++ return ret; ++} ++ ++#define raw_fan_val_to_rpm(x, y) ((((x) << 8 | (y)) / 2) * 60) ++static int iei_wt61p803_puzzle_read_fan_speed(struct iei_wt61p803_puzzle_hwmon *mcu_hwmon, ++ int channel, long *value) ++{ ++ unsigned char *resp_buf = mcu_hwmon->response_buffer; ++ unsigned char fan_speed_cmd[4] = {}; ++ size_t reply_size; ++ int ret; ++ ++ fan_speed_cmd[0] = IEI_WT61P803_PUZZLE_CMD_HEADER_START; ++ fan_speed_cmd[1] = IEI_WT61P803_PUZZLE_CMD_FAN; ++ fan_speed_cmd[2] = IEI_WT61P803_PUZZLE_CMD_FAN_RPM(channel); ++ ++ mutex_lock(&mcu_hwmon->lock); ++ ret = iei_wt61p803_puzzle_write_command(mcu_hwmon->mcu, fan_speed_cmd, ++ sizeof(fan_speed_cmd), resp_buf, ++ &reply_size); ++ if (ret) ++ goto exit; ++ ++ if (reply_size != 7) { ++ ret = -EIO; ++ goto exit; ++ } ++ ++ *value = raw_fan_val_to_rpm(resp_buf[3], resp_buf[4]); ++exit: ++ mutex_unlock(&mcu_hwmon->lock); ++ return ret; ++} ++ ++static int iei_wt61p803_puzzle_write_pwm_channel(struct iei_wt61p803_puzzle_hwmon *mcu_hwmon, ++ int channel, long pwm_set_val) ++{ ++ unsigned char *resp_buf = mcu_hwmon->response_buffer; ++ unsigned char pwm_set_cmd[6] = {}; ++ size_t reply_size; ++ int ret; ++ ++ pwm_set_cmd[0] = IEI_WT61P803_PUZZLE_CMD_HEADER_START; ++ pwm_set_cmd[1] = IEI_WT61P803_PUZZLE_CMD_FAN; ++ pwm_set_cmd[2] = IEI_WT61P803_PUZZLE_CMD_FAN_PWM_WRITE; ++ pwm_set_cmd[3] = IEI_WT61P803_PUZZLE_CMD_FAN_PWM(channel); ++ pwm_set_cmd[4] = pwm_set_val; ++ ++ mutex_lock(&mcu_hwmon->lock); ++ ret = iei_wt61p803_puzzle_write_command(mcu_hwmon->mcu, pwm_set_cmd, ++ sizeof(pwm_set_cmd), resp_buf, ++ &reply_size); ++ if (ret) ++ goto exit; ++ ++ if (reply_size != 3) { ++ ret = -EIO; ++ goto exit; ++ } ++ ++ if (!(resp_buf[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START && ++ resp_buf[1] == IEI_WT61P803_PUZZLE_CMD_RESPONSE_OK && ++ resp_buf[2] == IEI_WT61P803_PUZZLE_CHECKSUM_RESPONSE_OK)) { ++ ret = -EIO; ++ goto exit; ++ } ++exit: ++ mutex_unlock(&mcu_hwmon->lock); ++ return ret; ++} ++ ++static int iei_wt61p803_puzzle_read_pwm_channel(struct iei_wt61p803_puzzle_hwmon *mcu_hwmon, ++ int channel, long *value) ++{ ++ unsigned char *resp_buf = mcu_hwmon->response_buffer; ++ unsigned char pwm_get_cmd[5] = {}; ++ size_t reply_size; ++ int ret; ++ ++ pwm_get_cmd[0] = IEI_WT61P803_PUZZLE_CMD_HEADER_START; ++ pwm_get_cmd[1] = IEI_WT61P803_PUZZLE_CMD_FAN; ++ pwm_get_cmd[2] = IEI_WT61P803_PUZZLE_CMD_FAN_PWM_READ; ++ pwm_get_cmd[3] = IEI_WT61P803_PUZZLE_CMD_FAN_PWM(channel); ++ ++ ret = iei_wt61p803_puzzle_write_command(mcu_hwmon->mcu, pwm_get_cmd, ++ sizeof(pwm_get_cmd), resp_buf, ++ &reply_size); ++ if (ret) ++ return ret; ++ ++ if (reply_size != 5) ++ return -EIO; ++ ++ if (resp_buf[2] != IEI_WT61P803_PUZZLE_CMD_FAN_PWM_READ) ++ return -EIO; ++ ++ *value = resp_buf[3]; ++ ++ return 0; ++} ++ ++static int iei_wt61p803_puzzle_read(struct device *dev, enum hwmon_sensor_types type, ++ u32 attr, int channel, long *val) ++{ ++ struct iei_wt61p803_puzzle_hwmon *mcu_hwmon = dev_get_drvdata(dev->parent); ++ ++ switch (type) { ++ case hwmon_pwm: ++ return iei_wt61p803_puzzle_read_pwm_channel(mcu_hwmon, channel, val); ++ case hwmon_fan: ++ return iei_wt61p803_puzzle_read_fan_speed(mcu_hwmon, channel, val); ++ case hwmon_temp: ++ return iei_wt61p803_puzzle_read_temp_sensor(mcu_hwmon, channel, val); ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int iei_wt61p803_puzzle_write(struct device *dev, enum hwmon_sensor_types type, ++ u32 attr, int channel, long val) ++{ ++ struct iei_wt61p803_puzzle_hwmon *mcu_hwmon = dev_get_drvdata(dev->parent); ++ ++ return iei_wt61p803_puzzle_write_pwm_channel(mcu_hwmon, channel, val); ++} ++ ++static umode_t iei_wt61p803_puzzle_is_visible(const void *data, enum hwmon_sensor_types type, ++ u32 attr, int channel) ++{ ++ const struct iei_wt61p803_puzzle_hwmon *mcu_hwmon = data; ++ ++ switch (type) { ++ case hwmon_pwm: ++ if (mcu_hwmon->thermal_cooling_dev_present[channel]) ++ return 0444; ++ if (attr == hwmon_pwm_input) ++ return 0644; ++ break; ++ case hwmon_fan: ++ if (attr == hwmon_fan_input) ++ return 0444; ++ break; ++ case hwmon_temp: ++ if (attr == hwmon_temp_input) ++ return 0444; ++ break; ++ default: ++ return 0; ++ } ++ ++ return 0; ++} ++ ++static const struct hwmon_ops iei_wt61p803_puzzle_hwmon_ops = { ++ .is_visible = iei_wt61p803_puzzle_is_visible, ++ .read = iei_wt61p803_puzzle_read, ++ .write = iei_wt61p803_puzzle_write, ++}; ++ ++static const struct hwmon_channel_info *iei_wt61p803_puzzle_info[] = { ++ HWMON_CHANNEL_INFO(pwm, ++ HWMON_PWM_INPUT, ++ HWMON_PWM_INPUT), ++ HWMON_CHANNEL_INFO(fan, ++ HWMON_F_INPUT, ++ HWMON_F_INPUT, ++ HWMON_F_INPUT, ++ HWMON_F_INPUT, ++ HWMON_F_INPUT), ++ HWMON_CHANNEL_INFO(temp, ++ HWMON_T_INPUT, ++ HWMON_T_INPUT), ++ NULL ++}; ++ ++static const struct hwmon_chip_info iei_wt61p803_puzzle_chip_info = { ++ .ops = &iei_wt61p803_puzzle_hwmon_ops, ++ .info = iei_wt61p803_puzzle_info, ++}; ++ ++static int iei_wt61p803_puzzle_get_max_state(struct thermal_cooling_device *tcdev, ++ unsigned long *state) ++{ ++ struct iei_wt61p803_puzzle_thermal_cooling_device *cdev = tcdev->devdata; ++ ++ if (!cdev) ++ return -EINVAL; ++ ++ *state = cdev->num_levels - 1; ++ return 0; ++} ++ ++static int iei_wt61p803_puzzle_get_cur_state(struct thermal_cooling_device *tcdev, ++ unsigned long *state) ++{ ++ struct iei_wt61p803_puzzle_thermal_cooling_device *cdev = tcdev->devdata; ++ ++ if (!cdev) ++ return -EINVAL; ++ ++ if (cdev->cur_level < 0) ++ return -EAGAIN; ++ ++ *state = cdev->cur_level; ++ return 0; ++} ++ ++static int iei_wt61p803_puzzle_set_cur_state(struct thermal_cooling_device *tcdev, ++ unsigned long state) ++{ ++ struct iei_wt61p803_puzzle_thermal_cooling_device *cdev = tcdev->devdata; ++ u8 pwm_level; ++ ++ if (!cdev) ++ return -EINVAL; ++ ++ if (state >= cdev->num_levels) ++ return -EINVAL; ++ ++ if (state == cdev->cur_level) ++ return 0; ++ ++ cdev->cur_level = state; ++ pwm_level = cdev->cooling_levels[state]; ++ ++ return iei_wt61p803_puzzle_write_pwm_channel(cdev->mcu_hwmon, cdev->pwm_channel, pwm_level); ++} ++ ++static const struct thermal_cooling_device_ops iei_wt61p803_puzzle_cooling_ops = { ++ .get_max_state = iei_wt61p803_puzzle_get_max_state, ++ .get_cur_state = iei_wt61p803_puzzle_get_cur_state, ++ .set_cur_state = iei_wt61p803_puzzle_set_cur_state, ++}; ++ ++static int ++iei_wt61p803_puzzle_enable_thermal_cooling_dev(struct device *dev, ++ struct fwnode_handle *child, ++ struct iei_wt61p803_puzzle_hwmon *mcu_hwmon) ++{ ++ struct iei_wt61p803_puzzle_thermal_cooling_device *cdev; ++ u32 pwm_channel; ++ u8 num_levels; ++ int i, ret; ++ ++ ret = fwnode_property_read_u32(child, "reg", &pwm_channel); ++ if (ret) ++ return ret; ++ ++ mcu_hwmon->thermal_cooling_dev_present[pwm_channel] = true; ++ ++ num_levels = fwnode_property_count_u32(child, "cooling-levels"); ++ if (!num_levels) ++ return -EINVAL; ++ ++ cdev = devm_kzalloc(dev, sizeof(*cdev), GFP_KERNEL); ++ if (!cdev) ++ return -ENOMEM; ++ ++ cdev->cooling_levels = devm_kmalloc_array(dev, num_levels, sizeof(u32), GFP_KERNEL); ++ if (!cdev->cooling_levels) ++ return -ENOMEM; ++ ++ ret = fwnode_property_read_u32_array(child, "cooling-levels", ++ cdev->cooling_levels, ++ num_levels); ++ if (ret) { ++ dev_err(dev, "Couldn't read property 'cooling-levels'\n"); ++ return ret; ++ } ++ ++ for (i = 0; i < num_levels; i++) { ++ if (cdev->cooling_levels[i] > ++ IEI_WT61P803_PUZZLE_HWMON_MAX_PWM_VAL) { ++ dev_err(dev, "iei_wt61p803_fan state[%d]:%d > %d\n", i, ++ cdev->cooling_levels[i], ++ IEI_WT61P803_PUZZLE_HWMON_MAX_PWM_VAL); ++ return -EINVAL; ++ } ++ } ++ ++ cdev->mcu_hwmon = mcu_hwmon; ++ cdev->pwm_channel = pwm_channel; ++ cdev->num_levels = num_levels; ++ cdev->cur_level = -1; ++ mcu_hwmon->cdev[pwm_channel] = cdev; ++ ++ snprintf(cdev->name, THERMAL_NAME_LENGTH, "wt61p803_puzzle_%d", pwm_channel); ++ cdev->tcdev = devm_thermal_of_cooling_device_register(dev, to_of_node(child), cdev->name, ++ cdev, &iei_wt61p803_puzzle_cooling_ops); ++ if (IS_ERR(cdev->tcdev)) ++ return PTR_ERR(cdev->tcdev); ++ ++ return 0; ++} ++ ++static int iei_wt61p803_puzzle_hwmon_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev->parent); ++ struct iei_wt61p803_puzzle_hwmon *mcu_hwmon; ++ struct fwnode_handle *child; ++ struct device *hwmon_dev; ++ int ret; ++ ++ mcu_hwmon = devm_kzalloc(dev, sizeof(*mcu_hwmon), GFP_KERNEL); ++ if (!mcu_hwmon) ++ return -ENOMEM; ++ ++ mcu_hwmon->mcu = mcu; ++ platform_set_drvdata(pdev, mcu_hwmon); ++ mutex_init(&mcu_hwmon->lock); ++ ++ hwmon_dev = devm_hwmon_device_register_with_info(dev, "iei_wt61p803_puzzle", ++ mcu_hwmon, ++ &iei_wt61p803_puzzle_chip_info, ++ NULL); ++ if (IS_ERR(hwmon_dev)) ++ return PTR_ERR(hwmon_dev); ++ ++ /* Control fans via PWM lines via Linux Kernel */ ++ if (IS_ENABLED(CONFIG_THERMAL)) { ++ device_for_each_child_node(dev, child) { ++ ret = iei_wt61p803_puzzle_enable_thermal_cooling_dev(dev, child, mcu_hwmon); ++ if (ret) { ++ dev_err(dev, "Enabling the PWM fan failed\n"); ++ fwnode_handle_put(child); ++ return ret; ++ } ++ } ++ } ++ return 0; ++} ++ ++static const struct of_device_id iei_wt61p803_puzzle_hwmon_id_table[] = { ++ { .compatible = "iei,wt61p803-puzzle-hwmon" }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, iei_wt61p803_puzzle_hwmon_id_table); ++ ++static struct platform_driver iei_wt61p803_puzzle_hwmon_driver = { ++ .driver = { ++ .name = "iei-wt61p803-puzzle-hwmon", ++ .of_match_table = iei_wt61p803_puzzle_hwmon_id_table, ++ }, ++ .probe = iei_wt61p803_puzzle_hwmon_probe, ++}; ++ ++module_platform_driver(iei_wt61p803_puzzle_hwmon_driver); ++ ++MODULE_DESCRIPTION("IEI WT61P803 PUZZLE MCU HWMON Driver"); ++MODULE_AUTHOR("Luka Kovacic "); ++MODULE_LICENSE("GPL v2"); diff --git a/target/linux/mvebu/patches-6.1/904-drivers-leds-Add-the-IEI-WT61P803-PUZZLE-LED-driver.patch b/target/linux/mvebu/patches-6.1/904-drivers-leds-Add-the-IEI-WT61P803-PUZZLE-LED-driver.patch new file mode 100644 index 0000000000..a3fc731c47 --- /dev/null +++ b/target/linux/mvebu/patches-6.1/904-drivers-leds-Add-the-IEI-WT61P803-PUZZLE-LED-driver.patch @@ -0,0 +1,207 @@ +From f3b44eb69cc561cf05d00506dcec0dd9be003ed8 Mon Sep 17 00:00:00 2001 +From: Luka Kovacic +Date: Tue, 24 Aug 2021 12:44:35 +0000 +Subject: [PATCH 4/7] drivers: leds: Add the IEI WT61P803 PUZZLE LED driver + +Add support for the IEI WT61P803 PUZZLE LED driver. +Currently only the front panel power LED is supported, +since it is the only LED on this board wired through the +MCU. + +The LED is wired directly to the on-board MCU controller +and is toggled using an MCU command. + +Support for more LEDs is going to be added in case more +boards implement this microcontroller, as LEDs use many +different GPIOs. + +This driver depends on the IEI WT61P803 PUZZLE MFD driver. + +Signed-off-by: Luka Kovacic +Signed-off-by: Pavo Banicevic +Cc: Luka Perkov +Cc: Robert Marko +--- + drivers/leds/Kconfig | 8 ++ + drivers/leds/Makefile | 1 + + drivers/leds/leds-iei-wt61p803-puzzle.c | 147 ++++++++++++++++++++++++ + 3 files changed, 156 insertions(+) + create mode 100644 drivers/leds/leds-iei-wt61p803-puzzle.c + +--- a/drivers/leds/Kconfig ++++ b/drivers/leds/Kconfig +@@ -306,6 +306,14 @@ config LEDS_IPAQ_MICRO + Choose this option if you want to use the notification LED on + Compaq/HP iPAQ h3100 and h3600. + ++config LEDS_IEI_WT61P803_PUZZLE ++ tristate "LED Support for the IEI WT61P803 PUZZLE MCU" ++ depends on LEDS_CLASS ++ depends on MFD_IEI_WT61P803_PUZZLE ++ help ++ This option enables support for LEDs controlled by the IEI WT61P803 ++ M801 MCU. ++ + config LEDS_HP6XX + tristate "LED Support for the HP Jornada 6xx" + depends on LEDS_CLASS +--- a/drivers/leds/Makefile ++++ b/drivers/leds/Makefile +@@ -33,6 +33,7 @@ obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx. + obj-$(CONFIG_LEDS_INTEL_SS4200) += leds-ss4200.o + obj-$(CONFIG_LEDS_IP30) += leds-ip30.o + obj-$(CONFIG_LEDS_IPAQ_MICRO) += leds-ipaq-micro.o ++obj-$(CONFIG_LEDS_IEI_WT61P803_PUZZLE) += leds-iei-wt61p803-puzzle.o + obj-$(CONFIG_LEDS_IS31FL319X) += leds-is31fl319x.o + obj-$(CONFIG_LEDS_IS31FL32XX) += leds-is31fl32xx.o + obj-$(CONFIG_LEDS_LM3530) += leds-lm3530.o +--- /dev/null ++++ b/drivers/leds/leds-iei-wt61p803-puzzle.c +@@ -0,0 +1,147 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* IEI WT61P803 PUZZLE MCU LED Driver ++ * ++ * Copyright (C) 2020 Sartura Ltd. ++ * Author: Luka Kovacic ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++enum iei_wt61p803_puzzle_led_state { ++ IEI_LED_OFF = 0x30, ++ IEI_LED_ON = 0x31, ++ IEI_LED_BLINK_5HZ = 0x32, ++ IEI_LED_BLINK_1HZ = 0x33, ++}; ++ ++/** ++ * struct iei_wt61p803_puzzle_led - MCU LED Driver ++ * @cdev: LED classdev ++ * @mcu: MCU struct pointer ++ * @response_buffer Global MCU response buffer ++ * @lock: General mutex lock to protect simultaneous R/W access to led_power_state ++ * @led_power_state: State of the front panel power LED ++ */ ++struct iei_wt61p803_puzzle_led { ++ struct led_classdev cdev; ++ struct iei_wt61p803_puzzle *mcu; ++ unsigned char response_buffer[IEI_WT61P803_PUZZLE_BUF_SIZE]; ++ struct mutex lock; /* mutex to protect led_power_state */ ++ int led_power_state; ++}; ++ ++static inline struct iei_wt61p803_puzzle_led *cdev_to_iei_wt61p803_puzzle_led ++ (struct led_classdev *led_cdev) ++{ ++ return container_of(led_cdev, struct iei_wt61p803_puzzle_led, cdev); ++} ++ ++static int iei_wt61p803_puzzle_led_brightness_set_blocking(struct led_classdev *cdev, ++ enum led_brightness brightness) ++{ ++ struct iei_wt61p803_puzzle_led *priv = cdev_to_iei_wt61p803_puzzle_led(cdev); ++ unsigned char *resp_buf = priv->response_buffer; ++ unsigned char led_power_cmd[5] = {}; ++ size_t reply_size; ++ int ret; ++ ++ led_power_cmd[0] = IEI_WT61P803_PUZZLE_CMD_HEADER_START; ++ led_power_cmd[1] = IEI_WT61P803_PUZZLE_CMD_LED; ++ led_power_cmd[2] = IEI_WT61P803_PUZZLE_CMD_LED_POWER; ++ led_power_cmd[3] = brightness == LED_OFF ? IEI_LED_OFF : IEI_LED_ON; ++ ++ ret = iei_wt61p803_puzzle_write_command(priv->mcu, led_power_cmd, ++ sizeof(led_power_cmd), ++ resp_buf, ++ &reply_size); ++ if (ret) ++ return ret; ++ ++ if (reply_size != 3) ++ return -EIO; ++ ++ if (!(resp_buf[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START && ++ resp_buf[1] == IEI_WT61P803_PUZZLE_CMD_RESPONSE_OK && ++ resp_buf[2] == IEI_WT61P803_PUZZLE_CHECKSUM_RESPONSE_OK)) ++ return -EIO; ++ ++ mutex_lock(&priv->lock); ++ priv->led_power_state = brightness; ++ mutex_unlock(&priv->lock); ++ ++ return 0; ++} ++ ++static enum led_brightness iei_wt61p803_puzzle_led_brightness_get(struct led_classdev *cdev) ++{ ++ struct iei_wt61p803_puzzle_led *priv = cdev_to_iei_wt61p803_puzzle_led(cdev); ++ int led_state; ++ ++ mutex_lock(&priv->lock); ++ led_state = priv->led_power_state; ++ mutex_unlock(&priv->lock); ++ ++ return led_state; ++} ++ ++static int iei_wt61p803_puzzle_led_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev->parent); ++ struct iei_wt61p803_puzzle_led *priv; ++ struct led_init_data init_data = {}; ++ struct fwnode_handle *child; ++ int ret; ++ ++ if (device_get_child_node_count(dev) != 1) ++ return -EINVAL; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->mcu = mcu; ++ priv->led_power_state = 1; ++ mutex_init(&priv->lock); ++ dev_set_drvdata(dev, priv); ++ ++ child = device_get_next_child_node(dev, NULL); ++ init_data.fwnode = child; ++ ++ priv->cdev.brightness_set_blocking = iei_wt61p803_puzzle_led_brightness_set_blocking; ++ priv->cdev.brightness_get = iei_wt61p803_puzzle_led_brightness_get; ++ priv->cdev.max_brightness = 1; ++ ++ ret = devm_led_classdev_register_ext(dev, &priv->cdev, &init_data); ++ if (ret) ++ dev_err(dev, "Could not register LED\n"); ++ ++ fwnode_handle_put(child); ++ return ret; ++} ++ ++static const struct of_device_id iei_wt61p803_puzzle_led_of_match[] = { ++ { .compatible = "iei,wt61p803-puzzle-leds" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, iei_wt61p803_puzzle_led_of_match); ++ ++static struct platform_driver iei_wt61p803_puzzle_led_driver = { ++ .driver = { ++ .name = "iei-wt61p803-puzzle-led", ++ .of_match_table = iei_wt61p803_puzzle_led_of_match, ++ }, ++ .probe = iei_wt61p803_puzzle_led_probe, ++}; ++module_platform_driver(iei_wt61p803_puzzle_led_driver); ++ ++MODULE_DESCRIPTION("IEI WT61P803 PUZZLE front panel LED driver"); ++MODULE_AUTHOR("Luka Kovacic "); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:leds-iei-wt61p803-puzzle"); diff --git a/target/linux/mvebu/patches-6.1/905-Documentation-ABI-Add-iei-wt61p803-puzzle-driver-sys.patch b/target/linux/mvebu/patches-6.1/905-Documentation-ABI-Add-iei-wt61p803-puzzle-driver-sys.patch new file mode 100644 index 0000000000..b1d420ef0a --- /dev/null +++ b/target/linux/mvebu/patches-6.1/905-Documentation-ABI-Add-iei-wt61p803-puzzle-driver-sys.patch @@ -0,0 +1,82 @@ +From 2fab3b4956c5b2f83c1e1abffc1df39de2933d83 Mon Sep 17 00:00:00 2001 +From: Luka Kovacic +Date: Tue, 24 Aug 2021 12:44:36 +0000 +Subject: [PATCH 5/7] Documentation/ABI: Add iei-wt61p803-puzzle driver sysfs + interface documentation + +Add the iei-wt61p803-puzzle driver sysfs interface documentation to allow +monitoring and control of the microcontroller from user space. + +Signed-off-by: Luka Kovacic +Signed-off-by: Pavo Banicevic +Cc: Luka Perkov +Cc: Robert Marko +--- + .../testing/sysfs-driver-iei-wt61p803-puzzle | 61 +++++++++++++++++++ + 1 file changed, 61 insertions(+) + create mode 100644 Documentation/ABI/testing/sysfs-driver-iei-wt61p803-puzzle + +--- /dev/null ++++ b/Documentation/ABI/testing/sysfs-driver-iei-wt61p803-puzzle +@@ -0,0 +1,61 @@ ++What: /sys/bus/serial/devices/.../mac_address_* ++Date: September 2020 ++Contact: Luka Kovacic ++Description: (RW) Internal factory assigned MAC address values ++ ++What: /sys/bus/serial/devices/.../serial_number ++Date: September 2020 ++Contact: Luka Kovacic ++Description: (RW) Internal factory assigned serial number ++ ++What: /sys/bus/serial/devices/.../version ++Date: September 2020 ++Contact: Luka Kovacic ++Description: (RO) Internal MCU firmware version ++ ++What: /sys/bus/serial/devices/.../protocol_version ++Date: September 2020 ++Contact: Luka Kovacic ++Description: (RO) Internal MCU communication protocol version ++ ++What: /sys/bus/serial/devices/.../power_loss_recovery ++Date: September 2020 ++Contact: Luka Kovacic ++Description: (RW) Host platform power loss recovery settings ++ Value mapping: 0 - Always-On, 1 - Always-Off, 2 - Always-AC, 3 - Always-WA ++ ++What: /sys/bus/serial/devices/.../bootloader_mode ++Date: September 2020 ++Contact: Luka Kovacic ++Description: (RO) Internal MCU bootloader mode status ++ Value mapping: ++ 0 - normal mode ++ 1 - bootloader mode ++ ++What: /sys/bus/serial/devices/.../power_status ++Date: September 2020 ++Contact: Luka Kovacic ++Description: (RO) Power status indicates the host platform power on method. ++ Value mapping (bitwise list): ++ 0x80 - Null ++ 0x40 - Firmware flag ++ 0x20 - Power loss detection flag (powered off) ++ 0x10 - Power loss detection flag (AC mode) ++ 0x08 - Button power on ++ 0x04 - Wake-on-LAN power on ++ 0x02 - RTC alarm power on ++ 0x01 - AC recover power on ++ ++What: /sys/bus/serial/devices/.../build_info ++Date: September 2020 ++Contact: Luka Kovacic ++Description: (RO) Internal MCU firmware build date ++ Format: yyyy/mm/dd hh:mm ++ ++What: /sys/bus/serial/devices/.../ac_recovery_status ++Date: September 2020 ++Contact: Luka Kovacic ++Description: (RO) Host platform AC recovery status value ++ Value mapping: ++ 0 - board has not been recovered from power down ++ 1 - board has been recovered from power down diff --git a/target/linux/mvebu/patches-6.1/906-Documentation-hwmon-Add-iei-wt61p803-puzzle-hwmon-dr.patch b/target/linux/mvebu/patches-6.1/906-Documentation-hwmon-Add-iei-wt61p803-puzzle-hwmon-dr.patch new file mode 100644 index 0000000000..9015436f6a --- /dev/null +++ b/target/linux/mvebu/patches-6.1/906-Documentation-hwmon-Add-iei-wt61p803-puzzle-hwmon-dr.patch @@ -0,0 +1,74 @@ +From 0aff3e5923fecc6842473ad07a688d6e2f2c2d55 Mon Sep 17 00:00:00 2001 +From: Luka Kovacic +Date: Tue, 24 Aug 2021 12:44:37 +0000 +Subject: [PATCH 6/7] Documentation/hwmon: Add iei-wt61p803-puzzle hwmon driver + documentation + +Add the iei-wt61p803-puzzle driver hwmon driver interface documentation. + +Signed-off-by: Luka Kovacic +Signed-off-by: Pavo Banicevic +Cc: Luka Perkov +Cc: Robert Marko +--- + .../hwmon/iei-wt61p803-puzzle-hwmon.rst | 43 +++++++++++++++++++ + Documentation/hwmon/index.rst | 1 + + 2 files changed, 44 insertions(+) + create mode 100644 Documentation/hwmon/iei-wt61p803-puzzle-hwmon.rst + +--- /dev/null ++++ b/Documentation/hwmon/iei-wt61p803-puzzle-hwmon.rst +@@ -0,0 +1,43 @@ ++.. SPDX-License-Identifier: GPL-2.0-only ++ ++Kernel driver iei-wt61p803-puzzle-hwmon ++======================================= ++ ++Supported chips: ++ * IEI WT61P803 PUZZLE for IEI Puzzle M801 ++ ++ Prefix: 'iei-wt61p803-puzzle-hwmon' ++ ++Author: Luka Kovacic ++ ++ ++Description ++----------- ++ ++This driver adds fan and temperature sensor reading for some IEI Puzzle ++series boards. ++ ++Sysfs attributes ++---------------- ++ ++The following attributes are supported: ++ ++- IEI WT61P803 PUZZLE for IEI Puzzle M801 ++ ++/sys files in hwmon subsystem ++----------------------------- ++ ++================= == ===================================================== ++fan[1-5]_input RO files for fan speed (in RPM) ++pwm[1-2] RW files for fan[1-2] target duty cycle (0..255) ++temp[1-2]_input RO files for temperature sensors, in millidegree Celsius ++================= == ===================================================== ++ ++/sys files in thermal subsystem ++------------------------------- ++ ++================= == ===================================================== ++cur_state RW file for current cooling state of the cooling device ++ (0..max_state) ++max_state RO file for maximum cooling state of the cooling device ++================= == ===================================================== +--- a/Documentation/hwmon/index.rst ++++ b/Documentation/hwmon/index.rst +@@ -74,6 +74,7 @@ Hardware Monitoring Kernel Drivers + ibmaem + ibm-cffps + ibmpowernv ++ iei-wt61p803-puzzle-hwmon + ina209 + ina2xx + ina3221 diff --git a/target/linux/mvebu/patches-6.1/907-MAINTAINERS-Add-an-entry-for-the-IEI-WT61P803-PUZZLE.patch b/target/linux/mvebu/patches-6.1/907-MAINTAINERS-Add-an-entry-for-the-IEI-WT61P803-PUZZLE.patch new file mode 100644 index 0000000000..b8accf180b --- /dev/null +++ b/target/linux/mvebu/patches-6.1/907-MAINTAINERS-Add-an-entry-for-the-IEI-WT61P803-PUZZLE.patch @@ -0,0 +1,41 @@ +From 12479baad28d2a08c6cb9e83471057635fa1635c Mon Sep 17 00:00:00 2001 +From: Luka Kovacic +Date: Tue, 24 Aug 2021 12:44:38 +0000 +Subject: [PATCH 7/7] MAINTAINERS: Add an entry for the IEI WT61P803 PUZZLE + driver + +Add an entry for the IEI WT61P803 PUZZLE driver (MFD, HWMON, LED drivers). + +Signed-off-by: Luka Kovacic +Signed-off-by: Pavo Banicevic +Cc: Luka Perkov +Cc: Robert Marko +--- + MAINTAINERS | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -9063,6 +9063,22 @@ F: include/net/nl802154.h + F: net/ieee802154/ + F: net/mac802154/ + ++IEI WT61P803 M801 MFD DRIVER ++M: Luka Kovacic ++M: Luka Perkov ++M: Goran Medic ++L: linux-kernel@vger.kernel.org ++S: Maintained ++F: Documentation/ABI/stable/sysfs-driver-iei-wt61p803-puzzle ++F: Documentation/devicetree/bindings/hwmon/iei,wt61p803-puzzle-hwmon.yaml ++F: Documentation/devicetree/bindings/leds/iei,wt61p803-puzzle-leds.yaml ++F: Documentation/devicetree/bindings/mfd/iei,wt61p803-puzzle.yaml ++F: Documentation/hwmon/iei-wt61p803-puzzle-hwmon.rst ++F: drivers/hwmon/iei-wt61p803-puzzle-hwmon.c ++F: drivers/leds/leds-iei-wt61p803-puzzle.c ++F: drivers/mfd/iei-wt61p803-puzzle.c ++F: include/linux/mfd/iei-wt61p803-puzzle.h ++ + IFE PROTOCOL + M: Yotam Gigi + M: Jamal Hadi Salim diff --git a/target/linux/mvebu/patches-6.1/910-drivers-leds-wt61p803-puzzle-improvements.patch b/target/linux/mvebu/patches-6.1/910-drivers-leds-wt61p803-puzzle-improvements.patch new file mode 100644 index 0000000000..150a65498c --- /dev/null +++ b/target/linux/mvebu/patches-6.1/910-drivers-leds-wt61p803-puzzle-improvements.patch @@ -0,0 +1,271 @@ +--- a/drivers/leds/leds-iei-wt61p803-puzzle.c ++++ b/drivers/leds/leds-iei-wt61p803-puzzle.c +@@ -9,9 +9,13 @@ + #include + #include + #include ++#include + #include + #include + #include ++#include ++ ++#define IEI_LEDS_MAX 4 + + enum iei_wt61p803_puzzle_led_state { + IEI_LED_OFF = 0x30, +@@ -33,7 +37,11 @@ struct iei_wt61p803_puzzle_led { + struct iei_wt61p803_puzzle *mcu; + unsigned char response_buffer[IEI_WT61P803_PUZZLE_BUF_SIZE]; + struct mutex lock; /* mutex to protect led_power_state */ ++ struct work_struct work; + int led_power_state; ++ int id; ++ u8 blinking; ++ bool active_low; + }; + + static inline struct iei_wt61p803_puzzle_led *cdev_to_iei_wt61p803_puzzle_led +@@ -51,10 +59,18 @@ static int iei_wt61p803_puzzle_led_brigh + size_t reply_size; + int ret; + ++ if (priv->blinking) { ++ if (brightness == LED_OFF) ++ priv->blinking = 0; ++ else ++ return 0; ++ } ++ + led_power_cmd[0] = IEI_WT61P803_PUZZLE_CMD_HEADER_START; + led_power_cmd[1] = IEI_WT61P803_PUZZLE_CMD_LED; +- led_power_cmd[2] = IEI_WT61P803_PUZZLE_CMD_LED_POWER; +- led_power_cmd[3] = brightness == LED_OFF ? IEI_LED_OFF : IEI_LED_ON; ++ led_power_cmd[2] = IEI_WT61P803_PUZZLE_CMD_LED_SET(priv->id); ++ led_power_cmd[3] = ((brightness == LED_OFF) ^ priv->active_low) ? ++ IEI_LED_OFF : priv->blinking?priv->blinking:IEI_LED_ON; + + ret = iei_wt61p803_puzzle_write_command(priv->mcu, led_power_cmd, + sizeof(led_power_cmd), +@@ -90,39 +106,166 @@ static enum led_brightness iei_wt61p803_ + return led_state; + } + ++static void iei_wt61p803_puzzle_led_apply_blink(struct work_struct *work) ++{ ++ struct iei_wt61p803_puzzle_led *priv = container_of(work, struct iei_wt61p803_puzzle_led, work); ++ unsigned char led_blink_cmd[5] = {}; ++ unsigned char resp_buf[IEI_WT61P803_PUZZLE_BUF_SIZE]; ++ size_t reply_size; ++ ++ led_blink_cmd[0] = IEI_WT61P803_PUZZLE_CMD_HEADER_START; ++ led_blink_cmd[1] = IEI_WT61P803_PUZZLE_CMD_LED; ++ led_blink_cmd[2] = IEI_WT61P803_PUZZLE_CMD_LED_SET(priv->id); ++ led_blink_cmd[3] = priv->blinking; ++ ++ iei_wt61p803_puzzle_write_command(priv->mcu, led_blink_cmd, ++ sizeof(led_blink_cmd), ++ resp_buf, ++ &reply_size); ++ ++ return; ++} ++ ++static int iei_wt61p803_puzzle_led_set_blink(struct led_classdev *cdev, ++ unsigned long *delay_on, ++ unsigned long *delay_off) ++{ ++ struct iei_wt61p803_puzzle_led *priv = cdev_to_iei_wt61p803_puzzle_led(cdev); ++ u8 blink_mode = 0; ++ int ret = 0; ++ ++ /* set defaults */ ++ if (!*delay_on && !*delay_off) { ++ *delay_on = 500; ++ *delay_off = 500; ++ } ++ ++ /* minimum delay for soft-driven blinking is 100ms to keep load low */ ++ if (*delay_on < 100) ++ *delay_on = 100; ++ ++ if (*delay_off < 100) ++ *delay_off = 100; ++ ++ /* offload blinking to hardware, if possible */ ++ if (*delay_on != *delay_off) { ++ ret = -EINVAL; ++ } else if (*delay_on == 100) { ++ blink_mode = IEI_LED_BLINK_5HZ; ++ *delay_on = 100; ++ *delay_off = 100; ++ } else if (*delay_on <= 500) { ++ blink_mode = IEI_LED_BLINK_1HZ; ++ *delay_on = 500; ++ *delay_off = 500; ++ } else { ++ ret = -EINVAL; ++ } ++ ++ mutex_lock(&priv->lock); ++ priv->blinking = blink_mode; ++ mutex_unlock(&priv->lock); ++ ++ if (blink_mode) ++ schedule_work(&priv->work); ++ ++ return ret; ++} ++ ++ ++static int iei_wt61p803_puzzle_led_set_dt_default(struct led_classdev *cdev, ++ struct device_node *np) ++{ ++ const char *state; ++ int ret = 0; ++ ++ state = of_get_property(np, "default-state", NULL); ++ if (state) { ++ if (!strcmp(state, "on")) { ++ ret = ++ iei_wt61p803_puzzle_led_brightness_set_blocking( ++ cdev, cdev->max_brightness); ++ } else { ++ ret = iei_wt61p803_puzzle_led_brightness_set_blocking( ++ cdev, LED_OFF); ++ } ++ } ++ ++ return ret; ++} ++ + static int iei_wt61p803_puzzle_led_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; ++ struct device_node *np = dev_of_node(dev); ++ struct device_node *child; + struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev->parent); + struct iei_wt61p803_puzzle_led *priv; +- struct led_init_data init_data = {}; +- struct fwnode_handle *child; + int ret; ++ u32 reg; + +- if (device_get_child_node_count(dev) != 1) ++ if (device_get_child_node_count(dev) > IEI_LEDS_MAX) + return -EINVAL; + +- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); +- if (!priv) +- return -ENOMEM; +- +- priv->mcu = mcu; +- priv->led_power_state = 1; +- mutex_init(&priv->lock); +- dev_set_drvdata(dev, priv); +- +- child = device_get_next_child_node(dev, NULL); +- init_data.fwnode = child; +- +- priv->cdev.brightness_set_blocking = iei_wt61p803_puzzle_led_brightness_set_blocking; +- priv->cdev.brightness_get = iei_wt61p803_puzzle_led_brightness_get; +- priv->cdev.max_brightness = 1; ++ for_each_available_child_of_node(np, child) { ++ struct led_init_data init_data = {}; + +- ret = devm_led_classdev_register_ext(dev, &priv->cdev, &init_data); +- if (ret) +- dev_err(dev, "Could not register LED\n"); ++ ret = of_property_read_u32(child, "reg", ®); ++ if (ret) { ++ dev_err(dev, "Failed to read led 'reg' property\n"); ++ goto put_child_node; ++ } ++ ++ if (reg > IEI_LEDS_MAX) { ++ dev_err(dev, "Invalid led reg %u\n", reg); ++ ret = -EINVAL; ++ goto put_child_node; ++ } ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) { ++ ret = -ENOMEM; ++ goto put_child_node; ++ } ++ ++ mutex_init(&priv->lock); ++ ++ dev_set_drvdata(dev, priv); ++ ++ if (of_property_read_bool(child, "active-low")) ++ priv->active_low = true; ++ ++ priv->mcu = mcu; ++ priv->id = reg; ++ priv->led_power_state = 1; ++ priv->blinking = 0; ++ init_data.fwnode = of_fwnode_handle(child); ++ ++ priv->cdev.brightness_set_blocking = iei_wt61p803_puzzle_led_brightness_set_blocking; ++ priv->cdev.brightness_get = iei_wt61p803_puzzle_led_brightness_get; ++ priv->cdev.blink_set = iei_wt61p803_puzzle_led_set_blink; ++ ++ priv->cdev.max_brightness = 1; ++ ++ INIT_WORK(&priv->work, iei_wt61p803_puzzle_led_apply_blink); ++ ++ ret = iei_wt61p803_puzzle_led_set_dt_default(&priv->cdev, child); ++ if (ret) { ++ dev_err(dev, "Could apply default from DT\n"); ++ goto put_child_node; ++ } ++ ++ ret = devm_led_classdev_register_ext(dev, &priv->cdev, &init_data); ++ if (ret) { ++ dev_err(dev, "Could not register LED\n"); ++ goto put_child_node; ++ } ++ } ++ ++ return ret; + +- fwnode_handle_put(child); ++put_child_node: ++ of_node_put(child); + return ret; + } + +--- a/include/linux/mfd/iei-wt61p803-puzzle.h ++++ b/include/linux/mfd/iei-wt61p803-puzzle.h +@@ -36,7 +36,7 @@ + #define IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_POWER_LOSS 0x41 /* A */ + + #define IEI_WT61P803_PUZZLE_CMD_LED 0x52 /* R */ +-#define IEI_WT61P803_PUZZLE_CMD_LED_POWER 0x31 /* 1 */ ++#define IEI_WT61P803_PUZZLE_CMD_LED_SET(n) (0x30 | (n)) + + #define IEI_WT61P803_PUZZLE_CMD_TEMP 0x54 /* T */ + #define IEI_WT61P803_PUZZLE_CMD_TEMP_ALL 0x41 /* A */ +--- a/drivers/mfd/iei-wt61p803-puzzle.c ++++ b/drivers/mfd/iei-wt61p803-puzzle.c +@@ -176,6 +176,9 @@ static int iei_wt61p803_puzzle_recv_buf( + struct iei_wt61p803_puzzle *mcu = serdev_device_get_drvdata(serdev); + int ret; + ++ print_hex_dump_debug("puzzle-mcu rx: ", DUMP_PREFIX_NONE, ++ 16, 1, data, size, false); ++ + ret = iei_wt61p803_puzzle_process_resp(mcu, data, size); + /* Return the number of processed bytes if function returns error, + * discard the remaining incoming data, since the frame this data +@@ -246,6 +249,9 @@ int iei_wt61p803_puzzle_write_command(st + + cmd[size - 1] = iei_wt61p803_puzzle_checksum(cmd, size - 1); + ++ print_hex_dump_debug("puzzle-mcu tx: ", DUMP_PREFIX_NONE, ++ 16, 1, cmd, size, false); ++ + /* Initialize reply struct */ + reinit_completion(&mcu->reply->received); + mcu->reply->size = 0; diff --git a/target/linux/mvebu/patches-6.1/911-drivers-leds-wt61p803-puzzle-mcu-retry.patch b/target/linux/mvebu/patches-6.1/911-drivers-leds-wt61p803-puzzle-mcu-retry.patch new file mode 100644 index 0000000000..2f0b1788ff --- /dev/null +++ b/target/linux/mvebu/patches-6.1/911-drivers-leds-wt61p803-puzzle-mcu-retry.patch @@ -0,0 +1,63 @@ +--- a/drivers/mfd/iei-wt61p803-puzzle.c ++++ b/drivers/mfd/iei-wt61p803-puzzle.c +@@ -241,6 +241,7 @@ int iei_wt61p803_puzzle_write_command(st + { + struct device *dev = &mcu->serdev->dev; + int ret; ++ int retries; + + if (size <= 1 || size > IEI_WT61P803_PUZZLE_MAX_COMMAND_LENGTH) + return -EINVAL; +@@ -252,24 +253,36 @@ int iei_wt61p803_puzzle_write_command(st + print_hex_dump_debug("puzzle-mcu tx: ", DUMP_PREFIX_NONE, + 16, 1, cmd, size, false); + ++ retries = 3; + /* Initialize reply struct */ +- reinit_completion(&mcu->reply->received); +- mcu->reply->size = 0; +- usleep_range(2000, 10000); +- serdev_device_write_flush(mcu->serdev); +- ret = serdev_device_write_buf(mcu->serdev, cmd, size); +- if (ret < 0) +- goto exit; +- +- serdev_device_wait_until_sent(mcu->serdev, IEI_WT61P803_PUZZLE_GENERAL_TIMEOUT); +- ret = wait_for_completion_timeout(&mcu->reply->received, +- IEI_WT61P803_PUZZLE_GENERAL_TIMEOUT); +- if (ret == 0) { +- dev_err(dev, "Command reply receive timeout\n"); +- ret = -ETIMEDOUT; +- goto exit; ++ while (retries) { ++ reinit_completion(&mcu->reply->received); ++ mcu->reply->size = 0; ++ usleep_range(2000, 10000); ++ serdev_device_write_flush(mcu->serdev); ++ ret = serdev_device_write_buf(mcu->serdev, cmd, size); ++ if (ret < 0) ++ goto exit; ++ ++ serdev_device_wait_until_sent(mcu->serdev, IEI_WT61P803_PUZZLE_GENERAL_TIMEOUT); ++ ret = wait_for_completion_timeout(&mcu->reply->received, ++ IEI_WT61P803_PUZZLE_GENERAL_TIMEOUT); ++ retries--; ++ if (ret == 0) { ++ if (retries == 0) { ++ dev_err(dev, "Command reply receive timeout\n"); ++ ret = -ETIMEDOUT; ++ goto exit; ++ } ++ } ++ else { ++ if (mcu->reply->data[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START && ++ mcu->reply->data[1] == IEI_WT61P803_PUZZLE_CMD_RESPONSE_OK && ++ mcu->reply->data[2] == IEI_WT61P803_PUZZLE_CHECKSUM_RESPONSE_OK) { ++ break; ++ } ++ } + } +- + *reply_size = mcu->reply->size; + /* Copy the received data, as it will not be available after a new frame is received */ + memcpy(reply_data, mcu->reply->data, mcu->reply->size); From 7f257296ec2a71c26e753a8416d08e387b2557bd Mon Sep 17 00:00:00 2001 From: Stefan Kalscheuer Date: Sun, 18 Jun 2023 17:01:00 +0200 Subject: [PATCH 20/23] mvebu: refresh patches for 6.1 Remove the following patches: 100-ARM-dts-turris-omnia-configure-LED-0-pin-function-to [1] 101-ARM-dts-turris-omnia-enable-LED-controller-node [2] 702-net-next-ethernet-marvell-mvnetaMQPrioOffload [3] 703-net-next-ethernet-marvell-mvnetaMQPrioFlag [4] 704-net-next-ethernet-marvell-mvnetaMQPrioQueue [5] 705-net-next-ethernet-marvell-mvnetaMQPrioTCOffload [6] 710-v6.2-phy-marvell-phy-mvebu-a3700-comphy-Reset-COMPHY-regi [7] Manually rebased: 902-drivers-mfd-Add-a-driver-for-IEI-WT61P803-PUZZLE-MCU All other patches automatically rebased [1] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=94a29bffdd59498382131fd428fed221f5c96def [2] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=40624346b7ae0c2b1209fc9993ea30699e512c50 [3] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=75fa71e3acadbb4ab5eda18505277eb9a1f69b23 [4] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=e7ca75fe6662f78bfeb0112671c812e4c7b8e214 [5] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=e9f7099d0730341b24c057acbf545dd019581db6 [6] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=2551dc9e398c37a15e52122d385c29a8b06be45f [7] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=cd1e1735aeab49abc679218a79ee764c0d394880 Signed-off-by: Stefan Kalscheuer --- ...mnia-configure-LED-0-pin-function-to.patch | 38 ---- .../100-aardvark-workaround-PCIe.patch | 6 +- ...ris-omnia-enable-LED-controller-node.patch | 48 ----- ...Mangle-bootloader-s-kernel-arguments.patch | 4 +- ...-mvebu-armada-38x-enable-libata-leds.patch | 2 +- .../patches-6.1/302-add_powertables.patch | 2 +- .../306-ARM-mvebu-385-ap-Add-partitions.patch | 4 +- ...-armada-xp-linksys-mamba-broken-idle.patch | 2 +- .../308-armada-xp-linksys-mamba-wan.patch | 2 +- .../patches-6.1/309-linksys-status-led.patch | 2 +- ...da388-clearfog-emmc-on-clearfog-base.patch | 4 +- ...rmada-xp-linksys-mamba-resize-kernel.patch | 4 +- ...316-armada-370-dts-fix-crypto-engine.patch | 4 +- .../700-mvneta-tx-queue-workaround.patch | 4 +- ...ethernet-marvell-mvnetaMQPrioOffload.patch | 66 ------- ...xt-ethernet-marvell-mvnetaMQPrioFlag.patch | 30 --- ...t-ethernet-marvell-mvnetaMQPrioQueue.patch | 97 ---------- ...hernet-marvell-mvnetaMQPrioTCOffload.patch | 182 ------------------ ...mvebu-a3700-comphy-Reset-COMPHY-regi.patch | 50 ----- ...-pci-mvebu-time-out-reset-on-link-up.patch | 6 +- ...IEI-vendor-prefix-and-IEI-WT61P803-P.patch | 2 +- ...a-driver-for-IEI-WT61P803-PUZZLE-MCU.patch | 16 +- ...d-the-IEI-WT61P803-PUZZLE-HWMON-driv.patch | 8 +- ...d-the-IEI-WT61P803-PUZZLE-LED-driver.patch | 4 +- ...mon-Add-iei-wt61p803-puzzle-hwmon-dr.patch | 4 +- ...an-entry-for-the-IEI-WT61P803-PUZZLE.patch | 2 +- 26 files changed, 41 insertions(+), 552 deletions(-) delete mode 100644 target/linux/mvebu/patches-6.1/100-ARM-dts-turris-omnia-configure-LED-0-pin-function-to.patch delete mode 100644 target/linux/mvebu/patches-6.1/101-ARM-dts-turris-omnia-enable-LED-controller-node.patch delete mode 100644 target/linux/mvebu/patches-6.1/702-net-next-ethernet-marvell-mvnetaMQPrioOffload.patch delete mode 100644 target/linux/mvebu/patches-6.1/703-net-next-ethernet-marvell-mvnetaMQPrioFlag.patch delete mode 100644 target/linux/mvebu/patches-6.1/704-net-next-ethernet-marvell-mvnetaMQPrioQueue.patch delete mode 100644 target/linux/mvebu/patches-6.1/705-net-next-ethernet-marvell-mvnetaMQPrioTCOffload.patch delete mode 100644 target/linux/mvebu/patches-6.1/710-v6.2-phy-marvell-phy-mvebu-a3700-comphy-Reset-COMPHY-regi.patch diff --git a/target/linux/mvebu/patches-6.1/100-ARM-dts-turris-omnia-configure-LED-0-pin-function-to.patch b/target/linux/mvebu/patches-6.1/100-ARM-dts-turris-omnia-configure-LED-0-pin-function-to.patch deleted file mode 100644 index 67beb06541..0000000000 --- a/target/linux/mvebu/patches-6.1/100-ARM-dts-turris-omnia-configure-LED-0-pin-function-to.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 81c0004a6433ff90fa6129418802c3c367e453c2 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marek=20Beh=C3=BAn?= -Date: Mon, 4 Jul 2022 13:36:21 +0200 -Subject: [PATCH 1/5] ARM: dts: turris-omnia: configure LED[0] pin function to - link/activity -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The marvell PHY driver changes the LED[0] pin function to "On - 1000 -Mbps Link, Off - Else". - -Turris Omnia expects that the function is "On - Link, Blink - Activity, -Off - No link". - -Use the `marvell,reg-init` DT property to change the function. - -In the future, once netdev trigger will support HW offloading, we will -be able to have this configured via the combination of PHY driver and -leds-turris-omnia driver. - -Signed-off-by: Marek Behún ---- - arch/arm/boot/dts/armada-385-turris-omnia.dts | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/arch/arm/boot/dts/armada-385-turris-omnia.dts -+++ b/arch/arm/boot/dts/armada-385-turris-omnia.dts -@@ -396,7 +396,8 @@ - phy1: ethernet-phy@1 { - compatible = "ethernet-phy-ieee802.3-c22"; - reg = <1>; -- marvell,reg-init = <3 18 0 0x4985>; -+ marvell,reg-init = <3 18 0 0x4985>, -+ <3 16 0xfff0 0x0001>; - - /* irq is connected to &pcawan pin 7 */ - }; diff --git a/target/linux/mvebu/patches-6.1/100-aardvark-workaround-PCIe.patch b/target/linux/mvebu/patches-6.1/100-aardvark-workaround-PCIe.patch index 975eadb80e..4936f6ad16 100644 --- a/target/linux/mvebu/patches-6.1/100-aardvark-workaround-PCIe.patch +++ b/target/linux/mvebu/patches-6.1/100-aardvark-workaround-PCIe.patch @@ -48,7 +48,7 @@ Cc: stable@vger.kernel.org --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -210,6 +210,8 @@ enum { +@@ -212,6 +212,8 @@ enum { }; #define VENDOR_ID_REG (LMI_BASE_ADDR + 0x44) @@ -57,7 +57,7 @@ Cc: stable@vger.kernel.org /* PCIe core controller registers */ #define CTRL_CORE_BASE_ADDR 0x18000 -@@ -558,6 +560,11 @@ static void advk_pcie_setup_hw(struct ad +@@ -560,6 +562,11 @@ static void advk_pcie_setup_hw(struct ad PCIE_CORE_CTRL2_TD_ENABLE; advk_writel(pcie, reg, PCIE_CORE_CTRL2_REG); @@ -69,7 +69,7 @@ Cc: stable@vger.kernel.org /* Set lane X1 */ reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG); reg &= ~LANE_CNT_MSK; -@@ -1580,6 +1587,9 @@ static irqreturn_t advk_pcie_irq_handler +@@ -1661,6 +1668,9 @@ static irqreturn_t advk_pcie_irq_handler struct advk_pcie *pcie = arg; u32 status; diff --git a/target/linux/mvebu/patches-6.1/101-ARM-dts-turris-omnia-enable-LED-controller-node.patch b/target/linux/mvebu/patches-6.1/101-ARM-dts-turris-omnia-enable-LED-controller-node.patch deleted file mode 100644 index ecfb43553f..0000000000 --- a/target/linux/mvebu/patches-6.1/101-ARM-dts-turris-omnia-enable-LED-controller-node.patch +++ /dev/null @@ -1,48 +0,0 @@ -From fed7cef5e4f2df8c6a79bebf5da1fdd3783ff6f3 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marek=20Beh=C3=BAn?= -Date: Mon, 4 Jul 2022 13:36:22 +0200 -Subject: [PATCH] ARM: dts: turris-omnia: enable LED controller node -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The LED controller node is disabled because the leds-turris-omnia driver -does not support setting the LED blinking to be controlled by the MCU. - -The patches for that have now been sent [1], so let's enable the node. - -[1] https://lore.kernel.org/linux-leds/20220704105955.15474-1-kabel@kernel.org/T/ - -Signed-off-by: Marek Behún ---- - arch/arm/boot/dts/armada-385-turris-omnia.dts | 7 ++----- - 1 file changed, 2 insertions(+), 5 deletions(-) - ---- a/arch/arm/boot/dts/armada-385-turris-omnia.dts -+++ b/arch/arm/boot/dts/armada-385-turris-omnia.dts -@@ -194,15 +194,13 @@ - reg = <0x2b>; - #address-cells = <1>; - #size-cells = <0>; -+ status = "okay"; - - /* - * LEDs are controlled by MCU (STM32F0) at - * address 0x2b. - * -- * The driver does not support HW control mode -- * for the LEDs yet. Disable the LEDs for now. -- * -- * Also LED functions are not stable yet: -+ * LED functions are not stable yet: - * - there are 3 LEDs connected via MCU to PCIe - * ports. One of these ports supports mSATA. - * There is no mSATA nor PCIe function. -@@ -213,7 +211,6 @@ - * B. Again there is no such function defined. - * For now we use LED_FUNCTION_INDICATOR - */ -- status = "disabled"; - - multi-led@0 { - reg = <0x0>; diff --git a/target/linux/mvebu/patches-6.1/300-mvebu-Mangle-bootloader-s-kernel-arguments.patch b/target/linux/mvebu/patches-6.1/300-mvebu-Mangle-bootloader-s-kernel-arguments.patch index 9069de1614..5c3672659c 100644 --- a/target/linux/mvebu/patches-6.1/300-mvebu-Mangle-bootloader-s-kernel-arguments.patch +++ b/target/linux/mvebu/patches-6.1/300-mvebu-Mangle-bootloader-s-kernel-arguments.patch @@ -28,7 +28,7 @@ Signed-off-by: Michael Gray --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig -@@ -1727,6 +1727,17 @@ config ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEN +@@ -1586,6 +1586,17 @@ config ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEN The command-line arguments provided by the boot loader will be appended to the the device tree bootargs property. @@ -258,7 +258,7 @@ Signed-off-by: Michael Gray static int kernel_init(void *); extern void init_IRQ(void); -@@ -991,6 +995,18 @@ asmlinkage __visible void __init __no_sa +@@ -992,6 +996,18 @@ asmlinkage __visible void __init __no_sa page_alloc_init(); pr_notice("Kernel command line: %s\n", saved_command_line); diff --git a/target/linux/mvebu/patches-6.1/301-mvebu-armada-38x-enable-libata-leds.patch b/target/linux/mvebu/patches-6.1/301-mvebu-armada-38x-enable-libata-leds.patch index 615caac24f..b75dcf596a 100644 --- a/target/linux/mvebu/patches-6.1/301-mvebu-armada-38x-enable-libata-leds.patch +++ b/target/linux/mvebu/patches-6.1/301-mvebu-armada-38x-enable-libata-leds.patch @@ -1,6 +1,6 @@ --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig -@@ -67,6 +67,7 @@ config MACH_ARMADA_38X +@@ -66,6 +66,7 @@ config MACH_ARMADA_38X select HAVE_ARM_TWD if SMP select MACH_MVEBU_V7 select PINCTRL_ARMADA_38X diff --git a/target/linux/mvebu/patches-6.1/302-add_powertables.patch b/target/linux/mvebu/patches-6.1/302-add_powertables.patch index 93ad5de2cc..d0c0dbeb0c 100644 --- a/target/linux/mvebu/patches-6.1/302-add_powertables.patch +++ b/target/linux/mvebu/patches-6.1/302-add_powertables.patch @@ -667,7 +667,7 @@ pinctrl-0 = <&sdhci_pins>; --- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts +++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts -@@ -225,12 +225,100 @@ +@@ -223,12 +223,100 @@ pcie@2,0 { /* Port 0, Lane 1 */ status = "okay"; diff --git a/target/linux/mvebu/patches-6.1/306-ARM-mvebu-385-ap-Add-partitions.patch b/target/linux/mvebu/patches-6.1/306-ARM-mvebu-385-ap-Add-partitions.patch index 2057e31c7e..aee033d21f 100644 --- a/target/linux/mvebu/patches-6.1/306-ARM-mvebu-385-ap-Add-partitions.patch +++ b/target/linux/mvebu/patches-6.1/306-ARM-mvebu-385-ap-Add-partitions.patch @@ -5,8 +5,8 @@ Subject: [PATCH 2/2] ARM: mvebu: 385-ap: Add partitions Signed-off-by: Maxime Ripard --- - arch/arm/boot/dts/armada-385-db-ap.dts | 15 +++++++++++++++ - 1 file changed, 15 insertions(+) + arch/arm/boot/dts/armada-385-db-ap.dts | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) --- a/arch/arm/boot/dts/armada-385-db-ap.dts +++ b/arch/arm/boot/dts/armada-385-db-ap.dts diff --git a/target/linux/mvebu/patches-6.1/307-armada-xp-linksys-mamba-broken-idle.patch b/target/linux/mvebu/patches-6.1/307-armada-xp-linksys-mamba-broken-idle.patch index 16112d53fc..fc6d6239ca 100644 --- a/target/linux/mvebu/patches-6.1/307-armada-xp-linksys-mamba-broken-idle.patch +++ b/target/linux/mvebu/patches-6.1/307-armada-xp-linksys-mamba-broken-idle.patch @@ -1,6 +1,6 @@ --- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts +++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts -@@ -485,3 +485,7 @@ +@@ -483,3 +483,7 @@ }; }; }; diff --git a/target/linux/mvebu/patches-6.1/308-armada-xp-linksys-mamba-wan.patch b/target/linux/mvebu/patches-6.1/308-armada-xp-linksys-mamba-wan.patch index 4315abc7d2..389e03742e 100644 --- a/target/linux/mvebu/patches-6.1/308-armada-xp-linksys-mamba-wan.patch +++ b/target/linux/mvebu/patches-6.1/308-armada-xp-linksys-mamba-wan.patch @@ -1,6 +1,6 @@ --- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts +++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts -@@ -387,7 +387,7 @@ +@@ -385,7 +385,7 @@ port@4 { reg = <4>; diff --git a/target/linux/mvebu/patches-6.1/309-linksys-status-led.patch b/target/linux/mvebu/patches-6.1/309-linksys-status-led.patch index e5e83572c9..0ef15f2943 100644 --- a/target/linux/mvebu/patches-6.1/309-linksys-status-led.patch +++ b/target/linux/mvebu/patches-6.1/309-linksys-status-led.patch @@ -39,7 +39,7 @@ chosen { bootargs = "console=ttyS0,115200"; stdout-path = &uart0; -@@ -197,7 +204,7 @@ +@@ -195,7 +202,7 @@ pinctrl-0 = <&power_led_pin>; pinctrl-names = "default"; diff --git a/target/linux/mvebu/patches-6.1/312-ARM-dts-armada388-clearfog-emmc-on-clearfog-base.patch b/target/linux/mvebu/patches-6.1/312-ARM-dts-armada388-clearfog-emmc-on-clearfog-base.patch index dd2bef7f63..f52417e83a 100644 --- a/target/linux/mvebu/patches-6.1/312-ARM-dts-armada388-clearfog-emmc-on-clearfog-base.patch +++ b/target/linux/mvebu/patches-6.1/312-ARM-dts-armada388-clearfog-emmc-on-clearfog-base.patch @@ -5,8 +5,8 @@ Subject: ARM: dts: armada388-clearfog: emmc on clearfog base Signed-off-by: Russell King --- - arch/arm/boot/dts/armada-388-clearfog-base.dts | 1 + - .../dts/armada-38x-solidrun-microsom-emmc.dtsi | 62 ++++++++++++++++++++++ + .../arm/boot/dts/armada-388-clearfog-base.dts | 1 + + .../armada-38x-solidrun-microsom-emmc.dtsi | 62 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 arch/arm/boot/dts/armada-38x-solidrun-microsom-emmc.dtsi diff --git a/target/linux/mvebu/patches-6.1/315-armada-xp-linksys-mamba-resize-kernel.patch b/target/linux/mvebu/patches-6.1/315-armada-xp-linksys-mamba-resize-kernel.patch index f1fddceff4..c333df2784 100644 --- a/target/linux/mvebu/patches-6.1/315-armada-xp-linksys-mamba-resize-kernel.patch +++ b/target/linux/mvebu/patches-6.1/315-armada-xp-linksys-mamba-resize-kernel.patch @@ -11,7 +11,7 @@ Signed-off-by: Tad Davanzo --- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts +++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts -@@ -456,9 +456,9 @@ +@@ -454,9 +454,9 @@ reg = <0xa00000 0x2800000>; /* 40MB */ }; @@ -23,7 +23,7 @@ Signed-off-by: Tad Davanzo }; /* kernel2 overlaps with rootfs2 by design */ -@@ -467,9 +467,9 @@ +@@ -465,9 +465,9 @@ reg = <0x3200000 0x2800000>; /* 40MB */ }; diff --git a/target/linux/mvebu/patches-6.1/316-armada-370-dts-fix-crypto-engine.patch b/target/linux/mvebu/patches-6.1/316-armada-370-dts-fix-crypto-engine.patch index 19378870ef..b5ed5ece36 100644 --- a/target/linux/mvebu/patches-6.1/316-armada-370-dts-fix-crypto-engine.patch +++ b/target/linux/mvebu/patches-6.1/316-armada-370-dts-fix-crypto-engine.patch @@ -1,6 +1,6 @@ --- a/arch/arm/boot/dts/armada-370.dtsi +++ b/arch/arm/boot/dts/armada-370.dtsi -@@ -234,7 +234,7 @@ +@@ -254,7 +254,7 @@ clocks = <&gateclk 23>; clock-names = "cesa0"; marvell,crypto-srams = <&crypto_sram>; @@ -9,7 +9,7 @@ }; }; -@@ -255,12 +255,17 @@ +@@ -275,12 +275,17 @@ * cpuidle workaround. */ idle-sram@0 { diff --git a/target/linux/mvebu/patches-6.1/700-mvneta-tx-queue-workaround.patch b/target/linux/mvebu/patches-6.1/700-mvneta-tx-queue-workaround.patch index 32e8ef4b7d..307c46e7b8 100644 --- a/target/linux/mvebu/patches-6.1/700-mvneta-tx-queue-workaround.patch +++ b/target/linux/mvebu/patches-6.1/700-mvneta-tx-queue-workaround.patch @@ -9,7 +9,7 @@ Signed-off-by: Felix Fietkau --- --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c -@@ -5006,6 +5006,16 @@ static int mvneta_setup_tc(struct net_de +@@ -5222,6 +5222,16 @@ static int mvneta_setup_tc(struct net_de } } @@ -26,7 +26,7 @@ Signed-off-by: Felix Fietkau static const struct net_device_ops mvneta_netdev_ops = { .ndo_open = mvneta_open, .ndo_stop = mvneta_stop, -@@ -5016,6 +5026,9 @@ static const struct net_device_ops mvnet +@@ -5232,6 +5242,9 @@ static const struct net_device_ops mvnet .ndo_fix_features = mvneta_fix_features, .ndo_get_stats64 = mvneta_get_stats64, .ndo_eth_ioctl = mvneta_ioctl, diff --git a/target/linux/mvebu/patches-6.1/702-net-next-ethernet-marvell-mvnetaMQPrioOffload.patch b/target/linux/mvebu/patches-6.1/702-net-next-ethernet-marvell-mvnetaMQPrioOffload.patch deleted file mode 100644 index 019b9528c3..0000000000 --- a/target/linux/mvebu/patches-6.1/702-net-next-ethernet-marvell-mvnetaMQPrioOffload.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 75fa71e3acadbb4ab5eda18505277eb9a1f69b23 Mon Sep 17 00:00:00 2001 -From: Maxime Chevallier -Date: Fri, 26 Nov 2021 12:20:53 +0100 -Subject: net: mvneta: Use struct tc_mqprio_qopt_offload for MQPrio - configuration - -The struct tc_mqprio_qopt_offload is a container for struct tc_mqprio_qopt, -that allows passing extra parameters, such as traffic shaping. This commit -converts the current mqprio code to that new struct. - -Signed-off-by: Maxime Chevallier -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/marvell/mvneta.c | 17 ++++++++++------- - 1 file changed, 10 insertions(+), 7 deletions(-) - -(limited to 'drivers/net/ethernet/marvell/mvneta.c') - ---- a/drivers/net/ethernet/marvell/mvneta.c -+++ b/drivers/net/ethernet/marvell/mvneta.c -@@ -38,6 +38,7 @@ - #include - #include - #include -+#include - #include - - /* Registers */ -@@ -4966,14 +4967,14 @@ static void mvneta_setup_rx_prio_map(str - } - - static int mvneta_setup_mqprio(struct net_device *dev, -- struct tc_mqprio_qopt *qopt) -+ struct tc_mqprio_qopt_offload *mqprio) - { - struct mvneta_port *pp = netdev_priv(dev); - u8 num_tc; - int i; - -- qopt->hw = TC_MQPRIO_HW_OFFLOAD_TCS; -- num_tc = qopt->num_tc; -+ mqprio->qopt.hw = TC_MQPRIO_HW_OFFLOAD_TCS; -+ num_tc = mqprio->qopt.num_tc; - - if (num_tc > rxq_number) - return -EINVAL; -@@ -4984,13 +4985,15 @@ static int mvneta_setup_mqprio(struct ne - return 0; - } - -- memcpy(pp->prio_tc_map, qopt->prio_tc_map, sizeof(pp->prio_tc_map)); -+ memcpy(pp->prio_tc_map, mqprio->qopt.prio_tc_map, -+ sizeof(pp->prio_tc_map)); - - mvneta_setup_rx_prio_map(pp); - -- netdev_set_num_tc(dev, qopt->num_tc); -- for (i = 0; i < qopt->num_tc; i++) -- netdev_set_tc_queue(dev, i, qopt->count[i], qopt->offset[i]); -+ netdev_set_num_tc(dev, mqprio->qopt.num_tc); -+ for (i = 0; i < mqprio->qopt.num_tc; i++) -+ netdev_set_tc_queue(dev, i, mqprio->qopt.count[i], -+ mqprio->qopt.offset[i]); - - return 0; - } diff --git a/target/linux/mvebu/patches-6.1/703-net-next-ethernet-marvell-mvnetaMQPrioFlag.patch b/target/linux/mvebu/patches-6.1/703-net-next-ethernet-marvell-mvnetaMQPrioFlag.patch deleted file mode 100644 index c878a28843..0000000000 --- a/target/linux/mvebu/patches-6.1/703-net-next-ethernet-marvell-mvnetaMQPrioFlag.patch +++ /dev/null @@ -1,30 +0,0 @@ -From e7ca75fe6662f78bfeb0112671c812e4c7b8e214 Mon Sep 17 00:00:00 2001 -From: Maxime Chevallier -Date: Fri, 26 Nov 2021 12:20:54 +0100 -Subject: net: mvneta: Don't force-set the offloading flag - -The qopt->hw flag is set by the TC code according to the offloading mode -asked by user. Don't force-set it in the driver, but instead read it to -make sure we do what's asked. - -Signed-off-by: Maxime Chevallier -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/marvell/mvneta.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -(limited to 'drivers/net/ethernet/marvell/mvneta.c') - ---- a/drivers/net/ethernet/marvell/mvneta.c -+++ b/drivers/net/ethernet/marvell/mvneta.c -@@ -4973,7 +4973,9 @@ static int mvneta_setup_mqprio(struct ne - u8 num_tc; - int i; - -- mqprio->qopt.hw = TC_MQPRIO_HW_OFFLOAD_TCS; -+ if (mqprio->qopt.hw != TC_MQPRIO_HW_OFFLOAD_TCS) -+ return 0; -+ - num_tc = mqprio->qopt.num_tc; - - if (num_tc > rxq_number) diff --git a/target/linux/mvebu/patches-6.1/704-net-next-ethernet-marvell-mvnetaMQPrioQueue.patch b/target/linux/mvebu/patches-6.1/704-net-next-ethernet-marvell-mvnetaMQPrioQueue.patch deleted file mode 100644 index 546a8486ef..0000000000 --- a/target/linux/mvebu/patches-6.1/704-net-next-ethernet-marvell-mvnetaMQPrioQueue.patch +++ /dev/null @@ -1,97 +0,0 @@ -From e9f7099d0730341b24c057acbf545dd019581db6 Mon Sep 17 00:00:00 2001 -From: Maxime Chevallier -Date: Fri, 26 Nov 2021 12:20:55 +0100 -Subject: net: mvneta: Allow having more than one queue per TC - -The current mqprio implementation assumed that we are only using one -queue per TC. Use the offset and count parameters to allow using -multiple queues per TC. In that case, the controller will use a standard -round-robin algorithm to pick queues assigned to the same TC, with the -same priority. - -This only applies to VLAN priorities in ingress traffic, each TC -corresponding to a vlan priority. - -Signed-off-by: Maxime Chevallier -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/marvell/mvneta.c | 35 ++++++++++++++++++++--------------- - 1 file changed, 20 insertions(+), 15 deletions(-) - -(limited to 'drivers/net/ethernet/marvell/mvneta.c') - ---- a/drivers/net/ethernet/marvell/mvneta.c -+++ b/drivers/net/ethernet/marvell/mvneta.c -@@ -498,7 +498,6 @@ struct mvneta_port { - u8 mcast_count[256]; - u16 tx_ring_size; - u16 rx_ring_size; -- u8 prio_tc_map[8]; - - phy_interface_t phy_interface; - struct device_node *dn; -@@ -4955,13 +4954,12 @@ static void mvneta_clear_rx_prio_map(str - mvreg_write(pp, MVNETA_VLAN_PRIO_TO_RXQ, 0); - } - --static void mvneta_setup_rx_prio_map(struct mvneta_port *pp) -+static void mvneta_map_vlan_prio_to_rxq(struct mvneta_port *pp, u8 pri, u8 rxq) - { -- u32 val = 0; -- int i; -+ u32 val = mvreg_read(pp, MVNETA_VLAN_PRIO_TO_RXQ); - -- for (i = 0; i < rxq_number; i++) -- val |= MVNETA_VLAN_PRIO_RXQ_MAP(i, pp->prio_tc_map[i]); -+ val &= ~MVNETA_VLAN_PRIO_RXQ_MAP(pri, 0x7); -+ val |= MVNETA_VLAN_PRIO_RXQ_MAP(pri, rxq); - - mvreg_write(pp, MVNETA_VLAN_PRIO_TO_RXQ, val); - } -@@ -4970,8 +4968,8 @@ static int mvneta_setup_mqprio(struct ne - struct tc_mqprio_qopt_offload *mqprio) - { - struct mvneta_port *pp = netdev_priv(dev); -+ int rxq, tc; - u8 num_tc; -- int i; - - if (mqprio->qopt.hw != TC_MQPRIO_HW_OFFLOAD_TCS) - return 0; -@@ -4981,21 +4979,28 @@ static int mvneta_setup_mqprio(struct ne - if (num_tc > rxq_number) - return -EINVAL; - -+ mvneta_clear_rx_prio_map(pp); -+ - if (!num_tc) { -- mvneta_clear_rx_prio_map(pp); - netdev_reset_tc(dev); - return 0; - } - -- memcpy(pp->prio_tc_map, mqprio->qopt.prio_tc_map, -- sizeof(pp->prio_tc_map)); -+ netdev_set_num_tc(dev, mqprio->qopt.num_tc); - -- mvneta_setup_rx_prio_map(pp); -+ for (tc = 0; tc < mqprio->qopt.num_tc; tc++) { -+ netdev_set_tc_queue(dev, tc, mqprio->qopt.count[tc], -+ mqprio->qopt.offset[tc]); -+ -+ for (rxq = mqprio->qopt.offset[tc]; -+ rxq < mqprio->qopt.count[tc] + mqprio->qopt.offset[tc]; -+ rxq++) { -+ if (rxq >= rxq_number) -+ return -EINVAL; - -- netdev_set_num_tc(dev, mqprio->qopt.num_tc); -- for (i = 0; i < mqprio->qopt.num_tc; i++) -- netdev_set_tc_queue(dev, i, mqprio->qopt.count[i], -- mqprio->qopt.offset[i]); -+ mvneta_map_vlan_prio_to_rxq(pp, tc, rxq); -+ } -+ } - - return 0; - } diff --git a/target/linux/mvebu/patches-6.1/705-net-next-ethernet-marvell-mvnetaMQPrioTCOffload.patch b/target/linux/mvebu/patches-6.1/705-net-next-ethernet-marvell-mvnetaMQPrioTCOffload.patch deleted file mode 100644 index 1d4a055a71..0000000000 --- a/target/linux/mvebu/patches-6.1/705-net-next-ethernet-marvell-mvnetaMQPrioTCOffload.patch +++ /dev/null @@ -1,182 +0,0 @@ -From 2551dc9e398c37a15e52122d385c29a8b06be45f Mon Sep 17 00:00:00 2001 -From: Maxime Chevallier -Date: Fri, 26 Nov 2021 12:20:56 +0100 -Subject: net: mvneta: Add TC traffic shaping offload - -The mvneta controller is able to do some tocken-bucket per-queue traffic -shaping. This commit adds support for setting these using the TC mqprio -interface. - -The token-bucket parameters are customisable, but the current -implementation configures them to have a 10kbps resolution for the -rate limitation, since it allows to cover the whole range of max_rate -values from 10kbps to 5Gbps with 10kbps increments. - -Signed-off-by: Maxime Chevallier -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/marvell/mvneta.c | 120 +++++++++++++++++++++++++++++++++- - 1 file changed, 119 insertions(+), 1 deletion(-) - -(limited to 'drivers/net/ethernet/marvell/mvneta.c') - ---- a/drivers/net/ethernet/marvell/mvneta.c -+++ b/drivers/net/ethernet/marvell/mvneta.c -@@ -248,12 +248,39 @@ - #define MVNETA_TXQ_SENT_DESC_MASK 0x3fff0000 - #define MVNETA_PORT_TX_RESET 0x3cf0 - #define MVNETA_PORT_TX_DMA_RESET BIT(0) -+#define MVNETA_TXQ_CMD1_REG 0x3e00 -+#define MVNETA_TXQ_CMD1_BW_LIM_SEL_V1 BIT(3) -+#define MVNETA_TXQ_CMD1_BW_LIM_EN BIT(0) -+#define MVNETA_REFILL_NUM_CLK_REG 0x3e08 -+#define MVNETA_REFILL_MAX_NUM_CLK 0x0000ffff - #define MVNETA_TX_MTU 0x3e0c - #define MVNETA_TX_TOKEN_SIZE 0x3e14 - #define MVNETA_TX_TOKEN_SIZE_MAX 0xffffffff -+#define MVNETA_TXQ_BUCKET_REFILL_REG(q) (0x3e20 + ((q) << 2)) -+#define MVNETA_TXQ_BUCKET_REFILL_PERIOD_MASK 0x3ff00000 -+#define MVNETA_TXQ_BUCKET_REFILL_PERIOD_SHIFT 20 -+#define MVNETA_TXQ_BUCKET_REFILL_VALUE_MAX 0x0007ffff - #define MVNETA_TXQ_TOKEN_SIZE_REG(q) (0x3e40 + ((q) << 2)) - #define MVNETA_TXQ_TOKEN_SIZE_MAX 0x7fffffff - -+/* The values of the bucket refill base period and refill period are taken from -+ * the reference manual, and adds up to a base resolution of 10Kbps. This allows -+ * to cover all rate-limit values from 10Kbps up to 5Gbps -+ */ -+ -+/* Base period for the rate limit algorithm */ -+#define MVNETA_TXQ_BUCKET_REFILL_BASE_PERIOD_NS 100 -+ -+/* Number of Base Period to wait between each bucket refill */ -+#define MVNETA_TXQ_BUCKET_REFILL_PERIOD 1000 -+ -+/* The base resolution for rate limiting, in bps. Any max_rate value should be -+ * a multiple of that value. -+ */ -+#define MVNETA_TXQ_RATE_LIMIT_RESOLUTION (NSEC_PER_SEC / \ -+ (MVNETA_TXQ_BUCKET_REFILL_BASE_PERIOD_NS * \ -+ MVNETA_TXQ_BUCKET_REFILL_PERIOD)) -+ - #define MVNETA_LPI_CTRL_0 0x2cc0 - #define MVNETA_LPI_CTRL_1 0x2cc4 - #define MVNETA_LPI_REQUEST_ENABLE BIT(0) -@@ -4964,11 +4991,74 @@ static void mvneta_map_vlan_prio_to_rxq( - mvreg_write(pp, MVNETA_VLAN_PRIO_TO_RXQ, val); - } - -+static int mvneta_enable_per_queue_rate_limit(struct mvneta_port *pp) -+{ -+ unsigned long core_clk_rate; -+ u32 refill_cycles; -+ u32 val; -+ -+ core_clk_rate = clk_get_rate(pp->clk); -+ if (!core_clk_rate) -+ return -EINVAL; -+ -+ refill_cycles = MVNETA_TXQ_BUCKET_REFILL_BASE_PERIOD_NS / -+ (NSEC_PER_SEC / core_clk_rate); -+ -+ if (refill_cycles > MVNETA_REFILL_MAX_NUM_CLK) -+ return -EINVAL; -+ -+ /* Enable bw limit algorithm version 3 */ -+ val = mvreg_read(pp, MVNETA_TXQ_CMD1_REG); -+ val &= ~(MVNETA_TXQ_CMD1_BW_LIM_SEL_V1 | MVNETA_TXQ_CMD1_BW_LIM_EN); -+ mvreg_write(pp, MVNETA_TXQ_CMD1_REG, val); -+ -+ /* Set the base refill rate */ -+ mvreg_write(pp, MVNETA_REFILL_NUM_CLK_REG, refill_cycles); -+ -+ return 0; -+} -+ -+static void mvneta_disable_per_queue_rate_limit(struct mvneta_port *pp) -+{ -+ u32 val = mvreg_read(pp, MVNETA_TXQ_CMD1_REG); -+ -+ val |= (MVNETA_TXQ_CMD1_BW_LIM_SEL_V1 | MVNETA_TXQ_CMD1_BW_LIM_EN); -+ mvreg_write(pp, MVNETA_TXQ_CMD1_REG, val); -+} -+ -+static int mvneta_setup_queue_rates(struct mvneta_port *pp, int queue, -+ u64 min_rate, u64 max_rate) -+{ -+ u32 refill_val, rem; -+ u32 val = 0; -+ -+ /* Convert to from Bps to bps */ -+ max_rate *= 8; -+ -+ if (min_rate) -+ return -EINVAL; -+ -+ refill_val = div_u64_rem(max_rate, MVNETA_TXQ_RATE_LIMIT_RESOLUTION, -+ &rem); -+ -+ if (rem || !refill_val || -+ refill_val > MVNETA_TXQ_BUCKET_REFILL_VALUE_MAX) -+ return -EINVAL; -+ -+ val = refill_val; -+ val |= (MVNETA_TXQ_BUCKET_REFILL_PERIOD << -+ MVNETA_TXQ_BUCKET_REFILL_PERIOD_SHIFT); -+ -+ mvreg_write(pp, MVNETA_TXQ_BUCKET_REFILL_REG(queue), val); -+ -+ return 0; -+} -+ - static int mvneta_setup_mqprio(struct net_device *dev, - struct tc_mqprio_qopt_offload *mqprio) - { - struct mvneta_port *pp = netdev_priv(dev); -- int rxq, tc; -+ int rxq, txq, tc, ret; - u8 num_tc; - - if (mqprio->qopt.hw != TC_MQPRIO_HW_OFFLOAD_TCS) -@@ -4982,6 +5072,7 @@ static int mvneta_setup_mqprio(struct ne - mvneta_clear_rx_prio_map(pp); - - if (!num_tc) { -+ mvneta_disable_per_queue_rate_limit(pp); - netdev_reset_tc(dev); - return 0; - } -@@ -5002,6 +5093,33 @@ static int mvneta_setup_mqprio(struct ne - } - } - -+ if (mqprio->shaper != TC_MQPRIO_SHAPER_BW_RATE) { -+ mvneta_disable_per_queue_rate_limit(pp); -+ return 0; -+ } -+ -+ if (mqprio->qopt.num_tc > txq_number) -+ return -EINVAL; -+ -+ ret = mvneta_enable_per_queue_rate_limit(pp); -+ if (ret) -+ return ret; -+ -+ for (tc = 0; tc < mqprio->qopt.num_tc; tc++) { -+ for (txq = mqprio->qopt.offset[tc]; -+ txq < mqprio->qopt.count[tc] + mqprio->qopt.offset[tc]; -+ txq++) { -+ if (txq >= txq_number) -+ return -EINVAL; -+ -+ ret = mvneta_setup_queue_rates(pp, txq, -+ mqprio->min_rate[tc], -+ mqprio->max_rate[tc]); -+ if (ret) -+ return ret; -+ } -+ } -+ - return 0; - } - diff --git a/target/linux/mvebu/patches-6.1/710-v6.2-phy-marvell-phy-mvebu-a3700-comphy-Reset-COMPHY-regi.patch b/target/linux/mvebu/patches-6.1/710-v6.2-phy-marvell-phy-mvebu-a3700-comphy-Reset-COMPHY-regi.patch deleted file mode 100644 index a852dc1fc1..0000000000 --- a/target/linux/mvebu/patches-6.1/710-v6.2-phy-marvell-phy-mvebu-a3700-comphy-Reset-COMPHY-regi.patch +++ /dev/null @@ -1,50 +0,0 @@ -From b01d622d76134e9401970ffd3fbbb9a7051f976a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pali=20Roh=C3=A1r?= -Date: Tue, 20 Sep 2022 14:11:54 +0200 -Subject: [PATCH] phy: marvell: phy-mvebu-a3700-comphy: Reset COMPHY registers - before USB 3.0 power on -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Turris MOX board with older ARM Trusted Firmware version v1.5 is not able -to detect any USB 3.0 device connected to USB-A port on Mox-A module after -commit 0a6fc70d76bd ("phy: marvell: phy-mvebu-a3700-comphy: Remove broken -reset support"). On the other hand USB 2.0 devices connected to the same -USB-A port are working fine. - -It looks as if the older firmware configures COMPHY registers for USB 3.0 -somehow incompatibly for kernel driver. Experiments show that resetting -COMPHY registers via setting SFT_RST auto-clearing bit in COMPHY_SFT_RESET -register fixes this issue. - -Reset the COMPHY in mvebu_a3700_comphy_usb3_power_on() function as a first -step after selecting COMPHY lane and USB 3.0 function. With this change -Turris MOX board can successfully detect USB 3.0 devices again. - -Before the above mentioned commit this reset was implemented in PHY reset -method, so this is the reason why there was no issue with older firmware -version then. - -Fixes: 0a6fc70d76bd ("phy: marvell: phy-mvebu-a3700-comphy: Remove broken reset support") -Reported-by: Marek Behún -Signed-off-by: Pali Rohár -Tested-by: Shin'ichiro Kawasaki -Link: https://lore.kernel.org/r/20220920121154.30115-1-pali@kernel.org -Signed-off-by: Vinod Koul ---- - drivers/phy/marvell/phy-mvebu-a3700-comphy.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/phy/marvell/phy-mvebu-a3700-comphy.c -+++ b/drivers/phy/marvell/phy-mvebu-a3700-comphy.c -@@ -826,6 +826,9 @@ mvebu_a3700_comphy_usb3_power_on(struct - if (ret) - return ret; - -+ /* COMPHY register reset (cleared automatically) */ -+ comphy_lane_reg_set(lane, COMPHY_SFT_RESET, SFT_RST, SFT_RST); -+ - /* - * 0. Set PHY OTG Control(0x5d034), bit 4, Power up OTG module The - * register belong to UTMI module, so it is set in UTMI phy driver. diff --git a/target/linux/mvebu/patches-6.1/801-pci-mvebu-time-out-reset-on-link-up.patch b/target/linux/mvebu/patches-6.1/801-pci-mvebu-time-out-reset-on-link-up.patch index dba1253699..d2995b375c 100644 --- a/target/linux/mvebu/patches-6.1/801-pci-mvebu-time-out-reset-on-link-up.patch +++ b/target/linux/mvebu/patches-6.1/801-pci-mvebu-time-out-reset-on-link-up.patch @@ -13,7 +13,7 @@ Signed-off-by: Russell King --- a/drivers/pci/controller/pci-mvebu.c +++ b/drivers/pci/controller/pci-mvebu.c -@@ -1023,6 +1023,7 @@ static int mvebu_pcie_powerup(struct mve +@@ -1414,6 +1414,7 @@ static int mvebu_pcie_powerup(struct mve if (port->reset_gpio) { u32 reset_udelay = PCI_PM_D3COLD_WAIT * 1000; @@ -21,7 +21,7 @@ Signed-off-by: Russell King of_property_read_u32(port->dn, "reset-delay-us", &reset_udelay); -@@ -1030,7 +1031,13 @@ static int mvebu_pcie_powerup(struct mve +@@ -1421,7 +1422,13 @@ static int mvebu_pcie_powerup(struct mve udelay(100); gpiod_set_value_cansleep(port->reset_gpio, 0); @@ -36,7 +36,7 @@ Signed-off-by: Russell King } return 0; -@@ -1190,15 +1197,16 @@ static int mvebu_pcie_probe(struct platf +@@ -1538,15 +1545,16 @@ static int mvebu_pcie_probe(struct platf if (!child) continue; diff --git a/target/linux/mvebu/patches-6.1/901-dt-bindings-Add-IEI-vendor-prefix-and-IEI-WT61P803-P.patch b/target/linux/mvebu/patches-6.1/901-dt-bindings-Add-IEI-vendor-prefix-and-IEI-WT61P803-P.patch index 3446086cad..fc5c804582 100644 --- a/target/linux/mvebu/patches-6.1/901-dt-bindings-Add-IEI-vendor-prefix-and-IEI-WT61P803-P.patch +++ b/target/linux/mvebu/patches-6.1/901-dt-bindings-Add-IEI-vendor-prefix-and-IEI-WT61P803-P.patch @@ -207,7 +207,7 @@ Cc: Robert Marko + }; --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml -@@ -519,6 +519,8 @@ patternProperties: +@@ -579,6 +579,8 @@ patternProperties: description: IC Plus Corp. "^idt,.*": description: Integrated Device Technologies, Inc. diff --git a/target/linux/mvebu/patches-6.1/902-drivers-mfd-Add-a-driver-for-IEI-WT61P803-PUZZLE-MCU.patch b/target/linux/mvebu/patches-6.1/902-drivers-mfd-Add-a-driver-for-IEI-WT61P803-PUZZLE-MCU.patch index 0e546b426e..d213404250 100644 --- a/target/linux/mvebu/patches-6.1/902-drivers-mfd-Add-a-driver-for-IEI-WT61P803-PUZZLE-MCU.patch +++ b/target/linux/mvebu/patches-6.1/902-drivers-mfd-Add-a-driver-for-IEI-WT61P803-PUZZLE-MCU.patch @@ -16,17 +16,17 @@ Signed-off-by: Pavo Banicevic Cc: Luka Perkov Cc: Robert Marko --- - drivers/mfd/Kconfig | 8 + + drivers/mfd/Kconfig | 9 + drivers/mfd/Makefile | 1 + drivers/mfd/iei-wt61p803-puzzle.c | 908 ++++++++++++++++++++++++ include/linux/mfd/iei-wt61p803-puzzle.h | 66 ++ - 4 files changed, 983 insertions(+) + 4 files changed, 984 insertions(+) create mode 100644 drivers/mfd/iei-wt61p803-puzzle.c create mode 100644 include/linux/mfd/iei-wt61p803-puzzle.h --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig -@@ -2189,6 +2189,15 @@ config SGI_MFD_IOC3 +@@ -2221,6 +2221,15 @@ config SGI_MFD_IOC3 If you have an SGI Origin, Octane, or a PCI IOC3 card, then say Y. Otherwise say N. @@ -44,14 +44,14 @@ Cc: Robert Marko depends on SPI_MASTER --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile -@@ -237,6 +237,7 @@ obj-$(CONFIG_MFD_DLN2) += dln2.o - obj-$(CONFIG_MFD_RT4831) += rt4831.o +@@ -244,6 +244,7 @@ obj-$(CONFIG_MFD_RT4831) += rt4831.o obj-$(CONFIG_MFD_RT5033) += rt5033.o + obj-$(CONFIG_MFD_RT5120) += rt5120.o obj-$(CONFIG_MFD_SKY81452) += sky81452.o -+obj-$(CONFIG_MFD_IEI_WT61P803_PUZZLE) += iei-wt61p803-puzzle.o ++obj-$(CONFIG_MFD_IEI_WT61P803_PUZZLE) += iei-wt61p803-puzzle.o - intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o - obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o + obj-$(CONFIG_INTEL_SOC_PMIC) += intel_soc_pmic_crc.o + obj-$(CONFIG_INTEL_SOC_PMIC_BXTWC) += intel_soc_pmic_bxtwc.o --- /dev/null +++ b/drivers/mfd/iei-wt61p803-puzzle.c @@ -0,0 +1,908 @@ diff --git a/target/linux/mvebu/patches-6.1/903-drivers-hwmon-Add-the-IEI-WT61P803-PUZZLE-HWMON-driv.patch b/target/linux/mvebu/patches-6.1/903-drivers-hwmon-Add-the-IEI-WT61P803-PUZZLE-HWMON-driv.patch index 023495373b..a11b387d92 100644 --- a/target/linux/mvebu/patches-6.1/903-drivers-hwmon-Add-the-IEI-WT61P803-PUZZLE-HWMON-driv.patch +++ b/target/linux/mvebu/patches-6.1/903-drivers-hwmon-Add-the-IEI-WT61P803-PUZZLE-HWMON-driv.patch @@ -20,13 +20,13 @@ Cc: Robert Marko --- drivers/hwmon/Kconfig | 8 + drivers/hwmon/Makefile | 1 + - drivers/hwmon/iei-wt61p803-puzzle-hwmon.c | 413 ++++++++++++++++++++++ - 3 files changed, 422 insertions(+) + drivers/hwmon/iei-wt61p803-puzzle-hwmon.c | 445 ++++++++++++++++++++++ + 3 files changed, 454 insertions(+) create mode 100644 drivers/hwmon/iei-wt61p803-puzzle-hwmon.c --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig -@@ -732,6 +732,14 @@ config SENSORS_IBMPOWERNV +@@ -755,6 +755,14 @@ config SENSORS_IBMPOWERNV This driver can also be built as a module. If so, the module will be called ibmpowernv. @@ -43,7 +43,7 @@ Cc: Robert Marko depends on IIO --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile -@@ -84,6 +84,7 @@ obj-$(CONFIG_SENSORS_HIH6130) += hih6130 +@@ -87,6 +87,7 @@ obj-$(CONFIG_SENSORS_HIH6130) += hih6130 obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o obj-$(CONFIG_SENSORS_I5500) += i5500_temp.o obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o diff --git a/target/linux/mvebu/patches-6.1/904-drivers-leds-Add-the-IEI-WT61P803-PUZZLE-LED-driver.patch b/target/linux/mvebu/patches-6.1/904-drivers-leds-Add-the-IEI-WT61P803-PUZZLE-LED-driver.patch index a3fc731c47..ec783256e3 100644 --- a/target/linux/mvebu/patches-6.1/904-drivers-leds-Add-the-IEI-WT61P803-PUZZLE-LED-driver.patch +++ b/target/linux/mvebu/patches-6.1/904-drivers-leds-Add-the-IEI-WT61P803-PUZZLE-LED-driver.patch @@ -30,7 +30,7 @@ Cc: Robert Marko --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig -@@ -306,6 +306,14 @@ config LEDS_IPAQ_MICRO +@@ -299,6 +299,14 @@ config LEDS_IPAQ_MICRO Choose this option if you want to use the notification LED on Compaq/HP iPAQ h3100 and h3600. @@ -47,7 +47,7 @@ Cc: Robert Marko depends on LEDS_CLASS --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile -@@ -33,6 +33,7 @@ obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx. +@@ -32,6 +32,7 @@ obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx. obj-$(CONFIG_LEDS_INTEL_SS4200) += leds-ss4200.o obj-$(CONFIG_LEDS_IP30) += leds-ip30.o obj-$(CONFIG_LEDS_IPAQ_MICRO) += leds-ipaq-micro.o diff --git a/target/linux/mvebu/patches-6.1/906-Documentation-hwmon-Add-iei-wt61p803-puzzle-hwmon-dr.patch b/target/linux/mvebu/patches-6.1/906-Documentation-hwmon-Add-iei-wt61p803-puzzle-hwmon-dr.patch index 9015436f6a..0f1a6f306b 100644 --- a/target/linux/mvebu/patches-6.1/906-Documentation-hwmon-Add-iei-wt61p803-puzzle-hwmon-dr.patch +++ b/target/linux/mvebu/patches-6.1/906-Documentation-hwmon-Add-iei-wt61p803-puzzle-hwmon-dr.patch @@ -64,11 +64,11 @@ Cc: Robert Marko +================= == ===================================================== --- a/Documentation/hwmon/index.rst +++ b/Documentation/hwmon/index.rst -@@ -74,6 +74,7 @@ Hardware Monitoring Kernel Drivers +@@ -77,6 +77,7 @@ Hardware Monitoring Kernel Drivers ibmaem ibm-cffps ibmpowernv + iei-wt61p803-puzzle-hwmon ina209 ina2xx - ina3221 + ina238 diff --git a/target/linux/mvebu/patches-6.1/907-MAINTAINERS-Add-an-entry-for-the-IEI-WT61P803-PUZZLE.patch b/target/linux/mvebu/patches-6.1/907-MAINTAINERS-Add-an-entry-for-the-IEI-WT61P803-PUZZLE.patch index b8accf180b..e72df378ef 100644 --- a/target/linux/mvebu/patches-6.1/907-MAINTAINERS-Add-an-entry-for-the-IEI-WT61P803-PUZZLE.patch +++ b/target/linux/mvebu/patches-6.1/907-MAINTAINERS-Add-an-entry-for-the-IEI-WT61P803-PUZZLE.patch @@ -16,7 +16,7 @@ Cc: Robert Marko --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -9063,6 +9063,22 @@ F: include/net/nl802154.h +@@ -9900,6 +9900,22 @@ F: include/net/nl802154.h F: net/ieee802154/ F: net/mac802154/ From b1993f362a8a55d62ec995b0b34174a124fee869 Mon Sep 17 00:00:00 2001 From: Stefan Kalscheuer Date: Sun, 18 Jun 2023 17:04:18 +0200 Subject: [PATCH 21/23] mvebu: copy 5.15 kconfigs to 6.1 Start 6.1 migration with a full copy of the current stable config. Signed-off-by: Stefan Kalscheuer --- target/linux/mvebu/config-6.1 | 435 ++++++++++++++++++++++++ target/linux/mvebu/cortexa53/config-6.1 | 83 +++++ target/linux/mvebu/cortexa72/config-6.1 | 97 ++++++ target/linux/mvebu/cortexa9/config-6.1 | 3 + 4 files changed, 618 insertions(+) create mode 100644 target/linux/mvebu/config-6.1 create mode 100644 target/linux/mvebu/cortexa53/config-6.1 create mode 100644 target/linux/mvebu/cortexa72/config-6.1 create mode 100644 target/linux/mvebu/cortexa9/config-6.1 diff --git a/target/linux/mvebu/config-6.1 b/target/linux/mvebu/config-6.1 new file mode 100644 index 0000000000..0811ee6d4c --- /dev/null +++ b/target/linux/mvebu/config-6.1 @@ -0,0 +1,435 @@ +CONFIG_AHCI_MVEBU=y +CONFIG_ALIGNMENT_TRAP=y +CONFIG_ARCH_32BIT_OFF_T=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_KEEP_MEMBLOCK=y +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +CONFIG_ARCH_MULTIPLATFORM=y +CONFIG_ARCH_MULTI_V6_V7=y +CONFIG_ARCH_MULTI_V7=y +CONFIG_ARCH_MVEBU=y +CONFIG_ARCH_NR_GPIO=0 +CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y +CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM=y +CONFIG_ARMADA_370_CLK=y +CONFIG_ARMADA_370_XP_IRQ=y +CONFIG_ARMADA_370_XP_TIMER=y +# CONFIG_ARMADA_37XX_WATCHDOG is not set +CONFIG_ARMADA_38X_CLK=y +CONFIG_ARMADA_THERMAL=y +CONFIG_ARMADA_XP_CLK=y +CONFIG_ARM_APPENDED_DTB=y +# CONFIG_ARM_ARMADA_37XX_CPUFREQ is not set +# CONFIG_ARM_ARMADA_8K_CPUFREQ is not set +CONFIG_ARM_ATAG_DTB_COMPAT=y +# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER is not set +CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE=y +CONFIG_ARM_CPU_SUSPEND=y +CONFIG_ARM_CRYPTO=y +CONFIG_ARM_ERRATA_720789=y +CONFIG_ARM_ERRATA_764369=y +CONFIG_ARM_GIC=y +CONFIG_ARM_GLOBAL_TIMER=y +CONFIG_ARM_GT_INITIAL_PRESCALER_VAL=1 +CONFIG_ARM_HAS_SG_CHAIN=y +CONFIG_ARM_HEAVY_MB=y +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ARM_L1_CACHE_SHIFT_6=y +CONFIG_ARM_MVEBU_V7_CPUIDLE=y +CONFIG_ARM_PATCH_IDIV=y +CONFIG_ARM_PATCH_PHYS_VIRT=y +CONFIG_ARM_THUMB=y +CONFIG_ARM_UNWIND=y +CONFIG_ARM_VIRT_EXT=y +CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH=y +CONFIG_ATA=y +CONFIG_ATAGS=y +CONFIG_ATA_LEDS=y +CONFIG_AUTO_ZRELADDR=y +CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_NVME=y +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_MQ_PCI=y +CONFIG_BOUNCE=y +# CONFIG_CACHE_FEROCEON_L2 is not set +CONFIG_CACHE_L2X0=y +CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK=y +CONFIG_CLKSRC_MMIO=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_COMMON_CLK=y +CONFIG_COMPAT_32BIT_TIME=y +CONFIG_CPUFREQ_DT=y +CONFIG_CPUFREQ_DT_PLATDEV=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +CONFIG_CPU_FREQ_GOV_COMMON=y +# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_PJ4B=y +CONFIG_CPU_PM=y +CONFIG_CPU_RMAP=y +CONFIG_CPU_SPECTRE=y +CONFIG_CPU_THERMAL=y +CONFIG_CPU_THUMB_CAPABLE=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_V7=y +CONFIG_CRC16=y +CONFIG_CRYPTO_AES_ARM=y +CONFIG_CRYPTO_AES_ARM_BS=y +CONFIG_CRYPTO_AUTHENC=y +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CRC32=y +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_CRYPTD=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_DEV_MARVELL=y +CONFIG_CRYPTO_DEV_MARVELL_CESA=y +CONFIG_CRYPTO_ESSIV=y +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_LIB_DES=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA1_ARM=y +CONFIG_CRYPTO_SHA1_ARM_NEON=y +CONFIG_CRYPTO_SHA256_ARM=y +CONFIG_CRYPTO_SHA512_ARM=y +CONFIG_CRYPTO_SIMD=y +CONFIG_CRYPTO_ZSTD=y +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DEBUG_ALIGN_RODATA=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_LL=y +CONFIG_DEBUG_LL_INCLUDE="debug/8250.S" +CONFIG_DEBUG_MVEBU_UART0=y +# CONFIG_DEBUG_MVEBU_UART0_ALTERNATE is not set +# CONFIG_DEBUG_MVEBU_UART1_ALTERNATE is not set +CONFIG_DEBUG_UART_8250=y +CONFIG_DEBUG_UART_8250_SHIFT=2 +CONFIG_DEBUG_UART_PHYS=0xd0012000 +CONFIG_DEBUG_UART_VIRT=0xfec12000 +CONFIG_DEBUG_UNCOMPRESS=y +CONFIG_DEBUG_USER=y +CONFIG_DMADEVICES=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_ENGINE_RAID=y +CONFIG_DMA_OF=y +CONFIG_DMA_OPS=y +CONFIG_DMA_REMAP=y +CONFIG_DTC=y +CONFIG_EARLY_PRINTK=y +CONFIG_EDAC_ATOMIC_SCRUB=y +CONFIG_EDAC_SUPPORT=y +CONFIG_EXT4_FS=y +CONFIG_EXTCON=y +CONFIG_F2FS_FS=y +CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_FS_IOMAP=y +CONFIG_FS_MBCACHE=y +CONFIG_FWNODE_MDIO=y +CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_ARCH_TOPOLOGY=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_VULNERABILITIES=y +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_MIGRATION=y +CONFIG_GENERIC_IRQ_MULTI_HANDLER=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_MSI_IRQ_DOMAIN=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENERIC_VDSO_32=y +CONFIG_GLOB=y +CONFIG_GPIOLIB=y +CONFIG_GPIOLIB_IRQCHIP=y +CONFIG_GPIO_CDEV=y +CONFIG_GPIO_GENERIC=y +CONFIG_GPIO_GENERIC_PLATFORM=y +CONFIG_GPIO_MVEBU=y +CONFIG_GPIO_PCA953X=y +CONFIG_GPIO_PCA953X_IRQ=y +CONFIG_GRO_CELLS=y +CONFIG_HANDLE_DOMAIN_IRQ=y +CONFIG_HARDEN_BRANCH_PREDICTOR=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HAVE_SMP=y +CONFIG_HIGHMEM=y +CONFIG_HIGHPTE=y +CONFIG_HOTPLUG_CPU=y +CONFIG_HWBM=y +CONFIG_HWMON=y +CONFIG_HW_RANDOM=y +CONFIG_HZ_FIXED=0 +CONFIG_HZ_PERIODIC=y +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MV64XXX=y +# CONFIG_I2C_PXA is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_WORK=y +# CONFIG_IWMMXT is not set +CONFIG_JBD2=y +CONFIG_KMAP_LOCAL=y +CONFIG_KMAP_LOCAL_NON_LINEAR_PTE_ARRAY=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_PCA963X=y +CONFIG_LEDS_TLC591XX=y +CONFIG_LEDS_TRIGGER_DISK=y +CONFIG_LIBFDT=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_MACH_ARMADA_370=y +# CONFIG_MACH_ARMADA_375 is not set +CONFIG_MACH_ARMADA_38X=y +# CONFIG_MACH_ARMADA_39X is not set +CONFIG_MACH_ARMADA_XP=y +# CONFIG_MACH_DOVE is not set +CONFIG_MACH_MVEBU_ANY=y +CONFIG_MACH_MVEBU_V7=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_MANGLE_BOOTARGS=y +CONFIG_MARVELL_PHY=y +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_DEVRES=y +CONFIG_MDIO_I2C=y +CONFIG_MEMFD_CREATE=y +CONFIG_MEMORY=y +CONFIG_MIGHT_HAVE_CACHE_L2X0=y +CONFIG_MIGRATION=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_MVSDIO=y +CONFIG_MMC_SDHCI=y +# CONFIG_MMC_SDHCI_PCI is not set +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_PXAV3=y +CONFIG_MODULES_USE_ELF_REL=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_NAND_CORE=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_NAND_ECC_SW_HAMMING=y +CONFIG_MTD_NAND_MARVELL=y +CONFIG_MTD_RAW_NAND=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_BEB_LIMIT=20 +CONFIG_MTD_UBI_BLOCK=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_MVEBU_CLK_COMMON=y +CONFIG_MVEBU_CLK_COREDIV=y +CONFIG_MVEBU_CLK_CPU=y +CONFIG_MVEBU_DEVBUS=y +CONFIG_MVEBU_MBUS=y +CONFIG_MVMDIO=y +CONFIG_MVNETA=y +CONFIG_MVNETA_BM=y +CONFIG_MVNETA_BM_ENABLE=y +# CONFIG_MVPP2 is not set +CONFIG_MV_XOR=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEON=y +CONFIG_NET_DEVLINK=y +CONFIG_NET_DSA=y +CONFIG_NET_DSA_MV88E6XXX=y +CONFIG_NET_DSA_TAG_DSA=y +CONFIG_NET_DSA_TAG_DSA_COMMON=y +CONFIG_NET_DSA_TAG_EDSA=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_SELFTESTS=y +CONFIG_NET_SWITCHDEV=y +CONFIG_NLS=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_NR_CPUS=4 +CONFIG_NVMEM=y +CONFIG_NVME_CORE=y +# CONFIG_NVME_HWMON is not set +# CONFIG_NVME_MULTIPATH is not set +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_KOBJ=y +CONFIG_OF_MDIO=y +CONFIG_OLD_SIGACTION=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_ORION_WATCHDOG=y +CONFIG_OUTER_CACHE=y +CONFIG_OUTER_CACHE_SYNC=y +CONFIG_PADATA=y +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PAGE_POOL=y +CONFIG_PCI=y +CONFIG_PCI_BRIDGE_EMUL=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_IRQ_DOMAIN=y +CONFIG_PCI_MVEBU=y +CONFIG_PERF_USE_VMALLOC=y +CONFIG_PGTABLE_LEVELS=2 +CONFIG_PHYLIB=y +CONFIG_PHYLINK=y +# CONFIG_PHY_MVEBU_A3700_COMPHY is not set +# CONFIG_PHY_MVEBU_A3700_UTMI is not set +# CONFIG_PHY_MVEBU_A38X_COMPHY is not set +# CONFIG_PHY_MVEBU_CP110_COMPHY is not set +# CONFIG_PHY_MVEBU_CP110_UTMI is not set +CONFIG_PINCTRL=y +CONFIG_PINCTRL_ARMADA_370=y +CONFIG_PINCTRL_ARMADA_38X=y +CONFIG_PINCTRL_ARMADA_XP=y +CONFIG_PINCTRL_MVEBU=y +# CONFIG_PINCTRL_SINGLE is not set +CONFIG_PJ4B_ERRATA_4742=y +CONFIG_PL310_ERRATA_753970=y +CONFIG_PLAT_ORION=y +CONFIG_PM_OPP=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_GPIO=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +CONFIG_PWM=y +CONFIG_PWM_SYSFS=y +CONFIG_RATIONAL=y +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_RFS_ACCEL=y +CONFIG_RPS=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_ARMADA38X=y +# CONFIG_RTC_DRV_MV is not set +CONFIG_RTC_I2C_AND_SPI=y +CONFIG_RTC_MC146818_LIB=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_SATA_AHCI_PLATFORM=y +CONFIG_SATA_HOST=y +CONFIG_SATA_MV=y +CONFIG_SATA_PMP=y +CONFIG_SCSI=y +CONFIG_SCSI_COMMON=y +CONFIG_SENSORS_PWM_FAN=y +CONFIG_SENSORS_TMP421=y +CONFIG_SERIAL_8250_DW=y +CONFIG_SERIAL_8250_DWLIB=y +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_MVEBU_CONSOLE=y +CONFIG_SERIAL_MVEBU_UART=y +CONFIG_SFP=y +CONFIG_SGL_ALLOC=y +CONFIG_SG_POOL=y +CONFIG_SMP=y +CONFIG_SMP_ON_UP=y +CONFIG_SOCK_RX_QUEUE_MAPPING=y +CONFIG_SOC_BUS=y +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +# CONFIG_SPI_ARMADA_3700 is not set +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +CONFIG_SPI_ORION=y +CONFIG_SRAM=y +CONFIG_SRAM_EXEC=y +CONFIG_SRCU=y +CONFIG_SWPHY=y +CONFIG_SWP_EMULATE=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_THERMAL_HWMON=y +CONFIG_THERMAL_OF=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y +CONFIG_UBIFS_FS=y +CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" +CONFIG_UNWINDER_ARM=y +CONFIG_USB=y +CONFIG_USB_COMMON=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_HCD_ORION=y +CONFIG_USB_EHCI_HCD_PLATFORM=y +CONFIG_USB_LEDS_TRIGGER_USBPORT=y +CONFIG_USB_PHY=y +CONFIG_USB_STORAGE=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_MVEBU=y +CONFIG_USB_XHCI_PLATFORM=y +CONFIG_USE_OF=y +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_WATCHDOG_CORE=y +CONFIG_XPS=y +CONFIG_XXHASH=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_BCJ=y +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZSTD_COMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/mvebu/cortexa53/config-6.1 b/target/linux/mvebu/cortexa53/config-6.1 new file mode 100644 index 0000000000..27d410f68b --- /dev/null +++ b/target/linux/mvebu/cortexa53/config-6.1 @@ -0,0 +1,83 @@ +CONFIG_64BIT=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y +CONFIG_ARCH_MMAP_RND_BITS=18 +CONFIG_ARCH_MMAP_RND_BITS_MAX=24 +CONFIG_ARCH_MMAP_RND_BITS_MIN=18 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 +CONFIG_ARCH_PROC_KCORE_TEXT=y +CONFIG_ARCH_STACKWALK=y +CONFIG_ARCH_WANTS_NO_INSTR=y +CONFIG_ARM64=y +CONFIG_ARM64_4K_PAGES=y +CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y +CONFIG_ARM64_PAGE_SHIFT=12 +CONFIG_ARM64_PA_BITS=48 +CONFIG_ARM64_PA_BITS_48=y +CONFIG_ARM64_TAGGED_ADDR_ABI=y +CONFIG_ARM64_VA_BITS=39 +CONFIG_ARM64_VA_BITS_39=y +CONFIG_ARMADA_37XX_CLK=y +CONFIG_ARMADA_37XX_RWTM_MBOX=y +CONFIG_ARMADA_37XX_WATCHDOG=y +CONFIG_ARMADA_AP806_SYSCON=y +CONFIG_ARMADA_AP_CP_HELPER=y +CONFIG_ARMADA_CP110_SYSCON=y +CONFIG_ARM_AMBA=y +CONFIG_ARM_ARCH_TIMER=y +# CONFIG_ARM_ARCH_TIMER_EVTSTREAM is not set +CONFIG_ARM_ARMADA_37XX_CPUFREQ=y +CONFIG_ARM_GIC_V2M=y +CONFIG_ARM_GIC_V3=y +CONFIG_ARM_GIC_V3_ITS=y +CONFIG_ARM_GIC_V3_ITS_PCI=y +# CONFIG_ARM_MHU_V2 is not set +# CONFIG_ARM_PL172_MPMC is not set +CONFIG_ARM_PSCI_FW=y +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_DMA_DIRECT_REMAP=y +CONFIG_FRAME_POINTER=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_FIND_FIRST_BIT=y +CONFIG_GENERIC_PINCONF=y +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_MAILBOX=y +# CONFIG_MAILBOX_TEST is not set +CONFIG_MFD_SYSCON=y +CONFIG_MMC_SDHCI_XENON=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_MVEBU_GICP=y +CONFIG_MVEBU_ICU=y +CONFIG_MVEBU_ODMI=y +CONFIG_MVEBU_PIC=y +CONFIG_MVEBU_SEI=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_PARTITION_PERCPU=y +CONFIG_PCI_AARDVARK=y +CONFIG_PGTABLE_LEVELS=3 +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_PHY_MVEBU_A3700_COMPHY=y +CONFIG_PHY_MVEBU_A3700_UTMI=y +CONFIG_PINCTRL_ARMADA_37XX=y +CONFIG_PINCTRL_ARMADA_AP806=y +CONFIG_PINCTRL_ARMADA_CP110=y +CONFIG_POWER_SUPPLY=y +CONFIG_QUEUED_RWLOCKS=y +CONFIG_QUEUED_SPINLOCKS=y +CONFIG_REGULATOR_GPIO=y +CONFIG_RODATA_FULL_DEFAULT_ENABLED=y +CONFIG_SPARSEMEM=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPI_ARMADA_3700=y +CONFIG_SWIOTLB=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_THREAD_INFO_IN_TASK=y +CONFIG_TURRIS_MOX_RWTM=y +CONFIG_UNMAP_KERNEL_AT_EL0=y +CONFIG_VMAP_STACK=y +CONFIG_ZONE_DMA32=y diff --git a/target/linux/mvebu/cortexa72/config-6.1 b/target/linux/mvebu/cortexa72/config-6.1 new file mode 100644 index 0000000000..cb27e0285f --- /dev/null +++ b/target/linux/mvebu/cortexa72/config-6.1 @@ -0,0 +1,97 @@ +CONFIG_64BIT=y +CONFIG_AQUANTIA_PHY=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y +CONFIG_ARCH_MMAP_RND_BITS=18 +CONFIG_ARCH_MMAP_RND_BITS_MAX=24 +CONFIG_ARCH_MMAP_RND_BITS_MIN=18 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 +CONFIG_ARCH_PROC_KCORE_TEXT=y +CONFIG_ARCH_STACKWALK=y +CONFIG_ARCH_WANTS_NO_INSTR=y +CONFIG_ARM64=y +CONFIG_ARM64_4K_PAGES=y +CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y +CONFIG_ARM64_ERRATUM_1742098=y +CONFIG_ARM64_PAGE_SHIFT=12 +CONFIG_ARM64_PA_BITS=48 +CONFIG_ARM64_PA_BITS_48=y +CONFIG_ARM64_SVE=y +# CONFIG_ARM64_TAGGED_ADDR_ABI is not set +CONFIG_ARM64_VA_BITS=39 +CONFIG_ARM64_VA_BITS_39=y +CONFIG_ARMADA_37XX_CLK=y +CONFIG_ARMADA_AP806_SYSCON=y +CONFIG_ARMADA_AP_CPU_CLK=y +CONFIG_ARMADA_AP_CP_HELPER=y +CONFIG_ARMADA_CP110_SYSCON=y +CONFIG_ARM_AMBA=y +CONFIG_ARM_ARCH_TIMER=y +# CONFIG_ARM_ARCH_TIMER_EVTSTREAM is not set +CONFIG_ARM_ARMADA_8K_CPUFREQ=y +CONFIG_ARM_GIC_V2M=y +CONFIG_ARM_GIC_V3=y +CONFIG_ARM_GIC_V3_ITS=y +CONFIG_ARM_GIC_V3_ITS_PCI=y +# CONFIG_ARM_PL172_MPMC is not set +CONFIG_ARM_PSCI_FW=y +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_DMA_DIRECT_REMAP=y +CONFIG_FRAME_POINTER=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_FIND_FIRST_BIT=y +CONFIG_GENERIC_PINCONF=y +CONFIG_HW_RANDOM_OMAP=y +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_LEDS_IEI_WT61P803_PUZZLE=y +CONFIG_LEDS_IS31FL319X=y +CONFIG_MARVELL_10G_PHY=y +CONFIG_MFD_CORE=y +CONFIG_MFD_IEI_WT61P803_PUZZLE=y +CONFIG_MFD_SYSCON=y +CONFIG_MMC_SDHCI_XENON=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_MVEBU_GICP=y +CONFIG_MVEBU_ICU=y +CONFIG_MVEBU_ODMI=y +CONFIG_MVEBU_PIC=y +CONFIG_MVEBU_SEI=y +CONFIG_MVPP2=y +CONFIG_MV_XOR_V2=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_PARTITION_PERCPU=y +CONFIG_PCIEAER=y +CONFIG_PCIEPORTBUS=y +CONFIG_PCIE_ARMADA_8K=y +CONFIG_PCIE_DW=y +CONFIG_PCIE_DW_HOST=y +# CONFIG_PCI_AARDVARK is not set +CONFIG_PGTABLE_LEVELS=3 +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_PHY_MVEBU_CP110_COMPHY=y +CONFIG_PINCTRL_ARMADA_37XX=y +CONFIG_PINCTRL_ARMADA_AP806=y +CONFIG_PINCTRL_ARMADA_CP110=y +CONFIG_POWER_SUPPLY=y +CONFIG_QUEUED_RWLOCKS=y +CONFIG_QUEUED_SPINLOCKS=y +CONFIG_RAS=y +# CONFIG_RAVE_SP_CORE is not set +CONFIG_REGULATOR_GPIO=y +# CONFIG_RODATA_FULL_DEFAULT_ENABLED is not set +CONFIG_SENSORS_IEI_WT61P803_PUZZLE_HWMON=y +CONFIG_SERIAL_DEV_BUS=y +CONFIG_SERIAL_DEV_CTRL_TTYPORT=y +CONFIG_SPARSEMEM=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SWIOTLB=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_THREAD_INFO_IN_TASK=y +CONFIG_UNMAP_KERNEL_AT_EL0=y +CONFIG_VMAP_STACK=y +CONFIG_ZONE_DMA32=y diff --git a/target/linux/mvebu/cortexa9/config-6.1 b/target/linux/mvebu/cortexa9/config-6.1 new file mode 100644 index 0000000000..88a2f14c02 --- /dev/null +++ b/target/linux/mvebu/cortexa9/config-6.1 @@ -0,0 +1,3 @@ +CONFIG_LED_TRIGGER_PHY=y +CONFIG_PHY_MVEBU_A38X_COMPHY=y +CONFIG_RTC_DRV_MV=y From 801c67b4e09b16ac4a2b8a9fbde76d37cd67d91f Mon Sep 17 00:00:00 2001 From: Stefan Kalscheuer Date: Sun, 18 Jun 2023 17:06:57 +0200 Subject: [PATCH 22/23] mvebu: add kernel 6.1 as testing kernel With an initial set of patches and configs in place let's start testing with kernel 6.1. Run-tested on the cortexa9 subtarget (WRT1900ACS, Turris Omnia) Tested-by: Etienne Champetier Signed-off-by: Stefan Kalscheuer --- target/linux/mvebu/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/mvebu/Makefile b/target/linux/mvebu/Makefile index 2971f3fcaf..9f5d374abd 100644 --- a/target/linux/mvebu/Makefile +++ b/target/linux/mvebu/Makefile @@ -10,6 +10,7 @@ FEATURES:=fpu usb pci pcie gpio nand squashfs ramdisk boot-part rootfs-part lega SUBTARGETS:=cortexa9 cortexa53 cortexa72 KERNEL_PATCHVER:=5.15 +KERNEL_TESTING_PATCHVER:=6.1 include $(INCLUDE_DIR)/target.mk From 57fda4b743ecf06c217d2670002313d528ff817a Mon Sep 17 00:00:00 2001 From: Nick Hainke Date: Wed, 2 Aug 2023 14:18:31 +0200 Subject: [PATCH 23/23] tools/ccache: update to 4.8.2 Release Notes: https://ccache.dev/releasenotes.html#_ccache_4_8_2 Refresh patch: - 100-honour-copts.patch Signed-off-by: Nick Hainke --- tools/ccache/Makefile | 4 ++-- tools/ccache/patches/100-honour-copts.patch | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/ccache/Makefile b/tools/ccache/Makefile index 33255e9297..0571a994b8 100644 --- a/tools/ccache/Makefile +++ b/tools/ccache/Makefile @@ -7,11 +7,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ccache -PKG_VERSION:=4.8.1 +PKG_VERSION:=4.8.2 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=https://github.com/ccache/ccache/releases/download/v$(PKG_VERSION) -PKG_HASH:=87959b6819530b3dcaeb39992f585b9fc2c7120302809741378097774919fb6f +PKG_HASH:=3d3fb3f888a5b16c4fa7ee5214cca76348afd6130e8443de5f6f2424f2076a49 include $(INCLUDE_DIR)/host-build.mk include $(INCLUDE_DIR)/cmake.mk diff --git a/tools/ccache/patches/100-honour-copts.patch b/tools/ccache/patches/100-honour-copts.patch index da72af922d..91dc35536f 100644 --- a/tools/ccache/patches/100-honour-copts.patch +++ b/tools/ccache/patches/100-honour-copts.patch @@ -1,6 +1,6 @@ --- a/src/ccache.cpp +++ b/src/ccache.cpp -@@ -1813,6 +1813,7 @@ get_manifest_key(Context& ctx, Hash& has +@@ -1815,6 +1815,7 @@ get_manifest_key(Context& ctx, Hash& has "CPLUS_INCLUDE_PATH", "OBJC_INCLUDE_PATH", "OBJCPLUS_INCLUDE_PATH", // clang