From fcef1ead3ab95dff073d1c84cfe6320d483ea8e3 Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Mon, 2 Dec 2024 16:50:51 +0100 Subject: [PATCH 1/5] utils: kernel-refresh.sh: Only remove old patches if they exist E.g., when upgrading to a new version, there are no previous patches to remove. --- utils/kernel-refresh.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/utils/kernel-refresh.sh b/utils/kernel-refresh.sh index 760fc69e..74f9cad5 100755 --- a/utils/kernel-refresh.sh +++ b/utils/kernel-refresh.sh @@ -60,6 +60,9 @@ if ! [ "$PDIR" ]; then exit 1 fi -git -C $PDIR rm *.patch +KDIR=$(readlink -f $KDIR) +PDIR=$(readlink -f $PDIR) + +git ls-files --error-unmatch $PDIR 1>/dev/null 2>&1 && git -C $PDIR rm *.patch git -C $KDIR format-patch -o $PDIR $KTAG..HEAD git -C $PDIR add *.patch From a3f85a38729943209610767d2fe052390b3c57d9 Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Mon, 2 Dec 2024 16:25:46 +0100 Subject: [PATCH 2/5] linux: Upgrade to 6.12.1 Exploratory change to smoke out any regressions that this might introduce. --- board/aarch64/linux_defconfig | 14 +- board/x86_64/linux_defconfig | 1 - configs/aarch64_defconfig | 2 +- configs/aarch64_minimal_defconfig | 2 +- configs/x86_64_defconfig | 2 +- configs/x86_64_minimal_defconfig | 2 +- ...e6xxx-Fix-timeout-on-waiting-for-PPU.patch | 32 ++ ...x-Improve-indirect-register-access-p.patch | 216 ++++++++ ...x-Honor-ports-being-managed-via-in-b.patch | 48 ++ ...x-Limit-rsvd2cpu-policy-to-user-port.patch | 103 ++++ ...dsa-mv88e6xxx-Add-LED-infrastructure.patch | 316 +++++++++++ ...-mv88e6xxx-Add-LED-support-for-6393X.patch | 364 ++++++++++++ ...Use-tag-priority-as-initial-skb-prio.patch | 48 ++ ...MDB-memberships-whose-L2-addresses-o.patch | 74 +++ ...t-EtherType-based-priority-overrides.patch | 118 ++++ ...x-Support-EtherType-based-priority-o.patch | 376 +++++++++++++ ...a-mv88e6xxx-Add-mqprio-qdisc-support.patch | 162 ++++++ ...x-Use-VLAN-prio-over-IP-when-both-ar.patch | 62 +++ ...8e6xxx-Trap-locally-terminated-VLANs.patch | 161 ++++++ ...0g-Support-firmware-loading-on-88X33.patch | 241 ++++++++ ...0g-Fix-power-up-when-strapped-to-sta.patch | 50 ++ ...rvell10g-Add-LED-support-for-88X3310.patch | 517 ++++++++++++++++++ ...0g-Support-LEDs-tied-to-a-single-med.patch | 80 +++ ...phy-Do-not-resume-PHY-when-attaching.patch | 38 ++ ...-classifying-unknown-multicast-as-mr.patch | 237 ++++++++ ...e-router-ports-when-forwarding-L2-mu.patch | 37 ++ ...delay-for-applying-strict-multicast-.patch | 191 +++++++ ...rentiate-MDB-additions-from-modifica.patch | 109 ++++ ...ie-tlv-Let-device-probe-even-when-TL.patch | 55 ++ ...t-log-level-for-unauthorized-devices.patch | 50 ++ 30 files changed, 3700 insertions(+), 8 deletions(-) create mode 100644 patches/linux/6.12.1/0001-FIX-net-dsa-mv88e6xxx-Fix-timeout-on-waiting-for-PPU.patch create mode 100644 patches/linux/6.12.1/0002-net-dsa-mv88e6xxx-Improve-indirect-register-access-p.patch create mode 100644 patches/linux/6.12.1/0003-net-dsa-mv88e6xxx-Honor-ports-being-managed-via-in-b.patch create mode 100644 patches/linux/6.12.1/0004-net-dsa-mv88e6xxx-Limit-rsvd2cpu-policy-to-user-port.patch create mode 100644 patches/linux/6.12.1/0005-net-dsa-mv88e6xxx-Add-LED-infrastructure.patch create mode 100644 patches/linux/6.12.1/0006-net-dsa-mv88e6xxx-Add-LED-support-for-6393X.patch create mode 100644 patches/linux/6.12.1/0007-net-dsa-tag_dsa-Use-tag-priority-as-initial-skb-prio.patch create mode 100644 patches/linux/6.12.1/0008-net-dsa-Support-MDB-memberships-whose-L2-addresses-o.patch create mode 100644 patches/linux/6.12.1/0009-net-dsa-Support-EtherType-based-priority-overrides.patch create mode 100644 patches/linux/6.12.1/0010-net-dsa-mv88e6xxx-Support-EtherType-based-priority-o.patch create mode 100644 patches/linux/6.12.1/0011-net-dsa-mv88e6xxx-Add-mqprio-qdisc-support.patch create mode 100644 patches/linux/6.12.1/0012-net-dsa-mv88e6xxx-Use-VLAN-prio-over-IP-when-both-ar.patch create mode 100644 patches/linux/6.12.1/0013-FIX-net-dsa-mv88e6xxx-Trap-locally-terminated-VLANs.patch create mode 100644 patches/linux/6.12.1/0014-net-phy-marvell10g-Support-firmware-loading-on-88X33.patch create mode 100644 patches/linux/6.12.1/0015-net-phy-marvell10g-Fix-power-up-when-strapped-to-sta.patch create mode 100644 patches/linux/6.12.1/0016-net-phy-marvell10g-Add-LED-support-for-88X3310.patch create mode 100644 patches/linux/6.12.1/0017-net-phy-marvell10g-Support-LEDs-tied-to-a-single-med.patch create mode 100644 patches/linux/6.12.1/0018-net-phy-Do-not-resume-PHY-when-attaching.patch create mode 100644 patches/linux/6.12.1/0019-net-bridge-avoid-classifying-unknown-multicast-as-mr.patch create mode 100644 patches/linux/6.12.1/0020-net-bridge-Ignore-router-ports-when-forwarding-L2-mu.patch create mode 100644 patches/linux/6.12.1/0021-net-bridge-drop-delay-for-applying-strict-multicast-.patch create mode 100644 patches/linux/6.12.1/0022-net-bridge-Differentiate-MDB-additions-from-modifica.patch create mode 100644 patches/linux/6.12.1/0023-nvmem-layouts-onie-tlv-Let-device-probe-even-when-TL.patch create mode 100644 patches/linux/6.12.1/0024-usb-core-adjust-log-level-for-unauthorized-devices.patch diff --git a/board/aarch64/linux_defconfig b/board/aarch64/linux_defconfig index 054a13d6..f6efbf0d 100644 --- a/board/aarch64/linux_defconfig +++ b/board/aarch64/linux_defconfig @@ -34,6 +34,10 @@ CONFIG_PROFILING=y CONFIG_ARCH_SPARX5=y CONFIG_ARCH_MVEBU=y CONFIG_ARCH_VEXPRESS=y +CONFIG_ARM64_ERRATUM_2441007=y +CONFIG_ARM64_ERRATUM_1286807=y +CONFIG_ARM64_ERRATUM_1542419=y +CONFIG_ARM64_ERRATUM_2441009=y CONFIG_ARM64_VA_BITS_48=y CONFIG_SCHED_MC=y CONFIG_NR_CPUS=64 @@ -57,6 +61,7 @@ CONFIG_MODULE_UNLOAD=y CONFIG_KSM=y CONFIG_TRANSPARENT_HUGEPAGE=y CONFIG_CMA=y +CONFIG_CMA_AREAS=7 CONFIG_NET=y CONFIG_PACKET=y CONFIG_XDP_SOCKETS=y @@ -165,7 +170,6 @@ CONFIG_BRIDGE_EBT_REDIRECT=m CONFIG_BRIDGE_EBT_SNAT=m CONFIG_BRIDGE_EBT_LOG=m CONFIG_BRIDGE_EBT_NFLOG=m -CONFIG_BPFILTER=y CONFIG_BRIDGE=y CONFIG_BRIDGE_VLAN_FILTERING=y CONFIG_BRIDGE_MRP=y @@ -227,6 +231,7 @@ CONFIG_SCSI_SAS_ATA=y CONFIG_SCSI_VIRTIO=y CONFIG_ATA=y CONFIG_SATA_AHCI=y +CONFIG_SATA_MOBILE_LPM_POLICY=0 CONFIG_SATA_AHCI_PLATFORM=y CONFIG_AHCI_MVEBU=y CONFIG_PATA_OF_PLATFORM=y @@ -282,6 +287,7 @@ CONFIG_NET_DSA_MV88E6XXX_PTP=y CONFIG_MVNETA=m CONFIG_MVPP2=m # CONFIG_NET_VENDOR_MELLANOX is not set +# CONFIG_NET_VENDOR_META is not set # CONFIG_NET_VENDOR_MICREL is not set CONFIG_SPARX5_SWITCH=y # CONFIG_NET_VENDOR_MICROSEMI is not set @@ -353,13 +359,14 @@ CONFIG_SERIAL_XILINX_PS_UART=y CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y CONFIG_SERIAL_MVEBU_UART=y CONFIG_VIRTIO_CONSOLE=y +CONFIG_HW_RANDOM_CN10K=m CONFIG_I2C=y CONFIG_I2C_CHARDEV=y CONFIG_I2C_MUX=y CONFIG_I2C_MUX_GPIO=y CONFIG_I2C_MUX_PCA954x=y CONFIG_I2C_MUX_PINCTRL=y -CONFIG_I2C_DESIGNWARE_PLATFORM=y +CONFIG_I2C_DESIGNWARE_CORE=y CONFIG_I2C_MV64XXX=y CONFIG_I2C_SLAVE=y CONFIG_SPI=y @@ -495,6 +502,7 @@ CONFIG_EXTCON_USB_GPIO=y CONFIG_IIO=y CONFIG_TI_ADC081C=y CONFIG_PWM=y +CONFIG_RESET_GPIO=y CONFIG_PHY_MVEBU_CP110_COMPHY=y CONFIG_PHY_MVEBU_CP110_UTMI=y CONFIG_PHY_SAMSUNG_USB2=y @@ -523,13 +531,13 @@ CONFIG_9P_FS=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y CONFIG_SECURITY=y +CONFIG_LSM="landlock,lockdown,yama,loadpin,safesetid,bpf" CONFIG_CRYPTO_CCM=m CONFIG_CRYPTO_ECHAINIV=y CONFIG_CRYPTO_ANSI_CPRNG=y CONFIG_CRYPTO_GHASH_ARM64_CE=y CONFIG_CRYPTO_SHA1_ARM64_CE=y CONFIG_CRYPTO_SHA2_ARM64_CE=y -CONFIG_CRYPTO_AES_ARM64_CE_BLK=y CONFIG_CRYPTO_AES_ARM64_CE_CCM=y CONFIG_DMA_CMA=y CONFIG_CMA_SIZE_MBYTES=0 diff --git a/board/x86_64/linux_defconfig b/board/x86_64/linux_defconfig index 25fa755b..c2e05ac1 100644 --- a/board/x86_64/linux_defconfig +++ b/board/x86_64/linux_defconfig @@ -145,7 +145,6 @@ CONFIG_BRIDGE_EBT_REDIRECT=m CONFIG_BRIDGE_EBT_SNAT=m CONFIG_BRIDGE_EBT_LOG=m CONFIG_BRIDGE_EBT_NFLOG=m -CONFIG_BPFILTER=y CONFIG_BRIDGE=y CONFIG_BRIDGE_VLAN_FILTERING=y CONFIG_BRIDGE_MRP=y diff --git a/configs/aarch64_defconfig b/configs/aarch64_defconfig index 1b505875..797decfd 100644 --- a/configs/aarch64_defconfig +++ b/configs/aarch64_defconfig @@ -27,7 +27,7 @@ BR2_ROOTFS_POST_BUILD_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh" BR2_LINUX_KERNEL=y BR2_LINUX_KERNEL_CUSTOM_VERSION=y -BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.6.52" +BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.1" BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/aarch64/linux_defconfig" BR2_LINUX_KERNEL_DTS_SUPPORT=y diff --git a/configs/aarch64_minimal_defconfig b/configs/aarch64_minimal_defconfig index 736c64d0..ecb0ccd9 100644 --- a/configs/aarch64_minimal_defconfig +++ b/configs/aarch64_minimal_defconfig @@ -27,7 +27,7 @@ BR2_ROOTFS_POST_BUILD_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh" BR2_LINUX_KERNEL=y BR2_LINUX_KERNEL_CUSTOM_VERSION=y -BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.6.52" +BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.1" BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/aarch64/linux_defconfig" BR2_LINUX_KERNEL_DTS_SUPPORT=y diff --git a/configs/x86_64_defconfig b/configs/x86_64_defconfig index 5ec8fde0..c82b0937 100644 --- a/configs/x86_64_defconfig +++ b/configs/x86_64_defconfig @@ -26,7 +26,7 @@ BR2_ROOTFS_POST_BUILD_SCRIPT="board/qemu/x86_64/post-build.sh ${BR2_EXTERNAL_INF BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh" BR2_LINUX_KERNEL=y BR2_LINUX_KERNEL_CUSTOM_VERSION=y -BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.6.52" +BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.1" BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/x86_64/linux_defconfig" BR2_LINUX_KERNEL_INSTALL_TARGET=y diff --git a/configs/x86_64_minimal_defconfig b/configs/x86_64_minimal_defconfig index 9d6ca50f..0f3b70c9 100644 --- a/configs/x86_64_minimal_defconfig +++ b/configs/x86_64_minimal_defconfig @@ -26,7 +26,7 @@ BR2_ROOTFS_POST_BUILD_SCRIPT="board/qemu/x86_64/post-build.sh ${BR2_EXTERNAL_INF BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh" BR2_LINUX_KERNEL=y BR2_LINUX_KERNEL_CUSTOM_VERSION=y -BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.6.52" +BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.1" BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/x86_64/linux_defconfig" BR2_LINUX_KERNEL_INSTALL_TARGET=y diff --git a/patches/linux/6.12.1/0001-FIX-net-dsa-mv88e6xxx-Fix-timeout-on-waiting-for-PPU.patch b/patches/linux/6.12.1/0001-FIX-net-dsa-mv88e6xxx-Fix-timeout-on-waiting-for-PPU.patch new file mode 100644 index 00000000..326d24ca --- /dev/null +++ b/patches/linux/6.12.1/0001-FIX-net-dsa-mv88e6xxx-Fix-timeout-on-waiting-for-PPU.patch @@ -0,0 +1,32 @@ +From f5f25417c0e65f45c6a254e5a1f00c4fd5919058 Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Tue, 12 Mar 2024 10:27:24 +0100 +Subject: [PATCH 01/24] [FIX] net: dsa: mv88e6xxx: Fix timeout on waiting for + PPU on 6393X +Organization: Addiva Elektronik + +In a multi-chip setup, delays of up to 750ms are observed before the +device (6393X) signals completion of PPU initialization (Global 1, +register 0, bit 15). Therefore, increase the timeout threshold to 1s. + +Signed-off-by: Tobias Waldekranz +--- + drivers/net/dsa/mv88e6xxx/chip.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c +index 284270a4ade1..1f0b0c07ed9d 100644 +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -86,7 +86,7 @@ int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val) + int mv88e6xxx_wait_mask(struct mv88e6xxx_chip *chip, int addr, int reg, + u16 mask, u16 val) + { +- const unsigned long timeout = jiffies + msecs_to_jiffies(50); ++ const unsigned long timeout = jiffies + msecs_to_jiffies(1000); + u16 data; + int err; + int i; +-- +2.43.0 + diff --git a/patches/linux/6.12.1/0002-net-dsa-mv88e6xxx-Improve-indirect-register-access-p.patch b/patches/linux/6.12.1/0002-net-dsa-mv88e6xxx-Improve-indirect-register-access-p.patch new file mode 100644 index 00000000..6bbb6c47 --- /dev/null +++ b/patches/linux/6.12.1/0002-net-dsa-mv88e6xxx-Improve-indirect-register-access-p.patch @@ -0,0 +1,216 @@ +From fc68336f274aac22426b271c4d4a7ef0bfc76006 Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Wed, 27 Mar 2024 15:52:43 +0100 +Subject: [PATCH 02/24] net: dsa: mv88e6xxx: Improve indirect register access + perf on 6393 +Organization: Addiva Elektronik + +When operating in multi-chip mode, the 6393 family maps a subset of +commonly used global registers to the outermost address space (in +which only the SMI command and data registers were available in +previous families). + +Therefore, add a new set of SMI operations which remaps accesses to +such registers to the corresponding directly addressable register. All +other accesses use the regular indirect interface. + +Signed-off-by: Tobias Waldekranz +--- + drivers/net/dsa/mv88e6xxx/chip.c | 7 +++ + drivers/net/dsa/mv88e6xxx/global1.h | 3 ++ + drivers/net/dsa/mv88e6xxx/global2.h | 3 ++ + drivers/net/dsa/mv88e6xxx/smi.c | 76 +++++++++++++++++++++++++++++ + drivers/net/dsa/mv88e6xxx/smi.h | 30 ++++++++++++ + 5 files changed, 119 insertions(+) + +diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c +index 1f0b0c07ed9d..f9d892d036be 100644 +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -6472,6 +6472,13 @@ static int mv88e6xxx_detect(struct mv88e6xxx_chip *chip) + /* Update the compatible info with the probed one */ + chip->info = info; + ++ /* Now that we know the exact chip in use, we might be able to ++ * make use of more efficient SMI operations ++ */ ++ err = mv88e6xxx_smi_init(chip, chip->bus, chip->sw_addr); ++ if (err) ++ return err; ++ + dev_info(chip->dev, "switch 0x%x detected: %s, revision %u\n", + chip->info->prod_num, chip->info->name, rev); + +diff --git a/drivers/net/dsa/mv88e6xxx/global1.h b/drivers/net/dsa/mv88e6xxx/global1.h +index 3dbb7a1b8fe1..5ea956aadecc 100644 +--- a/drivers/net/dsa/mv88e6xxx/global1.h ++++ b/drivers/net/dsa/mv88e6xxx/global1.h +@@ -218,6 +218,9 @@ + #define MV88E6390_G1_MONITOR_MGMT_CTL_PTR_CPU_DEST_MGMTPRI 0x00e0 + #define MV88E6390_G1_MONITOR_MGMT_CTL_DATA_MASK 0x00ff + ++/* Offset 0x1B: Free Queue Size Register */ ++#define MV88E6XXX_G1_FREE_Q_SIZE 0x1b ++ + /* Offset 0x1C: Global Control 2 */ + #define MV88E6XXX_G1_CTL2 0x1c + #define MV88E6185_G1_CTL2_CASCADE_PORT_MASK 0xf000 +diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h +index 82f9b410de0b..3663645621c9 100644 +--- a/drivers/net/dsa/mv88e6xxx/global2.h ++++ b/drivers/net/dsa/mv88e6xxx/global2.h +@@ -143,6 +143,9 @@ + #define MV88E6XXX_G2_PRIO_OVERRIDE_QFPRIEN 0x0008 + #define MV88E6XXX_G2_PRIO_OVERRIDE_DATA_MASK 0x0007 + ++/* Offset 0x13: IMP Communication/Debug Register */ ++#define MV88E6390_G2_IMP_COMM 0x13 ++ + /* Offset 0x14: EEPROM Command */ + #define MV88E6XXX_G2_EEPROM_CMD 0x14 + #define MV88E6XXX_G2_EEPROM_CMD_BUSY 0x8000 +diff --git a/drivers/net/dsa/mv88e6xxx/smi.c b/drivers/net/dsa/mv88e6xxx/smi.c +index a990271b7482..f54bb0e79030 100644 +--- a/drivers/net/dsa/mv88e6xxx/smi.c ++++ b/drivers/net/dsa/mv88e6xxx/smi.c +@@ -8,6 +8,8 @@ + */ + + #include "chip.h" ++#include "global1.h" ++#include "global2.h" + #include "smi.h" + + /* The switch ADDR[4:1] configuration pins define the chip SMI device address +@@ -168,6 +170,78 @@ static const struct mv88e6xxx_bus_ops mv88e6xxx_smi_indirect_ops = { + .init = mv88e6xxx_smi_indirect_init, + }; + ++static u8 mv88e6393_smi_indirect_remap(int dev, int reg) ++{ ++ static const u8 g1_remap[32] = { ++ [MV88E6352_G1_VTU_FID] = MV88E6393_SMI_G1_VTU_FID, ++ [MV88E6352_G1_VTU_SID] = MV88E6393_SMI_G1_VTU_SID, ++ [MV88E6XXX_G1_STS] = MV88E6393_SMI_G1_STS, ++ [MV88E6XXX_G1_VTU_OP] = MV88E6393_SMI_G1_VTU_OP, ++ [MV88E6XXX_G1_VTU_VID] = MV88E6393_SMI_G1_VTU_VID, ++ [MV88E6XXX_G1_VTU_DATA1] = MV88E6393_SMI_G1_VTU_DATA1, ++ [MV88E6XXX_G1_VTU_DATA2] = MV88E6393_SMI_G1_VTU_DATA2, ++ [MV88E6352_G1_ATU_FID] = MV88E6393_SMI_G1_ATU_FID, ++ [MV88E6XXX_G1_ATU_CTL] = MV88E6393_SMI_G1_ATU_CTL, ++ [MV88E6XXX_G1_ATU_OP] = MV88E6393_SMI_G1_ATU_OP, ++ [MV88E6XXX_G1_ATU_DATA] = MV88E6393_SMI_G1_ATU_DATA, ++ [MV88E6XXX_G1_ATU_MAC01] = MV88E6393_SMI_G1_ATU_MAC01, ++ [MV88E6XXX_G1_ATU_MAC23] = MV88E6393_SMI_G1_ATU_MAC23, ++ [MV88E6XXX_G1_ATU_MAC45] = MV88E6393_SMI_G1_ATU_MAC45, ++ [MV88E6XXX_G1_FREE_Q_SIZE] = MV88E6393_SMI_G1_FREE_Q_SIZE, ++ [MV88E6XXX_G1_STATS_OP] = MV88E6393_SMI_G1_STATS_OP, ++ [MV88E6XXX_G1_STATS_COUNTER_32] = MV88E6393_SMI_G1_STATS_COUNTER_32, ++ [MV88E6XXX_G1_STATS_COUNTER_01] = MV88E6393_SMI_G1_STATS_COUNTER_01, ++ }; ++ ++ static const u8 g2_remap[32] = { ++ [MV88E6390_G2_IMP_COMM] = MV88E6393_SMI_G2_IMP_COMM, ++ [MV88E6352_G2_AVB_CMD] = MV88E6393_SMI_G2_AVB_CMD, ++ [MV88E6352_G2_AVB_DATA] = MV88E6393_SMI_G2_AVB_DATA, ++ [MV88E6XXX_G2_SMI_PHY_CMD] = MV88E6393_SMI_G2_SMI_PHY_CMD, ++ [MV88E6XXX_G2_SMI_PHY_DATA] = MV88E6393_SMI_G2_SMI_PHY_DATA, ++ [MV88E6393X_G2_MACLINK_INT_SRC] = MV88E6393_SMI_G2_MACLINK_INT_SRC, ++ }; ++ ++ switch (dev) { ++ case 0x1b: ++ return g1_remap[reg]; ++ case 0x1c: ++ return g2_remap[reg]; ++ } ++ ++ return 0; ++} ++ ++static int mv88e6393_smi_indirect_read(struct mv88e6xxx_chip *chip, ++ int dev, int reg, u16 *data) ++{ ++ u8 remap = mv88e6393_smi_indirect_remap(dev, reg); ++ ++ if (remap) ++ return mv88e6xxx_smi_direct_read(chip, chip->sw_addr, ++ remap, data); ++ ++ return mv88e6xxx_smi_indirect_read(chip, dev, reg, data); ++} ++ ++static int mv88e6393_smi_indirect_write(struct mv88e6xxx_chip *chip, ++ int dev, int reg, u16 data) ++{ ++ u8 remap = mv88e6393_smi_indirect_remap(dev, reg); ++ ++ if (remap) ++ return mv88e6xxx_smi_direct_write(chip, chip->sw_addr, ++ remap, data); ++ ++ return mv88e6xxx_smi_indirect_write(chip, dev, reg, data); ++} ++ ++static const struct mv88e6xxx_bus_ops mv88e6393_smi_indirect_ops = { ++ .read = mv88e6393_smi_indirect_read, ++ .write = mv88e6393_smi_indirect_write, ++ .init = mv88e6xxx_smi_indirect_init, ++}; ++ + int mv88e6xxx_smi_init(struct mv88e6xxx_chip *chip, + struct mii_bus *bus, int sw_addr) + { +@@ -175,6 +249,8 @@ int mv88e6xxx_smi_init(struct mv88e6xxx_chip *chip, + chip->smi_ops = &mv88e6xxx_smi_dual_direct_ops; + else if (sw_addr == 0) + chip->smi_ops = &mv88e6xxx_smi_direct_ops; ++ else if (chip->info->family == MV88E6XXX_FAMILY_6393) ++ chip->smi_ops = &mv88e6393_smi_indirect_ops; + else if (chip->info->multi_chip) + chip->smi_ops = &mv88e6xxx_smi_indirect_ops; + else +diff --git a/drivers/net/dsa/mv88e6xxx/smi.h b/drivers/net/dsa/mv88e6xxx/smi.h +index c6c71d5757f5..788cf68b7b33 100644 +--- a/drivers/net/dsa/mv88e6xxx/smi.h ++++ b/drivers/net/dsa/mv88e6xxx/smi.h +@@ -31,6 +31,36 @@ + /* Offset 0x01: SMI Data Register */ + #define MV88E6XXX_SMI_DATA 0x01 + ++/* When using the 6393 in indirect addressing mode, a subset of the ++ * most commonly used registers are directly mapped out to the chip's ++ * top address space, allowing them to be directly accessed. ++ */ ++#define MV88E6393_SMI_G1_VTU_FID 0x02 ++#define MV88E6393_SMI_G1_VTU_SID 0x03 ++#define MV88E6393_SMI_G1_STS 0x04 ++#define MV88E6393_SMI_G1_VTU_OP 0x05 ++#define MV88E6393_SMI_G1_VTU_VID 0x06 ++#define MV88E6393_SMI_G1_VTU_DATA1 0x07 ++#define MV88E6393_SMI_G1_VTU_DATA2 0x08 ++#define MV88E6393_SMI_G1_ATU_FID 0x09 ++#define MV88E6393_SMI_G1_ATU_CTL 0x0a ++#define MV88E6393_SMI_G1_ATU_OP 0x0b ++#define MV88E6393_SMI_G1_ATU_DATA 0x0c ++#define MV88E6393_SMI_G1_ATU_MAC01 0x0d ++#define MV88E6393_SMI_G1_ATU_MAC23 0x0e ++#define MV88E6393_SMI_G1_ATU_MAC45 0x0f ++#define MV88E6393_SMI_G2_IMP_COMM 0x13 ++#define MV88E6393_SMI_G2_AVB_CMD 0x16 ++#define MV88E6393_SMI_G2_AVB_DATA 0x17 ++#define MV88E6393_SMI_G2_SMI_PHY_CMD 0x18 ++#define MV88E6393_SMI_G2_SMI_PHY_DATA 0x19 ++#define MV88E6393_SMI_G2_MACLINK_INT_SRC 0x1a ++#define MV88E6393_SMI_G1_FREE_Q_SIZE 0x1b ++#define MV88E6393_SMI_G1_STATS_OP 0x1d ++#define MV88E6393_SMI_G1_STATS_COUNTER_32 0x1e ++#define MV88E6393_SMI_G1_STATS_COUNTER_01 0x1f ++ ++ + int mv88e6xxx_smi_init(struct mv88e6xxx_chip *chip, + struct mii_bus *bus, int sw_addr); + +-- +2.43.0 + diff --git a/patches/linux/6.12.1/0003-net-dsa-mv88e6xxx-Honor-ports-being-managed-via-in-b.patch b/patches/linux/6.12.1/0003-net-dsa-mv88e6xxx-Honor-ports-being-managed-via-in-b.patch new file mode 100644 index 00000000..60cff120 --- /dev/null +++ b/patches/linux/6.12.1/0003-net-dsa-mv88e6xxx-Honor-ports-being-managed-via-in-b.patch @@ -0,0 +1,48 @@ +From 66e1fc9ab54680989c02dab907743133674a07cf Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Mon, 22 Apr 2024 23:18:01 +0200 +Subject: [PATCH 03/24] net: dsa: mv88e6xxx: Honor ports being managed via + in-band-status +Organization: Addiva Elektronik + +Keep all link parameters in their unforced states when the port is +declared as being managed via in-band-status, and let the MAC +configure itself, via whatever method is being used (e.g. SGMII or +USXGMII autoneg) + +This state is the default set up by mv88e6xxx_port_setup_mac(), so all +we have to do is to make the phylink MAC callbacks no-ops in cases +when in-band-status is being used. + +Signed-off-by: Tobias Waldekranz +--- + drivers/net/dsa/mv88e6xxx/chip.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c +index f9d892d036be..98bd635b0ba9 100644 +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -964,6 +964,9 @@ static void mv88e6xxx_mac_link_down(struct phylink_config *config, + int port = dp->index; + int err = 0; + ++ if (mode == MLO_AN_INBAND) ++ return; ++ + ops = chip->info->ops; + + mv88e6xxx_reg_lock(chip); +@@ -996,6 +999,9 @@ static void mv88e6xxx_mac_link_up(struct phylink_config *config, + int port = dp->index; + int err = 0; + ++ if (mode == MLO_AN_INBAND) ++ return; ++ + ops = chip->info->ops; + + mv88e6xxx_reg_lock(chip); +-- +2.43.0 + diff --git a/patches/linux/6.12.1/0004-net-dsa-mv88e6xxx-Limit-rsvd2cpu-policy-to-user-port.patch b/patches/linux/6.12.1/0004-net-dsa-mv88e6xxx-Limit-rsvd2cpu-policy-to-user-port.patch new file mode 100644 index 00000000..067813ac --- /dev/null +++ b/patches/linux/6.12.1/0004-net-dsa-mv88e6xxx-Limit-rsvd2cpu-policy-to-user-port.patch @@ -0,0 +1,103 @@ +From 7c9d33f9176e5d2173646aee7b15176e40fabbb0 Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Wed, 24 Apr 2024 22:41:04 +0200 +Subject: [PATCH 04/24] net: dsa: mv88e6xxx: Limit rsvd2cpu policy to user + ports on 6393X +Organization: Addiva Elektronik + +For packets with a DA in the IEEE reserved L2 group range, originating +from a CPU, forward it as normal, rather than classifying it as +management. + +Example use-case: + + bridge (group_fwd_mask 0x4000) + / | \ + swp1 swp2 tap0 + \ / +(mv88e6xxx) + +We've created a bridge with a non-zero group_fwd_mask (allowing LLDP +in this example) containing a set of ports managed by mv88e6xxx and +some foreign interface (e.g. an L2 VPN tunnel). + +Since an LLDP packet coming in to the bridge from the other side of +tap0 is eligable for tx forward offloading, a FORWARD frame destined +for swp1 and swp2 would be send to the conduit interface. + +Before this change, due to rsvd2cpu being enabled on the CPU port, the +switch would try to trap it back to the CPU. Given that the CPU is +trusted, instead assume that it indeed meant for the packet to be +forwarded like any other. + +Signed-off-by: Tobias Waldekranz +--- + drivers/net/dsa/mv88e6xxx/port.c | 31 +++++++++++++++++++++++++------ + 1 file changed, 25 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c +index 04053fdc6489..f25fb3214acb 100644 +--- a/drivers/net/dsa/mv88e6xxx/port.c ++++ b/drivers/net/dsa/mv88e6xxx/port.c +@@ -1432,6 +1432,23 @@ static int mv88e6393x_port_policy_write_all(struct mv88e6xxx_chip *chip, + return 0; + } + ++static int mv88e6393x_port_policy_write_user(struct mv88e6xxx_chip *chip, ++ u16 pointer, u8 data) ++{ ++ int err, port; ++ ++ for (port = 0; port < mv88e6xxx_num_ports(chip); port++) { ++ if (!dsa_is_user_port(chip->ds, port)) ++ continue; ++ ++ err = mv88e6393x_port_policy_write(chip, port, pointer, data); ++ if (err) ++ return err; ++ } ++ ++ return 0; ++} ++ + int mv88e6393x_set_egress_port(struct mv88e6xxx_chip *chip, + enum mv88e6xxx_egress_direction direction, + int port) +@@ -1473,26 +1490,28 @@ int mv88e6393x_port_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip) + int err; + + /* Consider the frames with reserved multicast destination +- * addresses matching 01:80:c2:00:00:00 and +- * 01:80:c2:00:00:02 as MGMT. ++ * addresses matching 01:80:c2:00:00:00 and 01:80:c2:00:00:02 ++ * as MGMT when received on user ports. Forward as normal on ++ * CPU/DSA ports, to support bridges with non-zero ++ * group_fwd_masks. + */ + ptr = MV88E6393X_PORT_POLICY_MGMT_CTL_PTR_01C280000000XLO; +- err = mv88e6393x_port_policy_write_all(chip, ptr, 0xff); ++ err = mv88e6393x_port_policy_write_user(chip, ptr, 0xff); + if (err) + return err; + + ptr = MV88E6393X_PORT_POLICY_MGMT_CTL_PTR_01C280000000XHI; +- err = mv88e6393x_port_policy_write_all(chip, ptr, 0xff); ++ err = mv88e6393x_port_policy_write_user(chip, ptr, 0xff); + if (err) + return err; + + ptr = MV88E6393X_PORT_POLICY_MGMT_CTL_PTR_01C280000002XLO; +- err = mv88e6393x_port_policy_write_all(chip, ptr, 0xff); ++ err = mv88e6393x_port_policy_write_user(chip, ptr, 0xff); + if (err) + return err; + + ptr = MV88E6393X_PORT_POLICY_MGMT_CTL_PTR_01C280000002XHI; +- err = mv88e6393x_port_policy_write_all(chip, ptr, 0xff); ++ err = mv88e6393x_port_policy_write_user(chip, ptr, 0xff); + if (err) + return err; + +-- +2.43.0 + diff --git a/patches/linux/6.12.1/0005-net-dsa-mv88e6xxx-Add-LED-infrastructure.patch b/patches/linux/6.12.1/0005-net-dsa-mv88e6xxx-Add-LED-infrastructure.patch new file mode 100644 index 00000000..307db072 --- /dev/null +++ b/patches/linux/6.12.1/0005-net-dsa-mv88e6xxx-Add-LED-infrastructure.patch @@ -0,0 +1,316 @@ +From 408a1681d4bbb44ede8d7d738f96a2fc27deb813 Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Thu, 16 Nov 2023 19:44:32 +0100 +Subject: [PATCH 05/24] net: dsa: mv88e6xxx: Add LED infrastructure +Organization: Addiva Elektronik + +Parse DT for LEDs and register them for devices that support it, +though no actual implementations exist yet. + +Signed-off-by: Tobias Waldekranz +--- + drivers/net/dsa/mv88e6xxx/Makefile | 1 + + drivers/net/dsa/mv88e6xxx/chip.c | 5 +- + drivers/net/dsa/mv88e6xxx/chip.h | 16 +++ + drivers/net/dsa/mv88e6xxx/leds.c | 185 +++++++++++++++++++++++++++++ + drivers/net/dsa/mv88e6xxx/leds.h | 12 ++ + 5 files changed, 218 insertions(+), 1 deletion(-) + create mode 100644 drivers/net/dsa/mv88e6xxx/leds.c + create mode 100644 drivers/net/dsa/mv88e6xxx/leds.h + +diff --git a/drivers/net/dsa/mv88e6xxx/Makefile b/drivers/net/dsa/mv88e6xxx/Makefile +index a9a9651187db..6720d9303914 100644 +--- a/drivers/net/dsa/mv88e6xxx/Makefile ++++ b/drivers/net/dsa/mv88e6xxx/Makefile +@@ -9,6 +9,7 @@ mv88e6xxx-objs += global2.o + mv88e6xxx-objs += global2_avb.o + mv88e6xxx-objs += global2_scratch.o + mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_PTP) += hwtstamp.o ++mv88e6xxx-objs += leds.o + mv88e6xxx-objs += pcs-6185.o + mv88e6xxx-objs += pcs-6352.o + mv88e6xxx-objs += pcs-639x.o +diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c +index 98bd635b0ba9..97cebc490fac 100644 +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -37,6 +37,7 @@ + #include "global1.h" + #include "global2.h" + #include "hwtstamp.h" ++#include "leds.h" + #include "phy.h" + #include "port.h" + #include "ptp.h" +@@ -4115,7 +4116,9 @@ static int mv88e6xxx_port_setup(struct dsa_switch *ds, int port) + return err; + } + +- return mv88e6xxx_setup_devlink_regions_port(ds, port); ++ err = err ? : mv88e6xxx_setup_devlink_regions_port(ds, port); ++ err = err ? : mv88e6xxx_port_setup_leds(ds, port); ++ return err; + } + + static void mv88e6xxx_port_teardown(struct dsa_switch *ds, int port) +diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h +index a54682240839..32c87ab754d1 100644 +--- a/drivers/net/dsa/mv88e6xxx/chip.h ++++ b/drivers/net/dsa/mv88e6xxx/chip.h +@@ -207,6 +207,7 @@ struct mv88e6xxx_avb_ops; + struct mv88e6xxx_ptp_ops; + struct mv88e6xxx_pcs_ops; + struct mv88e6xxx_cc_coeffs; ++struct mv88e6xxx_led_ops; + + struct mv88e6xxx_irq { + u16 masked; +@@ -330,6 +331,8 @@ struct mv88e6xxx_hw_stat { + int type; + }; + ++struct mv88e6xxx_led; ++ + struct mv88e6xxx_chip { + const struct mv88e6xxx_info *info; + +@@ -661,6 +664,9 @@ struct mv88e6xxx_ops { + /* Precision Time Protocol operations */ + const struct mv88e6xxx_ptp_ops *ptp_ops; + ++ /* LED operations */ ++ const struct mv88e6xxx_led_ops *led_ops; ++ + /* Phylink */ + void (*phylink_get_caps)(struct mv88e6xxx_chip *chip, int port, + struct phylink_config *config); +@@ -740,7 +746,17 @@ struct mv88e6xxx_pcs_ops { + void (*pcs_teardown)(struct mv88e6xxx_chip *chip, int port); + struct phylink_pcs *(*pcs_select)(struct mv88e6xxx_chip *chip, int port, + phy_interface_t mode); ++}; + ++struct mv88e6xxx_led_ops { ++ int (*brightness_set)(struct mv88e6xxx_led *led, ++ enum led_brightness brightness); ++ int (*blink_set)(struct mv88e6xxx_led *led, ++ unsigned long *delay_on, unsigned long *delay_off); ++ int (*hw_control_is_supported)(struct mv88e6xxx_led *led, ++ unsigned long flags); ++ int (*hw_control_set)(struct mv88e6xxx_led *led, unsigned long flags); ++ int (*hw_control_get)(struct mv88e6xxx_led *led, unsigned long *flags); + }; + + static inline bool mv88e6xxx_has_stu(struct mv88e6xxx_chip *chip) +diff --git a/drivers/net/dsa/mv88e6xxx/leds.c b/drivers/net/dsa/mv88e6xxx/leds.c +new file mode 100644 +index 000000000000..e3de10991f29 +--- /dev/null ++++ b/drivers/net/dsa/mv88e6xxx/leds.c +@@ -0,0 +1,185 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++#include ++ ++#include "chip.h" ++#include "leds.h" ++#include "port.h" ++ ++struct mv88e6xxx_led { ++ struct mv88e6xxx_chip *chip; ++ int port; ++ u8 index; ++ ++ struct led_classdev ldev; ++}; ++ ++static int mv88e6xxx_led_brightness_set(struct led_classdev *ldev, ++ enum led_brightness brightness) ++{ ++ const struct mv88e6xxx_led_ops *ops; ++ struct mv88e6xxx_led *led; ++ ++ led = container_of(ldev, struct mv88e6xxx_led, ldev); ++ ops = led->chip->info->ops->led_ops; ++ ++ if (!ops->brightness_set) ++ return -EOPNOTSUPP; ++ ++ return ops->brightness_set(led, brightness); ++} ++ ++static int mv88e6xxx_led_blink_set(struct led_classdev *ldev, ++ unsigned long *delay_on, ++ unsigned long *delay_off) ++{ ++ const struct mv88e6xxx_led_ops *ops; ++ struct mv88e6xxx_led *led; ++ ++ led = container_of(ldev, struct mv88e6xxx_led, ldev); ++ ops = led->chip->info->ops->led_ops; ++ ++ if (!ops->blink_set) ++ return -EOPNOTSUPP; ++ ++ return ops->blink_set(led, delay_on, delay_off); ++} ++ ++static int mv88e6xxx_led_hw_control_is_supported(struct led_classdev *ldev, ++ unsigned long flags) ++{ ++ const struct mv88e6xxx_led_ops *ops; ++ struct mv88e6xxx_led *led; ++ ++ led = container_of(ldev, struct mv88e6xxx_led, ldev); ++ ops = led->chip->info->ops->led_ops; ++ ++ if (!ops->hw_control_is_supported) ++ return -EOPNOTSUPP; ++ ++ return ops->hw_control_is_supported(led, flags); ++} ++ ++static int mv88e6xxx_led_hw_control_set(struct led_classdev *ldev, ++ unsigned long flags) ++{ ++ const struct mv88e6xxx_led_ops *ops; ++ struct mv88e6xxx_led *led; ++ ++ led = container_of(ldev, struct mv88e6xxx_led, ldev); ++ ops = led->chip->info->ops->led_ops; ++ ++ if (!ops->hw_control_set) ++ return -EOPNOTSUPP; ++ ++ return ops->hw_control_set(led, flags); ++} ++ ++static int mv88e6xxx_led_hw_control_get(struct led_classdev *ldev, ++ unsigned long *flags) ++{ ++ const struct mv88e6xxx_led_ops *ops; ++ struct mv88e6xxx_led *led; ++ ++ led = container_of(ldev, struct mv88e6xxx_led, ldev); ++ ops = led->chip->info->ops->led_ops; ++ ++ if (!ops->hw_control_get) ++ return -EOPNOTSUPP; ++ ++ return ops->hw_control_get(led, flags); ++} ++ ++static struct device *mv88e6xxx_led_hw_control_get_device(struct led_classdev *ldev) ++{ ++ struct mv88e6xxx_led *led; ++ struct dsa_port *dp; ++ ++ led = container_of(ldev, struct mv88e6xxx_led, ldev); ++ dp = dsa_to_port(led->chip->ds, led->port); ++ ++ if (dp && dp->user) ++ return &dp->user->dev; ++ ++ return NULL; ++} ++ ++static int mv88e6xxx_port_setup_led(struct mv88e6xxx_chip *chip, int port, ++ struct device_node *np) ++{ ++ struct led_init_data init_data = {}; ++ struct mv88e6xxx_led *led; ++ char *devname; ++ u32 index; ++ int err; ++ ++ err = of_property_read_u32(np, "reg", &index); ++ if (err) ++ return err; ++ ++ if (index >= 2) ++ return -EINVAL; ++ ++ led = devm_kzalloc(chip->dev, sizeof(*led), GFP_KERNEL); ++ if (!led) ++ return -ENOMEM; ++ ++ *led = (struct mv88e6xxx_led) { ++ .chip = chip, ++ .port = port, ++ .index = index, ++ ++ .ldev = { ++ .max_brightness = 1, ++ .brightness_set_blocking = mv88e6xxx_led_brightness_set, ++ .blink_set = mv88e6xxx_led_blink_set, ++ ++#ifdef CONFIG_LEDS_TRIGGERS ++ .hw_control_trigger = "netdev", ++ .hw_control_get_device = mv88e6xxx_led_hw_control_get_device, ++ ++ .hw_control_is_supported = mv88e6xxx_led_hw_control_is_supported, ++ .hw_control_set = mv88e6xxx_led_hw_control_set, ++ .hw_control_get = mv88e6xxx_led_hw_control_get, ++#endif ++ }, ++ }; ++ ++ devname = devm_kasprintf(chip->dev, GFP_KERNEL, "%s.%d", ++ dev_name(chip->dev), port); ++ if (!devname) ++ return -ENOMEM; ++ ++ init_data = (struct led_init_data) { ++ .fwnode = of_fwnode_handle(np), ++ .devname_mandatory = true, ++ .devicename = devname, ++ }; ++ ++ return devm_led_classdev_register_ext(chip->dev, &led->ldev, &init_data); ++} ++ ++int mv88e6xxx_port_setup_leds(struct dsa_switch *ds, int port) ++{ ++ struct dsa_port *dp = dsa_to_port(ds, port); ++ struct mv88e6xxx_chip *chip = ds->priv; ++ struct device_node *pnp, *np; ++ int err; ++ ++ if (!chip->info->ops->led_ops) ++ return 0; ++ ++ if (!dp->dn) ++ return 0; ++ ++ pnp = of_get_child_by_name(dp->dn, "leds"); ++ if (!pnp) ++ return 0; ++ ++ for_each_available_child_of_node(pnp, np) { ++ err = mv88e6xxx_port_setup_led(chip, port, np); ++ if (err) ++ return err; ++ } ++ ++ return 0; ++} +diff --git a/drivers/net/dsa/mv88e6xxx/leds.h b/drivers/net/dsa/mv88e6xxx/leds.h +new file mode 100644 +index 000000000000..8afa2a0c0527 +--- /dev/null ++++ b/drivers/net/dsa/mv88e6xxx/leds.h +@@ -0,0 +1,12 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++ ++/* Marvell 88E6xxx Switch leds support. */ ++ ++#ifndef _MV88E6XXX_LEDS_H ++#define _MV88E6XXX_LEDS_H ++ ++#include "chip.h" ++ ++int mv88e6xxx_port_setup_leds(struct dsa_switch *ds, int port); ++ ++#endif /* _MV88E6XXX_LEDS_H */ +-- +2.43.0 + diff --git a/patches/linux/6.12.1/0006-net-dsa-mv88e6xxx-Add-LED-support-for-6393X.patch b/patches/linux/6.12.1/0006-net-dsa-mv88e6xxx-Add-LED-support-for-6393X.patch new file mode 100644 index 00000000..63d6c460 --- /dev/null +++ b/patches/linux/6.12.1/0006-net-dsa-mv88e6xxx-Add-LED-support-for-6393X.patch @@ -0,0 +1,364 @@ +From 9bfe65e40336c449720f96230ccc22c831045e9d Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Thu, 16 Nov 2023 21:59:35 +0100 +Subject: [PATCH 06/24] net: dsa: mv88e6xxx: Add LED support for 6393X +Organization: Addiva Elektronik + +Trigger support: +- "none" +- "timer" +- "netdev" + +Signed-off-by: Tobias Waldekranz +--- + drivers/net/dsa/mv88e6xxx/chip.c | 1 + + drivers/net/dsa/mv88e6xxx/leds.c | 229 +++++++++++++++++++++++++++++++ + drivers/net/dsa/mv88e6xxx/leds.h | 2 + + drivers/net/dsa/mv88e6xxx/port.c | 33 +++++ + drivers/net/dsa/mv88e6xxx/port.h | 7 + + 5 files changed, 272 insertions(+) + +diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c +index 97cebc490fac..e8edf3970940 100644 +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -5627,6 +5627,7 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = { + .gpio_ops = &mv88e6352_gpio_ops, + .avb_ops = &mv88e6390_avb_ops, + .ptp_ops = &mv88e6352_ptp_ops, ++ .led_ops = &mv88e6393x_led_ops, + .phylink_get_caps = mv88e6393x_phylink_get_caps, + .pcs_ops = &mv88e6393x_pcs_ops, + }; +diff --git a/drivers/net/dsa/mv88e6xxx/leds.c b/drivers/net/dsa/mv88e6xxx/leds.c +index e3de10991f29..acdb5eca6647 100644 +--- a/drivers/net/dsa/mv88e6xxx/leds.c ++++ b/drivers/net/dsa/mv88e6xxx/leds.c +@@ -5,6 +5,13 @@ + #include "leds.h" + #include "port.h" + ++#define FLAG_ACT (BIT(TRIGGER_NETDEV_RX) | BIT(TRIGGER_NETDEV_TX)) ++#define FLAG_LINK BIT(TRIGGER_NETDEV_LINK) ++#define FLAG_LINK_10 BIT(TRIGGER_NETDEV_LINK_10) ++#define FLAG_LINK_100 BIT(TRIGGER_NETDEV_LINK_100) ++#define FLAG_LINK_1G BIT(TRIGGER_NETDEV_LINK_1000) ++#define FLAG_FULL BIT(TRIGGER_NETDEV_FULL_DUPLEX) ++ + struct mv88e6xxx_led { + struct mv88e6xxx_chip *chip; + int port; +@@ -13,6 +20,228 @@ struct mv88e6xxx_led { + struct led_classdev ldev; + }; + ++enum mv88e6393x_led_mode { ++ MV88E6393X_LED_MODE_BLINK = 0xd, ++ MV88E6393X_LED_MODE_OFF = 0xe, ++ MV88E6393X_LED_MODE_ON = 0xf, ++ ++ MV88E6393X_LED_MODES = 0x10 ++}; ++ ++static const unsigned long mv88e6393x_led_map_p1_p8[2][MV88E6393X_LED_MODES] = { ++ { ++ [0x1] = FLAG_ACT | FLAG_LINK_100 | FLAG_LINK_1G, ++ [0x2] = FLAG_ACT | FLAG_LINK_1G, ++ [0x3] = FLAG_ACT | FLAG_LINK, ++ [0x6] = FLAG_FULL, ++ [0x7] = FLAG_ACT | FLAG_LINK_10 | FLAG_LINK_1G, ++ [0x8] = FLAG_LINK, ++ [0x9] = FLAG_LINK_10, ++ [0xa] = FLAG_ACT | FLAG_LINK_10, ++ [0xb] = FLAG_LINK_100 | FLAG_LINK_1G, ++ }, ++ { ++ [0x1] = FLAG_ACT, ++ [0x2] = FLAG_ACT | FLAG_LINK_10 | FLAG_LINK_100, ++ [0x3] = FLAG_LINK_1G, ++ [0x5] = FLAG_ACT | FLAG_LINK, ++ [0x6] = FLAG_ACT | FLAG_LINK_10 | FLAG_LINK_1G, ++ [0x7] = FLAG_LINK_10 | FLAG_LINK_1G, ++ [0x9] = FLAG_LINK_100, ++ [0xa] = FLAG_ACT | FLAG_LINK_100, ++ [0xb] = FLAG_LINK_10 | FLAG_LINK_100, ++ } ++}; ++ ++static const unsigned long mv88e6393x_led_map_p9_p10[2][MV88E6393X_LED_MODES] = { ++ { ++ [0x1] = FLAG_ACT | FLAG_LINK, ++ }, ++ { ++ [0x6] = FLAG_FULL, ++ [0x7] = FLAG_ACT | FLAG_LINK, ++ [0x8] = FLAG_LINK, ++ } ++}; ++ ++static const unsigned long *mv88e6393x_led_map(struct mv88e6xxx_led *led) ++{ ++ switch (led->port) { ++ case 1: ++ case 2: ++ case 3: ++ case 4: ++ case 5: ++ case 6: ++ case 7: ++ case 8: ++ return mv88e6393x_led_map_p1_p8[led->index]; ++ case 9: ++ case 10: ++ return mv88e6393x_led_map_p9_p10[led->index]; ++ } ++ ++ return NULL; ++} ++ ++static int mv88e6393x_led_flags_to_mode(struct mv88e6xxx_led *led, unsigned long flags) ++{ ++ const unsigned long *map = mv88e6393x_led_map(led); ++ int i; ++ ++ if (!map) ++ return -ENODEV; ++ ++ if (!flags) ++ return MV88E6393X_LED_MODE_OFF; ++ ++ for (i = 0; i < MV88E6393X_LED_MODES; i++) { ++ if (map[i] == flags) ++ return i; ++ } ++ ++ return -EOPNOTSUPP; ++} ++ ++static int mv88e6393x_led_mode_to_flags(struct mv88e6xxx_led *led, u8 mode, ++ unsigned long *flags) ++{ ++ const unsigned long *map = mv88e6393x_led_map(led); ++ ++ if (!map) ++ return -ENODEV; ++ ++ if (mode == MV88E6393X_LED_MODE_OFF) { ++ *flags = 0; ++ return 0; ++ } ++ ++ if (map[mode]) { ++ *flags = map[mode]; ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++ ++static int mv88e6393x_led_set(struct mv88e6xxx_led *led, int mode) ++{ ++ u16 ctrl; ++ int err; ++ ++ if (mode < 0) ++ return mode; ++ ++ mv88e6xxx_reg_lock(led->chip); ++ ++ err = mv88e6393x_port_led_read(led->chip, led->port, 0, &ctrl); ++ if (err) ++ goto out; ++ ++ switch (led->index) { ++ case 0: ++ ctrl &= ~0x0f; ++ ctrl |= mode; ++ break; ++ case 1: ++ ctrl &= ~0xf0; ++ ctrl |= mode << 4; ++ } ++ ++ err = mv88e6393x_port_led_write(led->chip, led->port, 0, ctrl); ++out: ++ mv88e6xxx_reg_unlock(led->chip); ++ return err; ++} ++ ++static int mv88e6393x_led_get(struct mv88e6xxx_led *led) ++{ ++ u16 ctrl; ++ int err; ++ ++ mv88e6xxx_reg_lock(led->chip); ++ err = mv88e6393x_port_led_read(led->chip, led->port, 0, &ctrl); ++ mv88e6xxx_reg_unlock(led->chip); ++ if (err) ++ return err; ++ ++ switch (led->index) { ++ case 0: ++ return ctrl & 0xf; ++ case 1: ++ return (ctrl >> 4) & 0xf; ++ } ++ ++ return -EINVAL; ++} ++ ++static int mv88e6393x_led_brightness_set(struct mv88e6xxx_led *led, ++ enum led_brightness brightness) ++{ ++ if (brightness == LED_OFF) ++ return mv88e6393x_led_set(led, MV88E6393X_LED_MODE_OFF); ++ ++ return mv88e6393x_led_set(led, MV88E6393X_LED_MODE_ON); ++} ++static int mv88e6393x_led_blink_set(struct mv88e6xxx_led *led, ++ unsigned long *delay_on, ++ unsigned long *delay_off) ++{ ++ int err; ++ ++ /* Defer anything other than 50% duty cycles to software */ ++ if (*delay_on != *delay_off) ++ return -EINVAL; ++ ++ /* Reject values outside ~20% of our default rate (84ms) */ ++ if (*delay_on && ((*delay_on < 30) || (*delay_on > 50))) ++ return -EINVAL; ++ ++ err = mv88e6393x_led_set(led, MV88E6393X_LED_MODE_BLINK); ++ if (!err) ++ *delay_on = *delay_off = 42; ++ ++ return err; ++} ++ ++static int mv88e6393x_led_hw_control_is_supported(struct mv88e6xxx_led *led, ++ unsigned long flags) ++{ ++ int mode = mv88e6393x_led_flags_to_mode(led, flags); ++ ++ return (mode < 0) ? mode : 0; ++} ++ ++static int mv88e6393x_led_hw_control_set(struct mv88e6xxx_led *led, ++ unsigned long flags) ++{ ++ int mode = mv88e6393x_led_flags_to_mode(led, flags); ++ ++ if (mode < 0) ++ return mode; ++ ++ return mv88e6393x_led_set(led, mode); ++} ++ ++static int mv88e6393x_led_hw_control_get(struct mv88e6xxx_led *led, ++ unsigned long *flags) ++{ ++ int mode = mv88e6393x_led_get(led); ++ ++ if (mode < 0) ++ return mode; ++ ++ return mv88e6393x_led_mode_to_flags(led, mode, flags); ++} ++ ++const struct mv88e6xxx_led_ops mv88e6393x_led_ops = { ++ .brightness_set = mv88e6393x_led_brightness_set, ++ .blink_set = mv88e6393x_led_blink_set, ++ .hw_control_is_supported = mv88e6393x_led_hw_control_is_supported, ++ .hw_control_set = mv88e6393x_led_hw_control_set, ++ .hw_control_get = mv88e6393x_led_hw_control_get, ++}; ++ + static int mv88e6xxx_led_brightness_set(struct led_classdev *ldev, + enum led_brightness brightness) + { +diff --git a/drivers/net/dsa/mv88e6xxx/leds.h b/drivers/net/dsa/mv88e6xxx/leds.h +index 8afa2a0c0527..542345d23dc5 100644 +--- a/drivers/net/dsa/mv88e6xxx/leds.h ++++ b/drivers/net/dsa/mv88e6xxx/leds.h +@@ -7,6 +7,8 @@ + + #include "chip.h" + ++extern const struct mv88e6xxx_led_ops mv88e6393x_led_ops; ++ + int mv88e6xxx_port_setup_leds(struct dsa_switch *ds, int port); + + #endif /* _MV88E6XXX_LEDS_H */ +diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c +index f25fb3214acb..aa5d312d8aa5 100644 +--- a/drivers/net/dsa/mv88e6xxx/port.c ++++ b/drivers/net/dsa/mv88e6xxx/port.c +@@ -1558,6 +1558,39 @@ int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port, + return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ETH_TYPE, etype); + } + ++/* Offset 0x16: LED Control Register */ ++ ++int mv88e6393x_port_led_write(struct mv88e6xxx_chip *chip, int port, ++ unsigned int pointer, u16 data) ++{ ++ u16 cmd = BIT(15) | ((pointer & 0x7) << 12) | (data & 0x7ff); ++ int err; ++ ++ err = mv88e6xxx_port_write(chip, port, MV88E6393X_PORT_LED_CONTROL, cmd); ++ if (err) ++ return err; ++ ++ return mv88e6xxx_port_wait_bit(chip, port, MV88E6393X_PORT_LED_CONTROL, 15, 0); ++} ++ ++int mv88e6393x_port_led_read(struct mv88e6xxx_chip *chip, int port, ++ unsigned int pointer, u16 *data) ++{ ++ u16 cmd = (pointer & 0x7) << 12; ++ int err; ++ ++ err = mv88e6xxx_port_write(chip, port, MV88E6393X_PORT_LED_CONTROL, cmd); ++ if (err) ++ return err; ++ ++ err = mv88e6xxx_port_read(chip, port, MV88E6393X_PORT_LED_CONTROL, &cmd); ++ if (err) ++ return err; ++ ++ *data = cmd & 0x7ff; ++ return 0; ++} ++ + /* Offset 0x18: Port IEEE Priority Remapping Registers [0-3] + * Offset 0x19: Port IEEE Priority Remapping Registers [4-7] + */ +diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h +index ddadeb9bfdae..7157864dc20f 100644 +--- a/drivers/net/dsa/mv88e6xxx/port.h ++++ b/drivers/net/dsa/mv88e6xxx/port.h +@@ -309,6 +309,9 @@ + /* Offset 0x13: OutFiltered Counter */ + #define MV88E6XXX_PORT_OUT_FILTERED 0x13 + ++/* Offset 0x16: LED Control Register */ ++#define MV88E6393X_PORT_LED_CONTROL 0x16 ++ + /* Offset 0x18: IEEE Priority Mapping Table */ + #define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE 0x18 + #define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_UPDATE 0x8000 +@@ -425,6 +428,10 @@ int mv88e6393x_port_set_policy(struct mv88e6xxx_chip *chip, int port, + enum mv88e6xxx_policy_action action); + int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port, + u16 etype); ++int mv88e6393x_port_led_write(struct mv88e6xxx_chip *chip, int port, ++ unsigned int pointer, u16 data); ++int mv88e6393x_port_led_read(struct mv88e6xxx_chip *chip, int port, ++ unsigned int pointer, u16 *data); + int mv88e6393x_set_egress_port(struct mv88e6xxx_chip *chip, + enum mv88e6xxx_egress_direction direction, + int port); +-- +2.43.0 + diff --git a/patches/linux/6.12.1/0007-net-dsa-tag_dsa-Use-tag-priority-as-initial-skb-prio.patch b/patches/linux/6.12.1/0007-net-dsa-tag_dsa-Use-tag-priority-as-initial-skb-prio.patch new file mode 100644 index 00000000..00cce3f1 --- /dev/null +++ b/patches/linux/6.12.1/0007-net-dsa-tag_dsa-Use-tag-priority-as-initial-skb-prio.patch @@ -0,0 +1,48 @@ +From 0f009562d467672b7f5ff9366ad4ec9df9044137 Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Tue, 28 May 2024 10:38:42 +0200 +Subject: [PATCH 07/24] net: dsa: tag_dsa: Use tag priority as initial + skb->priority +Organization: Addiva Elektronik + +Use the 3-bit priority field from the DSA tag as the initial packet +priority on ingress to the CPU. + +These bits contain the frame priority (FPri) of the packet. Barring +any non-standard policy configuration, this corresponds to: + +1. The original PCP bits if the packet is received with a VLAN tag +2. ...or the the 3 MSBs of the DSCP field, if it is an IP packet +3. ...otherwise 0 + +Ideally we could then map this priority to an internal one, like we +can do with an "ingress-qos-map" on VLAN interfaces. Until that is +implemented, support the setup that is likely to be the most common; a +1:1 mapping from FPri to skb->priority. + +Signed-off-by: Tobias Waldekranz +--- + net/dsa/tag_dsa.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c +index 2a2c4fb61a65..a00ae6bf2971 100644 +--- a/net/dsa/tag_dsa.c ++++ b/net/dsa/tag_dsa.c +@@ -323,6 +323,13 @@ static struct sk_buff *dsa_rcv_ll(struct sk_buff *skb, struct net_device *dev, + dsa_strip_etype_header(skb, DSA_HLEN + extra); + } + ++ /* Ideally we would have a way of configuring the mapping of PCP ++ * bits to skb->priority on DSA ports (like ingress-qos-map for ++ * vlan interfaces). For now, assume that a 1:1 mapping is more ++ * useful than ignoring the priority altogether. ++ */ ++ skb->priority = dsa_header[2] >> 5; ++ + return skb; + } + +-- +2.43.0 + diff --git a/patches/linux/6.12.1/0008-net-dsa-Support-MDB-memberships-whose-L2-addresses-o.patch b/patches/linux/6.12.1/0008-net-dsa-Support-MDB-memberships-whose-L2-addresses-o.patch new file mode 100644 index 00000000..ac3690be --- /dev/null +++ b/patches/linux/6.12.1/0008-net-dsa-Support-MDB-memberships-whose-L2-addresses-o.patch @@ -0,0 +1,74 @@ +From 027a5fcd4da6cf02ff8d2f6dc5ff1202f81db8ca Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Tue, 16 Jan 2024 16:00:55 +0100 +Subject: [PATCH 08/24] net: dsa: Support MDB memberships whose L2 addresses + overlap +Organization: Addiva Elektronik + +Multiple IP multicast groups (32 for v4, 2^80 for v6) map to the same +L2 address. This means that switchdev drivers may receive multiple MDB +additions for a particular L2 group on the same port. Since these were +not reference counted before this change, removing a group membership +after two overlapping memberships had been added would result in the +membership being removed from hardware, even though one reference to +the address still remained. + +Steps to reproduce: + + root@infix:~# mvls atu | grep 01:02:03 + root@infix:~# bridge mdb add dev br0 port e8 grp 238.1.2.3 permanent + root@infix:~# bridge mdb add dev br0 port e8 grp 239.1.2.3 permanent + root@infix:~# mvls atu | grep 01:02:03 + 01:00:5e:01:02:03 1 static - - . . . . . . . . 8 . . + root@infix:~# bridge mdb del dev br0 port e8 grp 239.1.2.3 + root@infix:~# mvls atu | grep 01:02:03 + root@infix:~# + +Therefore, reference count MDB memberships and keep them in hardware +as long as the count is positive. Fortunately, all the infrastructure +needed to do this is already in place, since it is also needed on CPU +and DSA ports. Thus, "implement" this by simply removing the guards +which previously skipped reference countung on user ports. + +Signed-off-by: Tobias Waldekranz +--- + net/dsa/switch.c | 16 ---------------- + 1 file changed, 16 deletions(-) + +diff --git a/net/dsa/switch.c b/net/dsa/switch.c +index 3d2feeea897b..628e8a884dde 100644 +--- a/net/dsa/switch.c ++++ b/net/dsa/switch.c +@@ -164,14 +164,6 @@ static int dsa_port_do_mdb_add(struct dsa_port *dp, + int port = dp->index; + int err = 0; + +- /* No need to bother with refcounting for user ports */ +- if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) { +- err = ds->ops->port_mdb_add(ds, port, mdb, db); +- trace_dsa_mdb_add_hw(dp, mdb->addr, mdb->vid, &db, err); +- +- return err; +- } +- + mutex_lock(&dp->addr_lists_lock); + + a = dsa_mac_addr_find(&dp->mdbs, mdb->addr, mdb->vid, db); +@@ -216,14 +208,6 @@ static int dsa_port_do_mdb_del(struct dsa_port *dp, + int port = dp->index; + int err = 0; + +- /* No need to bother with refcounting for user ports */ +- if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) { +- err = ds->ops->port_mdb_del(ds, port, mdb, db); +- trace_dsa_mdb_del_hw(dp, mdb->addr, mdb->vid, &db, err); +- +- return err; +- } +- + mutex_lock(&dp->addr_lists_lock); + + a = dsa_mac_addr_find(&dp->mdbs, mdb->addr, mdb->vid, db); +-- +2.43.0 + diff --git a/patches/linux/6.12.1/0009-net-dsa-Support-EtherType-based-priority-overrides.patch b/patches/linux/6.12.1/0009-net-dsa-Support-EtherType-based-priority-overrides.patch new file mode 100644 index 00000000..d1b20d18 --- /dev/null +++ b/patches/linux/6.12.1/0009-net-dsa-Support-EtherType-based-priority-overrides.patch @@ -0,0 +1,118 @@ +From ef232a32e69a5edb1a62067d4871fb70e8c3ddd7 Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Thu, 21 Mar 2024 19:12:15 +0100 +Subject: [PATCH 09/24] net: dsa: Support EtherType based priority overrides +Organization: Addiva Elektronik + +Signed-off-by: Tobias Waldekranz +--- + include/net/dsa.h | 4 ++++ + net/dsa/user.c | 56 +++++++++++++++++++++++++++++++++++++++++++++-- + 2 files changed, 58 insertions(+), 2 deletions(-) + +diff --git a/include/net/dsa.h b/include/net/dsa.h +index d7a6c2930277..db30c059b3c2 100644 +--- a/include/net/dsa.h ++++ b/include/net/dsa.h +@@ -968,6 +968,10 @@ struct dsa_switch_ops { + const u8 *sel, int nsel); + int (*port_get_apptrust)(struct dsa_switch *ds, int port, u8 *sel, + int *nsel); ++ int (*port_add_etype_prio)(struct dsa_switch *ds, int port, u16 etype, ++ u8 prio); ++ int (*port_del_etype_prio)(struct dsa_switch *ds, int port, u16 etype, ++ u8 prio); + + /* + * Suspend and resume +diff --git a/net/dsa/user.c b/net/dsa/user.c +index 64f660d2334b..e13fb22e2c2b 100644 +--- a/net/dsa/user.c ++++ b/net/dsa/user.c +@@ -2294,6 +2294,34 @@ dsa_user_dcbnl_add_dscp_prio(struct net_device *dev, struct dcb_app *app) + return 0; + } + ++static int __maybe_unused ++dsa_user_dcbnl_set_etype_prio(struct net_device *dev, struct dcb_app *app) ++{ ++ struct dsa_port *dp = dsa_user_to_port(dev); ++ struct dsa_switch *ds = dp->ds; ++ unsigned long mask, new_prio; ++ int err; ++ ++ if (!ds->ops->port_add_etype_prio) ++ return -EOPNOTSUPP; ++ ++ err = dcb_ieee_setapp(dev, app); ++ if (err) ++ return err; ++ ++ mask = dcb_ieee_getapp_mask(dev, app); ++ new_prio = __fls(mask); ++ ++ err = ds->ops->port_add_etype_prio(ds, dp->index, ++ app->protocol, new_prio); ++ if (err) { ++ dcb_ieee_delapp(dev, app); ++ return err; ++ } ++ ++ return 0; ++} ++ + static int __maybe_unused dsa_user_dcbnl_ieee_setapp(struct net_device *dev, + struct dcb_app *app) + { +@@ -2303,7 +2331,7 @@ static int __maybe_unused dsa_user_dcbnl_ieee_setapp(struct net_device *dev, + case 0: + return dsa_user_dcbnl_set_default_prio(dev, app); + default: +- return -EOPNOTSUPP; ++ return dsa_user_dcbnl_set_etype_prio(dev, app); + } + break; + case IEEE_8021QAZ_APP_SEL_DSCP: +@@ -2376,6 +2404,30 @@ dsa_user_dcbnl_del_dscp_prio(struct net_device *dev, struct dcb_app *app) + return 0; + } + ++static int __maybe_unused ++dsa_user_dcbnl_del_etype_prio(struct net_device *dev, struct dcb_app *app) ++{ ++ struct dsa_port *dp = dsa_user_to_port(dev); ++ struct dsa_switch *ds = dp->ds; ++ int err; ++ ++ if (!ds->ops->port_del_etype_prio) ++ return -EOPNOTSUPP; ++ ++ err = dcb_ieee_delapp(dev, app); ++ if (err) ++ return err; ++ ++ err = ds->ops->port_del_etype_prio(ds, dp->index, ++ app->protocol, app->priority); ++ if (err) { ++ dcb_ieee_setapp(dev, app); ++ return err; ++ } ++ ++ return 0; ++} ++ + static int __maybe_unused dsa_user_dcbnl_ieee_delapp(struct net_device *dev, + struct dcb_app *app) + { +@@ -2385,7 +2437,7 @@ static int __maybe_unused dsa_user_dcbnl_ieee_delapp(struct net_device *dev, + case 0: + return dsa_user_dcbnl_del_default_prio(dev, app); + default: +- return -EOPNOTSUPP; ++ return dsa_user_dcbnl_del_etype_prio(dev, app); + } + break; + case IEEE_8021QAZ_APP_SEL_DSCP: +-- +2.43.0 + diff --git a/patches/linux/6.12.1/0010-net-dsa-mv88e6xxx-Support-EtherType-based-priority-o.patch b/patches/linux/6.12.1/0010-net-dsa-mv88e6xxx-Support-EtherType-based-priority-o.patch new file mode 100644 index 00000000..be0ee635 --- /dev/null +++ b/patches/linux/6.12.1/0010-net-dsa-mv88e6xxx-Support-EtherType-based-priority-o.patch @@ -0,0 +1,376 @@ +From 48338a7ca5f0a7be3b16acd1762ec0b73088ac4c Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Fri, 22 Mar 2024 16:15:43 +0100 +Subject: [PATCH 10/24] net: dsa: mv88e6xxx: Support EtherType based priority + overrides +Organization: Addiva Elektronik + +Signed-off-by: Tobias Waldekranz +--- + drivers/net/dsa/mv88e6xxx/chip.c | 64 +++++++++++++++++++++++++++++ + drivers/net/dsa/mv88e6xxx/chip.h | 21 ++++++++++ + drivers/net/dsa/mv88e6xxx/global2.c | 56 ++++++++++++++++++++++++- + drivers/net/dsa/mv88e6xxx/global2.h | 4 ++ + drivers/net/dsa/mv88e6xxx/port.c | 46 +++++++++++++++++++++ + drivers/net/dsa/mv88e6xxx/port.h | 20 +++++++-- + 6 files changed, 207 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c +index e8edf3970940..3151df2a27c7 100644 +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -1715,6 +1715,11 @@ static int mv88e6xxx_rmu_setup(struct mv88e6xxx_chip *chip) + + static int mv88e6xxx_pot_setup(struct mv88e6xxx_chip *chip) + { ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(chip->qpri_po); i++) ++ refcount_set(&chip->qpri_po[i].refcnt, 0); ++ + if (chip->info->ops->pot_clear) + return chip->info->ops->pot_clear(chip); + +@@ -3386,6 +3391,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) + + chip->ports[port].chip = chip; + chip->ports[port].port = port; ++ refcount_set(&chip->ports[port].etype.refcnt, 0); + + err = mv88e6xxx_port_setup_mac(chip, port, LINK_UNFORCED, + SPEED_UNFORCED, DUPLEX_UNFORCED, +@@ -6532,6 +6538,7 @@ static struct mv88e6xxx_chip *mv88e6xxx_alloc_chip(struct device *dev) + chip->dev = dev; + + mutex_init(&chip->reg_lock); ++ mutex_init(&chip->arb_lock); + INIT_LIST_HEAD(&chip->mdios); + idr_init(&chip->policies); + INIT_LIST_HEAD(&chip->msts); +@@ -7064,6 +7071,61 @@ static int mv88e6xxx_crosschip_lag_leave(struct dsa_switch *ds, int sw_index, + return err_sync ? : err_pvt; + } + ++static int mv88e6xxx_port_add_etype_prio(struct dsa_switch *ds, int port, ++ u16 etype, u8 prio) ++{ ++ struct mv88e6xxx_chip *chip = ds->priv; ++ int err; ++ ++ mv88e6xxx_reg_lock(chip); ++ err = mv88e6xxx_port_claim_ether_type(chip, port, etype); ++ if (err) ++ goto err; ++ ++ err = mv88e6xxx_g2_claim_qpri_po(chip, ++ MV88E6XXX_G2_PRIO_OVERRIDE_PTR_ETYPE, ++ prio); ++ if (err) ++ goto err_relinquish_etype; ++ ++ mv88e6xxx_reg_unlock(chip); ++ return 0; ++ ++err_relinquish_etype: ++ mv88e6xxx_port_relinquish_ether_type(chip, port); ++err: ++ mv88e6xxx_reg_unlock(chip); ++ return err; ++} ++ ++static int mv88e6xxx_port_del_etype_prio(struct dsa_switch *ds, int port, ++ u16 etype, u8 prio) ++{ ++ struct mv88e6xxx_chip *chip = ds->priv; ++ int err; ++ ++ mv88e6xxx_reg_lock(chip); ++ err = mv88e6xxx_g2_relinquish_qpri_po(chip, ++ MV88E6XXX_G2_PRIO_OVERRIDE_PTR_ETYPE); ++ if (err) ++ goto err; ++ ++ err = mv88e6xxx_port_relinquish_ether_type(chip, port); ++ if (err) ++ goto err_claim_po; ++ ++ mv88e6xxx_reg_unlock(chip); ++ return 0; ++ ++err_claim_po: ++ mv88e6xxx_g2_claim_qpri_po(chip, ++ MV88E6XXX_G2_PRIO_OVERRIDE_PTR_ETYPE, ++ prio); ++err: ++ mv88e6xxx_reg_unlock(chip); ++ return err; ++} ++ + static const struct phylink_mac_ops mv88e6xxx_phylink_mac_ops = { + .mac_select_pcs = mv88e6xxx_mac_select_pcs, + .mac_prepare = mv88e6xxx_mac_prepare, +@@ -7133,6 +7195,8 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = { + .crosschip_lag_change = mv88e6xxx_crosschip_lag_change, + .crosschip_lag_join = mv88e6xxx_crosschip_lag_join, + .crosschip_lag_leave = mv88e6xxx_crosschip_lag_leave, ++ .port_add_etype_prio = mv88e6xxx_port_add_etype_prio, ++ .port_del_etype_prio = mv88e6xxx_port_del_etype_prio, + }; + + static int mv88e6xxx_register_switch(struct mv88e6xxx_chip *chip) +diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h +index 32c87ab754d1..25edc2534979 100644 +--- a/drivers/net/dsa/mv88e6xxx/chip.h ++++ b/drivers/net/dsa/mv88e6xxx/chip.h +@@ -293,6 +293,11 @@ struct mv88e6xxx_port { + + /* MacAuth Bypass control flag */ + bool mab; ++ ++ struct { ++ refcount_t refcnt; ++ u16 proto; ++ } etype; + }; + + enum mv88e6xxx_region_id { +@@ -331,6 +336,11 @@ struct mv88e6xxx_hw_stat { + int type; + }; + ++struct mv88e6xxx_po { ++ refcount_t refcnt; ++ u8 pri; ++}; ++ + struct mv88e6xxx_led; + + struct mv88e6xxx_chip { +@@ -348,6 +358,14 @@ struct mv88e6xxx_chip { + /* This mutex protects the access to the switch registers */ + struct mutex reg_lock; + ++ /* This mutex protects arbitration of hardware resources which ++ * may be allocated by multiple kernel consumers. As an ++ * example, the dcb(8) facility manages priority overrides ++ * independently per interface, whereas the hardware only ++ * supports a single priority per chip. ++ */ ++ struct mutex arb_lock; ++ + /* The MII bus and the address on the bus that is used to + * communication with the switch + */ +@@ -437,6 +455,9 @@ struct mv88e6xxx_chip { + + /* Bridge MST to SID mappings */ + struct list_head msts; ++ ++ /* Queue priority overrides */ ++ struct mv88e6xxx_po qpri_po[16]; + }; + + struct mv88e6xxx_bus_ops { +diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c +index b2b5f6ba438f..2c52903e8992 100644 +--- a/drivers/net/dsa/mv88e6xxx/global2.c ++++ b/drivers/net/dsa/mv88e6xxx/global2.c +@@ -315,7 +315,7 @@ int mv88e6xxx_g2_atu_stats_get(struct mv88e6xxx_chip *chip, u16 *stats) + static int mv88e6xxx_g2_pot_write(struct mv88e6xxx_chip *chip, int pointer, + u8 data) + { +- u16 val = (pointer << 8) | (data & 0x7); ++ u16 val = (pointer << 8) | (data & 0xf); + + return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_PRIO_OVERRIDE, + MV88E6XXX_G2_PRIO_OVERRIDE_UPDATE | val); +@@ -335,6 +335,60 @@ int mv88e6xxx_g2_pot_clear(struct mv88e6xxx_chip *chip) + return err; + } + ++int mv88e6xxx_g2_claim_qpri_po(struct mv88e6xxx_chip *chip, u8 pointer, ++ u8 qpri) ++{ ++ struct mv88e6xxx_po *po; ++ int err = 0; ++ ++ if (pointer > ARRAY_SIZE(chip->qpri_po)) ++ return -EINVAL; ++ ++ if (qpri > 7) ++ return -ERANGE; ++ ++ po = &chip->qpri_po[pointer]; ++ ++ mutex_lock(&chip->arb_lock); ++ if (refcount_read(&po->refcnt)) { ++ if (qpri == po->pri) ++ refcount_inc(&po->refcnt); ++ else ++ err = -EBUSY; ++ } else { ++ err = mv88e6xxx_g2_pot_write(chip, pointer, ++ MV88E6XXX_G2_PRIO_OVERRIDE_QFPRIEN | qpri); ++ if (!err) { ++ refcount_set(&po->refcnt, 1); ++ po->pri = qpri; ++ } ++ } ++ mutex_unlock(&chip->arb_lock); ++ ++ return err; ++} ++ ++int mv88e6xxx_g2_relinquish_qpri_po(struct mv88e6xxx_chip *chip, u8 pointer) ++{ ++ struct mv88e6xxx_po *po; ++ int err = 0; ++ ++ if (pointer > ARRAY_SIZE(chip->qpri_po)) ++ return -EINVAL; ++ ++ po = &chip->qpri_po[pointer]; ++ ++ mutex_lock(&chip->arb_lock); ++ if (refcount_dec_and_test(&po->refcnt)) { ++ err = mv88e6xxx_g2_pot_write(chip, pointer, 0); ++ if (err) ++ refcount_set(&po->refcnt, 1); ++ } ++ mutex_unlock(&chip->arb_lock); ++ ++ return err; ++} ++ + /* Offset 0x14: EEPROM Command + * Offset 0x15: EEPROM Data (for 16-bit data access) + * Offset 0x15: EEPROM Addr (for 8-bit data access) +diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h +index 3663645621c9..496269c26c50 100644 +--- a/drivers/net/dsa/mv88e6xxx/global2.h ++++ b/drivers/net/dsa/mv88e6xxx/global2.h +@@ -138,6 +138,7 @@ + #define MV88E6XXX_G2_PRIO_OVERRIDE_UPDATE 0x8000 + #define MV88E6XXX_G2_PRIO_OVERRIDE_FPRISET 0x1000 + #define MV88E6XXX_G2_PRIO_OVERRIDE_PTR_MASK 0x0f00 ++#define MV88E6XXX_G2_PRIO_OVERRIDE_PTR_ETYPE 0xc + #define MV88E6352_G2_PRIO_OVERRIDE_QPRIAVBEN 0x0080 + #define MV88E6352_G2_PRIO_OVERRIDE_DATAAVB_MASK 0x0030 + #define MV88E6XXX_G2_PRIO_OVERRIDE_QFPRIEN 0x0008 +@@ -359,6 +360,9 @@ int mv88e6185_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip); + int mv88e6352_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip); + + int mv88e6xxx_g2_pot_clear(struct mv88e6xxx_chip *chip); ++int mv88e6xxx_g2_claim_qpri_po(struct mv88e6xxx_chip *chip, u8 pointer, ++ u8 qpri); ++int mv88e6xxx_g2_relinquish_qpri_po(struct mv88e6xxx_chip *chip, u8 pointer); + + int mv88e6xxx_g2_trunk_mask_write(struct mv88e6xxx_chip *chip, int num, + bool hash, u16 mask); +diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c +index aa5d312d8aa5..84900814c456 100644 +--- a/drivers/net/dsa/mv88e6xxx/port.c ++++ b/drivers/net/dsa/mv88e6xxx/port.c +@@ -1558,6 +1558,52 @@ int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port, + return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ETH_TYPE, etype); + } + ++int mv88e6xxx_port_claim_ether_type(struct mv88e6xxx_chip *chip, int port, ++ u16 etype) ++{ ++ struct mv88e6xxx_port *p = &chip->ports[port]; ++ int err = 0; ++ ++ if (!chip->info->ops->port_set_ether_type) ++ return -EOPNOTSUPP; ++ ++ mutex_lock(&chip->arb_lock); ++ if (refcount_read(&p->etype.refcnt)) { ++ if (etype == p->etype.proto) ++ refcount_inc(&p->etype.refcnt); ++ else ++ err = -EBUSY; ++ } else { ++ err = chip->info->ops->port_set_ether_type(chip, port, etype); ++ if (!err) { ++ refcount_set(&p->etype.refcnt, 1); ++ p->etype.proto = etype; ++ } ++ } ++ mutex_unlock(&chip->arb_lock); ++ ++ return err; ++} ++ ++int mv88e6xxx_port_relinquish_ether_type(struct mv88e6xxx_chip *chip, int port) ++{ ++ struct mv88e6xxx_port *p = &chip->ports[port]; ++ int err = 0; ++ ++ if (!chip->info->ops->port_set_ether_type) ++ return -EOPNOTSUPP; ++ ++ mutex_lock(&chip->arb_lock); ++ if (refcount_dec_and_test(&p->etype.refcnt)) { ++ err = chip->info->ops->port_set_ether_type(chip, port, ++ MV88E6XXX_PORT_ETH_TYPE_DEFAULT); ++ if (err) ++ refcount_set(&p->etype.refcnt, 1); ++ } ++ mutex_unlock(&chip->arb_lock); ++ return err; ++} ++ + /* Offset 0x16: LED Control Register */ + + int mv88e6393x_port_led_write(struct mv88e6xxx_chip *chip, int port, +diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h +index 7157864dc20f..7edb04c41ac8 100644 +--- a/drivers/net/dsa/mv88e6xxx/port.h ++++ b/drivers/net/dsa/mv88e6xxx/port.h +@@ -286,7 +286,18 @@ + + /* Offset 0x0F: Port Special Ether Type */ + #define MV88E6XXX_PORT_ETH_TYPE 0x0f +-#define MV88E6XXX_PORT_ETH_TYPE_DEFAULT 0x9100 ++ ++/* When MV88E6XXX_PORT_ETH_TYPE is used to override the queue priority ++ * of matching packets, the override applies to all the chip's ++ * ports. However, if the packet also matches a traffic class that the ++ * hardware classifies as being of higher priority, then that class's ++ * override configuration is used instead, even if that override is ++ * disabled. The class which is one level higher than EType is PPPoE, ++ * so by using that as the default value when no other value has been ++ * requested, we effectively disable the EType class for that port. ++ */ ++#define MV88E6XXX_PORT_ETH_TYPE_DEFAULT ETH_P_PPP_DISC ++ + + /* Offset 0x10: InDiscards Low Counter */ + #define MV88E6XXX_PORT_IN_DISCARD_LO 0x10 +@@ -426,8 +437,13 @@ int mv88e6352_port_set_policy(struct mv88e6xxx_chip *chip, int port, + int mv88e6393x_port_set_policy(struct mv88e6xxx_chip *chip, int port, + enum mv88e6xxx_policy_mapping mapping, + enum mv88e6xxx_policy_action action); ++int mv88e6393x_port_set_ether_type(struct mv88e6xxx_chip *chip, int port, ++ u16 etype); + int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port, + u16 etype); ++int mv88e6xxx_port_claim_ether_type(struct mv88e6xxx_chip *chip, int port, ++ u16 etype); ++int mv88e6xxx_port_relinquish_ether_type(struct mv88e6xxx_chip *chip, int port); + int mv88e6393x_port_led_write(struct mv88e6xxx_chip *chip, int port, + unsigned int pointer, u16 data); + int mv88e6393x_port_led_read(struct mv88e6xxx_chip *chip, int port, +@@ -438,8 +454,6 @@ int mv88e6393x_set_egress_port(struct mv88e6xxx_chip *chip, + int mv88e6393x_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port, + int upstream_port); + int mv88e6393x_port_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip); +-int mv88e6393x_port_set_ether_type(struct mv88e6xxx_chip *chip, int port, +- u16 etype); + int mv88e6xxx_port_set_message_port(struct mv88e6xxx_chip *chip, int port, + bool message_port); + int mv88e6xxx_port_set_trunk(struct mv88e6xxx_chip *chip, int port, +-- +2.43.0 + diff --git a/patches/linux/6.12.1/0011-net-dsa-mv88e6xxx-Add-mqprio-qdisc-support.patch b/patches/linux/6.12.1/0011-net-dsa-mv88e6xxx-Add-mqprio-qdisc-support.patch new file mode 100644 index 00000000..30c23eb2 --- /dev/null +++ b/patches/linux/6.12.1/0011-net-dsa-mv88e6xxx-Add-mqprio-qdisc-support.patch @@ -0,0 +1,162 @@ +From 2c3ceab75d2ebb36326a5bc09b17d9409a11d2fa Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Tue, 28 May 2024 11:04:22 +0200 +Subject: [PATCH 11/24] net: dsa: mv88e6xxx: Add mqprio qdisc support +Organization: Addiva Elektronik + +Add support for attaching mqprio qdisc's to mv88e6xxx ports and use +the packet's traffic class as the outgoing priority when no PCP bits +are available. + +We cannot directly target a particular transmit queue on mv88e6xxx +chips, we can only specify the frame priority (FPri), which will +typically cause the switch to set the packet's queue priority (QPri) +to the same value. + +For symmetry, we give precedence to an explicit PCP value available in +the packet, since that maps directly to the chip's FPri. + +In cases where no PCP bits are available, use the packet's queue +mapping to derive its traffic class and use that as the FPri. Since +the packet will always be egressing without a tag in these cases, we +are effectively only specifying the QPri. + +Since FPri is always a 3-bit field, even on older chips with only 4 +physical queues, always report 8 queues and let the chip's policy +handle the mapping down to the "real" number. + +Signed-off-by: Tobias Waldekranz +--- + drivers/net/dsa/mv88e6xxx/chip.c | 70 ++++++++++++++++++++++++++++++++ + net/dsa/tag_dsa.c | 4 +- + 2 files changed, 73 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c +index 3151df2a27c7..f50ad71bb28b 100644 +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + + #include "chip.h" + #include "devlink.h" +@@ -7126,6 +7127,68 @@ static int mv88e6xxx_port_del_etype_prio(struct dsa_switch *ds, int port, + return err; + } + ++static int mv88e6xxx_qos_port_mqprio(struct mv88e6xxx_chip *chip, int port, ++ struct tc_mqprio_qopt_offload *mqprio) ++{ ++ struct net_device *dev = dsa_to_port(chip->ds, port)->user; ++ struct tc_mqprio_qopt *qopt = &mqprio->qopt; ++ int tc, err = 0, num_txq = 0; ++ ++ if (!qopt->num_tc) ++ goto out_reset; ++ ++ err = netdev_set_num_tc(dev, qopt->num_tc); ++ if (err) ++ return err; ++ ++ for (tc = 0; tc < qopt->num_tc; tc++) { ++ num_txq += qopt->count[tc]; ++ ++ err = netdev_set_tc_queue(dev, tc, qopt->count[tc], qopt->offset[tc]); ++ if (err) ++ goto out_reset; ++ } ++ ++ err = netif_set_real_num_tx_queues(dev, num_txq); ++ if (err) ++ goto out_reset; ++ ++ return 0; ++ ++out_reset: ++ netdev_reset_tc(dev); ++ return err; ++ ++} ++ ++static int mv88e6xxx_qos_query_caps(struct tc_query_caps_base *base) ++{ ++ switch (base->type) { ++ case TC_SETUP_QDISC_MQPRIO: ++ struct tc_mqprio_caps *caps = base->caps; ++ ++ caps->validate_queue_counts = true; ++ return 0; ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++static int mv88e6xxx_port_setup_tc(struct dsa_switch *ds, int port, ++ enum tc_setup_type type, ++ void *type_data) ++{ ++ struct mv88e6xxx_chip *chip = ds->priv; ++ ++ switch (type) { ++ case TC_QUERY_CAPS: ++ return mv88e6xxx_qos_query_caps(type_data); ++ case TC_SETUP_QDISC_MQPRIO: ++ return mv88e6xxx_qos_port_mqprio(chip, port, type_data); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ + static const struct phylink_mac_ops mv88e6xxx_phylink_mac_ops = { + .mac_select_pcs = mv88e6xxx_mac_select_pcs, + .mac_prepare = mv88e6xxx_mac_prepare, +@@ -7197,6 +7260,7 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = { + .crosschip_lag_leave = mv88e6xxx_crosschip_lag_leave, + .port_add_etype_prio = mv88e6xxx_port_add_etype_prio, + .port_del_etype_prio = mv88e6xxx_port_del_etype_prio, ++ .port_setup_tc = mv88e6xxx_port_setup_tc, + }; + + static int mv88e6xxx_register_switch(struct mv88e6xxx_chip *chip) +@@ -7223,6 +7287,12 @@ static int mv88e6xxx_register_switch(struct mv88e6xxx_chip *chip) + */ + ds->num_lag_ids = mv88e6xxx_has_lag(chip) ? 16 : 0; + ++ /* Even though older chips only have 4 queues, we always have ++ * 3 bits of priority information in the DSA tag, which is how ++ * we indirectly address the queues. ++ */ ++ ds->num_tx_queues = 8; ++ + dev_set_drvdata(dev, ds); + + return dsa_register_switch(ds); +diff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c +index a00ae6bf2971..55c296e0b5b0 100644 +--- a/net/dsa/tag_dsa.c ++++ b/net/dsa/tag_dsa.c +@@ -180,8 +180,10 @@ static struct sk_buff *dsa_xmit_ll(struct sk_buff *skb, struct net_device *dev, + } + } else { + u16 vid; ++ u8 tc; + + vid = br_dev ? MV88E6XXX_VID_BRIDGED : MV88E6XXX_VID_STANDALONE; ++ tc = netdev_txq_to_tc(dev, skb_get_queue_mapping(skb)); + + skb_push(skb, DSA_HLEN + extra); + dsa_alloc_etype_header(skb, DSA_HLEN + extra); +@@ -191,7 +193,7 @@ static struct sk_buff *dsa_xmit_ll(struct sk_buff *skb, struct net_device *dev, + + dsa_header[0] = (cmd << 6) | tag_dev; + dsa_header[1] = tag_port << 3; +- dsa_header[2] = vid >> 8; ++ dsa_header[2] = (tc << 5) | (vid >> 8); + dsa_header[3] = vid & 0xff; + } + +-- +2.43.0 + diff --git a/patches/linux/6.12.1/0012-net-dsa-mv88e6xxx-Use-VLAN-prio-over-IP-when-both-ar.patch b/patches/linux/6.12.1/0012-net-dsa-mv88e6xxx-Use-VLAN-prio-over-IP-when-both-ar.patch new file mode 100644 index 00000000..ba7d64c9 --- /dev/null +++ b/patches/linux/6.12.1/0012-net-dsa-mv88e6xxx-Use-VLAN-prio-over-IP-when-both-ar.patch @@ -0,0 +1,62 @@ +From b1f2d857a7457c8c965d281d8c8875ad491670a7 Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Wed, 29 May 2024 13:20:41 +0200 +Subject: [PATCH 12/24] net: dsa: mv88e6xxx: Use VLAN prio over IP when both + are available +Organization: Addiva Elektronik + +Switch the priority sourcing precdence to prefer VLAN PCP over IP +DSCP, when both are available. + +Ever since the initial commit of this driver, IP priority (DSCP/TOS) +has instead taken precedence over VLAN priority (PCP) when determining +a packet's initial queue and frame priority (Qpri/Fpri). There are two +main reasons for choosing the new default: + +1. It matches the chip's hardware default settings and thus follows + the principle of least astonishment. + +2. In the typical case where a packet initially ingresses a network on + a UNI port, the first switch will have the most context available + about that flow; and is therefore entrusted to determine the + packet's priority. As the packet then moves through the network + core over trusted VLAN trunks, the packet should keep its original + priority, independent of what inner protocol fields may indicate. + +Signed-off-by: Tobias Waldekranz +--- + drivers/net/dsa/mv88e6xxx/chip.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c +index f50ad71bb28b..2a46bf5f3da8 100644 +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -3402,9 +3402,13 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) + + /* Port Control: disable Drop-on-Unlock, disable Drop-on-Lock, + * disable Header mode, enable IGMP/MLD snooping, disable VLAN +- * tunneling, determine priority by looking at 802.1p and IP +- * priority fields (IP prio has precedence), and set STP state +- * to Forwarding. ++ * tunneling, and set STP state to Forwarding. ++ * ++ * Use the following sources of information, in order of ++ * precedence, to determine a packet's initial Qpri/Fpri: ++ * 1. VLAN PCP field, if available ++ * 2. IPv4/6 DSCP field, if available ++ * 3. Ingress port defaults + * + * If this is the CPU link, use DSA or EDSA tagging depending + * on which tagging mode was configured. +@@ -3415,6 +3419,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) + * forwarding of unknown unicasts and multicasts. + */ + reg = MV88E6185_PORT_CTL0_USE_TAG | MV88E6185_PORT_CTL0_USE_IP | ++ MV88E6XXX_PORT_CTL0_TAG_IF_BOTH | + MV88E6XXX_PORT_CTL0_STATE_FORWARDING; + /* Forward any IPv4 IGMP or IPv6 MLD frames received + * by a USER port to the CPU port to allow snooping. +-- +2.43.0 + diff --git a/patches/linux/6.12.1/0013-FIX-net-dsa-mv88e6xxx-Trap-locally-terminated-VLANs.patch b/patches/linux/6.12.1/0013-FIX-net-dsa-mv88e6xxx-Trap-locally-terminated-VLANs.patch new file mode 100644 index 00000000..e751ecbb --- /dev/null +++ b/patches/linux/6.12.1/0013-FIX-net-dsa-mv88e6xxx-Trap-locally-terminated-VLANs.patch @@ -0,0 +1,161 @@ +From eedb27bcce73ed62534528bd098b897954f98d3c Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Tue, 26 Nov 2024 19:45:59 +0100 +Subject: [PATCH 13/24] [FIX] net: dsa: mv88e6xxx: Trap locally terminated + VLANs +Organization: Addiva Elektronik + +Before this change, in a setup like the following, packets assigned to +VLAN 10 were forwarded between the switch ports, even though the +configuration dictates that they should only be locally terminated. + +ip link add dev br0 up type bridge vlan_filtering 1 +ip link set dev swp1 master br0 +ip link set dev swp2 master br0 +ip link add dev swp1.10 link swp1 up type vlan id 10 +ip link add dev swp2.10 link swp2 up type vlan id 10 + +swp1.10 br0 swp2.10 + \ / \ / + swp1 swp2 + +Therefore, make sure that VLANs that are added to the VTU to terminate +a VLAN upper interface, rather than to offload bridge VLANs, are +marked as policy entries. As the VTU policy of user ports is already +set to TRAP (to ensure proper standalone port operation), this will +cause all packets assigned to these VLANs to properly terminated. + +Signed-off-by: Tobias Waldekranz +--- + drivers/net/dsa/mv88e6xxx/chip.c | 33 ++++++++++++++++++-------------- + include/net/switchdev.h | 4 ++++ + net/dsa/user.c | 4 ++++ + 3 files changed, 27 insertions(+), 14 deletions(-) + +diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c +index 2a46bf5f3da8..785cd3d0e2b1 100644 +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -2631,7 +2631,7 @@ static int mv88e6xxx_port_broadcast_sync(struct mv88e6xxx_chip *chip, int port, + } + + static int mv88e6xxx_port_vlan_join(struct mv88e6xxx_chip *chip, int port, +- u16 vid, u8 member, bool warn) ++ u16 vid, u8 member, bool warn, bool policy) + { + const u8 non_member = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER; + struct mv88e6xxx_vtu_entry vlan; +@@ -2643,9 +2643,7 @@ static int mv88e6xxx_port_vlan_join(struct mv88e6xxx_chip *chip, int port, + + if (!vlan.valid) { + memset(&vlan, 0, sizeof(vlan)); +- +- if (vid == MV88E6XXX_VID_STANDALONE) +- vlan.policy = true; ++ vlan.policy = policy; + + err = mv88e6xxx_atu_new(chip, &vlan.fid); + if (err) +@@ -2668,6 +2666,9 @@ static int mv88e6xxx_port_vlan_join(struct mv88e6xxx_chip *chip, int port, + if (err) + return err; + } else if (vlan.member[port] != member) { ++ if (vlan.policy != policy) ++ return -EBUSY; ++ + vlan.member[port] = member; + + err = mv88e6xxx_vtu_loadpurge(chip, &vlan); +@@ -2714,7 +2715,8 @@ static int mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, + + mv88e6xxx_reg_lock(chip); + +- err = mv88e6xxx_port_vlan_join(chip, port, vlan->vid, member, warn); ++ err = mv88e6xxx_port_vlan_join(chip, port, vlan->vid, member, warn, ++ vlan->from_upper); + if (err) { + dev_err(ds->dev, "p%d: failed to add VLAN %d%c\n", port, + vlan->vid, untagged ? 'u' : 't'); +@@ -3454,14 +3456,17 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) + if (err) + return err; + +- /* On chips that support it, set all downstream DSA ports' +- * VLAN policy to TRAP. In combination with loading +- * MV88E6XXX_VID_STANDALONE as a policy entry in the VTU, this +- * provides a better isolation barrier between standalone +- * ports, as the ATU is bypassed on any intermediate switches +- * between the incoming port and the CPU. ++ /* On chips that support it, set all downstream DSA and user ++ * ports' VLAN policy to TRAP. for downstream DSA ports, in ++ * combination with loading MV88E6XXX_VID_STANDALONE as a ++ * policy entry in the VTU, this provides a better isolation ++ * barrier between standalone ports, as the ATU is bypassed on ++ * any intermediate switches between the incoming port and the ++ * CPU. On user ports we need it to support stacked VLAN ++ * uppers on ports that are simultaneously attached to a VLAN ++ * filtering bridge. + */ +- if (dsa_is_downstream_port(ds, port) && ++ if ((dsa_is_downstream_port(ds, port) || dsa_is_user_port(ds, port)) && + chip->info->ops->port_set_policy) { + err = chip->info->ops->port_set_policy(chip, port, + MV88E6XXX_POLICY_MAPPING_VTU, +@@ -3491,7 +3496,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) + */ + err = mv88e6xxx_port_vlan_join(chip, port, MV88E6XXX_VID_STANDALONE, + MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_UNMODIFIED, +- false); ++ false, true); + if (err) + return err; + +@@ -3505,7 +3510,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) + */ + err = mv88e6xxx_port_vlan_join(chip, port, MV88E6XXX_VID_BRIDGED, + MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_UNMODIFIED, +- false); ++ false, false); + if (err) + return err; + +diff --git a/include/net/switchdev.h b/include/net/switchdev.h +index 8346b0d29542..764cd3dd4645 100644 +--- a/include/net/switchdev.h ++++ b/include/net/switchdev.h +@@ -104,6 +104,10 @@ struct switchdev_obj_port_vlan { + * Entries with BRIDGE_VLAN_INFO_BRENTRY unset are not notified at all. + */ + bool changed; ++ ++ /* If set, this VLAN object stems from an upper interface ++ * being stacked on/removed from the original device. */ ++ bool from_upper; + }; + + #define SWITCHDEV_OBJ_PORT_VLAN(OBJ) \ +diff --git a/net/dsa/user.c b/net/dsa/user.c +index e13fb22e2c2b..f45e313f1dd0 100644 +--- a/net/dsa/user.c ++++ b/net/dsa/user.c +@@ -1754,6 +1754,8 @@ static int dsa_user_vlan_rx_add_vid(struct net_device *dev, __be16 proto, + .vid = vid, + /* This API only allows programming tagged, non-PVID VIDs */ + .flags = 0, ++ ++ .from_upper = true, + }; + struct netlink_ext_ack extack = {0}; + struct dsa_switch *ds = dp->ds; +@@ -1828,6 +1830,8 @@ static int dsa_user_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, + .vid = vid, + /* This API only allows programming tagged, non-PVID VIDs */ + .flags = 0, ++ ++ .from_upper = true, + }; + struct dsa_switch *ds = dp->ds; + struct netdev_hw_addr *ha; +-- +2.43.0 + diff --git a/patches/linux/6.12.1/0014-net-phy-marvell10g-Support-firmware-loading-on-88X33.patch b/patches/linux/6.12.1/0014-net-phy-marvell10g-Support-firmware-loading-on-88X33.patch new file mode 100644 index 00000000..fc232276 --- /dev/null +++ b/patches/linux/6.12.1/0014-net-phy-marvell10g-Support-firmware-loading-on-88X33.patch @@ -0,0 +1,241 @@ +From f84d14369aad6ad2d2aec71dcf907d2ff70aa4fa Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Tue, 19 Sep 2023 18:38:10 +0200 +Subject: [PATCH 14/24] net: phy: marvell10g: Support firmware loading on + 88X3310 +Organization: Addiva Elektronik + +When probing, if a device is waiting for firmware to be loaded into +its RAM, ask userspace for the binary and load it over XMDIO. + +We have no choice but to bail out of the probe if firmware is not +available, as the device does not have any built-in image on which to +fall back. + +Signed-off-by: Tobias Waldekranz +--- + drivers/net/phy/marvell10g.c | 161 +++++++++++++++++++++++++++++++++++ + 1 file changed, 161 insertions(+) + +diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c +index 6642eb642d4b..79d9483419c0 100644 +--- a/drivers/net/phy/marvell10g.c ++++ b/drivers/net/phy/marvell10g.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -50,6 +51,10 @@ enum { + MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH = 0x6, + MV_PMA_BOOT = 0xc050, + MV_PMA_BOOT_FATAL = BIT(0), ++ MV_PMA_BOOT_PRGS_MASK = 0x0006, ++ MV_PMA_BOOT_PRGS_WAIT = 0x0002, ++ MV_PMA_BOOT_APP_STARTED = BIT(4), ++ MV_PMA_BOOT_APP_LOADED = BIT(6), + + MV_PCS_BASE_T = 0x0000, + MV_PCS_BASE_R = 0x1000, +@@ -96,6 +101,12 @@ enum { + MV_PCS_PORT_INFO_NPORTS_MASK = 0x0380, + MV_PCS_PORT_INFO_NPORTS_SHIFT = 7, + ++ /* Firmware downloading */ ++ MV_PCS_FW_ADDR_LOW = 0xd0f0, ++ MV_PCS_FW_ADDR_HIGH = 0xd0f1, ++ MV_PCS_FW_DATA = 0xd0f2, ++ MV_PCS_FW_CSUM = 0xd0f3, ++ + /* SerDes reinitialization 88E21X0 */ + MV_AN_21X0_SERDES_CTRL2 = 0x800f, + MV_AN_21X0_SERDES_CTRL2_AUTO_INIT_DIS = BIT(13), +@@ -157,6 +168,8 @@ struct mv3310_chip { + const struct mv3310_mactype *mactypes; + size_t n_mactypes; + ++ const char *firmware_path; ++ + #ifdef CONFIG_HWMON + int (*hwmon_read_temp_reg)(struct phy_device *phydev); + #endif +@@ -508,6 +521,145 @@ static const struct sfp_upstream_ops mv3310_sfp_ops = { + .module_insert = mv3310_sfp_insert, + }; + ++struct mv3310_fw_hdr { ++ __le32 data_size; ++ __le32 data_addr; ++ __le16 data_csum; ++ __le16 flags; ++#define MV3310_FW_HDR_DATA_ONLY BIT(6) ++ __le32 next_hdr; ++ __le16 csum; ++ ++ u8 pad[14]; ++} __packed; ++ ++struct mv3310_fw_sect_info { ++ const u8 *data; ++ u32 size; ++ u32 addr; ++ u16 csum; ++}; ++ ++static int mv3310_load_fw_sect(struct phy_device *phydev, ++ const struct mv3310_fw_sect_info *si) ++{ ++ size_t i; ++ u16 csum; ++ ++ dev_dbg(&phydev->mdio.dev, "Loading %u byte section at 0x%08x\n", ++ si->size, si->addr); ++ ++ for (i = 0, csum = 0; i < si->size; i++) ++ csum += si->data[i]; ++ ++ if ((u16)~csum != si->csum) { ++ dev_err(&phydev->mdio.dev, "Corrupt section data\n"); ++ return -EINVAL; ++ } ++ ++ /* Any existing checksum is cleared by a read */ ++ __phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_FW_CSUM); ++ ++ __phy_write_mmd(phydev, MDIO_MMD_PCS, MV_PCS_FW_ADDR_LOW, si->addr & 0xffff); ++ __phy_write_mmd(phydev, MDIO_MMD_PCS, MV_PCS_FW_ADDR_HIGH, si->addr >> 16); ++ ++ for (i = 0; i < si->size; i += 2) { ++ __phy_write_mmd(phydev, MDIO_MMD_PCS, MV_PCS_FW_DATA, ++ (si->data[i + 1] << 8) | si->data[i]); ++ } ++ ++ csum = __phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_FW_CSUM); ++ if ((u16)~csum != si->csum) { ++ dev_err(&phydev->mdio.dev, "Download failed\n"); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static int mv3310_load_fw(struct phy_device *phydev) ++{ ++ const struct mv3310_chip *chip = to_mv3310_chip(phydev); ++ struct mv3310_fw_sect_info si; ++ const struct firmware *fw; ++ struct mv3310_fw_hdr hdr; ++ bool need_boot = false; ++ const u8 *sect; ++ size_t i; ++ u32 next; ++ u16 csum; ++ int err; ++ ++ if (!chip->firmware_path) ++ return -EOPNOTSUPP; ++ ++ err = request_firmware(&fw, chip->firmware_path, &phydev->mdio.dev); ++ if (err) ++ return err; ++ ++ if (fw->size & 1) { ++ err = -EINVAL; ++ goto release; ++ } ++ ++ phy_lock_mdio_bus(phydev); ++ ++ for (sect = fw->data; (sect + sizeof(hdr)) < (fw->data + fw->size);) { ++ memcpy(&hdr, sect, sizeof(hdr)); ++ ++ for (i = 0, csum = 0; i < offsetof(struct mv3310_fw_hdr, csum); i++) ++ csum += sect[i]; ++ ++ if ((u16)~csum != le16_to_cpu(hdr.csum)) { ++ dev_err(&phydev->mdio.dev, "Corrupt section header\n"); ++ err = -EINVAL; ++ goto unlock; ++ } ++ ++ si.data = sect + sizeof(hdr); ++ si.size = le32_to_cpu(hdr.data_size); ++ si.addr = le32_to_cpu(hdr.data_addr); ++ si.csum = le16_to_cpu(hdr.data_csum); ++ ++ if ((si.data + si.size) > (fw->data + fw->size)) { ++ dev_err(&phydev->mdio.dev, "Invalid section length\n"); ++ err = -EINVAL; ++ goto unlock; ++ } ++ ++ err = mv3310_load_fw_sect(phydev, &si); ++ if (err) ++ goto unlock; ++ ++ if (!(le16_to_cpu(hdr.flags) & MV3310_FW_HDR_DATA_ONLY)) ++ need_boot = true; ++ ++ next = le32_to_cpu(hdr.next_hdr); ++ if (!next) ++ break; ++ ++ sect = fw->data + next; ++ } ++ ++ if (need_boot) { ++ __phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_BOOT, 0, ++ MV_PMA_BOOT_APP_LOADED); ++ mdelay(200); ++ if (!(__phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_BOOT) & ++ MV_PMA_BOOT_APP_STARTED)) { ++ dev_err(&phydev->mdio.dev, "Firmware boot failed\n"); ++ err = -ENODEV; ++ } ++ } ++ ++unlock: ++ phy_unlock_mdio_bus(phydev); ++ ++release: ++ release_firmware(fw); ++ return err; ++} ++ + static int mv3310_probe(struct phy_device *phydev) + { + const struct mv3310_chip *chip = to_mv3310_chip(phydev); +@@ -529,6 +681,12 @@ static int mv3310_probe(struct phy_device *phydev) + return -ENODEV; + } + ++ if ((ret & MV_PMA_BOOT_PRGS_MASK) == MV_PMA_BOOT_PRGS_WAIT) { ++ ret = mv3310_load_fw(phydev); ++ if (ret) ++ return ret; ++ } ++ + priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; +@@ -1222,6 +1380,8 @@ static const struct mv3310_chip mv3310_type = { + .mactypes = mv3310_mactypes, + .n_mactypes = ARRAY_SIZE(mv3310_mactypes), + ++ .firmware_path = "mrvl/x3310fw.hdr", ++ + #ifdef CONFIG_HWMON + .hwmon_read_temp_reg = mv3310_hwmon_read_temp_reg, + #endif +@@ -1491,4 +1651,5 @@ static struct mdio_device_id __maybe_unused mv3310_tbl[] = { + }; + MODULE_DEVICE_TABLE(mdio, mv3310_tbl); + MODULE_DESCRIPTION("Marvell Alaska X/M multi-gigabit Ethernet PHY driver"); ++MODULE_FIRMWARE("mrvl/x3310fw.hdr"); + MODULE_LICENSE("GPL"); +-- +2.43.0 + diff --git a/patches/linux/6.12.1/0015-net-phy-marvell10g-Fix-power-up-when-strapped-to-sta.patch b/patches/linux/6.12.1/0015-net-phy-marvell10g-Fix-power-up-when-strapped-to-sta.patch new file mode 100644 index 00000000..b5ef7467 --- /dev/null +++ b/patches/linux/6.12.1/0015-net-phy-marvell10g-Fix-power-up-when-strapped-to-sta.patch @@ -0,0 +1,50 @@ +From 0ffa9ba9b48fbd9f818b8c789202ae85bc401f47 Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Tue, 21 Nov 2023 20:15:24 +0100 +Subject: [PATCH 15/24] net: phy: marvell10g: Fix power-up when strapped to + start powered down +Organization: Addiva Elektronik + +On devices which are hardware strapped to start powered down (PDSTATE +== 1), make sure that we clear the power-down bit on all units +affected by this setting. + +Signed-off-by: Tobias Waldekranz +--- + drivers/net/phy/marvell10g.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c +index 79d9483419c0..268484092776 100644 +--- a/drivers/net/phy/marvell10g.c ++++ b/drivers/net/phy/marvell10g.c +@@ -342,11 +342,23 @@ static int mv3310_power_down(struct phy_device *phydev) + + static int mv3310_power_up(struct phy_device *phydev) + { ++ static const u16 resets[][2] = { ++ { MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_CTRL1 }, ++ { MDIO_MMD_PCS, MV_PCS_BASE_T + MDIO_CTRL1 }, ++ { MDIO_MMD_PMAPMD, MDIO_CTRL1 }, ++ }; + struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); +- int ret; ++ int i, ret; ++ ++ for (i = 0; i < ARRAY_SIZE(resets); i++) { ++ ret = phy_clear_bits_mmd(phydev, resets[i][0], resets[i][1], ++ MDIO_CTRL1_LPOWER); ++ if (ret) ++ break; ++ } + +- ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL, +- MV_V2_PORT_CTRL_PWRDOWN); ++ ret = ret ? : phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL, ++ MV_V2_PORT_CTRL_PWRDOWN); + + /* Sometimes, the power down bit doesn't clear immediately, and + * a read of this register causes the bit not to clear. Delay +-- +2.43.0 + diff --git a/patches/linux/6.12.1/0016-net-phy-marvell10g-Add-LED-support-for-88X3310.patch b/patches/linux/6.12.1/0016-net-phy-marvell10g-Add-LED-support-for-88X3310.patch new file mode 100644 index 00000000..f3cab423 --- /dev/null +++ b/patches/linux/6.12.1/0016-net-phy-marvell10g-Add-LED-support-for-88X3310.patch @@ -0,0 +1,517 @@ +From 2c99fab374153c7eac6ba9874d47367871cec640 Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Wed, 15 Nov 2023 20:58:42 +0100 +Subject: [PATCH 16/24] net: phy: marvell10g: Add LED support for 88X3310 +Organization: Addiva Elektronik + +Pickup the LEDs from the state in which the hardware reset or +bootloader left them, but also support further configuration via +device tree. This is primarily needed because the electrical polarity +and drive behavior is software controlled and not possible to set via +hardware strapping. + +Trigger support: +- "none" +- "timer": Map 60-100 ms periods to the fast rate (81ms) and 1000-1600 + ms periods to the slow rate (1300ms). Defer everything else to + software blinking +- "netdev": Offload link or duplex information to the solid behavior; + tx and/or rx activity to blink behavior. + +Signed-off-by: Tobias Waldekranz +--- + drivers/net/phy/marvell10g.c | 422 +++++++++++++++++++++++++++++++++++ + 1 file changed, 422 insertions(+) + +diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c +index 268484092776..9f8475b67ef7 100644 +--- a/drivers/net/phy/marvell10g.c ++++ b/drivers/net/phy/marvell10g.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -133,6 +134,16 @@ enum { + MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_NO_SGMII_AN = 0x5, + MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH = 0x6, + MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII = 0x7, ++ MV_V2_LED0_CONTROL = 0xf020, ++ MV_V2_LED_CONTROL_POLARITY_MASK = 0x0003, ++ MV_V2_LED_CONTROL_POLARITY_SHIFT = 0, ++ MV_V2_LED_CONTROL_ACTIVE_HIGH = BIT(0), ++ MV_V2_LED_CONTROL_TRISTATE = BIT(1), ++ MV_V2_LED_CONTROL_BLINK_RATE = BIT(2), ++ MV_V2_LED_CONTROL_SOLID_FUNC_MASK = 0x00f8, ++ MV_V2_LED_CONTROL_SOLID_FUNC_SHIFT = 3, ++ MV_V2_LED_CONTROL_BLINK_FUNC_MASK = 0x1f00, ++ MV_V2_LED_CONTROL_BLINK_FUNC_SHIFT = 8, + MV_V2_PORT_INTR_STS = 0xf040, + MV_V2_PORT_INTR_MASK = 0xf043, + MV_V2_PORT_INTR_STS_WOL_EN = BIT(8), +@@ -161,6 +172,7 @@ struct mv3310_mactype { + struct mv3310_chip { + bool (*has_downshift)(struct phy_device *phydev); + void (*init_supported_interfaces)(unsigned long *mask); ++ int (*leds_probe)(struct phy_device *phydev); + int (*get_mactype)(struct phy_device *phydev); + int (*set_mactype)(struct phy_device *phydev, int mactype); + int (*select_mactype)(unsigned long *interfaces); +@@ -175,6 +187,13 @@ struct mv3310_chip { + #endif + }; + ++#define MV3310_N_LEDS 4 ++ ++struct mv3310_led { ++ u8 index; ++ u16 ctrl; ++}; ++ + struct mv3310_priv { + DECLARE_BITMAP(supported_interfaces, PHY_INTERFACE_MODE_MAX); + const struct mv3310_mactype *mactype; +@@ -184,6 +203,8 @@ struct mv3310_priv { + + struct device *hwmon_dev; + char *hwmon_name; ++ ++ struct mv3310_led led[MV3310_N_LEDS]; + }; + + static const struct mv3310_chip *to_mv3310_chip(struct phy_device *phydev) +@@ -191,6 +212,396 @@ static const struct mv3310_chip *to_mv3310_chip(struct phy_device *phydev) + return phydev->drv->driver_data; + } + ++enum mv3310_led_func { ++ MV3310_LED_FUNC_OFF = 0x00, ++ MV3310_LED_FUNC_TX_RX = 0x01, ++ MV3310_LED_FUNC_TX = 0x02, ++ MV3310_LED_FUNC_RX = 0x03, ++ MV3310_LED_FUNC_COLLISION = 0x04, ++ MV3310_LED_FUNC_LINK_COPPER = 0x05, ++ MV3310_LED_FUNC_LINK_FIBER = 0x06, ++ MV3310_LED_FUNC_LINK = 0x07, ++ MV3310_LED_FUNC_10M_LINK = 0x08, ++ MV3310_LED_FUNC_100M_LINK = 0x09, ++ MV3310_LED_FUNC_1G_LINK = 0x0a, ++ MV3310_LED_FUNC_10G_LINK = 0x0b, ++ MV3310_LED_FUNC_10M_100M_LINK = 0x0c, ++ MV3310_LED_FUNC_10M_100M_1G_LINK = 0x0d, ++ MV3310_LED_FUNC_100M_10G_LINK = 0x0e, ++ MV3310_LED_FUNC_1G_10G_LINK = 0x0f, ++ MV3310_LED_FUNC_1G_10G_SLAVE = 0x10, ++ MV3310_LED_FUNC_1G_10G_MASTER = 0x11, ++ MV3310_LED_FUNC_HALF_DUPLEX = 0x12, ++ MV3310_LED_FUNC_FULL_DUPLEX = 0x13, ++ MV3310_LED_FUNC_LINK_EEE = 0x14, ++ MV3310_LED_FUNC_2G5_LINK = 0x15, ++ MV3310_LED_FUNC_5G_LINK = 0x16, ++ MV3310_LED_FUNC_ON = 0x17, ++ MV3310_LED_FUNC_2G5_5G_SLAVE = 0x18, ++ MV3310_LED_FUNC_2G5_5G_MASTER = 0x19, ++ ++ MV3310_LED_FUNC_SPEED_BLINK = 0x1f ++}; ++ ++static int mv3310_led_flags_from_funcs(struct mv3310_led *led, ++ enum mv3310_led_func solid, ++ enum mv3310_led_func blink, ++ unsigned long *flagsp) ++{ ++ unsigned long flags = 0; ++ ++ switch (solid) { ++ case MV3310_LED_FUNC_OFF: ++ break; ++ case MV3310_LED_FUNC_LINK_COPPER: ++ case MV3310_LED_FUNC_LINK_FIBER: ++ case MV3310_LED_FUNC_LINK: ++ flags |= TRIGGER_NETDEV_LINK; ++ break; ++ case MV3310_LED_FUNC_HALF_DUPLEX: ++ flags |= TRIGGER_NETDEV_HALF_DUPLEX; ++ break; ++ case MV3310_LED_FUNC_FULL_DUPLEX: ++ flags |= TRIGGER_NETDEV_FULL_DUPLEX; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ switch (blink) { ++ case MV3310_LED_FUNC_OFF: ++ break; ++ case MV3310_LED_FUNC_TX: ++ flags |= TRIGGER_NETDEV_TX; ++ break; ++ case MV3310_LED_FUNC_RX: ++ flags |= TRIGGER_NETDEV_RX; ++ break; ++ case MV3310_LED_FUNC_TX_RX: ++ flags |= TRIGGER_NETDEV_TX | TRIGGER_NETDEV_RX; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ *flagsp = flags; ++ return 0; ++} ++ ++static int mv3310_led_funcs_from_flags(struct mv3310_led *led, ++ unsigned long flags, ++ enum mv3310_led_func *solid, ++ enum mv3310_led_func *blink) ++{ ++ unsigned long activity, duplex, link; ++ ++ if (flags & ~(BIT(TRIGGER_NETDEV_LINK) | ++ BIT(TRIGGER_NETDEV_HALF_DUPLEX) | ++ BIT(TRIGGER_NETDEV_FULL_DUPLEX) | ++ BIT(TRIGGER_NETDEV_TX) | ++ BIT(TRIGGER_NETDEV_RX))) ++ return -EINVAL; ++ ++ link = flags & BIT(TRIGGER_NETDEV_LINK); ++ ++ duplex = flags & (BIT(TRIGGER_NETDEV_HALF_DUPLEX) | ++ BIT(TRIGGER_NETDEV_FULL_DUPLEX)); ++ ++ activity = flags & (BIT(TRIGGER_NETDEV_TX) | ++ BIT(TRIGGER_NETDEV_RX)); ++ ++ if (link && duplex) ++ return -EINVAL; ++ ++ if (solid) { ++ if (link) { ++ *solid = MV3310_LED_FUNC_LINK; ++ } else if (duplex) { ++ switch (duplex) { ++ case BIT(TRIGGER_NETDEV_HALF_DUPLEX): ++ *solid = MV3310_LED_FUNC_HALF_DUPLEX; ++ break; ++ case BIT(TRIGGER_NETDEV_FULL_DUPLEX): ++ *solid = MV3310_LED_FUNC_FULL_DUPLEX; ++ break; ++ default: ++ break; ++ } ++ } else { ++ *solid = MV3310_LED_FUNC_OFF; ++ } ++ } ++ ++ if (blink) { ++ switch (activity) { ++ case 0: ++ *blink = MV3310_LED_FUNC_OFF; ++ break; ++ case BIT(TRIGGER_NETDEV_TX): ++ *blink = MV3310_LED_FUNC_TX; ++ break; ++ case BIT(TRIGGER_NETDEV_RX): ++ *blink = MV3310_LED_FUNC_RX; ++ break; ++ default: ++ *blink = MV3310_LED_FUNC_TX_RX; ++ break; ++ } ++ } ++ ++ return 0; ++} ++ ++static int mv3310_led_get(struct phy_device *phydev, ++ struct mv3310_led *led, ++ enum mv3310_led_func *solid, ++ enum mv3310_led_func *blink, ++ bool *slow_blink) ++{ ++ int ctrl; ++ ++ ctrl = phy_read_mmd(phydev, MDIO_MMD_VEND2, ++ MV_V2_LED0_CONTROL + led->index); ++ if (ctrl < 0) ++ return ctrl; ++ ++ *solid = (ctrl & MV_V2_LED_CONTROL_SOLID_FUNC_MASK) >> ++ MV_V2_LED_CONTROL_SOLID_FUNC_SHIFT; ++ *blink = (ctrl & MV_V2_LED_CONTROL_BLINK_FUNC_MASK) >> ++ MV_V2_LED_CONTROL_BLINK_FUNC_SHIFT; ++ ++ *slow_blink = !!(ctrl & MV_V2_LED_CONTROL_BLINK_RATE); ++ return 0; ++} ++ ++static int mv3310_led_set(struct phy_device *phydev, ++ struct mv3310_led *led, ++ enum mv3310_led_func solid, ++ enum mv3310_led_func blink, ++ bool slow_blink) ++{ ++ u16 ctrl = led->ctrl; ++ ++ ctrl &= ~MV_V2_LED_CONTROL_SOLID_FUNC_MASK; ++ ctrl &= ~MV_V2_LED_CONTROL_BLINK_FUNC_MASK; ++ ctrl &= ~MV_V2_LED_CONTROL_BLINK_RATE; ++ ++ ctrl |= solid << MV_V2_LED_CONTROL_SOLID_FUNC_SHIFT; ++ ctrl |= blink << MV_V2_LED_CONTROL_BLINK_FUNC_SHIFT; ++ ++ if (slow_blink) ++ ctrl |= MV_V2_LED_CONTROL_BLINK_RATE; ++ ++ return phy_write_mmd(phydev, MDIO_MMD_VEND2, ++ MV_V2_LED0_CONTROL + led->index, ctrl); ++} ++ ++static int mv3310_led_polarity_set(struct phy_device *phydev, ++ int index, unsigned long modes) ++{ ++ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); ++ struct mv3310_led *led; ++ u16 ctrl; ++ int err; ++ ++ if (index < 0 || index >= MV3310_N_LEDS) ++ return -ENODEV; ++ ++ led = &priv->led[index]; ++ ctrl = led->ctrl; ++ ++ if (test_bit(PHY_LED_ACTIVE_LOW, &modes)) ++ ctrl &= ~MV_V2_LED_CONTROL_ACTIVE_HIGH; ++ else ++ ctrl |= MV_V2_LED_CONTROL_ACTIVE_HIGH; ++ ++ if (test_bit(PHY_LED_INACTIVE_HIGH_IMPEDANCE, &modes)) ++ ctrl |= MV_V2_LED_CONTROL_TRISTATE; ++ else ++ ctrl &= ~MV_V2_LED_CONTROL_TRISTATE; ++ ++ err = phy_write_mmd(phydev, MDIO_MMD_VEND2, ++ MV_V2_LED0_CONTROL + index, ctrl); ++ if (err) ++ return err; ++ ++ led->ctrl = ctrl; ++ return 0; ++} ++ ++static int mv3310_led_brightness_set(struct phy_device *phydev, ++ u8 index, enum led_brightness value) ++{ ++ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); ++ enum mv3310_led_func solid; ++ struct mv3310_led *led; ++ ++ if (index >= MV3310_N_LEDS) ++ return -ENODEV; ++ ++ led = &priv->led[index]; ++ ++ if (value == LED_OFF) ++ solid = MV3310_LED_FUNC_OFF; ++ else ++ solid = MV3310_LED_FUNC_ON; ++ ++ return mv3310_led_set(phydev, led, solid, MV3310_LED_FUNC_OFF, false); ++} ++ ++static int mv3310_led_blink_set(struct phy_device *phydev, u8 index, ++ unsigned long *delay_on, ++ unsigned long *delay_off) ++{ ++ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); ++ struct mv3310_led *led; ++ bool slow_blink; ++ int err; ++ ++ if (index >= MV3310_N_LEDS) ++ return -ENODEV; ++ ++ led = &priv->led[index]; ++ ++ if (*delay_on != *delay_off) ++ /* Defer anything other than 50% duty cycles to ++ * software. ++ */ ++ return -EINVAL; ++ ++ /* Accept values within ~20% of our supported rates (80ms or ++ * 1300ms periods). ++ */ ++ if ((*delay_on >= 30) && (*delay_on <= 50)) ++ slow_blink = false; ++ else if (((*delay_on >= 500) && (*delay_on <= 800)) || (*delay_on == 0)) ++ slow_blink = true; ++ else ++ return -EINVAL; ++ ++ err = mv3310_led_set(phydev, led, MV3310_LED_FUNC_OFF, ++ MV3310_LED_FUNC_ON, slow_blink); ++ if (!err) ++ *delay_on = *delay_off = slow_blink ? 650 : 40; ++ ++ return err; ++} ++ ++static int mv3310_led_hw_is_supported(struct phy_device *phydev, u8 index, ++ unsigned long flags) ++{ ++ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); ++ struct mv3310_led *led; ++ ++ if (index >= MV3310_N_LEDS) ++ return -ENODEV; ++ ++ led = &priv->led[index]; ++ ++ return mv3310_led_funcs_from_flags(led, flags, NULL, NULL); ++} ++ ++static int mv3310_led_hw_control_set(struct phy_device *phydev, u8 index, ++ unsigned long flags) ++{ ++ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); ++ enum mv3310_led_func solid, blink; ++ struct mv3310_led *led; ++ int err; ++ ++ if (index >= MV3310_N_LEDS) ++ return -ENODEV; ++ ++ led = &priv->led[index]; ++ ++ err = mv3310_led_funcs_from_flags(led, flags, &solid, &blink); ++ if (err) ++ return err; ++ ++ return mv3310_led_set(phydev, led, solid, blink, false); ++} ++ ++static int mv3310_led_hw_control_get(struct phy_device *phydev, u8 index, ++ unsigned long *flags) ++{ ++ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); ++ enum mv3310_led_func solid, blink; ++ struct mv3310_led *led; ++ bool slow_blink; ++ int err; ++ ++ if (index >= MV3310_N_LEDS) ++ return -ENODEV; ++ ++ led = &priv->led[index]; ++ ++ err = mv3310_led_get(phydev, led, &solid, &blink, &slow_blink); ++ if (err) ++ return err; ++ ++ return mv3310_led_flags_from_funcs(led, solid, blink, flags); ++} ++ ++static int mv3310_led_probe_of(struct phy_device *phydev, ++ struct device_node *np) ++{ ++ u32 index; ++ int err; ++ ++ err = of_property_read_u32(np, "reg", &index); ++ if (err) ++ return err; ++ ++ if (index >= MV3310_N_LEDS) ++ return -EINVAL; ++ ++ /* mv3310_led_polarity_set() will not be called unless the ++ * device tree specifies a mode that of_phy_led() considers to ++ * be a non-default configuration. I.e., something other than ++ * (active-high, drive low on inactive). But the 3310's HW ++ * default is (active-low, drive low on inactive). Therefore, ++ * configure all LEDs defined in the DT with the kernel ++ * defaults, and then let of_phy_led() set the final value if ++ * the config deviates from that. ++ */ ++ return mv3310_led_polarity_set(phydev, index, 0); ++} ++ ++static int mv3310_leds_probe(struct phy_device *phydev) ++{ ++ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); ++ struct device_node *node = phydev->mdio.dev.of_node; ++ struct device_node *pnp, *np; ++ int err, val, index; ++ ++ for (index = 0; index < MV3310_N_LEDS; index++) { ++ val = phy_read_mmd(phydev, MDIO_MMD_VEND2, ++ MV_V2_LED0_CONTROL + index); ++ if (val < 0) ++ return val; ++ ++ priv->led[index] = (struct mv3310_led) { ++ .index = index, ++ .ctrl = val, ++ }; ++ } ++ ++ if (!node) ++ return 0; ++ ++ pnp = of_get_child_by_name(node, "leds"); ++ if (!pnp) ++ return 0; ++ ++ for_each_available_child_of_node(pnp, np) { ++ err = mv3310_led_probe_of(phydev, np); ++ if (err) ++ return err; ++ } ++ ++ return 0; ++} ++ + #ifdef CONFIG_HWMON + static umode_t mv3310_hwmon_is_visible(const void *data, + enum hwmon_sensor_types type, +@@ -733,6 +1144,10 @@ static int mv3310_probe(struct phy_device *phydev) + if (ret) + return ret; + ++ ret = chip->leds_probe ? chip->leds_probe(phydev) : 0; ++ if (ret) ++ return ret; ++ + chip->init_supported_interfaces(priv->supported_interfaces); + + return phy_sfp_probe(phydev, &mv3310_sfp_ops); +@@ -1385,6 +1800,7 @@ static void mv2111_init_supported_interfaces(unsigned long *mask) + static const struct mv3310_chip mv3310_type = { + .has_downshift = mv3310_has_downshift, + .init_supported_interfaces = mv3310_init_supported_interfaces, ++ .leds_probe = mv3310_leds_probe, + .get_mactype = mv3310_get_mactype, + .set_mactype = mv3310_set_mactype, + .select_mactype = mv3310_select_mactype, +@@ -1594,6 +2010,12 @@ static struct phy_driver mv3310_drivers[] = { + .set_loopback = genphy_c45_loopback, + .get_wol = mv3110_get_wol, + .set_wol = mv3110_set_wol, ++ .led_polarity_set = mv3310_led_polarity_set, ++ .led_brightness_set = mv3310_led_brightness_set, ++ .led_blink_set = mv3310_led_blink_set, ++ .led_hw_is_supported = mv3310_led_hw_is_supported, ++ .led_hw_control_set = mv3310_led_hw_control_set, ++ .led_hw_control_get = mv3310_led_hw_control_get, + }, + { + .phy_id = MARVELL_PHY_ID_88X3310, +-- +2.43.0 + diff --git a/patches/linux/6.12.1/0017-net-phy-marvell10g-Support-LEDs-tied-to-a-single-med.patch b/patches/linux/6.12.1/0017-net-phy-marvell10g-Support-LEDs-tied-to-a-single-med.patch new file mode 100644 index 00000000..934db5ac --- /dev/null +++ b/patches/linux/6.12.1/0017-net-phy-marvell10g-Support-LEDs-tied-to-a-single-med.patch @@ -0,0 +1,80 @@ +From 6dd8ed1ea83d55469e20b9c13b41810fc2e29af4 Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Tue, 12 Dec 2023 09:51:05 +0100 +Subject: [PATCH 17/24] net: phy: marvell10g: Support LEDs tied to a single + media side +Organization: Addiva Elektronik + +In a combo-port setup, i.e. where both the copper and fiber interface +are available to the user, the LEDs may be physically located either +by the RJ45 jack, or by an SFP cage. + +For those scenarios, allow the device tree to indicate that an LED is +tied to a particular media side, and use that information to refine +the offloading of the "netdev" trigger, such that LEDs attached to the +RJ45 jack only lights up when a copper link is established, and vice +versa for the SFP cage. + +Signed-off-by: Tobias Waldekranz +--- + drivers/net/phy/marvell10g.c | 23 ++++++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c +index 9f8475b67ef7..82b2e9b55b67 100644 +--- a/drivers/net/phy/marvell10g.c ++++ b/drivers/net/phy/marvell10g.c +@@ -192,6 +192,9 @@ struct mv3310_chip { + struct mv3310_led { + u8 index; + u16 ctrl; ++ ++ unsigned copper:1; ++ unsigned fiber:1; + }; + + struct mv3310_priv { +@@ -315,7 +318,12 @@ static int mv3310_led_funcs_from_flags(struct mv3310_led *led, + + if (solid) { + if (link) { +- *solid = MV3310_LED_FUNC_LINK; ++ if (led->copper) ++ *solid = MV3310_LED_FUNC_LINK_COPPER; ++ else if (led->fiber) ++ *solid = MV3310_LED_FUNC_LINK_FIBER; ++ else ++ *solid = MV3310_LED_FUNC_LINK; + } else if (duplex) { + switch (duplex) { + case BIT(TRIGGER_NETDEV_HALF_DUPLEX): +@@ -545,6 +553,9 @@ static int mv3310_led_hw_control_get(struct phy_device *phydev, u8 index, + static int mv3310_led_probe_of(struct phy_device *phydev, + struct device_node *np) + { ++ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); ++ struct mv3310_led *led; ++ const char *media; + u32 index; + int err; + +@@ -555,6 +566,16 @@ static int mv3310_led_probe_of(struct phy_device *phydev, + if (index >= MV3310_N_LEDS) + return -EINVAL; + ++ led = &priv->led[index]; ++ ++ err = of_property_read_string(np, "marvell,media", &media); ++ if (!err) { ++ if (!strcmp(media, "copper")) ++ led->copper = 1; ++ else if (!strcmp(media, "fiber")) ++ led->fiber = 1; ++ } ++ + /* mv3310_led_polarity_set() will not be called unless the + * device tree specifies a mode that of_phy_led() considers to + * be a non-default configuration. I.e., something other than +-- +2.43.0 + diff --git a/patches/linux/6.12.1/0018-net-phy-Do-not-resume-PHY-when-attaching.patch b/patches/linux/6.12.1/0018-net-phy-Do-not-resume-PHY-when-attaching.patch new file mode 100644 index 00000000..7546b99b --- /dev/null +++ b/patches/linux/6.12.1/0018-net-phy-Do-not-resume-PHY-when-attaching.patch @@ -0,0 +1,38 @@ +From 17cfde24d88c30c303659f2d8f488c2717592422 Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Wed, 27 Mar 2024 10:10:19 +0100 +Subject: [PATCH 18/24] net: phy: Do not resume PHY when attaching +Organization: Addiva Elektronik + +The PHY should not start negotiating with its link-partner until +explicitly instructed to do so. + +Therefore, skip resuming the PHY in the attach phase, deferring it to +when phy_start() is called from the net_device's open() callback, +possibly via phylink_start(). + +Otherwise, drivers that attached to their PHYs during +probing (e.g. DSA) would end up with a physical link being +established, even though the corresponding interface was still +administratively down. + +Signed-off-by: Tobias Waldekranz +--- + drivers/net/phy/phy_device.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c +index 499797646580..0acfef4fe43e 100644 +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -1634,7 +1634,6 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, + if (err) + goto error; + +- phy_resume(phydev); + if (!phydev->is_on_sfp_module) + phy_led_triggers_register(phydev); + +-- +2.43.0 + diff --git a/patches/linux/6.12.1/0019-net-bridge-avoid-classifying-unknown-multicast-as-mr.patch b/patches/linux/6.12.1/0019-net-bridge-avoid-classifying-unknown-multicast-as-mr.patch new file mode 100644 index 00000000..21d90568 --- /dev/null +++ b/patches/linux/6.12.1/0019-net-bridge-avoid-classifying-unknown-multicast-as-mr.patch @@ -0,0 +1,237 @@ +From c75c32e677f22caf857981d1c8a3f580bf367230 Mon Sep 17 00:00:00 2001 +From: Joachim Wiberg +Date: Mon, 4 Mar 2024 16:47:28 +0100 +Subject: [PATCH 19/24] net: bridge: avoid classifying unknown multicast as + mrouters_only +Organization: Addiva Elektronik + +Unknown multicast, MAC/IPv4/IPv6, should always be flooded according to +the per-port mcast_flood setting, as well as to detected and configured +mcast_router ports. + +This patch drops the mrouters_only classifier of unknown IP multicast +and moves the flow handling from br_multicast_flood() to br_flood(). +This in turn means br_flood() must know about multicast router ports. +Because a multicast router should always receive both known and unknown +multicast. + +Signed-off-by: Joachim Wiberg +Signed-off-by: Tobias Waldekranz +--- + include/uapi/linux/if_bridge.h | 1 + + net/bridge/br.c | 5 +++++ + net/bridge/br_device.c | 10 ++++++---- + net/bridge/br_forward.c | 14 ++++++++++++-- + net/bridge/br_input.c | 2 +- + net/bridge/br_multicast.c | 11 +++++++++-- + net/bridge/br_private.h | 18 ++++++++++++++++-- + 7 files changed, 50 insertions(+), 11 deletions(-) + +diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h +index a5b743a2f775..3bffc39d7800 100644 +--- a/include/uapi/linux/if_bridge.h ++++ b/include/uapi/linux/if_bridge.h +@@ -830,6 +830,7 @@ enum br_boolopt_id { + BR_BOOLOPT_NO_LL_LEARN, + BR_BOOLOPT_MCAST_VLAN_SNOOPING, + BR_BOOLOPT_MST_ENABLE, ++ BR_BOOLOPT_MCAST_FLOOD_ALWAYS, + BR_BOOLOPT_MAX + }; + +diff --git a/net/bridge/br.c b/net/bridge/br.c +index 2cab878e0a39..006fb2e5eafb 100644 +--- a/net/bridge/br.c ++++ b/net/bridge/br.c +@@ -277,6 +277,9 @@ int br_boolopt_toggle(struct net_bridge *br, enum br_boolopt_id opt, bool on, + case BR_BOOLOPT_MST_ENABLE: + err = br_mst_set_enabled(br, on, extack); + break; ++ case BR_BOOLOPT_MCAST_FLOOD_ALWAYS: ++ br_opt_toggle(br, BROPT_MCAST_FLOOD_ALWAYS, on); ++ break; + default: + /* shouldn't be called with unsupported options */ + WARN_ON(1); +@@ -295,6 +298,8 @@ int br_boolopt_get(const struct net_bridge *br, enum br_boolopt_id opt) + return br_opt_get(br, BROPT_MCAST_VLAN_SNOOPING_ENABLED); + case BR_BOOLOPT_MST_ENABLE: + return br_opt_get(br, BROPT_MST_ENABLED); ++ case BR_BOOLOPT_MCAST_FLOOD_ALWAYS: ++ return br_opt_get(br, BROPT_MCAST_FLOOD_ALWAYS); + default: + /* shouldn't be called with unsupported options */ + WARN_ON(1); +diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c +index 26b79feb385d..f3ecc70a47dc 100644 +--- a/net/bridge/br_device.c ++++ b/net/bridge/br_device.c +@@ -87,10 +87,10 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) + + dest = eth_hdr(skb)->h_dest; + if (is_broadcast_ether_addr(dest)) { +- br_flood(br, skb, BR_PKT_BROADCAST, false, true, vid); ++ br_flood(br, skb, NULL, BR_PKT_BROADCAST, false, true, vid); + } else if (is_multicast_ether_addr(dest)) { + if (unlikely(netpoll_tx_running(dev))) { +- br_flood(br, skb, BR_PKT_MULTICAST, false, true, vid); ++ br_flood(br, skb, brmctx, BR_PKT_MULTICAST, false, true, vid); + goto out; + } + if (br_multicast_rcv(&brmctx, &pmctx_null, vlan, skb, vid)) { +@@ -103,11 +103,11 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) + br_multicast_querier_exists(brmctx, eth_hdr(skb), mdst)) + br_multicast_flood(mdst, skb, brmctx, false, true); + else +- br_flood(br, skb, BR_PKT_MULTICAST, false, true, vid); ++ br_flood(br, skb, brmctx, BR_PKT_MULTICAST, false, true, vid); + } else if ((dst = br_fdb_find_rcu(br, dest, vid)) != NULL) { + br_forward(dst->dst, skb, false, true); + } else { +- br_flood(br, skb, BR_PKT_UNICAST, false, true, vid); ++ br_flood(br, skb, NULL, BR_PKT_UNICAST, false, true, vid); + } + out: + rcu_read_unlock(); +@@ -526,6 +526,8 @@ void br_dev_setup(struct net_device *dev) + br->bridge_ageing_time = br->ageing_time = BR_DEFAULT_AGEING_TIME; + dev->max_mtu = ETH_MAX_MTU; + ++ br_opt_toggle(br, BROPT_MCAST_FLOOD_ALWAYS, false); ++ + br_netfilter_rtable_init(br); + br_stp_timer_init(br); + br_multicast_init(br); +diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c +index e19b583ff2c6..1094364d96e0 100644 +--- a/net/bridge/br_forward.c ++++ b/net/bridge/br_forward.c +@@ -198,14 +198,19 @@ static struct net_bridge_port *maybe_deliver( + + /* called under rcu_read_lock */ + void br_flood(struct net_bridge *br, struct sk_buff *skb, +- enum br_pkt_type pkt_type, bool local_rcv, bool local_orig, +- u16 vid) ++ struct net_bridge_mcast *brmctx, enum br_pkt_type pkt_type, ++ bool local_rcv, bool local_orig, u16 vid) + { ++ struct net_bridge_port *rport = NULL; + struct net_bridge_port *prev = NULL; ++ struct hlist_node *rp = NULL; + struct net_bridge_port *p; + + br_tc_skb_miss_set(skb, pkt_type != BR_PKT_BROADCAST); + ++ if (pkt_type == BR_PKT_MULTICAST) ++ rp = br_multicast_get_first_rport_node(brmctx, skb); ++ + list_for_each_entry_rcu(p, &br->port_list, list) { + /* Do not flood unicast traffic to ports that turn it off, nor + * other traffic if flood off, except for traffic we originate +@@ -216,6 +221,11 @@ void br_flood(struct net_bridge *br, struct sk_buff *skb, + continue; + break; + case BR_PKT_MULTICAST: ++ rport = br_multicast_rport_from_node_skb(rp, skb); ++ if (rport == p) { ++ rp = rcu_dereference(hlist_next_rcu(rp)); ++ break; ++ } + if (!(p->flags & BR_MCAST_FLOOD) && skb->dev != br->dev) + continue; + break; +diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c +index ceaa5a89b947..e54d648db7de 100644 +--- a/net/bridge/br_input.c ++++ b/net/bridge/br_input.c +@@ -212,7 +212,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb + br_forward(dst->dst, skb, local_rcv, false); + } else { + if (!mcast_hit) +- br_flood(br, skb, pkt_type, local_rcv, false, vid); ++ br_flood(br, skb, brmctx, pkt_type, local_rcv, false, vid); + else + br_multicast_flood(mdst, skb, brmctx, local_rcv, false); + } +diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c +index b2ae0d2434d2..3137c1fcfc6a 100644 +--- a/net/bridge/br_multicast.c ++++ b/net/bridge/br_multicast.c +@@ -3774,6 +3774,11 @@ static void br_multicast_err_count(const struct net_bridge *br, + u64_stats_update_end(&pstats->syncp); + } + ++static bool br_flood_mrouters(const struct net_bridge *br) ++{ ++ return br_opt_get(br, BROPT_MCAST_FLOOD_ALWAYS) ? false : true; ++} ++ + static void br_multicast_pim(struct net_bridge_mcast *brmctx, + struct net_bridge_mcast_port *pmctx, + const struct sk_buff *skb) +@@ -3820,7 +3825,8 @@ static int br_multicast_ipv4_rcv(struct net_bridge_mcast *brmctx, + + if (err == -ENOMSG) { + if (!ipv4_is_local_multicast(ip_hdr(skb)->daddr)) { +- BR_INPUT_SKB_CB(skb)->mrouters_only = 1; ++ BR_INPUT_SKB_CB(skb)->mrouters_only = ++ br_flood_mrouters(brmctx->br); + } else if (pim_ipv4_all_pim_routers(ip_hdr(skb)->daddr)) { + if (ip_hdr(skb)->protocol == IPPROTO_PIM) + br_multicast_pim(brmctx, pmctx, skb); +@@ -3889,7 +3895,8 @@ static int br_multicast_ipv6_rcv(struct net_bridge_mcast *brmctx, + + if (err == -ENOMSG || err == -ENODATA) { + if (!ipv6_addr_is_ll_all_nodes(&ipv6_hdr(skb)->daddr)) +- BR_INPUT_SKB_CB(skb)->mrouters_only = 1; ++ BR_INPUT_SKB_CB(skb)->mrouters_only = ++ br_flood_mrouters(brmctx->br); + if (err == -ENODATA && + ipv6_addr_is_all_snoopers(&ipv6_hdr(skb)->daddr)) + br_ip6_multicast_mrd_rcv(brmctx, pmctx, skb); +diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h +index 041f6e571a20..40651b07df94 100644 +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -483,6 +483,7 @@ enum net_bridge_opts { + BROPT_VLAN_BRIDGE_BINDING, + BROPT_MCAST_VLAN_SNOOPING_ENABLED, + BROPT_MST_ENABLED, ++ BROPT_MCAST_FLOOD_ALWAYS, + }; + + struct net_bridge { +@@ -886,8 +887,8 @@ void br_forward(const struct net_bridge_port *to, struct sk_buff *skb, + bool local_rcv, bool local_orig); + int br_forward_finish(struct net *net, struct sock *sk, struct sk_buff *skb); + void br_flood(struct net_bridge *br, struct sk_buff *skb, +- enum br_pkt_type pkt_type, bool local_rcv, bool local_orig, +- u16 vid); ++ struct net_bridge_mcast *brmctx, enum br_pkt_type pkt_type, ++ bool local_rcv, bool local_orig, u16 vid); + + /* return true if both source port and dest port are isolated */ + static inline bool br_skb_isolated(const struct net_bridge_port *to, +@@ -1408,6 +1409,19 @@ static inline void br_multicast_flood(struct net_bridge_mdb_entry *mdst, + { + } + ++static inline struct hlist_node * ++br_multicast_get_first_rport_node(struct net_bridge_mcast *brmctx, ++ struct sk_buff *skb) ++{ ++ return NULL; ++} ++ ++static inline struct net_bridge_port * ++br_multicast_rport_from_node_skb(struct hlist_node *rp, struct sk_buff *skb) ++{ ++ return NULL; ++} ++ + static inline bool br_multicast_is_router(struct net_bridge_mcast *brmctx, + struct sk_buff *skb) + { +-- +2.43.0 + diff --git a/patches/linux/6.12.1/0020-net-bridge-Ignore-router-ports-when-forwarding-L2-mu.patch b/patches/linux/6.12.1/0020-net-bridge-Ignore-router-ports-when-forwarding-L2-mu.patch new file mode 100644 index 00000000..9946f7f7 --- /dev/null +++ b/patches/linux/6.12.1/0020-net-bridge-Ignore-router-ports-when-forwarding-L2-mu.patch @@ -0,0 +1,37 @@ +From d8c84564a7ef2a5faf4caf76ed797131967258bb Mon Sep 17 00:00:00 2001 +From: Joachim Wiberg +Date: Tue, 5 Mar 2024 06:44:41 +0100 +Subject: [PATCH 20/24] net: bridge: Ignore router ports when forwarding L2 + multicast +Organization: Addiva Elektronik + +Multicast router ports are either statically configured or learned from +control protocol traffic (IGMP/MLD/PIM). These protocols regulate IP +multicast -- MAC multicast should always be forwarded through flooding +of unknown multicast or using permanent MDB entries. + +Signed-off-by: Tobias Waldekranz +Signed-off-by: Joachim Wiberg +--- + net/bridge/br_private.h | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h +index 40651b07df94..e90b4f5cab76 100644 +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -1086,7 +1086,10 @@ br_multicast_get_first_rport_node(struct net_bridge_mcast *brmctx, + if (skb->protocol == htons(ETH_P_IPV6)) + return rcu_dereference(hlist_first_rcu(&brmctx->ip6_mc_router_list)); + #endif +- return rcu_dereference(hlist_first_rcu(&brmctx->ip4_mc_router_list)); ++ if (skb->protocol == htons(ETH_P_IP)) ++ return rcu_dereference(hlist_first_rcu(&brmctx->ip4_mc_router_list)); ++ ++ return NULL; + } + + static inline struct net_bridge_port * +-- +2.43.0 + diff --git a/patches/linux/6.12.1/0021-net-bridge-drop-delay-for-applying-strict-multicast-.patch b/patches/linux/6.12.1/0021-net-bridge-drop-delay-for-applying-strict-multicast-.patch new file mode 100644 index 00000000..48373f86 --- /dev/null +++ b/patches/linux/6.12.1/0021-net-bridge-drop-delay-for-applying-strict-multicast-.patch @@ -0,0 +1,191 @@ +From bc2cbf4dd3c5a756e949f6abe7ffc7fe16e499d6 Mon Sep 17 00:00:00 2001 +From: Joachim Wiberg +Date: Thu, 4 Apr 2024 16:36:30 +0200 +Subject: [PATCH 21/24] net: bridge: drop delay for applying strict multicast + filtering +Organization: Addiva Elektronik + +This *local* patch drops the initial delay before applying strict multicast +filtering, introduced in [1] and recently updated in [2]. + +The main reason for this patch is RFC conformance and customer expectations. +At power on we assume the querier role by default and are expected to stop +unknown flooding as soon as we have a membership report in place, not after +10 seconds. + +A proper fix for upstreaming could be to add a knob to disable the delay. + +[1]: https://lore.kernel.org/netdev/1375311980-25575-1-git-send-email-linus.luessing@web.de/ +[2]: https://lore.kernel.org/netdev/20240127175033.9640-1-linus.luessing@c0d3.blue/ + +Signed-off-by: Joachim Wiberg +Signed-off-by: Tobias Waldekranz +--- + net/bridge/br_multicast.c | 42 +++++++-------------------------------- + net/bridge/br_private.h | 4 +--- + 2 files changed, 8 insertions(+), 38 deletions(-) + +diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c +index 3137c1fcfc6a..34be07a1fd00 100644 +--- a/net/bridge/br_multicast.c ++++ b/net/bridge/br_multicast.c +@@ -1762,10 +1762,6 @@ static void br_ip6_multicast_querier_expired(struct timer_list *t) + } + #endif + +-static void br_multicast_query_delay_expired(struct timer_list *t) +-{ +-} +- + static void br_multicast_select_own_querier(struct net_bridge_mcast *brmctx, + struct br_ip *ip, + struct sk_buff *skb) +@@ -3196,12 +3192,8 @@ int br_multicast_dump_querier_state(struct sk_buff *skb, + + static void + br_multicast_update_query_timer(struct net_bridge_mcast *brmctx, +- struct bridge_mcast_other_query *query, +- unsigned long max_delay) ++ struct bridge_mcast_other_query *query) + { +- if (!timer_pending(&query->timer)) +- mod_timer(&query->delay_timer, jiffies + max_delay); +- + mod_timer(&query->timer, jiffies + brmctx->multicast_querier_interval); + } + +@@ -3392,13 +3384,12 @@ static void + br_ip4_multicast_query_received(struct net_bridge_mcast *brmctx, + struct net_bridge_mcast_port *pmctx, + struct bridge_mcast_other_query *query, +- struct br_ip *saddr, +- unsigned long max_delay) ++ struct br_ip *saddr) + { + if (!br_multicast_select_querier(brmctx, pmctx, saddr)) + return; + +- br_multicast_update_query_timer(brmctx, query, max_delay); ++ br_multicast_update_query_timer(brmctx, query); + br_ip4_multicast_mark_router(brmctx, pmctx); + } + +@@ -3407,13 +3398,12 @@ static void + br_ip6_multicast_query_received(struct net_bridge_mcast *brmctx, + struct net_bridge_mcast_port *pmctx, + struct bridge_mcast_other_query *query, +- struct br_ip *saddr, +- unsigned long max_delay) ++ struct br_ip *saddr) + { + if (!br_multicast_select_querier(brmctx, pmctx, saddr)) + return; + +- br_multicast_update_query_timer(brmctx, query, max_delay); ++ br_multicast_update_query_timer(brmctx, query); + br_ip6_multicast_mark_router(brmctx, pmctx); + } + #endif +@@ -3467,7 +3457,7 @@ static void br_ip4_multicast_query(struct net_bridge_mcast *brmctx, + + br_ip4_multicast_query_received(brmctx, pmctx, + &brmctx->ip4_other_query, +- &saddr, max_delay); ++ &saddr); + goto out; + } + +@@ -3555,7 +3545,7 @@ static int br_ip6_multicast_query(struct net_bridge_mcast *brmctx, + + br_ip6_multicast_query_received(brmctx, pmctx, + &brmctx->ip6_other_query, +- &saddr, max_delay); ++ &saddr); + goto out; + } else if (!group) { + goto out; +@@ -4063,8 +4053,6 @@ void br_multicast_ctx_init(struct net_bridge *br, + br_ip4_multicast_local_router_expired, 0); + timer_setup(&brmctx->ip4_other_query.timer, + br_ip4_multicast_querier_expired, 0); +- timer_setup(&brmctx->ip4_other_query.delay_timer, +- br_multicast_query_delay_expired, 0); + timer_setup(&brmctx->ip4_own_query.timer, + br_ip4_multicast_query_expired, 0); + #if IS_ENABLED(CONFIG_IPV6) +@@ -4072,8 +4060,6 @@ void br_multicast_ctx_init(struct net_bridge *br, + br_ip6_multicast_local_router_expired, 0); + timer_setup(&brmctx->ip6_other_query.timer, + br_ip6_multicast_querier_expired, 0); +- timer_setup(&brmctx->ip6_other_query.delay_timer, +- br_multicast_query_delay_expired, 0); + timer_setup(&brmctx->ip6_own_query.timer, + br_ip6_multicast_query_expired, 0); + #endif +@@ -4208,12 +4194,10 @@ static void __br_multicast_stop(struct net_bridge_mcast *brmctx) + { + del_timer_sync(&brmctx->ip4_mc_router_timer); + del_timer_sync(&brmctx->ip4_other_query.timer); +- del_timer_sync(&brmctx->ip4_other_query.delay_timer); + del_timer_sync(&brmctx->ip4_own_query.timer); + #if IS_ENABLED(CONFIG_IPV6) + del_timer_sync(&brmctx->ip6_mc_router_timer); + del_timer_sync(&brmctx->ip6_other_query.timer); +- del_timer_sync(&brmctx->ip6_other_query.delay_timer); + del_timer_sync(&brmctx->ip6_own_query.timer); + #endif + } +@@ -4641,8 +4625,6 @@ EXPORT_SYMBOL_GPL(br_multicast_router); + + int br_multicast_set_querier(struct net_bridge_mcast *brmctx, unsigned long val) + { +- unsigned long max_delay; +- + val = !!val; + + spin_lock_bh(&brmctx->br->multicast_lock); +@@ -4653,19 +4635,9 @@ int br_multicast_set_querier(struct net_bridge_mcast *brmctx, unsigned long val) + if (!val) + goto unlock; + +- max_delay = brmctx->multicast_query_response_interval; +- +- if (!timer_pending(&brmctx->ip4_other_query.timer)) +- mod_timer(&brmctx->ip4_other_query.delay_timer, +- jiffies + max_delay); +- + br_multicast_start_querier(brmctx, &brmctx->ip4_own_query); + + #if IS_ENABLED(CONFIG_IPV6) +- if (!timer_pending(&brmctx->ip6_other_query.timer)) +- mod_timer(&brmctx->ip6_other_query.delay_timer, +- jiffies + max_delay); +- + br_multicast_start_querier(brmctx, &brmctx->ip6_own_query); + #endif + +diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h +index e90b4f5cab76..73b78c594564 100644 +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -78,7 +78,6 @@ struct bridge_mcast_own_query { + /* other querier */ + struct bridge_mcast_other_query { + struct timer_list timer; +- struct timer_list delay_timer; + }; + + /* selected querier */ +@@ -1164,8 +1163,7 @@ __br_multicast_querier_exists(struct net_bridge_mcast *brmctx, + own_querier_enabled = false; + } + +- return !timer_pending(&querier->delay_timer) && +- (own_querier_enabled || timer_pending(&querier->timer)); ++ return own_querier_enabled || timer_pending(&querier->timer); + } + + static inline bool br_multicast_querier_exists(struct net_bridge_mcast *brmctx, +-- +2.43.0 + diff --git a/patches/linux/6.12.1/0022-net-bridge-Differentiate-MDB-additions-from-modifica.patch b/patches/linux/6.12.1/0022-net-bridge-Differentiate-MDB-additions-from-modifica.patch new file mode 100644 index 00000000..190930fa --- /dev/null +++ b/patches/linux/6.12.1/0022-net-bridge-Differentiate-MDB-additions-from-modifica.patch @@ -0,0 +1,109 @@ +From 65bf34b0195259808333b8fa7b53b8f588c58f32 Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Thu, 16 May 2024 14:51:54 +0200 +Subject: [PATCH 22/24] net: bridge: Differentiate MDB additions from + modifications +Organization: Addiva Elektronik + +Before this change, the reception of an IGMPv3 report (and analogously +for MLDv2) that adds a new group, would trigger two MDB RTM_NEWMDB +notifications from br_ip4_multicast_igmp3_report(): + +1. In br_ip4_multicast_add_group() when creating the entry +2. Directly at the end of br_ip4_multicast_igmp3_report(), as the new + group is also deemed to be "changed" + +The corresponding switchdev notifications generated by these present a +problem for drivers wanting to reference count group memberships, +since logically there is only a single reference to the group. Indeed, +when the membership eventually times out, only a single RTM_DELMDB is +generated. + +Therefore, discriminate new groups from changes to existing groups by +introducing a RTM_SETMDB events to be used in the latter scenario. + +Signed-off-by: Tobias Waldekranz +--- + include/uapi/linux/rtnetlink.h | 2 ++ + net/bridge/br_mdb.c | 4 ++-- + net/bridge/br_multicast.c | 8 ++++---- + 3 files changed, 8 insertions(+), 6 deletions(-) + +diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h +index 3b687d20c9ed..c459cddb1e97 100644 +--- a/include/uapi/linux/rtnetlink.h ++++ b/include/uapi/linux/rtnetlink.h +@@ -134,6 +134,8 @@ enum { + #define RTM_DELMDB RTM_DELMDB + RTM_GETMDB = 86, + #define RTM_GETMDB RTM_GETMDB ++ RTM_SETMDB = 87, ++#define RTM_SETMDB RTM_SETMDB + + RTM_NEWNSID = 88, + #define RTM_NEWNSID RTM_NEWNSID +diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c +index 1a52a0bca086..d5757ab72d2f 100644 +--- a/net/bridge/br_mdb.c ++++ b/net/bridge/br_mdb.c +@@ -734,7 +734,7 @@ static int br_mdb_replace_group_sg(const struct br_mdb_config *cfg, + else + del_timer(&pg->timer); + +- br_mdb_notify(cfg->br->dev, mp, pg, RTM_NEWMDB); ++ br_mdb_notify(cfg->br->dev, mp, pg, RTM_SETMDB); + + return 0; + } +@@ -955,7 +955,7 @@ static int br_mdb_replace_group_star_g(const struct br_mdb_config *cfg, + else + del_timer(&pg->timer); + +- br_mdb_notify(cfg->br->dev, mp, pg, RTM_NEWMDB); ++ br_mdb_notify(cfg->br->dev, mp, pg, RTM_SETMDB); + + if (br_multicast_should_handle_mode(brmctx, cfg->group.proto)) + br_multicast_star_g_handle_mode(pg, cfg->filter_mode); +diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c +index 34be07a1fd00..9c8bf38e0079 100644 +--- a/net/bridge/br_multicast.c ++++ b/net/bridge/br_multicast.c +@@ -619,7 +619,7 @@ static void br_multicast_fwd_src_handle(struct net_bridge_group_src *src) + sg_mp = br_mdb_ip_get(src->br, &sg_key.addr); + if (!sg_mp) + return; +- br_mdb_notify(src->br->dev, sg_mp, sg, RTM_NEWMDB); ++ br_mdb_notify(src->br->dev, sg_mp, sg, RTM_SETMDB); + } + } + +@@ -886,7 +886,7 @@ static void br_multicast_port_group_expired(struct timer_list *t) + + if (WARN_ON(!mp)) + goto out; +- br_mdb_notify(br->dev, mp, pg, RTM_NEWMDB); ++ br_mdb_notify(br->dev, mp, pg, RTM_SETMDB); + } + out: + spin_unlock(&br->multicast_lock); +@@ -2887,7 +2887,7 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge_mcast *brmctx, + break; + } + if (changed) +- br_mdb_notify(brmctx->br->dev, mdst, pg, RTM_NEWMDB); ++ br_mdb_notify(brmctx->br->dev, mdst, pg, RTM_SETMDB); + unlock_continue: + spin_unlock(&brmctx->br->multicast_lock); + } +@@ -3029,7 +3029,7 @@ static int br_ip6_multicast_mld2_report(struct net_bridge_mcast *brmctx, + break; + } + if (changed) +- br_mdb_notify(brmctx->br->dev, mdst, pg, RTM_NEWMDB); ++ br_mdb_notify(brmctx->br->dev, mdst, pg, RTM_SETMDB); + unlock_continue: + spin_unlock(&brmctx->br->multicast_lock); + } +-- +2.43.0 + diff --git a/patches/linux/6.12.1/0023-nvmem-layouts-onie-tlv-Let-device-probe-even-when-TL.patch b/patches/linux/6.12.1/0023-nvmem-layouts-onie-tlv-Let-device-probe-even-when-TL.patch new file mode 100644 index 00000000..ddaa6428 --- /dev/null +++ b/patches/linux/6.12.1/0023-nvmem-layouts-onie-tlv-Let-device-probe-even-when-TL.patch @@ -0,0 +1,55 @@ +From 9a15a9276f0bc1fd10c74ebb244e615af3f60880 Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Fri, 24 Nov 2023 23:29:55 +0100 +Subject: [PATCH 23/24] nvmem: layouts: onie-tlv: Let device probe even when + TLV is invalid +Organization: Addiva Elektronik + +Before this change, probing an NVMEM device, expected to contain a +valid TLV, would fail if it had not been provisioned yet. But an +obvious way of provisioning is to write the TLV to the nvmem +attribute, which would not be possible because the device would not +be successfully probed. + +Therefore, settle for reporting data corruption issues in the log, and +simply refrain from registering any cells in those cases. + +Signed-off-by: Tobias Waldekranz +--- + drivers/nvmem/layouts/onie-tlv.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/nvmem/layouts/onie-tlv.c b/drivers/nvmem/layouts/onie-tlv.c +index 0967a32319a2..48547d5bb502 100644 +--- a/drivers/nvmem/layouts/onie-tlv.c ++++ b/drivers/nvmem/layouts/onie-tlv.c +@@ -197,7 +197,7 @@ static int onie_tlv_parse_table(struct nvmem_layout *layout) + + if (!onie_tlv_hdr_is_valid(dev, &hdr)) { + dev_err(dev, "Invalid ONIE TLV header\n"); +- return -EINVAL; ++ return 0; + } + + hdr_len = sizeof(hdr.id) + sizeof(hdr.version) + sizeof(hdr.data_len); +@@ -205,7 +205,7 @@ static int onie_tlv_parse_table(struct nvmem_layout *layout) + table_len = hdr_len + data_len; + if (table_len > ONIE_TLV_MAX_LEN) { + dev_err(dev, "Invalid ONIE TLV data length\n"); +- return -EINVAL; ++ return 0; + } + + table = devm_kmalloc(dev, table_len, GFP_KERNEL); +@@ -217,7 +217,7 @@ static int onie_tlv_parse_table(struct nvmem_layout *layout) + return ret; + + if (!onie_tlv_crc_is_valid(dev, table_len, table)) +- return -EINVAL; ++ return 0; + + data = table + hdr_len; + ret = onie_tlv_add_cells(dev, nvmem, data_len, data); +-- +2.43.0 + diff --git a/patches/linux/6.12.1/0024-usb-core-adjust-log-level-for-unauthorized-devices.patch b/patches/linux/6.12.1/0024-usb-core-adjust-log-level-for-unauthorized-devices.patch new file mode 100644 index 00000000..19e52bcd --- /dev/null +++ b/patches/linux/6.12.1/0024-usb-core-adjust-log-level-for-unauthorized-devices.patch @@ -0,0 +1,50 @@ +From 867929d898d12c8322091352cc8b59da77032e3f Mon Sep 17 00:00:00 2001 +From: Joachim Wiberg +Date: Mon, 29 Apr 2024 15:14:51 +0200 +Subject: [PATCH 24/24] usb: core: adjust log level for unauthorized devices +Organization: Addiva Elektronik + +The fact that a USB device currently is not authorized is not an error, +so let's adjust the log level so these messages slip below radar for the +commonly used 'quiet' log level. + +Signed-off-by: Joachim Wiberg +Signed-off-by: Tobias Waldekranz +--- + drivers/usb/core/driver.c | 4 ++-- + drivers/usb/core/generic.c | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c +index 0c3f12daac79..037f03aace9f 100644 +--- a/drivers/usb/core/driver.c ++++ b/drivers/usb/core/driver.c +@@ -335,10 +335,10 @@ static int usb_probe_interface(struct device *dev) + return error; + + if (udev->authorized == 0) { +- dev_err(&intf->dev, "Device is not authorized for usage\n"); ++ dev_warn(&intf->dev, "Device is not authorized for usage\n"); + return error; + } else if (intf->authorized == 0) { +- dev_err(&intf->dev, "Interface %d is not authorized for usage\n", ++ dev_warn(&intf->dev, "Interface %d is not authorized for usage\n", + intf->altsetting->desc.bInterfaceNumber); + return error; + } +diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c +index b134bff5c3fe..60575a01a810 100644 +--- a/drivers/usb/core/generic.c ++++ b/drivers/usb/core/generic.c +@@ -247,7 +247,7 @@ int usb_generic_driver_probe(struct usb_device *udev) + * with the driver core and lets interface drivers bind to them. + */ + if (udev->authorized == 0) +- dev_err(&udev->dev, "Device is not authorized for usage\n"); ++ dev_warn(&udev->dev, "Device is not authorized for usage\n"); + else { + c = usb_choose_configuration(udev); + if (c >= 0) { +-- +2.43.0 + From 88f7c6070a089d79c988d0c8c99344006cff04e2 Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Tue, 3 Dec 2024 13:07:33 +0100 Subject: [PATCH 3/5] package/board: Let the user select the set of boards to support Introduce a new approach to dtb-building: Old way: `rsync` an overlay containing our dt source to the kernel, and then build via buildroot's `_INTREE_DTS_NAME`. This does not work in recent kernels (at least since 6.12), which requires all dtb's to be explicitly listed in a `Makefile`. New way: Create a separate package for every board, and build the device trees via the kernel's standard interface for building external modules. This has two main advantages: 1. We can easily interpose a patched version of an upstream device tree. E.g., we can easily set the factory password. 2. It is much easier to get an overview of which boards are enabled, rather than scrolling back and forth in the `_INTREE_DTS_NAME` list. Enable all fully supported boards in the defconfigs. --- configs/aarch64_defconfig | 8 ++-- configs/aarch64_minimal_defconfig | 8 ++-- package/Config.in | 4 ++ package/board/Config.in | 9 ++++ package/board/alder-alder/Config.in | 5 +++ package/board/alder-alder/alder-alder.mk | 2 + package/board/board.mk | 45 +++++++++++++++++++ package/board/dtb-inst.makefile | 9 ++++ package/board/marvell-cn9130-crb/Config.in | 5 +++ .../marvell-cn9130-crb/marvell-cn9130-crb.mk | 2 + package/board/marvell-espressobin/Config.in | 5 +++ .../marvell-espressobin.mk | 2 + .../board/microchip-sparx5-pcb135/Config.in | 5 +++ .../microchip-sparx5-pcb135.mk | 2 + package/board/styx-dcp-sc-28p/Config.in | 5 +++ .../board/styx-dcp-sc-28p/styx-dcp-sc-28p.mk | 2 + src/board/alder-alder/LICENSE | 13 ++++++ src/board/alder-alder/dts/Makefile | 1 + .../board/alder-alder}/dts/alder/alder-mpp.h | 0 .../board/alder-alder}/dts/alder/alder.dts | 0 .../board/alder-alder}/dts/alder/alder.dtsi | 0 .../dts/marvell/cn9130-patched.dtsi | 2 +- src/board/marvell-cn9130-crb/LICENSE | 13 ++++++ src/board/marvell-cn9130-crb/dts/Makefile | 1 + .../dts/marvell/cn9130-crb-A.dts | 2 +- src/board/marvell-espressobin/LICENSE | 13 ++++++ src/board/marvell-espressobin/dts/Makefile | 5 +++ .../marvell/armada-3720-espressobin-emmc.dts | 10 +++++ .../marvell/armada-3720-espressobin-ultra.dts | 10 +++++ .../armada-3720-espressobin-v7-emmc.dts | 10 +++++ .../marvell/armada-3720-espressobin-v7.dts | 10 +++++ .../dts/marvell/armada-3720-espressobin.dts | 10 +++++ src/board/microchip-sparx5-pcb135/LICENSE | 13 ++++++ .../microchip-sparx5-pcb135/dts/Makefile | 1 + .../microchip/sparx5_pcb135_emmc_no_psci.dts | 2 +- src/board/styx-dcp-sc-28p/LICENSE | 13 ++++++ src/board/styx-dcp-sc-28p/dts/Makefile | 2 + .../dts/marvell/cn9130-patched.dtsi | 12 +++++ .../dts/styx/dcp-sc-28p-a.dts | 0 .../dts/styx/dcp-sc-28p-b.dts | 0 .../dts/styx/dcp-sc-28p-mpp.h | 0 .../styx-dcp-sc-28p}/dts/styx/dcp-sc-28p.dtsi | 0 42 files changed, 250 insertions(+), 11 deletions(-) create mode 100644 package/board/Config.in create mode 100644 package/board/alder-alder/Config.in create mode 100644 package/board/alder-alder/alder-alder.mk create mode 100644 package/board/board.mk create mode 100644 package/board/dtb-inst.makefile create mode 100644 package/board/marvell-cn9130-crb/Config.in create mode 100644 package/board/marvell-cn9130-crb/marvell-cn9130-crb.mk create mode 100644 package/board/marvell-espressobin/Config.in create mode 100644 package/board/marvell-espressobin/marvell-espressobin.mk create mode 100644 package/board/microchip-sparx5-pcb135/Config.in create mode 100644 package/board/microchip-sparx5-pcb135/microchip-sparx5-pcb135.mk create mode 100644 package/board/styx-dcp-sc-28p/Config.in create mode 100644 package/board/styx-dcp-sc-28p/styx-dcp-sc-28p.mk create mode 100644 src/board/alder-alder/LICENSE create mode 100644 src/board/alder-alder/dts/Makefile rename {board/aarch64 => src/board/alder-alder}/dts/alder/alder-mpp.h (100%) rename {board/aarch64 => src/board/alder-alder}/dts/alder/alder.dts (100%) rename {board/aarch64 => src/board/alder-alder}/dts/alder/alder.dtsi (100%) rename {board/aarch64 => src/board/alder-alder}/dts/marvell/cn9130-patched.dtsi (86%) create mode 100644 src/board/marvell-cn9130-crb/LICENSE create mode 100644 src/board/marvell-cn9130-crb/dts/Makefile rename {board/aarch64 => src/board/marvell-cn9130-crb}/dts/marvell/cn9130-crb-A.dts (97%) create mode 100644 src/board/marvell-espressobin/LICENSE create mode 100644 src/board/marvell-espressobin/dts/Makefile create mode 100644 src/board/marvell-espressobin/dts/marvell/armada-3720-espressobin-emmc.dts create mode 100644 src/board/marvell-espressobin/dts/marvell/armada-3720-espressobin-ultra.dts create mode 100644 src/board/marvell-espressobin/dts/marvell/armada-3720-espressobin-v7-emmc.dts create mode 100644 src/board/marvell-espressobin/dts/marvell/armada-3720-espressobin-v7.dts create mode 100644 src/board/marvell-espressobin/dts/marvell/armada-3720-espressobin.dts create mode 100644 src/board/microchip-sparx5-pcb135/LICENSE create mode 100644 src/board/microchip-sparx5-pcb135/dts/Makefile rename {board/aarch64 => src/board/microchip-sparx5-pcb135}/dts/microchip/sparx5_pcb135_emmc_no_psci.dts (89%) create mode 100644 src/board/styx-dcp-sc-28p/LICENSE create mode 100644 src/board/styx-dcp-sc-28p/dts/Makefile create mode 100644 src/board/styx-dcp-sc-28p/dts/marvell/cn9130-patched.dtsi rename {board/aarch64 => src/board/styx-dcp-sc-28p}/dts/styx/dcp-sc-28p-a.dts (100%) rename {board/aarch64 => src/board/styx-dcp-sc-28p}/dts/styx/dcp-sc-28p-b.dts (100%) rename {board/aarch64 => src/board/styx-dcp-sc-28p}/dts/styx/dcp-sc-28p-mpp.h (100%) rename {board/aarch64 => src/board/styx-dcp-sc-28p}/dts/styx/dcp-sc-28p.dtsi (100%) diff --git a/configs/aarch64_defconfig b/configs/aarch64_defconfig index 797decfd..6564f038 100644 --- a/configs/aarch64_defconfig +++ b/configs/aarch64_defconfig @@ -30,10 +30,6 @@ BR2_LINUX_KERNEL_CUSTOM_VERSION=y BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.1" BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/aarch64/linux_defconfig" -BR2_LINUX_KERNEL_DTS_SUPPORT=y -BR2_LINUX_KERNEL_INTREE_DTS_NAME="alder/alder styx/dcp-sc-28p-a styx/dcp-sc-28p-b marvell/armada-3720-espressobin marvell/armada-3720-espressobin-emmc marvell/armada-3720-espressobin-v7 marvell/armada-3720-espressobin-v7-emmc marvell/armada-3720-espressobin-ultra marvell/cn9130-crb-A marvell/cn9130-crb-B microchip/sparx5_pcb135_emmc_no_psci" -BR2_LINUX_KERNEL_CUSTOM_DTS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/aarch64/dts" -BR2_LINUX_KERNEL_DTB_KEEP_DIRNAME=y BR2_LINUX_KERNEL_INSTALL_TARGET=y BR2_PACKAGE_BUSYBOX_CONFIG="${BR2_EXTERNAL_INFIX_PATH}/board/common/busybox_defconfig" BR2_PACKAGE_STRACE=y @@ -130,6 +126,10 @@ INFIX_DESC="Infix is a Network Operating System based on Linux. It can be set u INFIX_HOME="https://github.com/kernelkit/infix/" INFIX_DOC="https://github.com/kernelkit/infix/tree/main/doc" INFIX_SUPPORT="mailto:kernelkit@googlegroups.com" +BR2_PACKAGE_ALDER_ALDER=y +BR2_PACKAGE_MARVELL_CN9130_CRB=y +BR2_PACKAGE_MARVELL_ESPRESSOBIN=y +BR2_PACKAGE_STYX_DCP_SC_28P=y BR2_PACKAGE_CONFD=y BR2_PACKAGE_CONFD_TEST_MODE=y BR2_PACKAGE_CURIOS_HTTPD=y diff --git a/configs/aarch64_minimal_defconfig b/configs/aarch64_minimal_defconfig index ecb0ccd9..63b491f2 100644 --- a/configs/aarch64_minimal_defconfig +++ b/configs/aarch64_minimal_defconfig @@ -30,10 +30,6 @@ BR2_LINUX_KERNEL_CUSTOM_VERSION=y BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.1" BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/aarch64/linux_defconfig" -BR2_LINUX_KERNEL_DTS_SUPPORT=y -BR2_LINUX_KERNEL_INTREE_DTS_NAME="alder/alder styx/dcp-sc-28p-a styx/dcp-sc-28p-b marvell/armada-3720-espressobin marvell/armada-3720-espressobin-emmc marvell/armada-3720-espressobin-v7 marvell/armada-3720-espressobin-v7-emmc marvell/armada-3720-espressobin-ultra marvell/cn9130-crb-A marvell/cn9130-crb-B microchip/sparx5_pcb135_emmc_no_psci" -BR2_LINUX_KERNEL_CUSTOM_DTS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/aarch64/dts" -BR2_LINUX_KERNEL_DTB_KEEP_DIRNAME=y BR2_LINUX_KERNEL_INSTALL_TARGET=y BR2_PACKAGE_BUSYBOX_CONFIG="${BR2_EXTERNAL_INFIX_PATH}/board/common/busybox_defconfig" BR2_PACKAGE_STRACE=y @@ -113,6 +109,10 @@ INFIX_DESC="Infix is a Network Operating System based on Linux. It can be set u INFIX_HOME="https://github.com/kernelkit/infix/" INFIX_DOC="https://github.com/kernelkit/infix/tree/main/doc" INFIX_SUPPORT="mailto:kernelkit@googlegroups.com" +BR2_PACKAGE_ALDER_ALDER=y +BR2_PACKAGE_MARVELL_CN9130_CRB=y +BR2_PACKAGE_MARVELL_ESPRESSOBIN=y +BR2_PACKAGE_STYX_DCP_SC_28P=y BR2_PACKAGE_CONFD=y BR2_PACKAGE_CONFD_TEST_MODE=y BR2_PACKAGE_GENCERT=y diff --git a/package/Config.in b/package/Config.in index b3899562..4fe7dbd6 100644 --- a/package/Config.in +++ b/package/Config.in @@ -1,5 +1,9 @@ menu "Packages" +comment "Hardware Support" +source "$BR2_EXTERNAL_INFIX_PATH/package/board/Config.in" + +comment "Software Packages" source "$BR2_EXTERNAL_INFIX_PATH/package/bin/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/confd/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/confd-test-mode/Config.in" diff --git a/package/board/Config.in b/package/board/Config.in new file mode 100644 index 00000000..ebeff591 --- /dev/null +++ b/package/board/Config.in @@ -0,0 +1,9 @@ +menu "Boards" + +source "$BR2_EXTERNAL_INFIX_PATH/package/board/alder-alder/Config.in" +source "$BR2_EXTERNAL_INFIX_PATH/package/board/marvell-cn9130-crb/Config.in" +source "$BR2_EXTERNAL_INFIX_PATH/package/board/marvell-espressobin/Config.in" +source "$BR2_EXTERNAL_INFIX_PATH/package/board/microchip-sparx5-pcb135/Config.in" +source "$BR2_EXTERNAL_INFIX_PATH/package/board/styx-dcp-sc-28p/Config.in" + +endmenu diff --git a/package/board/alder-alder/Config.in b/package/board/alder-alder/Config.in new file mode 100644 index 00000000..12a19e1d --- /dev/null +++ b/package/board/alder-alder/Config.in @@ -0,0 +1,5 @@ +config BR2_PACKAGE_ALDER_ALDER + bool "Alder" + depends on BR2_aarch64 + help + Alder diff --git a/package/board/alder-alder/alder-alder.mk b/package/board/alder-alder/alder-alder.mk new file mode 100644 index 00000000..41f6f7fd --- /dev/null +++ b/package/board/alder-alder/alder-alder.mk @@ -0,0 +1,2 @@ +$(eval $(ix-board)) +$(eval $(generic-package)) diff --git a/package/board/board.mk b/package/board/board.mk new file mode 100644 index 00000000..56b68b9a --- /dev/null +++ b/package/board/board.mk @@ -0,0 +1,45 @@ +define inner-ix-board + +$(2)_VERSION = ix-board +$(2)_LICENSE = BSD-3-Clause +$(2)_LICENSE_FILES = LICENSE +$(2)_SITE_METHOD = local +$(2)_SITE = $$(BR2_EXTERNAL_INFIX_PATH)/src/board/$(1) +$(2)_REDISTRIBUTE = NO + +# The kernel must be built first. +$(2)_DEPENDENCIES += \ + linux \ + $$(BR2_MAKE_HOST_DEPENDENCY) + +# This is only defined in some infrastructures (e.g. autotools, cmake), +# but not in others (e.g. generic). So define it here as well. +$(2)_MAKE ?= $$(BR2_MAKE) + +define $(2)_DTBS_BUILD + @$$(call MESSAGE,"Building device tree blob(s)") + $$(LINUX_MAKE_ENV) $$($$(PKG)_MAKE) \ + -C $$(LINUX_DIR) \ + $$(LINUX_MAKE_FLAGS) \ + $$($(2)_DTB_MAKE_OPTS) \ + PWD=$$(@D)/dts \ + M=$$(@D)/dts \ + modules +endef +$(2)_POST_BUILD_HOOKS += $(2)_DTBS_BUILD + +define $(2)_DTBS_INSTALL_TARGET + @$$(call MESSAGE,"Installing device tree blob(s)") + $$(TARGET_MAKE_ENV) $$(TARGET_CONFIGURE_OPTS) $$($$(PKG)_MAKE) \ + -f $$(BR2_EXTERNAL_INFIX_PATH)/package/board/dtb-inst.makefile \ + -C $$(@D)/dts \ + DESTDIR="$$(TARGET_DIR)" \ + install +endef +$(2)_POST_INSTALL_TARGET_HOOKS += $(2)_DTBS_INSTALL_TARGET + +endef + +ix-board = $(call inner-ix-board,$(pkgname),$(call UPPERCASE,$(pkgname))) + +include $(sort $(wildcard $(BR2_EXTERNAL_INFIX_PATH)/package/board/*/*.mk)) diff --git a/package/board/dtb-inst.makefile b/package/board/dtb-inst.makefile new file mode 100644 index 00000000..62b0f059 --- /dev/null +++ b/package/board/dtb-inst.makefile @@ -0,0 +1,9 @@ +include Makefile + +install: $(addprefix $(DESTDIR)/boot/,$(dtb-y)) + +$(DESTDIR)/boot/%.dtb: %.dtb + @echo " DTB-INSTALL $<" + @install -D $< $@ + +.PHONY: install diff --git a/package/board/marvell-cn9130-crb/Config.in b/package/board/marvell-cn9130-crb/Config.in new file mode 100644 index 00000000..3ede2b83 --- /dev/null +++ b/package/board/marvell-cn9130-crb/Config.in @@ -0,0 +1,5 @@ +config BR2_PACKAGE_MARVELL_CN9130_CRB + bool "Marvell CN9130-CRB" + depends on BR2_aarch64 + help + Customer Reference Board for CN9130 diff --git a/package/board/marvell-cn9130-crb/marvell-cn9130-crb.mk b/package/board/marvell-cn9130-crb/marvell-cn9130-crb.mk new file mode 100644 index 00000000..41f6f7fd --- /dev/null +++ b/package/board/marvell-cn9130-crb/marvell-cn9130-crb.mk @@ -0,0 +1,2 @@ +$(eval $(ix-board)) +$(eval $(generic-package)) diff --git a/package/board/marvell-espressobin/Config.in b/package/board/marvell-espressobin/Config.in new file mode 100644 index 00000000..a8bed5f6 --- /dev/null +++ b/package/board/marvell-espressobin/Config.in @@ -0,0 +1,5 @@ +config BR2_PACKAGE_MARVELL_ESPRESSOBIN + bool "Marvell ESPRESSObin" + depends on BR2_aarch64 + help + Marvell ESPRESSObin diff --git a/package/board/marvell-espressobin/marvell-espressobin.mk b/package/board/marvell-espressobin/marvell-espressobin.mk new file mode 100644 index 00000000..41f6f7fd --- /dev/null +++ b/package/board/marvell-espressobin/marvell-espressobin.mk @@ -0,0 +1,2 @@ +$(eval $(ix-board)) +$(eval $(generic-package)) diff --git a/package/board/microchip-sparx5-pcb135/Config.in b/package/board/microchip-sparx5-pcb135/Config.in new file mode 100644 index 00000000..4cf7c8d0 --- /dev/null +++ b/package/board/microchip-sparx5-pcb135/Config.in @@ -0,0 +1,5 @@ +config BR2_PACKAGE_MICROCHIP_SPARX5_PCB135 + bool "Microchip SparX-5i PCB135" + depends on BR2_aarch64 + help + Microchip's evaluation board for SparX-5i diff --git a/package/board/microchip-sparx5-pcb135/microchip-sparx5-pcb135.mk b/package/board/microchip-sparx5-pcb135/microchip-sparx5-pcb135.mk new file mode 100644 index 00000000..41f6f7fd --- /dev/null +++ b/package/board/microchip-sparx5-pcb135/microchip-sparx5-pcb135.mk @@ -0,0 +1,2 @@ +$(eval $(ix-board)) +$(eval $(generic-package)) diff --git a/package/board/styx-dcp-sc-28p/Config.in b/package/board/styx-dcp-sc-28p/Config.in new file mode 100644 index 00000000..2fa8832b --- /dev/null +++ b/package/board/styx-dcp-sc-28p/Config.in @@ -0,0 +1,5 @@ +config BR2_PACKAGE_STYX_DCP_SC_28P + bool "Styx DCP-SC-28P" + depends on BR2_aarch64 + help + Styx DCP-SC-28P diff --git a/package/board/styx-dcp-sc-28p/styx-dcp-sc-28p.mk b/package/board/styx-dcp-sc-28p/styx-dcp-sc-28p.mk new file mode 100644 index 00000000..41f6f7fd --- /dev/null +++ b/package/board/styx-dcp-sc-28p/styx-dcp-sc-28p.mk @@ -0,0 +1,2 @@ +$(eval $(ix-board)) +$(eval $(generic-package)) diff --git a/src/board/alder-alder/LICENSE b/src/board/alder-alder/LICENSE new file mode 100644 index 00000000..f9b6d6c1 --- /dev/null +++ b/src/board/alder-alder/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2024 The KernelKit Authors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/src/board/alder-alder/dts/Makefile b/src/board/alder-alder/dts/Makefile new file mode 100644 index 00000000..12a78a2a --- /dev/null +++ b/src/board/alder-alder/dts/Makefile @@ -0,0 +1 @@ +dtb-y += alder/alder.dtb diff --git a/board/aarch64/dts/alder/alder-mpp.h b/src/board/alder-alder/dts/alder/alder-mpp.h similarity index 100% rename from board/aarch64/dts/alder/alder-mpp.h rename to src/board/alder-alder/dts/alder/alder-mpp.h diff --git a/board/aarch64/dts/alder/alder.dts b/src/board/alder-alder/dts/alder/alder.dts similarity index 100% rename from board/aarch64/dts/alder/alder.dts rename to src/board/alder-alder/dts/alder/alder.dts diff --git a/board/aarch64/dts/alder/alder.dtsi b/src/board/alder-alder/dts/alder/alder.dtsi similarity index 100% rename from board/aarch64/dts/alder/alder.dtsi rename to src/board/alder-alder/dts/alder/alder.dtsi diff --git a/board/aarch64/dts/marvell/cn9130-patched.dtsi b/src/board/alder-alder/dts/marvell/cn9130-patched.dtsi similarity index 86% rename from board/aarch64/dts/marvell/cn9130-patched.dtsi rename to src/board/alder-alder/dts/marvell/cn9130-patched.dtsi index 8625f5cc..6ab6dd47 100644 --- a/board/aarch64/dts/marvell/cn9130-patched.dtsi +++ b/src/board/alder-alder/dts/marvell/cn9130-patched.dtsi @@ -1,4 +1,4 @@ -#include "cn9130.dtsi" +#include &cp0_syscon0 { cp0_pinctrl: pinctrl { diff --git a/src/board/marvell-cn9130-crb/LICENSE b/src/board/marvell-cn9130-crb/LICENSE new file mode 100644 index 00000000..f9b6d6c1 --- /dev/null +++ b/src/board/marvell-cn9130-crb/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2024 The KernelKit Authors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/src/board/marvell-cn9130-crb/dts/Makefile b/src/board/marvell-cn9130-crb/dts/Makefile new file mode 100644 index 00000000..2ecb28f5 --- /dev/null +++ b/src/board/marvell-cn9130-crb/dts/Makefile @@ -0,0 +1 @@ +dtb-y += marvell/cn9130-crb-A.dtb diff --git a/board/aarch64/dts/marvell/cn9130-crb-A.dts b/src/board/marvell-cn9130-crb/dts/marvell/cn9130-crb-A.dts similarity index 97% rename from board/aarch64/dts/marvell/cn9130-crb-A.dts rename to src/board/marvell-cn9130-crb/dts/marvell/cn9130-crb-A.dts index 1a60a7a0..4b1abcdc 100644 --- a/board/aarch64/dts/marvell/cn9130-crb-A.dts +++ b/src/board/marvell-cn9130-crb/dts/marvell/cn9130-crb-A.dts @@ -3,7 +3,7 @@ * Copyright (C) 2020 Marvell International Ltd. */ -#include "cn9130-crb.dtsi" +#include "arm64/marvell/cn9130-crb.dtsi" / { model = "Marvell Armada CN9130-CRB-A"; diff --git a/src/board/marvell-espressobin/LICENSE b/src/board/marvell-espressobin/LICENSE new file mode 100644 index 00000000..f9b6d6c1 --- /dev/null +++ b/src/board/marvell-espressobin/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2024 The KernelKit Authors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/src/board/marvell-espressobin/dts/Makefile b/src/board/marvell-espressobin/dts/Makefile new file mode 100644 index 00000000..c801c8db --- /dev/null +++ b/src/board/marvell-espressobin/dts/Makefile @@ -0,0 +1,5 @@ +dtb-y += marvell/armada-3720-espressobin.dtb +dtb-y += marvell/armada-3720-espressobin-emmc.dtb +dtb-y += marvell/armada-3720-espressobin-ultra.dtb +dtb-y += marvell/armada-3720-espressobin-v7.dtb +dtb-y += marvell/armada-3720-espressobin-v7-emmc.dtb diff --git a/src/board/marvell-espressobin/dts/marvell/armada-3720-espressobin-emmc.dts b/src/board/marvell-espressobin/dts/marvell/armada-3720-espressobin-emmc.dts new file mode 100644 index 00000000..0fc22c8e --- /dev/null +++ b/src/board/marvell-espressobin/dts/marvell/armada-3720-espressobin-emmc.dts @@ -0,0 +1,10 @@ +#include + +/ { + chosen { + infix { + /* "admin" */ + factory-password-hash = "$5$mI/zpOAqZYKLC2WU$i7iPzZiIjOjrBF3NyftS9CCq8dfYwHwrmUK097Jca9A"; + }; + }; +}; diff --git a/src/board/marvell-espressobin/dts/marvell/armada-3720-espressobin-ultra.dts b/src/board/marvell-espressobin/dts/marvell/armada-3720-espressobin-ultra.dts new file mode 100644 index 00000000..61c4b459 --- /dev/null +++ b/src/board/marvell-espressobin/dts/marvell/armada-3720-espressobin-ultra.dts @@ -0,0 +1,10 @@ +#include + +/ { + chosen { + infix { + /* "admin" */ + factory-password-hash = "$5$mI/zpOAqZYKLC2WU$i7iPzZiIjOjrBF3NyftS9CCq8dfYwHwrmUK097Jca9A"; + }; + }; +}; diff --git a/src/board/marvell-espressobin/dts/marvell/armada-3720-espressobin-v7-emmc.dts b/src/board/marvell-espressobin/dts/marvell/armada-3720-espressobin-v7-emmc.dts new file mode 100644 index 00000000..038d96e3 --- /dev/null +++ b/src/board/marvell-espressobin/dts/marvell/armada-3720-espressobin-v7-emmc.dts @@ -0,0 +1,10 @@ +#include + +/ { + chosen { + infix { + /* "admin" */ + factory-password-hash = "$5$mI/zpOAqZYKLC2WU$i7iPzZiIjOjrBF3NyftS9CCq8dfYwHwrmUK097Jca9A"; + }; + }; +}; diff --git a/src/board/marvell-espressobin/dts/marvell/armada-3720-espressobin-v7.dts b/src/board/marvell-espressobin/dts/marvell/armada-3720-espressobin-v7.dts new file mode 100644 index 00000000..a9009712 --- /dev/null +++ b/src/board/marvell-espressobin/dts/marvell/armada-3720-espressobin-v7.dts @@ -0,0 +1,10 @@ +#include + +/ { + chosen { + infix { + /* "admin" */ + factory-password-hash = "$5$mI/zpOAqZYKLC2WU$i7iPzZiIjOjrBF3NyftS9CCq8dfYwHwrmUK097Jca9A"; + }; + }; +}; diff --git a/src/board/marvell-espressobin/dts/marvell/armada-3720-espressobin.dts b/src/board/marvell-espressobin/dts/marvell/armada-3720-espressobin.dts new file mode 100644 index 00000000..0bd39720 --- /dev/null +++ b/src/board/marvell-espressobin/dts/marvell/armada-3720-espressobin.dts @@ -0,0 +1,10 @@ +#include + +/ { + chosen { + infix { + /* "admin" */ + factory-password-hash = "$5$mI/zpOAqZYKLC2WU$i7iPzZiIjOjrBF3NyftS9CCq8dfYwHwrmUK097Jca9A"; + }; + }; +}; diff --git a/src/board/microchip-sparx5-pcb135/LICENSE b/src/board/microchip-sparx5-pcb135/LICENSE new file mode 100644 index 00000000..f9b6d6c1 --- /dev/null +++ b/src/board/microchip-sparx5-pcb135/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2024 The KernelKit Authors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/src/board/microchip-sparx5-pcb135/dts/Makefile b/src/board/microchip-sparx5-pcb135/dts/Makefile new file mode 100644 index 00000000..1c56e4d0 --- /dev/null +++ b/src/board/microchip-sparx5-pcb135/dts/Makefile @@ -0,0 +1 @@ +dtb-y += microchip/sparx5_pcb135_emmc_no_psci.dtb diff --git a/board/aarch64/dts/microchip/sparx5_pcb135_emmc_no_psci.dts b/src/board/microchip-sparx5-pcb135/dts/microchip/sparx5_pcb135_emmc_no_psci.dts similarity index 89% rename from board/aarch64/dts/microchip/sparx5_pcb135_emmc_no_psci.dts rename to src/board/microchip-sparx5-pcb135/dts/microchip/sparx5_pcb135_emmc_no_psci.dts index 4b5b2b06..aeede774 100644 --- a/board/aarch64/dts/microchip/sparx5_pcb135_emmc_no_psci.dts +++ b/src/board/microchip-sparx5-pcb135/dts/microchip/sparx5_pcb135_emmc_no_psci.dts @@ -5,7 +5,7 @@ */ /dts-v1/; -#include "sparx5_pcb135_emmc.dts" +#include &cpu0 { enable-method = "spin-table"; diff --git a/src/board/styx-dcp-sc-28p/LICENSE b/src/board/styx-dcp-sc-28p/LICENSE new file mode 100644 index 00000000..f9b6d6c1 --- /dev/null +++ b/src/board/styx-dcp-sc-28p/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2024 The KernelKit Authors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/src/board/styx-dcp-sc-28p/dts/Makefile b/src/board/styx-dcp-sc-28p/dts/Makefile new file mode 100644 index 00000000..7c07ccff --- /dev/null +++ b/src/board/styx-dcp-sc-28p/dts/Makefile @@ -0,0 +1,2 @@ +dtb-y += styx/dcp-sc-28p-a.dtb +dtb-y += styx/dcp-sc-28p-b.dtb diff --git a/src/board/styx-dcp-sc-28p/dts/marvell/cn9130-patched.dtsi b/src/board/styx-dcp-sc-28p/dts/marvell/cn9130-patched.dtsi new file mode 100644 index 00000000..6ab6dd47 --- /dev/null +++ b/src/board/styx-dcp-sc-28p/dts/marvell/cn9130-patched.dtsi @@ -0,0 +1,12 @@ +#include + +&cp0_syscon0 { + cp0_pinctrl: pinctrl { + /* For some reason, this is missing from cn9130.dtsi */ + compatible = "marvell,cp115-standalone-pinctrl"; + }; +}; + +&cp0_xmdio { + clock-names = "gop_clk", "mg_clk", "mg_core_clk", "axi_clk"; +}; diff --git a/board/aarch64/dts/styx/dcp-sc-28p-a.dts b/src/board/styx-dcp-sc-28p/dts/styx/dcp-sc-28p-a.dts similarity index 100% rename from board/aarch64/dts/styx/dcp-sc-28p-a.dts rename to src/board/styx-dcp-sc-28p/dts/styx/dcp-sc-28p-a.dts diff --git a/board/aarch64/dts/styx/dcp-sc-28p-b.dts b/src/board/styx-dcp-sc-28p/dts/styx/dcp-sc-28p-b.dts similarity index 100% rename from board/aarch64/dts/styx/dcp-sc-28p-b.dts rename to src/board/styx-dcp-sc-28p/dts/styx/dcp-sc-28p-b.dts diff --git a/board/aarch64/dts/styx/dcp-sc-28p-mpp.h b/src/board/styx-dcp-sc-28p/dts/styx/dcp-sc-28p-mpp.h similarity index 100% rename from board/aarch64/dts/styx/dcp-sc-28p-mpp.h rename to src/board/styx-dcp-sc-28p/dts/styx/dcp-sc-28p-mpp.h diff --git a/board/aarch64/dts/styx/dcp-sc-28p.dtsi b/src/board/styx-dcp-sc-28p/dts/styx/dcp-sc-28p.dtsi similarity index 100% rename from board/aarch64/dts/styx/dcp-sc-28p.dtsi rename to src/board/styx-dcp-sc-28p/dts/styx/dcp-sc-28p.dtsi From f0ae1aa8350c53b31802f45d236ea28121d60b39 Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Tue, 3 Dec 2024 15:30:43 +0100 Subject: [PATCH 4/5] package/board: Rsync overlay directory, if available --- package/board/board.mk | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/package/board/board.mk b/package/board/board.mk index 56b68b9a..5a20eef0 100644 --- a/package/board/board.mk +++ b/package/board/board.mk @@ -38,6 +38,14 @@ define $(2)_DTBS_INSTALL_TARGET endef $(2)_POST_INSTALL_TARGET_HOOKS += $(2)_DTBS_INSTALL_TARGET +define $(2)_OVERLAY_INSTALL_TARGET + @test -d $$(@D)/rootfs && \ + $$(call MESSAGE,"Copying overlay") && \ + $$(call SYSTEM_RSYNC,$$(@D)/rootfs,$(TARGET_DIR)) || \ + true +endef +$(2)_POST_INSTALL_TARGET_HOOKS += $(2)_OVERLAY_INSTALL_TARGET + endef ix-board = $(call inner-ix-board,$(pkgname),$(call UPPERCASE,$(pkgname))) From 27b7d831d0da1650122d80ea63f97ce4be35b626 Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Tue, 3 Dec 2024 15:29:43 +0100 Subject: [PATCH 5/5] styx-dcp-sc-28p: Move board specific overlay files to package This way, we only install these files if the board is enabled. --- .../board/styx-dcp-sc-28p}/rootfs/boot/styx/styx-b.dtb | 0 .../board/styx-dcp-sc-28p}/rootfs/boot/styx/styx.dtb | 0 .../board/styx-dcp-sc-28p}/rootfs/usr/libexec/styx/led.sh | 0 .../usr/share/product/dcp-sc-28p/etc/finit.d/available/iitod.conf | 0 .../usr/share/product/styx,dcp-sc-28p/etc/product/init.d/S10-led | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename {board/aarch64 => src/board/styx-dcp-sc-28p}/rootfs/boot/styx/styx-b.dtb (100%) rename {board/aarch64 => src/board/styx-dcp-sc-28p}/rootfs/boot/styx/styx.dtb (100%) rename {board/aarch64 => src/board/styx-dcp-sc-28p}/rootfs/usr/libexec/styx/led.sh (100%) rename {board/aarch64 => src/board/styx-dcp-sc-28p}/rootfs/usr/share/product/dcp-sc-28p/etc/finit.d/available/iitod.conf (100%) rename {board/aarch64 => src/board/styx-dcp-sc-28p}/rootfs/usr/share/product/styx,dcp-sc-28p/etc/product/init.d/S10-led (100%) diff --git a/board/aarch64/rootfs/boot/styx/styx-b.dtb b/src/board/styx-dcp-sc-28p/rootfs/boot/styx/styx-b.dtb similarity index 100% rename from board/aarch64/rootfs/boot/styx/styx-b.dtb rename to src/board/styx-dcp-sc-28p/rootfs/boot/styx/styx-b.dtb diff --git a/board/aarch64/rootfs/boot/styx/styx.dtb b/src/board/styx-dcp-sc-28p/rootfs/boot/styx/styx.dtb similarity index 100% rename from board/aarch64/rootfs/boot/styx/styx.dtb rename to src/board/styx-dcp-sc-28p/rootfs/boot/styx/styx.dtb diff --git a/board/aarch64/rootfs/usr/libexec/styx/led.sh b/src/board/styx-dcp-sc-28p/rootfs/usr/libexec/styx/led.sh similarity index 100% rename from board/aarch64/rootfs/usr/libexec/styx/led.sh rename to src/board/styx-dcp-sc-28p/rootfs/usr/libexec/styx/led.sh diff --git a/board/aarch64/rootfs/usr/share/product/dcp-sc-28p/etc/finit.d/available/iitod.conf b/src/board/styx-dcp-sc-28p/rootfs/usr/share/product/dcp-sc-28p/etc/finit.d/available/iitod.conf similarity index 100% rename from board/aarch64/rootfs/usr/share/product/dcp-sc-28p/etc/finit.d/available/iitod.conf rename to src/board/styx-dcp-sc-28p/rootfs/usr/share/product/dcp-sc-28p/etc/finit.d/available/iitod.conf diff --git a/board/aarch64/rootfs/usr/share/product/styx,dcp-sc-28p/etc/product/init.d/S10-led b/src/board/styx-dcp-sc-28p/rootfs/usr/share/product/styx,dcp-sc-28p/etc/product/init.d/S10-led similarity index 100% rename from board/aarch64/rootfs/usr/share/product/styx,dcp-sc-28p/etc/product/init.d/S10-led rename to src/board/styx-dcp-sc-28p/rootfs/usr/share/product/styx,dcp-sc-28p/etc/product/init.d/S10-led