From 53d14ca9a6daa5edee979a8b2d053acc269cd73c Mon Sep 17 00:00:00 2001 From: Josef Schlehofer <josef.schlehofer@nic.cz> Date: Tue, 29 Nov 2022 11:10:09 +0100 Subject: [PATCH] patches/openwrt: 5.15: generic pending patches: rebase --- .../0003-Generic-pending-patches-5.15.patch | 10847 ++++++++++------ 1 file changed, 6870 insertions(+), 3977 deletions(-) diff --git a/patches/openwrt/a-new-kernel-5.15/0003-Generic-pending-patches-5.15.patch b/patches/openwrt/a-new-kernel-5.15/0003-Generic-pending-patches-5.15.patch index 2a31394ea..b85c89d88 100644 --- a/patches/openwrt/a-new-kernel-5.15/0003-Generic-pending-patches-5.15.patch +++ b/patches/openwrt/a-new-kernel-5.15/0003-Generic-pending-patches-5.15.patch @@ -1,13 +1,13 @@ -From 86b7905251dc6b34461f91fc32be6775fc7bf165 Mon Sep 17 00:00:00 2001 +From dde8512fc111ac1c1f5df602f86c4810651c109a Mon Sep 17 00:00:00 2001 From: Josef Schlehofer <pepe.schlehofer@gmail.com> -Date: Mon, 4 Jul 2022 14:20:22 +0200 +Date: Tue, 29 Nov 2022 10:55:43 +0100 Subject: [PATCH] Generic pending 5.15 patches --- - ...terrupt-provider-address-cells-check.patch | 28 + ...include-asm-rwonce.h-for-kernel-code.patch | 29 + - ...-Use-stddefs.h-instead-of-compiler.h.patch | 26 + + ...-Use-stddefs.h-instead-of-compiler.h.patch | 22 + ...s-negative-stack-offsets-on-stack-tr.patch | 57 + + .../103-kbuild-export-SUBARCH.patch | 21 + ...e_mem_map-with-ARCH_PFN_OFFSET-calcu.patch | 82 + ...0-add-linux-spidev-compatible-si3210.patch | 18 + ...ame2-and-add-RENAME_WHITEOUT-support.patch | 81 + @@ -26,13 +26,12 @@ Subject: [PATCH] Generic pending 5.15 patches .../pending-5.15/305-mips_module_reloc.patch | 370 ++ .../307-mips_highmem_offset.patch | 19 + .../pending-5.15/308-mips32r2_tune.patch | 22 + - ...CPU-option-reporting-to-proc-cpuinfo.patch | 136 + .../310-arm_module_unresolved_weak_sym.patch | 22 + - ...t-command-line-parameters-from-users.patch | 283 + + ...t-command-line-parameters-from-users.patch | 282 + .../332-arc-add-OWRTDTB-section.patch | 84 + ...able-unaligned-access-in-kernel-mode.patch | 24 + ...ernel-XZ-compression-option-on-PPC_8.patch | 25 + - .../400-mtd-mtdsplit-support.patch | 339 ++ + .../400-mtd-mtdsplit-support.patch | 328 ++ ...support-for-minor-aligned-partitions.patch | 245 + .../pending-5.15/420-mtd-redboot_space.patch | 41 + ...30-mtd-add-myloader-partition-parser.patch | 229 + @@ -45,23 +44,22 @@ Subject: [PATCH] Generic pending 5.15 patches .../476-mtd-spi-nor-add-eon-en25q128.patch | 18 + .../479-mtd-spi-nor-add-xtx-xt25f128b.patch | 79 + ...r-add-support-for-Gigadevice-GD25D05.patch | 22 + - .../482-mtd-spi-nor-add-gd25q512.patch | 25 + - ...spinand-add-support-for-xtx-xt26g0xa.patch | 178 + - .../484-mtd-spi-nor-add-esmt-f25l16pa.patch | 27 + - .../485-mtd-spi-nor-add-xmc-xm25qh128c.patch | 28 + + .../482-mtd-spi-nor-add-gd25q512.patch | 21 + + .../484-mtd-spi-nor-add-esmt-f25l16pa.patch | 23 + + .../485-mtd-spi-nor-add-xmc-xm25qh128c.patch | 24 + ...nand-add-support-for-ESMT-F50x1G41LB.patch | 143 + + ...nd-Add-support-for-Etron-EM73D044VCx.patch | 168 + ...mtd-device-named-ubi-or-data-on-boot.patch | 97 + ...to-create-ubiblock-device-for-rootfs.patch | 69 + ...ting-ubi0-rootfs-in-init-do_mounts.c.patch | 53 + ...ROOT_DEV-to-ubiblock-rootfs-if-unset.patch | 34 + .../494-mtd-ubi-add-EOF-marker-support.patch | 60 + - ...-mtd-core-add-get_mtd_device_by_node.patch | 75 + ...-add-bindings-for-mtd-concat-devices.patch | 52 + ...cat-add-dt-driver-for-concat-devices.patch | 216 + ...i-nor-locking-support-for-MX25L6405D.patch | 34 + ...i-nor-disable-16-bit-sr-for-macronix.patch | 30 + - .../500-fs_cdrom_dependencies.patch | 62 + - .../530-jffs2_make_lzma_available.patch | 5180 +++++++++++++++++ + .../500-fs_cdrom_dependencies.patch | 52 + + .../530-jffs2_make_lzma_available.patch | 4581 +++++++++++++++++ .../pending-5.15/532-jffs2_eofdetect.patch | 65 + .../600-netfilter_conntrack_flush.patch | 88 + ...etfilter_match_bypass_default_checks.patch | 110 + @@ -76,11 +74,43 @@ Subject: [PATCH] Generic pending 5.15 patches ...nes-for-_POLICY_FAILED-until-all-cod.patch | 50 + ...T-skip-GRO-for-foreign-MAC-addresses.patch | 149 + ...et-add-mac-address-increment-support.patch | 89 + - ...83-of_net-add-mac-address-to-of-tree.patch | 59 + + ...83-of_net-add-mac-address-to-of-tree.patch | 55 + + ...t-do-mac-address-increment-only-once.patch | 31 + + ...ow_offload-handle-netdevice-events-f.patch | 106 + + ...er-nf_flow_table-add-missing-locking.patch | 39 + ...net-mtk_eth_soc-enable-threaded-NAPI.patch | 41 + ...detach-callback-to-struct-phy_driver.patch | 38 + ...a-tag_mtk-add-padding-for-tx-packets.patch | 29 + ...d-knob-for-filtering-rx-tx-BPDU-pack.patch | 174 + + ...rtl8221-allow-to-configure-SERDES-mo.patch | 101 + + ...e-all-MACs-are-powered-down-before-r.patch | 28 + + ...-net-mtk_sgmii-implement-mtk_pcs_ops.patch | 46 + + ..._sgmii-fix-powering-up-the-SGMII-phy.patch | 39 + + ...sure-the-SGMII-PHY-is-powered-down-o.patch | 65 + + ...k_pcs_setup_mode_an-don-t-rely-on-re.patch | 31 + + ...t-the-speed-according-to-the-phy-int.patch | 47 + + .../729-net-mtk_eth_soc-improve-comment.patch | 22 + + ...enable-PCS-polling-to-allow-SFP-work.patch | 23 + + ...iatek-ppe-add-support-for-flow-accou.patch | 409 ++ + ..._eth_soc-account-for-vlan-in-rx-head.patch | 22 + + ..._eth_soc-increase-tx-ring-side-for-Q.patch | 143 + + ..._eth_soc-avoid-port_mg-assignment-on.patch | 52 + + ..._eth_soc-implement-multi-queue-suppo.patch | 654 +++ + ...t-dsa-tag_mtk-assign-per-port-queues.patch | 20 + + ...iatek-ppe-assign-per-port-queues-for.patch | 93 + + ..._eth_soc-compile-out-netsys-v2-code-.patch | 28 + + ...ort-for-DSA-rx-offloading-via-metada.patch | 72 + + ..._eth_soc-fix-VLAN-rx-hardware-accele.patch | 192 + + ..._eth_soc-work-around-issue-with-send.patch | 78 + + ...rnet-mtk_eth_soc-set-NETIF_F_ALL_TSO.patch | 21 + + ..._eth_soc-drop-packets-to-WDMA-if-the.patch | 37 + + ..._eth_soc-fix-flow_offload-related-re.patch | 52 + + ..._eth_soc-drop-generic-vlan-rx-offloa.patch | 181 + + ...et-mtk_wed-introduce-wed-mcu-support.patch | 591 +++ + ...net-mtk_wed-introduce-wed-wo-support.patch | 737 +++ + ..._wed-rename-tx_wdma-array-in-rx_wdma.patch | 79 + + ...mtk_wed-add-configure-wed-wo-support.patch | 1521 ++++++ + ...ethernet-mtk_wed-add-rx-mib-counters.patch | 149 + ...equest-assisted-learning-on-CPU-port.patch | 27 + ...-missing-linux-if_ether.h-for-ETH_AL.patch | 61 + ...ice-struct-copy-its-DMA-params-to-th.patch | 73 + @@ -90,20 +120,13 @@ Subject: [PATCH] Generic pending 5.15 patches ...problem-with-platfom-data-in-w1-gpio.patch | 26 + .../pending-5.15/834-ledtrig-libata.patch | 149 + ...40-hwrng-bcm2835-set-quality-to-1000.patch | 26 + - ..._wwan-add-ZTE-MF286D-modem-19d2-1485.patch | 59 + ...e-main-irq_chip-structure-a-static-d.patch | 102 + - ...mvebu-a3700-comphy-Remove-port-from-.patch | 217 + - ...mvebu-a3700-comphy-Add-native-kernel.patch | 1564 +++++ - ...l-armada-37xx-Add-xtal-clock-to-comp.patch | 31 + - ...mvebu-Make-SATA-PHY-optional-for-Arm.patch | 61 + - ...xhci-mvebu-make-USB-3.0-PHY-optional.patch | 163 + - ...ark-Fix-initialization-with-old-Marv.patch | 36 + .../pending-5.15/920-mangle_bootargs.patch | 71 + - 95 files changed, 14636 insertions(+) - create mode 100644 target/linux/generic/pending-5.15/050-dtc-checks-Drop-interrupt-provider-address-cells-check.patch + 118 files changed, 17345 insertions(+) create mode 100644 target/linux/generic/pending-5.15/100-compiler.h-only-include-asm-rwonce.h-for-kernel-code.patch create mode 100644 target/linux/generic/pending-5.15/101-Use-stddefs.h-instead-of-compiler.h.patch create mode 100644 target/linux/generic/pending-5.15/102-MIPS-only-process-negative-stack-offsets-on-stack-tr.patch + create mode 100644 target/linux/generic/pending-5.15/103-kbuild-export-SUBARCH.patch create mode 100644 target/linux/generic/pending-5.15/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch create mode 100644 target/linux/generic/pending-5.15/130-add-linux-spidev-compatible-si3210.patch create mode 100644 target/linux/generic/pending-5.15/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch @@ -122,7 +145,6 @@ Subject: [PATCH] Generic pending 5.15 patches create mode 100644 target/linux/generic/pending-5.15/305-mips_module_reloc.patch create mode 100644 target/linux/generic/pending-5.15/307-mips_highmem_offset.patch create mode 100644 target/linux/generic/pending-5.15/308-mips32r2_tune.patch - create mode 100644 target/linux/generic/pending-5.15/309-MIPS-Add-CPU-option-reporting-to-proc-cpuinfo.patch create mode 100644 target/linux/generic/pending-5.15/310-arm_module_unresolved_weak_sym.patch create mode 100644 target/linux/generic/pending-5.15/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch create mode 100644 target/linux/generic/pending-5.15/332-arc-add-OWRTDTB-section.patch @@ -142,16 +164,15 @@ Subject: [PATCH] Generic pending 5.15 patches create mode 100644 target/linux/generic/pending-5.15/479-mtd-spi-nor-add-xtx-xt25f128b.patch create mode 100644 target/linux/generic/pending-5.15/481-mtd-spi-nor-add-support-for-Gigadevice-GD25D05.patch create mode 100644 target/linux/generic/pending-5.15/482-mtd-spi-nor-add-gd25q512.patch - create mode 100644 target/linux/generic/pending-5.15/483-mtd-spinand-add-support-for-xtx-xt26g0xa.patch create mode 100644 target/linux/generic/pending-5.15/484-mtd-spi-nor-add-esmt-f25l16pa.patch create mode 100644 target/linux/generic/pending-5.15/485-mtd-spi-nor-add-xmc-xm25qh128c.patch create mode 100644 target/linux/generic/pending-5.15/486-01-mtd-spinand-add-support-for-ESMT-F50x1G41LB.patch + create mode 100644 target/linux/generic/pending-5.15/487-mtd-spinand-Add-support-for-Etron-EM73D044VCx.patch create mode 100644 target/linux/generic/pending-5.15/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch create mode 100644 target/linux/generic/pending-5.15/491-ubi-auto-create-ubiblock-device-for-rootfs.patch create mode 100644 target/linux/generic/pending-5.15/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch create mode 100644 target/linux/generic/pending-5.15/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch create mode 100644 target/linux/generic/pending-5.15/494-mtd-ubi-add-EOF-marker-support.patch - create mode 100644 target/linux/generic/pending-5.15/495-mtd-core-add-get_mtd_device_by_node.patch create mode 100644 target/linux/generic/pending-5.15/496-dt-bindings-add-bindings-for-mtd-concat-devices.patch create mode 100644 target/linux/generic/pending-5.15/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch create mode 100644 target/linux/generic/pending-5.15/498-mtd-spi-nor-locking-support-for-MX25L6405D.patch @@ -173,10 +194,42 @@ Subject: [PATCH] Generic pending 5.15 patches create mode 100644 target/linux/generic/pending-5.15/680-NET-skip-GRO-for-foreign-MAC-addresses.patch create mode 100644 target/linux/generic/pending-5.15/682-of_net-add-mac-address-increment-support.patch create mode 100644 target/linux/generic/pending-5.15/683-of_net-add-mac-address-to-of-tree.patch + create mode 100644 target/linux/generic/pending-5.15/684-of_net-do-mac-address-increment-only-once.patch + create mode 100644 target/linux/generic/pending-5.15/700-netfilter-nft_flow_offload-handle-netdevice-events-f.patch + create mode 100644 target/linux/generic/pending-5.15/701-netfilter-nf_flow_table-add-missing-locking.patch create mode 100644 target/linux/generic/pending-5.15/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch create mode 100644 target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch create mode 100644 target/linux/generic/pending-5.15/705-net-dsa-tag_mtk-add-padding-for-tx-packets.patch create mode 100644 target/linux/generic/pending-5.15/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch + create mode 100644 target/linux/generic/pending-5.15/721-net-phy-realtek-rtl8221-allow-to-configure-SERDES-mo.patch + create mode 100644 target/linux/generic/pending-5.15/723-net-mt7531-ensure-all-MACs-are-powered-down-before-r.patch + create mode 100644 target/linux/generic/pending-5.15/724-net-mtk_sgmii-implement-mtk_pcs_ops.patch + create mode 100644 target/linux/generic/pending-5.15/725-net-mtk_sgmii-fix-powering-up-the-SGMII-phy.patch + create mode 100644 target/linux/generic/pending-5.15/726-net-mtk_sgmii-ensure-the-SGMII-PHY-is-powered-down-o.patch + create mode 100644 target/linux/generic/pending-5.15/727-net-mtk_sgmii-mtk_pcs_setup_mode_an-don-t-rely-on-re.patch + create mode 100644 target/linux/generic/pending-5.15/728-net-mtk_sgmii-set-the-speed-according-to-the-phy-int.patch + create mode 100644 target/linux/generic/pending-5.15/729-net-mtk_eth_soc-improve-comment.patch + create mode 100644 target/linux/generic/pending-5.15/730-mtk_sgmii-enable-PCS-polling-to-allow-SFP-work.patch + create mode 100644 target/linux/generic/pending-5.15/731-net-ethernet-mediatek-ppe-add-support-for-flow-accou.patch + create mode 100644 target/linux/generic/pending-5.15/732-01-net-ethernet-mtk_eth_soc-account-for-vlan-in-rx-head.patch + create mode 100644 target/linux/generic/pending-5.15/732-02-net-ethernet-mtk_eth_soc-increase-tx-ring-side-for-Q.patch + create mode 100644 target/linux/generic/pending-5.15/732-03-net-ethernet-mtk_eth_soc-avoid-port_mg-assignment-on.patch + create mode 100644 target/linux/generic/pending-5.15/732-04-net-ethernet-mtk_eth_soc-implement-multi-queue-suppo.patch + create mode 100644 target/linux/generic/pending-5.15/732-05-net-dsa-tag_mtk-assign-per-port-queues.patch + create mode 100644 target/linux/generic/pending-5.15/732-06-net-ethernet-mediatek-ppe-assign-per-port-queues-for.patch + create mode 100644 target/linux/generic/pending-5.15/732-07-net-ethernet-mtk_eth_soc-compile-out-netsys-v2-code-.patch + create mode 100644 target/linux/generic/pending-5.15/732-08-net-dsa-add-support-for-DSA-rx-offloading-via-metada.patch + create mode 100644 target/linux/generic/pending-5.15/732-09-net-ethernet-mtk_eth_soc-fix-VLAN-rx-hardware-accele.patch + create mode 100644 target/linux/generic/pending-5.15/732-10-net-ethernet-mtk_eth_soc-work-around-issue-with-send.patch + create mode 100644 target/linux/generic/pending-5.15/732-11-net-ethernet-mtk_eth_soc-set-NETIF_F_ALL_TSO.patch + create mode 100644 target/linux/generic/pending-5.15/732-12-net-ethernet-mtk_eth_soc-drop-packets-to-WDMA-if-the.patch + create mode 100644 target/linux/generic/pending-5.15/732-13-net-ethernet-mtk_eth_soc-fix-flow_offload-related-re.patch + create mode 100644 target/linux/generic/pending-5.15/732-14-net-ethernet-mtk_eth_soc-drop-generic-vlan-rx-offloa.patch + create mode 100644 target/linux/generic/pending-5.15/733-01-net-ethernet-mtk_wed-introduce-wed-mcu-support.patch + create mode 100644 target/linux/generic/pending-5.15/733-02-net-ethernet-mtk_wed-introduce-wed-wo-support.patch + create mode 100644 target/linux/generic/pending-5.15/733-03-net-ethernet-mtk_wed-rename-tx_wdma-array-in-rx_wdma.patch + create mode 100644 target/linux/generic/pending-5.15/733-04-net-ethernet-mtk_wed-add-configure-wed-wo-support.patch + create mode 100644 target/linux/generic/pending-5.15/733-05-net-ethernet-mtk_wed-add-rx-mib-counters.patch create mode 100644 target/linux/generic/pending-5.15/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch create mode 100644 target/linux/generic/pending-5.15/780-ARM-kirkwood-add-missing-linux-if_ether.h-for-ETH_AL.patch create mode 100644 target/linux/generic/pending-5.15/800-bcma-get-SoC-device-struct-copy-its-DMA-params-to-th.patch @@ -186,50 +239,9 @@ Subject: [PATCH] Generic pending 5.15 patches create mode 100644 target/linux/generic/pending-5.15/820-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch create mode 100644 target/linux/generic/pending-5.15/834-ledtrig-libata.patch create mode 100644 target/linux/generic/pending-5.15/840-hwrng-bcm2835-set-quality-to-1000.patch - create mode 100644 target/linux/generic/pending-5.15/842-net-qmi_wwan-add-ZTE-MF286D-modem-19d2-1485.patch create mode 100644 target/linux/generic/pending-5.15/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch - create mode 100644 target/linux/generic/pending-5.15/851-0001-phy-marvell-phy-mvebu-a3700-comphy-Remove-port-from-.patch - create mode 100644 target/linux/generic/pending-5.15/851-0002-phy-marvell-phy-mvebu-a3700-comphy-Add-native-kernel.patch - create mode 100644 target/linux/generic/pending-5.15/851-0003-arm64-dts-marvell-armada-37xx-Add-xtal-clock-to-comp.patch - create mode 100644 target/linux/generic/pending-5.15/851-0004-Revert-ata-ahci-mvebu-Make-SATA-PHY-optional-for-Arm.patch - create mode 100644 target/linux/generic/pending-5.15/851-0005-Revert-usb-host-xhci-mvebu-make-USB-3.0-PHY-optional.patch - create mode 100644 target/linux/generic/pending-5.15/851-0006-Revert-PCI-aardvark-Fix-initialization-with-old-Marv.patch create mode 100644 target/linux/generic/pending-5.15/920-mangle_bootargs.patch -diff --git a/target/linux/generic/pending-5.15/050-dtc-checks-Drop-interrupt-provider-address-cells-check.patch b/target/linux/generic/pending-5.15/050-dtc-checks-Drop-interrupt-provider-address-cells-check.patch -new file mode 100644 -index 0000000000..75f63728ec ---- /dev/null -+++ b/target/linux/generic/pending-5.15/050-dtc-checks-Drop-interrupt-provider-address-cells-check.patch -@@ -0,0 +1,28 @@ -+From d8d1a9a77863a8c7031ae82a1d461aa78eb72a7b Mon Sep 17 00:00:00 2001 -+From: Rob Herring <robh@kernel.org> -+Date: Mon, 11 Oct 2021 14:12:43 -0500 -+Subject: [PATCH] checks: Drop interrupt provider '#address-cells' check -+ -+'#address-cells' is only needed when parsing 'interrupt-map' properties, so -+remove it from the common interrupt-provider test. -+ -+Cc: Andre Przywara <andre.przywara@arm.com> -+Reviewed-by: David Gibson <david@gibson.dropbear.id.au> -+Signed-off-by: Rob Herring <robh@kernel.org> -+Message-Id: <20211011191245.1009682-3-robh@kernel.org> -+Signed-off-by: David Gibson <david@gibson.dropbear.id.au> -+--- -+--- a/scripts/dtc/checks.c -++++ b/scripts/dtc/checks.c -+@@ -1569,11 +1569,6 @@ static void check_interrupt_provider(str -+ if (!prop) -+ FAIL(c, dti, node, -+ "Missing #interrupt-cells in interrupt provider"); -+- -+- prop = get_property(node, "#address-cells"); -+- if (!prop) -+- FAIL(c, dti, node, -+- "Missing #address-cells in interrupt provider"); -+ } -+ WARNING(interrupt_provider, check_interrupt_provider, NULL); -+ diff --git a/target/linux/generic/pending-5.15/100-compiler.h-only-include-asm-rwonce.h-for-kernel-code.patch b/target/linux/generic/pending-5.15/100-compiler.h-only-include-asm-rwonce.h-for-kernel-code.patch new file mode 100644 index 0000000000..22f52c1d46 @@ -267,10 +279,10 @@ index 0000000000..22f52c1d46 + #endif /* __LINUX_COMPILER_H */ diff --git a/target/linux/generic/pending-5.15/101-Use-stddefs.h-instead-of-compiler.h.patch b/target/linux/generic/pending-5.15/101-Use-stddefs.h-instead-of-compiler.h.patch new file mode 100644 -index 0000000000..eefbe4b543 +index 0000000000..55388fb58a --- /dev/null +++ b/target/linux/generic/pending-5.15/101-Use-stddefs.h-instead-of-compiler.h.patch -@@ -0,0 +1,26 @@ +@@ -0,0 +1,22 @@ +From d3c5b26768dbe990c4e1bd79e420c11ce7491d51 Mon Sep 17 00:00:00 2001 +From: OpenWrt community <openwrt-devel@lists.openwrt.org> +Date: Wed, 13 Jul 2022 11:36:00 +0200 @@ -282,8 +294,6 @@ index 0000000000..eefbe4b543 + include/uapi/linux/swab.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + -+diff --git a/include/uapi/linux/swab.h b/include/uapi/linux/swab.h -+index 7272f85d6d6a..3736f2fe1541 100644 +--- a/include/uapi/linux/swab.h ++++ b/include/uapi/linux/swab.h +@@ -3,7 +3,7 @@ @@ -295,8 +305,6 @@ index 0000000000..eefbe4b543 + #include <asm/bitsperlong.h> + #include <asm/swab.h> + -+-- -+ diff --git a/target/linux/generic/pending-5.15/102-MIPS-only-process-negative-stack-offsets-on-stack-tr.patch b/target/linux/generic/pending-5.15/102-MIPS-only-process-negative-stack-offsets-on-stack-tr.patch new file mode 100644 index 0000000000..95a9656d26 @@ -360,9 +368,36 @@ index 0000000000..95a9656d26 + *frame_size = -ip->i_format.simmediate; + return 1; + } +diff --git a/target/linux/generic/pending-5.15/103-kbuild-export-SUBARCH.patch b/target/linux/generic/pending-5.15/103-kbuild-export-SUBARCH.patch +new file mode 100644 +index 0000000000..d378dabdda +--- /dev/null ++++ b/target/linux/generic/pending-5.15/103-kbuild-export-SUBARCH.patch +@@ -0,0 +1,21 @@ ++From 173019b66dcc9d68ad9333aa744dad1e369b5aa8 Mon Sep 17 00:00:00 2001 ++From: Felix Fietkau <nbd@nbd.name> ++Date: Sun, 9 Jul 2017 00:26:53 +0200 ++Subject: [PATCH 34/34] kernel: add compile fix for linux 4.9 on x86 ++ ++Signed-off-by: Felix Fietkau <nbd@nbd.name> ++--- ++ Makefile | 4 ++-- ++ 1 file changed, 2 insertions(+), 2 deletions(-) ++ ++--- a/Makefile +++++ b/Makefile ++@@ -526,7 +526,7 @@ KBUILD_LDFLAGS_MODULE := ++ KBUILD_LDFLAGS := ++ CLANG_FLAGS := ++ ++-export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC +++export ARCH SRCARCH SUBARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC ++ export CPP AR NM STRIP OBJCOPY OBJDUMP READELF PAHOLE RESOLVE_BTFIDS LEX YACC AWK INSTALLKERNEL ++ export PERL PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX ++ export KGZIP KBZIP2 KLZOP LZMA LZ4 XZ ZSTD diff --git a/target/linux/generic/pending-5.15/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch b/target/linux/generic/pending-5.15/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch new file mode 100644 -index 0000000000..30c70a6be9 +index 0000000000..1ba95d3ffa --- /dev/null +++ b/target/linux/generic/pending-5.15/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch @@ -0,0 +1,82 @@ @@ -439,7 +474,7 @@ index 0000000000..30c70a6be9 + +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c -+@@ -7552,7 +7552,7 @@ static void __init alloc_node_mem_map(st ++@@ -7602,7 +7602,7 @@ static void __init alloc_node_mem_map(st + if (pgdat == NODE_DATA(0)) { + mem_map = NODE_DATA(0)->node_mem_map; + if (page_to_pfn(mem_map) != pgdat->node_start_pfn) @@ -893,7 +928,7 @@ index 0000000000..7e9d0e66c0 + exit: diff --git a/target/linux/generic/pending-5.15/203-kallsyms_uncompressed.patch b/target/linux/generic/pending-5.15/203-kallsyms_uncompressed.patch new file mode 100644 -index 0000000000..ea407d6db9 +index 0000000000..b525976fc9 --- /dev/null +++ b/target/linux/generic/pending-5.15/203-kallsyms_uncompressed.patch @@ -0,0 +1,119 @@ @@ -1005,7 +1040,7 @@ index 0000000000..ea407d6db9 + } +--- a/scripts/link-vmlinux.sh ++++ b/scripts/link-vmlinux.sh -+@@ -263,6 +263,10 @@ kallsyms() ++@@ -257,6 +257,10 @@ kallsyms() + kallsymopt="${kallsymopt} --base-relative" + fi + @@ -1665,148 +1700,6 @@ index 0000000000..ef92a5dfb6 + cflags-$(CONFIG_CPU_MIPS32_R5) += -march=mips32r5 -Wa,--trap -modd-spreg + cflags-$(CONFIG_CPU_MIPS32_R6) += -march=mips32r6 -Wa,--trap -modd-spreg + cflags-$(CONFIG_CPU_MIPS64_R1) += -march=mips64 -Wa,--trap -diff --git a/target/linux/generic/pending-5.15/309-MIPS-Add-CPU-option-reporting-to-proc-cpuinfo.patch b/target/linux/generic/pending-5.15/309-MIPS-Add-CPU-option-reporting-to-proc-cpuinfo.patch -new file mode 100644 -index 0000000000..318c0b1b25 ---- /dev/null -+++ b/target/linux/generic/pending-5.15/309-MIPS-Add-CPU-option-reporting-to-proc-cpuinfo.patch -@@ -0,0 +1,136 @@ -+From 87ec87c2ad615c1a177cd08ef5fa29fc739f6e50 Mon Sep 17 00:00:00 2001 -+From: Hauke Mehrtens <hauke@hauke-m.de> -+Date: Sun, 23 Dec 2018 18:06:53 +0100 -+Subject: [PATCH] MIPS: Add CPU option reporting to /proc/cpuinfo -+ -+Many MIPS CPUs have optional CPU features which are not activates for -+all CPU cores. Print the CPU options which are implemented in the core -+in /proc/cpuinfo. This makes it possible to see what features are -+supported and which are not supported. This should cover all standard -+MIPS extensions, before it only printed information about the main MIPS -+ASEs. -+ -+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> -+--- -+ arch/mips/kernel/proc.c | 116 ++++++++++++++++++++++++++++++++++++++++ -+ 1 file changed, 116 insertions(+) -+ -+--- a/arch/mips/kernel/proc.c -++++ b/arch/mips/kernel/proc.c -+@@ -138,6 +138,116 @@ static int show_cpuinfo(struct seq_file -+ seq_printf(m, "micromips kernel\t: %s\n", -+ (read_c0_config3() & MIPS_CONF3_ISA_OE) ? "yes" : "no"); -+ } -++ -++ seq_printf(m, "Options implemented\t:"); -++ if (cpu_has_tlb) -++ seq_printf(m, "%s", " tlb"); -++ if (cpu_has_ftlb) -++ seq_printf(m, "%s", " ftlb"); -++ if (cpu_has_tlbinv) -++ seq_printf(m, "%s", " tlbinv"); -++ if (cpu_has_segments) -++ seq_printf(m, "%s", " segments"); -++ if (cpu_has_rixiex) -++ seq_printf(m, "%s", " rixiex"); -++ if (cpu_has_ldpte) -++ seq_printf(m, "%s", " ldpte"); -++ if (cpu_has_maar) -++ seq_printf(m, "%s", " maar"); -++ if (cpu_has_rw_llb) -++ seq_printf(m, "%s", " rw_llb"); -++ if (cpu_has_4kex) -++ seq_printf(m, "%s", " 4kex"); -++ if (cpu_has_3k_cache) -++ seq_printf(m, "%s", " 3k_cache"); -++ if (cpu_has_4k_cache) -++ seq_printf(m, "%s", " 4k_cache"); -++ if (cpu_has_tx39_cache) -++ seq_printf(m, "%s", " tx39_cache"); -++ if (cpu_has_octeon_cache) -++ seq_printf(m, "%s", " octeon_cache"); -++ if (cpu_has_fpu) -++ seq_printf(m, "%s", " fpu"); -++ if (cpu_has_32fpr) -++ seq_printf(m, "%s", " 32fpr"); -++ if (cpu_has_cache_cdex_p) -++ seq_printf(m, "%s", " cache_cdex_p"); -++ if (cpu_has_cache_cdex_s) -++ seq_printf(m, "%s", " cache_cdex_s"); -++ if (cpu_has_prefetch) -++ seq_printf(m, "%s", " prefetch"); -++ if (cpu_has_mcheck) -++ seq_printf(m, "%s", " mcheck"); -++ if (cpu_has_ejtag) -++ seq_printf(m, "%s", " ejtag"); -++ if (cpu_has_llsc) -++ seq_printf(m, "%s", " llsc"); -++ if (cpu_has_guestctl0ext) -++ seq_printf(m, "%s", " guestctl0ext"); -++ if (cpu_has_guestctl1) -++ seq_printf(m, "%s", " guestctl1"); -++ if (cpu_has_guestctl2) -++ seq_printf(m, "%s", " guestctl2"); -++ if (cpu_has_guestid) -++ seq_printf(m, "%s", " guestid"); -++ if (cpu_has_drg) -++ seq_printf(m, "%s", " drg"); -++ if (cpu_has_rixi) -++ seq_printf(m, "%s", " rixi"); -++ if (cpu_has_lpa) -++ seq_printf(m, "%s", " lpa"); -++ if (cpu_has_mvh) -++ seq_printf(m, "%s", " mvh"); -++ if (cpu_has_vtag_icache) -++ seq_printf(m, "%s", " vtag_icache"); -++ if (cpu_has_dc_aliases) -++ seq_printf(m, "%s", " dc_aliases"); -++ if (cpu_has_ic_fills_f_dc) -++ seq_printf(m, "%s", " ic_fills_f_dc"); -++ if (cpu_has_pindexed_dcache) -++ seq_printf(m, "%s", " pindexed_dcache"); -++ if (cpu_has_userlocal) -++ seq_printf(m, "%s", " userlocal"); -++ if (cpu_has_nofpuex) -++ seq_printf(m, "%s", " nofpuex"); -++ if (cpu_has_vint) -++ seq_printf(m, "%s", " vint"); -++ if (cpu_has_veic) -++ seq_printf(m, "%s", " veic"); -++ if (cpu_has_inclusive_pcaches) -++ seq_printf(m, "%s", " inclusive_pcaches"); -++ if (cpu_has_perf_cntr_intr_bit) -++ seq_printf(m, "%s", " perf_cntr_intr_bit"); -++ if (cpu_has_ufr) -++ seq_printf(m, "%s", " ufr"); -++ if (cpu_has_fre) -++ seq_printf(m, "%s", " fre"); -++ if (cpu_has_cdmm) -++ seq_printf(m, "%s", " cdmm"); -++ if (cpu_has_small_pages) -++ seq_printf(m, "%s", " small_pages"); -++ if (cpu_has_nan_legacy) -++ seq_printf(m, "%s", " nan_legacy"); -++ if (cpu_has_nan_2008) -++ seq_printf(m, "%s", " nan_2008"); -++ if (cpu_has_ebase_wg) -++ seq_printf(m, "%s", " ebase_wg"); -++ if (cpu_has_badinstr) -++ seq_printf(m, "%s", " badinstr"); -++ if (cpu_has_badinstrp) -++ seq_printf(m, "%s", " badinstrp"); -++ if (cpu_has_contextconfig) -++ seq_printf(m, "%s", " contextconfig"); -++ if (cpu_has_perf) -++ seq_printf(m, "%s", " perf"); -++ if (cpu_has_shared_ftlb_ram) -++ seq_printf(m, "%s", " shared_ftlb_ram"); -++ if (cpu_has_shared_ftlb_entries) -++ seq_printf(m, "%s", " shared_ftlb_entries"); -++ if (cpu_has_mipsmt_pertccounters) -++ seq_printf(m, "%s", " mipsmt_pertccounters"); -++ seq_printf(m, "\n"); -++ -+ seq_printf(m, "shadow register sets\t: %d\n", -+ cpu_data[n].srsets); -+ seq_printf(m, "kscratch registers\t: %d\n", diff --git a/target/linux/generic/pending-5.15/310-arm_module_unresolved_weak_sym.patch b/target/linux/generic/pending-5.15/310-arm_module_unresolved_weak_sym.patch new file mode 100644 index 0000000000..191dc6ac3c @@ -1837,10 +1730,10 @@ index 0000000000..191dc6ac3c + switch (ELF32_R_TYPE(rel->r_info)) { diff --git a/target/linux/generic/pending-5.15/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch b/target/linux/generic/pending-5.15/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch new file mode 100644 -index 0000000000..3a5f5a238d +index 0000000000..3f553b28b3 --- /dev/null +++ b/target/linux/generic/pending-5.15/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch -@@ -0,0 +1,283 @@ +@@ -0,0 +1,282 @@ +From: Yousong Zhou <yszhou4tech@gmail.com> +Subject: MIPS: kexec: Accept command line parameters from userspace. + @@ -2103,7 +1996,7 @@ index 0000000000..3a5f5a238d + + #ifdef CONFIG_SMP + /* -+@@ -181,9 +182,15 @@ kexec_indirection_page: ++@@ -177,8 +178,15 @@ EXPORT(kexec_indirection_page) + PTR_WD 0 + .size kexec_indirection_page, PTRSIZE + @@ -2118,8 +2011,7 @@ index 0000000000..3a5f5a238d ++ .skip KEXEC_ARGV_SIZE ++ .size kexec_argv, KEXEC_ARGV_SIZE + -+-relocate_new_kernel_size: -+- EXPORT(relocate_new_kernel_size) ++-EXPORT(relocate_new_kernel_size) +- PTR_WD relocate_new_kernel_end - relocate_new_kernel +- .size relocate_new_kernel_size, PTRSIZE ++kexec_relocate_new_kernel_end: @@ -2277,10 +2169,10 @@ index 0000000000..082b122cb4 + select HAVE_KRETPROBES diff --git a/target/linux/generic/pending-5.15/400-mtd-mtdsplit-support.patch b/target/linux/generic/pending-5.15/400-mtd-mtdsplit-support.patch new file mode 100644 -index 0000000000..63df1d070d +index 0000000000..bf82bb3950 --- /dev/null +++ b/target/linux/generic/pending-5.15/400-mtd-mtdsplit-support.patch -@@ -0,0 +1,339 @@ +@@ -0,0 +1,328 @@ +From 39717277d5c87bdb183cf2f258957b44ba99b4df Mon Sep 17 00:00:00 2001 +From: OpenWrt community <openwrt-devel@lists.openwrt.org> +Date: Wed, 13 Jul 2022 11:47:35 +0200 @@ -2294,8 +2186,6 @@ index 0000000000..63df1d070d + include/linux/mtd/partitions.h | 7 ++ + 5 files changed, 197 insertions(+), 25 deletions(-) + -+diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig -+index 796a2eccbef0..f9ed93c4cf0f 100644 +--- a/drivers/mtd/Kconfig ++++ b/drivers/mtd/Kconfig +@@ -12,6 +12,25 @@ menuconfig MTD @@ -2324,11 +2214,9 @@ index 0000000000..63df1d070d + config MTD_TESTS + tristate "MTD tests support (DANGEROUS)" + depends on m -+diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile -+index 593d0593a038..b14b7fe0f597 100644 +--- a/drivers/mtd/Makefile ++++ b/drivers/mtd/Makefile -+@@ -9,6 +9,8 @@ mtd-y := mtdcore.o mtdsuper.o mtdconcat.o mtdpart.o mtdchar.o ++@@ -9,6 +9,8 @@ mtd-y := mtdcore.o mtdsuper.o mtdconc + + obj-y += parsers/ + @@ -2337,8 +2225,6 @@ index 0000000000..63df1d070d + # 'Users' - code which presents functionality to userspace. + obj-$(CONFIG_MTD_BLKDEVS) += mtd_blkdevs.o + obj-$(CONFIG_MTD_BLOCK) += mtdblock.o -+diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c -+index d442fa94c872..f1ed12aae1fe 100644 +--- a/drivers/mtd/mtdpart.c ++++ b/drivers/mtd/mtdpart.c +@@ -15,11 +15,13 @@ @@ -2355,7 +2241,7 @@ index 0000000000..63df1d070d + + /* + * MTD methods which simply translate the effective address and pass through -+@@ -236,6 +238,146 @@ static int mtd_add_partition_attrs(struct mtd_info *new) ++@@ -236,6 +238,147 @@ static int mtd_add_partition_attrs(struc + return ret; + } + @@ -2487,7 +2373,8 @@ index 0000000000..63df1d070d ++ if (rootfs_found) ++ return; ++ -++ if (!strcmp(part->name, "rootfs")) { +++ if (of_find_property(mtd_get_of_node(part), "linux,rootfs", NULL) || +++ !strcmp(part->name, "rootfs")) { ++ run_parsers_by_type(part, MTD_PARSER_TYPE_ROOTFS); ++ ++ rootfs_found = 1; @@ -2502,7 +2389,7 @@ index 0000000000..63df1d070d + int mtd_add_partition(struct mtd_info *parent, const char *name, + long long offset, long long length) + { -+@@ -274,6 +416,7 @@ int mtd_add_partition(struct mtd_info *parent, const char *name, ++@@ -274,6 +417,7 @@ int mtd_add_partition(struct mtd_info *p + if (ret) + goto err_remove_part; + @@ -2510,7 +2397,7 @@ index 0000000000..63df1d070d + mtd_add_partition_attrs(child); + + return 0; -+@@ -422,6 +565,7 @@ int add_mtd_partitions(struct mtd_info *parent, ++@@ -422,6 +566,7 @@ int add_mtd_partitions(struct mtd_info * + goto err_del_partitions; + } + @@ -2518,7 +2405,7 @@ index 0000000000..63df1d070d + mtd_add_partition_attrs(child); + + /* Look for subpartitions */ -+@@ -438,31 +582,6 @@ int add_mtd_partitions(struct mtd_info *parent, ++@@ -438,31 +583,6 @@ err_del_partitions: + return ret; + } + @@ -2550,11 +2437,9 @@ index 0000000000..63df1d070d + /* + * Many partition parsers just expected the core to kfree() all their data in + * one chunk. Do that by default. -+diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h -+index 8a2c60235ebb..b092bf6ff97d 100644 +--- a/include/linux/mtd/mtd.h ++++ b/include/linux/mtd/mtd.h -+@@ -613,6 +613,24 @@ static inline void mtd_align_erase_req(struct mtd_info *mtd, ++@@ -613,6 +613,24 @@ static inline void mtd_align_erase_req(s + req->len += mtd->erasesize - mod; + } + @@ -2579,7 +2464,7 @@ index 0000000000..63df1d070d + static inline uint32_t mtd_div_by_ws(uint64_t sz, struct mtd_info *mtd) + { + if (mtd->writesize_shift) -+@@ -685,6 +703,13 @@ extern void __put_mtd_device(struct mtd_info *mtd); ++@@ -686,6 +704,13 @@ extern struct mtd_info *of_get_mtd_devic + extern struct mtd_info *get_mtd_device_nm(const char *name); + extern void put_mtd_device(struct mtd_info *mtd); + @@ -2593,8 +2478,6 @@ index 0000000000..63df1d070d + + struct mtd_notifier { + void (*add)(struct mtd_info *mtd); -+diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h -+index b74a539ec581..65ba0dbf961d 100644 +--- a/include/linux/mtd/partitions.h ++++ b/include/linux/mtd/partitions.h +@@ -75,6 +75,12 @@ struct mtd_part_parser_data { @@ -2618,11 +2501,9 @@ index 0000000000..63df1d070d + }; + + /* Container for passing around a set of parsed partitions */ -+-- -+ diff --git a/target/linux/generic/pending-5.15/402-mtd-spi-nor-write-support-for-minor-aligned-partitions.patch b/target/linux/generic/pending-5.15/402-mtd-spi-nor-write-support-for-minor-aligned-partitions.patch new file mode 100644 -index 0000000000..ed9d1c9dc1 +index 0000000000..b4fa08f0ea --- /dev/null +++ b/target/linux/generic/pending-5.15/402-mtd-spi-nor-write-support-for-minor-aligned-partitions.patch @@ -0,0 +1,245 @@ @@ -2708,7 +2589,7 @@ index 0000000000..ed9d1c9dc1 + +--- a/drivers/mtd/mtdcore.c ++++ b/drivers/mtd/mtdcore.c -+@@ -168,6 +168,15 @@ static ssize_t mtd_erasesize_show(struct ++@@ -169,6 +169,15 @@ static ssize_t mtd_erasesize_show(struct + } + MTD_DEVICE_ATTR_RO(erasesize); + @@ -2724,7 +2605,7 @@ index 0000000000..ed9d1c9dc1 + static ssize_t mtd_writesize_show(struct device *dev, + struct device_attribute *attr, char *buf) + { -+@@ -313,6 +322,7 @@ static struct attribute *mtd_attrs[] = { ++@@ -314,6 +323,7 @@ static struct attribute *mtd_attrs[] = { + &dev_attr_flags.attr, + &dev_attr_size.attr, + &dev_attr_erasesize.attr, @@ -2873,7 +2754,7 @@ index 0000000000..ed9d1c9dc1 + * one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR diff --git a/target/linux/generic/pending-5.15/420-mtd-redboot_space.patch b/target/linux/generic/pending-5.15/420-mtd-redboot_space.patch new file mode 100644 -index 0000000000..fee1936593 +index 0000000000..5518ea71dd --- /dev/null +++ b/target/linux/generic/pending-5.15/420-mtd-redboot_space.patch @@ -0,0 +1,41 @@ @@ -2890,7 +2771,7 @@ index 0000000000..fee1936593 + +--- a/drivers/mtd/parsers/redboot.c ++++ b/drivers/mtd/parsers/redboot.c -+@@ -277,14 +277,21 @@ nogood: ++@@ -278,14 +278,21 @@ nogood: + #endif + names += strlen(names) + 1; + @@ -2920,7 +2801,7 @@ index 0000000000..fee1936593 + kfree(tmp_fl); diff --git a/target/linux/generic/pending-5.15/430-mtd-add-myloader-partition-parser.patch b/target/linux/generic/pending-5.15/430-mtd-add-myloader-partition-parser.patch new file mode 100644 -index 0000000000..0889c9a343 +index 0000000000..8a6e630530 --- /dev/null +++ b/target/linux/generic/pending-5.15/430-mtd-add-myloader-partition-parser.patch @@ -0,0 +1,229 @@ @@ -2946,7 +2827,7 @@ index 0000000000..0889c9a343 ++ help ++ MyLoader is a bootloader which allows the user to define partitions ++ in flash devices, by putting a table in the second erase block -++ on the device, similar to a partition table. This table gives the +++ on the device, similar to a partition table. This table gives the ++ offsets and lengths of the user defined partitions. ++ ++ If you need code which can detect and parse these tables, and @@ -3272,7 +3153,7 @@ index 0000000000..852654d924 + if (buf[0x000 / 4] == TRX_MAGIC) { diff --git a/target/linux/generic/pending-5.15/435-mtd-add-routerbootpart-parser-config.patch b/target/linux/generic/pending-5.15/435-mtd-add-routerbootpart-parser-config.patch new file mode 100644 -index 0000000000..30f5334af4 +index 0000000000..ee949f73c0 --- /dev/null +++ b/target/linux/generic/pending-5.15/435-mtd-add-routerbootpart-parser-config.patch @@ -0,0 +1,38 @@ @@ -3294,7 +3175,7 @@ index 0000000000..30f5334af4 + +--- a/drivers/mtd/parsers/Kconfig ++++ b/drivers/mtd/parsers/Kconfig -+@@ -211,3 +211,12 @@ config MTD_SERCOMM_PARTS ++@@ -226,3 +226,12 @@ config MTD_SERCOMM_PARTS + partition map. This partition table contains real partition + offsets, which may differ from device to device depending on the + number and location of bad blocks on NAND. @@ -3309,7 +3190,7 @@ index 0000000000..30f5334af4 ++ formatted DTS. +--- a/drivers/mtd/parsers/Makefile ++++ b/drivers/mtd/parsers/Makefile -+@@ -15,3 +15,4 @@ obj-$(CONFIG_MTD_SERCOMM_PARTS) += scpa ++@@ -16,3 +16,4 @@ obj-$(CONFIG_MTD_SERCOMM_PARTS) += scpa + obj-$(CONFIG_MTD_SHARPSL_PARTS) += sharpslpart.o + obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o + obj-$(CONFIG_MTD_QCOMSMEM_PARTS) += qcomsmempart.o @@ -3531,10 +3412,10 @@ index 0000000000..c32cde559d + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, diff --git a/target/linux/generic/pending-5.15/482-mtd-spi-nor-add-gd25q512.patch b/target/linux/generic/pending-5.15/482-mtd-spi-nor-add-gd25q512.patch new file mode 100644 -index 0000000000..96848e103f +index 0000000000..7c8b686277 --- /dev/null +++ b/target/linux/generic/pending-5.15/482-mtd-spi-nor-add-gd25q512.patch -@@ -0,0 +1,25 @@ +@@ -0,0 +1,21 @@ +From f8943df3beb0d3f9754bb35320c3a378727175a8 Mon Sep 17 00:00:00 2001 +From: OpenWrt community <openwrt-devel@lists.openwrt.org> +Date: Thu, 14 Jul 2022 08:38:07 +0200 @@ -3544,11 +3425,9 @@ index 0000000000..96848e103f + drivers/mtd/spi-nor/gigadevice.c | 3 +++ + 1 file changed, 3 insertions(+) + -+diff --git a/drivers/mtd/spi-nor/gigadevice.c b/drivers/mtd/spi-nor/gigadevice.c -+index e52ed19d864f..d25292ec1eb9 100644 +--- a/drivers/mtd/spi-nor/gigadevice.c ++++ b/drivers/mtd/spi-nor/gigadevice.c -+@@ -53,6 +53,9 @@ static const struct flash_info gigadevice_parts[] = { ++@@ -53,6 +53,9 @@ static const struct flash_info gigadevic + SPI_NOR_4B_OPCODES | SPI_NOR_HAS_LOCK | + SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6) + .fixups = &gd25q256_fixups }, @@ -3558,198 +3437,12 @@ index 0000000000..96848e103f + }; + + const struct spi_nor_manufacturer spi_nor_gigadevice = { -+-- -+ -diff --git a/target/linux/generic/pending-5.15/483-mtd-spinand-add-support-for-xtx-xt26g0xa.patch b/target/linux/generic/pending-5.15/483-mtd-spinand-add-support-for-xtx-xt26g0xa.patch -new file mode 100644 -index 0000000000..a73c9fa97d ---- /dev/null -+++ b/target/linux/generic/pending-5.15/483-mtd-spinand-add-support-for-xtx-xt26g0xa.patch -@@ -0,0 +1,178 @@ -+From a07e31adf2753cad2fd9790db5bfc047c81e8152 Mon Sep 17 00:00:00 2001 -+From: Felix Matouschek <felix@matouschek.org> -+Date: Fri, 2 Jul 2021 20:31:23 +0200 -+Subject: [PATCH] mtd: spinand: Add support for XTX XT26G0xA -+ -+Add support for XTX Technology XT26G01AXXXXX, XTX26G02AXXXXX and -+XTX26G04AXXXXX SPI NAND. -+ -+These are 3V, 1G/2G/4Gbit serial SLC NAND flash devices with on-die ECC -+(8bit strength per 512bytes). -+ -+Tested on Teltonika RUTX10 flashed with OpenWrt. -+ -+Datasheets available at -+http://www.xtxtech.com/download/?AId=225 -+https://datasheet.lcsc.com/szlcsc/2005251034_XTX-XT26G01AWSEGA_C558841.pdf -+ -+Signed-off-by: Felix Matouschek <felix@matouschek.org> -+--- -+ drivers/mtd/nand/spi/Makefile | 2 +- -+ drivers/mtd/nand/spi/core.c | 1 + -+ drivers/mtd/nand/spi/xtx.c | 122 ++++++++++++++++++++++++++++++++++ -+ include/linux/mtd/spinand.h | 1 + -+ 4 files changed, 125 insertions(+), 1 deletion(-) -+ create mode 100644 drivers/mtd/nand/spi/xtx.c -+ -+--- a/drivers/mtd/nand/spi/Makefile -++++ b/drivers/mtd/nand/spi/Makefile -+@@ -1,3 +1,3 @@ -+ # SPDX-License-Identifier: GPL-2.0 -+-spinand-objs := core.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o -++spinand-objs := core.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o -+ obj-$(CONFIG_MTD_SPI_NAND) += spinand.o -+--- a/drivers/mtd/nand/spi/core.c -++++ b/drivers/mtd/nand/spi/core.c -+@@ -902,6 +902,7 @@ static const struct spinand_manufacturer -+ ¶gon_spinand_manufacturer, -+ &toshiba_spinand_manufacturer, -+ &winbond_spinand_manufacturer, -++ &xtx_spinand_manufacturer, -+ }; -+ -+ static int spinand_manufacturer_match(struct spinand_device *spinand, -+--- /dev/null -++++ b/drivers/mtd/nand/spi/xtx.c -+@@ -0,0 +1,122 @@ -++// SPDX-License-Identifier: GPL-2.0 -++/* -++ * Author: -++ * Felix Matouschek <felix@matouschek.org> -++ */ -++ -++#include <linux/device.h> -++#include <linux/kernel.h> -++#include <linux/mtd/spinand.h> -++ -++#define SPINAND_MFR_XTX 0x0B -++ -++#define XT26G0XA_STATUS_ECC_MASK GENMASK(5, 2) -++#define XT26G0XA_STATUS_ECC_NO_DETECTED (0 << 2) -++#define XT26G0XA_STATUS_ECC_8_CORRECTED (3 << 4) -++#define XT26G0XA_STATUS_ECC_UNCOR_ERROR (2 << 4) -++ -++static SPINAND_OP_VARIANTS(read_cache_variants, -++ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, NULL, 0), -++ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), -++ SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0), -++ SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), -++ SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), -++ SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); -++ -++static SPINAND_OP_VARIANTS(write_cache_variants, -++ SPINAND_PROG_LOAD_X4(true, 0, NULL, 0), -++ SPINAND_PROG_LOAD(true, 0, NULL, 0)); -++ -++static SPINAND_OP_VARIANTS(update_cache_variants, -++ SPINAND_PROG_LOAD_X4(false, 0, NULL, 0), -++ SPINAND_PROG_LOAD(false, 0, NULL, 0)); -++ -++static int xt26g0xa_ooblayout_ecc(struct mtd_info *mtd, int section, -++ struct mtd_oob_region *region) -++{ -++ if (section) -++ return -ERANGE; -++ -++ region->offset = 48; -++ region->length = 16; -++ -++ return 0; -++} -++ -++static int xt26g0xa_ooblayout_free(struct mtd_info *mtd, int section, -++ struct mtd_oob_region *region) -++{ -++ if (section) -++ return -ERANGE; -++ -++ region->offset = 1; -++ region->length = 47; -++ -++ return 0; -++} -++ -++static const struct mtd_ooblayout_ops xt26g0xa_ooblayout = { -++ .ecc = xt26g0xa_ooblayout_ecc, -++ .free = xt26g0xa_ooblayout_free, -++}; -++ -++static int xt26g0xa_ecc_get_status(struct spinand_device *spinand, -++ u8 status) -++{ -++ switch (status & XT26G0XA_STATUS_ECC_MASK) { -++ case XT26G0XA_STATUS_ECC_NO_DETECTED: -++ return 0; -++ case XT26G0XA_STATUS_ECC_8_CORRECTED: -++ return 8; -++ case XT26G0XA_STATUS_ECC_UNCOR_ERROR: -++ return -EBADMSG; -++ default: /* (1 << 2) through (7 << 2) are 1-7 corrected errors */ -++ return (status & XT26G0XA_STATUS_ECC_MASK) >> 2; -++ } -++ -++ return -EINVAL; -++} -++ -++static const struct spinand_info xtx_spinand_table[] = { -++ SPINAND_INFO("XT26G01A", -++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xE1), -++ NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), -++ NAND_ECCREQ(8, 512), -++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, -++ &write_cache_variants, -++ &update_cache_variants), -++ SPINAND_HAS_QE_BIT, -++ SPINAND_ECCINFO(&xt26g0xa_ooblayout, -++ xt26g0xa_ecc_get_status)), -++ SPINAND_INFO("XT26G02A", -++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xE2), -++ NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1), -++ NAND_ECCREQ(8, 512), -++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, -++ &write_cache_variants, -++ &update_cache_variants), -++ SPINAND_HAS_QE_BIT, -++ SPINAND_ECCINFO(&xt26g0xa_ooblayout, -++ xt26g0xa_ecc_get_status)), -++ SPINAND_INFO("XT26G04A", -++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xE3), -++ NAND_MEMORG(1, 2048, 64, 128, 2048, 40, 1, 1, 1), -++ NAND_ECCREQ(8, 512), -++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, -++ &write_cache_variants, -++ &update_cache_variants), -++ SPINAND_HAS_QE_BIT, -++ SPINAND_ECCINFO(&xt26g0xa_ooblayout, -++ xt26g0xa_ecc_get_status)), -++}; -++ -++static const struct spinand_manufacturer_ops xtx_spinand_manuf_ops = { -++}; -++ -++const struct spinand_manufacturer xtx_spinand_manufacturer = { -++ .id = SPINAND_MFR_XTX, -++ .name = "XTX", -++ .chips = xtx_spinand_table, -++ .nchips = ARRAY_SIZE(xtx_spinand_table), -++ .ops = &xtx_spinand_manuf_ops, -++}; -+--- a/include/linux/mtd/spinand.h -++++ b/include/linux/mtd/spinand.h -+@@ -266,6 +266,7 @@ extern const struct spinand_manufacturer -+ extern const struct spinand_manufacturer paragon_spinand_manufacturer; -+ extern const struct spinand_manufacturer toshiba_spinand_manufacturer; -+ extern const struct spinand_manufacturer winbond_spinand_manufacturer; -++extern const struct spinand_manufacturer xtx_spinand_manufacturer; -+ -+ /** -+ * struct spinand_op_variants - SPI NAND operation variants diff --git a/target/linux/generic/pending-5.15/484-mtd-spi-nor-add-esmt-f25l16pa.patch b/target/linux/generic/pending-5.15/484-mtd-spi-nor-add-esmt-f25l16pa.patch new file mode 100644 -index 0000000000..d5b7259351 +index 0000000000..ab402e622a --- /dev/null +++ b/target/linux/generic/pending-5.15/484-mtd-spi-nor-add-esmt-f25l16pa.patch -@@ -0,0 +1,27 @@ +@@ -0,0 +1,23 @@ +From 87363cc0e522de3294ea6ae10fb468d2a8d6fb2f Mon Sep 17 00:00:00 2001 +From: OpenWrt community <openwrt-devel@lists.openwrt.org> +Date: Wed, 13 Jul 2022 12:17:21 +0200 @@ -3762,8 +3455,6 @@ index 0000000000..d5b7259351 + drivers/mtd/spi-nor/esmt.c | 2 ++ + 1 file changed, 2 insertions(+) + -+diff --git a/drivers/mtd/spi-nor/esmt.c b/drivers/mtd/spi-nor/esmt.c -+index cfc9218c1053..d1750807f005 100644 +--- a/drivers/mtd/spi-nor/esmt.c ++++ b/drivers/mtd/spi-nor/esmt.c +@@ -10,6 +10,8 @@ @@ -3775,14 +3466,12 @@ index 0000000000..d5b7259351 + { "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64, + SECT_4K | SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE) }, + { "f25l32qa", INFO(0x8c4116, 0, 64 * 1024, 64, -+-- -+ diff --git a/target/linux/generic/pending-5.15/485-mtd-spi-nor-add-xmc-xm25qh128c.patch b/target/linux/generic/pending-5.15/485-mtd-spi-nor-add-xmc-xm25qh128c.patch new file mode 100644 -index 0000000000..2823464a60 +index 0000000000..68e373ea23 --- /dev/null +++ b/target/linux/generic/pending-5.15/485-mtd-spi-nor-add-xmc-xm25qh128c.patch -@@ -0,0 +1,28 @@ +@@ -0,0 +1,24 @@ +From f6b33d850f7f12555df2fa0e3349b33427bf5890 Mon Sep 17 00:00:00 2001 +From: OpenWrt community <openwrt-devel@lists.openwrt.org> +Date: Wed, 13 Jul 2022 12:19:01 +0200 @@ -3796,11 +3485,9 @@ index 0000000000..2823464a60 + drivers/mtd/spi-nor/xmc.c | 2 ++ + 1 file changed, 2 insertions(+) + -+diff --git a/drivers/mtd/spi-nor/xmc.c b/drivers/mtd/spi-nor/xmc.c -+index 2c7773b68993..99ee43a654c4 100644 +--- a/drivers/mtd/spi-nor/xmc.c ++++ b/drivers/mtd/spi-nor/xmc.c -+@@ -14,6 +14,8 @@ static const struct flash_info xmc_parts[] = { ++@@ -14,6 +14,8 @@ static const struct flash_info xmc_parts + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { "XM25QH128A", INFO(0x207018, 0, 64 * 1024, 256, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, @@ -3809,8 +3496,6 @@ index 0000000000..2823464a60 + }; + + const struct spi_nor_manufacturer spi_nor_xmc = { -+-- -+ diff --git a/target/linux/generic/pending-5.15/486-01-mtd-spinand-add-support-for-ESMT-F50x1G41LB.patch b/target/linux/generic/pending-5.15/486-01-mtd-spinand-add-support-for-ESMT-F50x1G41LB.patch new file mode 100644 index 0000000000..c170fedc67 @@ -3960,6 +3645,180 @@ index 0000000000..c170fedc67 + extern const struct spinand_manufacturer gigadevice_spinand_manufacturer; + extern const struct spinand_manufacturer macronix_spinand_manufacturer; + extern const struct spinand_manufacturer micron_spinand_manufacturer; +diff --git a/target/linux/generic/pending-5.15/487-mtd-spinand-Add-support-for-Etron-EM73D044VCx.patch b/target/linux/generic/pending-5.15/487-mtd-spinand-Add-support-for-Etron-EM73D044VCx.patch +new file mode 100644 +index 0000000000..2f604cfa98 +--- /dev/null ++++ b/target/linux/generic/pending-5.15/487-mtd-spinand-Add-support-for-Etron-EM73D044VCx.patch +@@ -0,0 +1,168 @@ ++From f32085fc0b87049491b07e198d924d738a1a2834 Mon Sep 17 00:00:00 2001 ++From: Daniel Danzberger <daniel@dd-wrt.com> ++Date: Wed, 3 Aug 2022 17:31:03 +0200 ++Subject: [PATCH] mtd: spinand: Add support for Etron EM73D044VCx ++ ++Airoha is a new ARM platform based on Cortex-A53 which has recently been ++merged into linux-next. ++ ++Due to BootROM limitations on this platform, the Cortex-A53 can't run in ++Aarch64 mode and code must be compiled for 32-Bit ARM. ++ ++This support is based mostly on those linux-next commits backported ++for kernel 5.15. ++ ++Patches: ++1 - platform support = linux-next ++2 - clock driver = linux-next ++3 - gpio driver = linux-next ++4 - linux,usable-memory-range dts support = linux-next ++5 - mtd spinand driver ++6 - spi driver ++7 - pci driver (kconfig only, uses mediatek PCI) = linux-next ++ ++Still missing: ++- Ethernet driver ++- Sysupgrade support ++ ++A.t.m there exists one subtarget EN7523 with only one evaluation ++board. ++ ++The initramfs can be run with the following commands from u-boot: ++- ++u-boot> setenv bootfile \ ++ openwrt-airoha-airoha_en7523-evb-initramfs-kernel.bin ++u-boot> tftpboot ++u-boot> bootm 0x81800000 ++- ++ ++Submitted-by: Daniel Danzberger <daniel@dd-wrt.com> ++ ++--- a/drivers/mtd/nand/spi/Makefile +++++ b/drivers/mtd/nand/spi/Makefile ++@@ -1,3 +1,3 @@ ++ # SPDX-License-Identifier: GPL-2.0 ++-spinand-objs := core.o esmt.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o +++spinand-objs := core.o esmt.o etron.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o ++ obj-$(CONFIG_MTD_SPI_NAND) += spinand.o ++--- a/drivers/mtd/nand/spi/core.c +++++ b/drivers/mtd/nand/spi/core.c ++@@ -898,6 +898,7 @@ static const struct nand_ops spinand_ops ++ static const struct spinand_manufacturer *spinand_manufacturers[] = { ++ &esmt_c8_spinand_manufacturer, ++ &gigadevice_spinand_manufacturer, +++ &etron_spinand_manufacturer, ++ ¯onix_spinand_manufacturer, ++ µn_spinand_manufacturer, ++ ¶gon_spinand_manufacturer, ++--- /dev/null +++++ b/drivers/mtd/nand/spi/etron.c ++@@ -0,0 +1,98 @@ +++// SPDX-License-Identifier: GPL-2.0 +++ +++#include <linux/device.h> +++#include <linux/kernel.h> +++#include <linux/mtd/spinand.h> +++ +++#define SPINAND_MFR_ETRON 0xd5 +++ +++ +++static SPINAND_OP_VARIANTS(read_cache_variants, +++ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, NULL, 0), +++ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), +++ SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0), +++ SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), +++ SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), +++ SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); +++ +++static SPINAND_OP_VARIANTS(write_cache_variants, +++ SPINAND_PROG_LOAD_X4(true, 0, NULL, 0), +++ SPINAND_PROG_LOAD(true, 0, NULL, 0)); +++ +++static SPINAND_OP_VARIANTS(update_cache_variants, +++ SPINAND_PROG_LOAD_X4(false, 0, NULL, 0), +++ SPINAND_PROG_LOAD(false, 0, NULL, 0)); +++ +++static int etron_ooblayout_ecc(struct mtd_info *mtd, int section, +++ struct mtd_oob_region *oobregion) +++{ +++ if (section) +++ return -ERANGE; +++ +++ oobregion->offset = 72; +++ oobregion->length = 56; +++ +++ return 0; +++} +++ +++static int etron_ooblayout_free(struct mtd_info *mtd, int section, +++ struct mtd_oob_region *oobregion) +++{ +++ if (section) +++ return -ERANGE; +++ +++ oobregion->offset = 1; +++ oobregion->length = 71; +++ +++ return 0; +++} +++ +++static int etron_ecc_get_status(struct spinand_device *spinand, u8 status) +++{ +++ switch (status & STATUS_ECC_MASK) { +++ case STATUS_ECC_NO_BITFLIPS: +++ return 0; +++ +++ case STATUS_ECC_HAS_BITFLIPS: +++ /* Between 1-7 bitflips were corrected */ +++ return 7; +++ +++ case STATUS_ECC_MASK: +++ /* Maximum bitflips were corrected */ +++ return 8; +++ +++ case STATUS_ECC_UNCOR_ERROR: +++ return -EBADMSG; +++ } +++ +++ return -EINVAL; +++} +++ +++static const struct mtd_ooblayout_ops etron_ooblayout = { +++ .ecc = etron_ooblayout_ecc, +++ .free = etron_ooblayout_free, +++}; +++ +++static const struct spinand_info etron_spinand_table[] = { +++ SPINAND_INFO("EM73D044VCx", +++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x1f), +++ // bpc, pagesize, oobsize, pagesperblock, bperlun, maxbadplun, ppl, lpt, #t +++ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), +++ NAND_ECCREQ(8, 512), +++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +++ &write_cache_variants, +++ &update_cache_variants), +++ SPINAND_HAS_QE_BIT, +++ SPINAND_ECCINFO(&etron_ooblayout, etron_ecc_get_status)), +++}; +++ +++static const struct spinand_manufacturer_ops etron_spinand_manuf_ops = { +++}; +++ +++const struct spinand_manufacturer etron_spinand_manufacturer = { +++ .id = SPINAND_MFR_ETRON, +++ .name = "Etron", +++ .chips = etron_spinand_table, +++ .nchips = ARRAY_SIZE(etron_spinand_table), +++ .ops = &etron_spinand_manuf_ops, +++}; ++--- a/include/linux/mtd/spinand.h +++++ b/include/linux/mtd/spinand.h ++@@ -261,6 +261,7 @@ struct spinand_manufacturer { ++ ++ /* SPI NAND manufacturers */ ++ extern const struct spinand_manufacturer esmt_c8_spinand_manufacturer; +++extern const struct spinand_manufacturer etron_spinand_manufacturer; ++ extern const struct spinand_manufacturer gigadevice_spinand_manufacturer; ++ extern const struct spinand_manufacturer macronix_spinand_manufacturer; ++ extern const struct spinand_manufacturer micron_spinand_manufacturer; diff --git a/target/linux/generic/pending-5.15/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch b/target/linux/generic/pending-5.15/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch new file mode 100644 index 0000000000..b120548d2e @@ -4303,87 +4162,6 @@ index 0000000000..413431755f + struct kmem_cache *aeb_slab_cache; + struct ubi_ec_hdr *ech; + struct ubi_vid_io_buf *vidb; -diff --git a/target/linux/generic/pending-5.15/495-mtd-core-add-get_mtd_device_by_node.patch b/target/linux/generic/pending-5.15/495-mtd-core-add-get_mtd_device_by_node.patch -new file mode 100644 -index 0000000000..431c80795e ---- /dev/null -+++ b/target/linux/generic/pending-5.15/495-mtd-core-add-get_mtd_device_by_node.patch -@@ -0,0 +1,75 @@ -+From 1bd1b740f208d1cf4071932cc51860d37266c402 Mon Sep 17 00:00:00 2001 -+From: Bernhard Frauendienst <kernel@nospam.obeliks.de> -+Date: Sat, 1 Sep 2018 00:30:11 +0200 -+Subject: [PATCH 495/497] mtd: core: add get_mtd_device_by_node -+ -+Add function to retrieve a mtd device by its OF node. Since drivers can -+assign arbitrary names to mtd devices in the absence of a label -+property, there is no other reliable way to retrieve a mtd device for a -+given OF node. -+ -+Signed-off-by: Bernhard Frauendienst <kernel@nospam.obeliks.de> -+Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com> -+--- -+ drivers/mtd/mtdcore.c | 38 ++++++++++++++++++++++++++++++++++++++ -+ include/linux/mtd/mtd.h | 2 ++ -+ 2 files changed, 40 insertions(+) -+ -+--- a/drivers/mtd/mtdcore.c -++++ b/drivers/mtd/mtdcore.c -+@@ -1274,6 +1274,44 @@ out_unlock: -+ } -+ EXPORT_SYMBOL_GPL(get_mtd_device_nm); -+ -++/** -++ * get_mtd_device_by_node - obtain a validated handle for an MTD device -++ * by of_node -++ * @of_node: OF node of MTD device to open -++ * -++ * This function returns MTD device description structure in case of -++ * success and an error code in case of failure. -++ */ -++struct mtd_info *get_mtd_device_by_node(const struct device_node *of_node) -++{ -++ int err = -ENODEV; -++ struct mtd_info *mtd = NULL, *other; -++ -++ mutex_lock(&mtd_table_mutex); -++ -++ mtd_for_each_device(other) { -++ if (of_node == other->dev.of_node) { -++ mtd = other; -++ break; -++ } -++ } -++ -++ if (!mtd) -++ goto out_unlock; -++ -++ err = __get_mtd_device(mtd); -++ if (err) -++ goto out_unlock; -++ -++ mutex_unlock(&mtd_table_mutex); -++ return mtd; -++ -++out_unlock: -++ mutex_unlock(&mtd_table_mutex); -++ return ERR_PTR(err); -++} -++EXPORT_SYMBOL_GPL(get_mtd_device_by_node); -++ -+ void put_mtd_device(struct mtd_info *mtd) -+ { -+ mutex_lock(&mtd_table_mutex); -+--- a/include/linux/mtd/mtd.h -++++ b/include/linux/mtd/mtd.h -+@@ -703,6 +703,8 @@ extern struct mtd_info *get_mtd_device(s -+ extern int __get_mtd_device(struct mtd_info *mtd); -+ extern void __put_mtd_device(struct mtd_info *mtd); -+ extern struct mtd_info *get_mtd_device_nm(const char *name); -++extern struct mtd_info *get_mtd_device_by_node( -++ const struct device_node *of_node); -+ extern void put_mtd_device(struct mtd_info *mtd); -+ -+ static inline uint64_t mtdpart_get_offset(const struct mtd_info *mtd) diff --git a/target/linux/generic/pending-5.15/496-dt-bindings-add-bindings-for-mtd-concat-devices.patch b/target/linux/generic/pending-5.15/496-dt-bindings-add-bindings-for-mtd-concat-devices.patch new file mode 100644 index 0000000000..01f3b9ec2d @@ -4444,7 +4222,7 @@ index 0000000000..01f3b9ec2d ++} diff --git a/target/linux/generic/pending-5.15/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch b/target/linux/generic/pending-5.15/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch new file mode 100644 -index 0000000000..321680154d +index 0000000000..e0cbc4508b --- /dev/null +++ b/target/linux/generic/pending-5.15/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch @@ -0,0 +1,216 @@ @@ -4615,7 +4393,7 @@ index 0000000000..321680154d ++ platform_set_drvdata(pdev, info); ++ ++ of_for_each_phandle(&it, err, node, "devices", NULL, 0) { -++ mtd = get_mtd_device_by_node(it.node); +++ mtd = of_get_mtd_device_by_node(it.node); ++ if (IS_ERR(mtd)) { ++ of_node_put(it.node); ++ err = -EPROBE_DEFER; @@ -4742,10 +4520,10 @@ index 0000000000..ec14f6341c + diff --git a/target/linux/generic/pending-5.15/500-fs_cdrom_dependencies.patch b/target/linux/generic/pending-5.15/500-fs_cdrom_dependencies.patch new file mode 100644 -index 0000000000..b46865fb55 +index 0000000000..2053c0fbe2 --- /dev/null +++ b/target/linux/generic/pending-5.15/500-fs_cdrom_dependencies.patch -@@ -0,0 +1,62 @@ +@@ -0,0 +1,52 @@ +From af7b91bcecce0eae24e90acd35d96ecee73e1407 Mon Sep 17 00:00:00 2001 +From: OpenWrt community <openwrt-devel@lists.openwrt.org> +Date: Wed, 13 Jul 2022 12:21:15 +0200 @@ -4758,8 +4536,6 @@ index 0000000000..b46865fb55 + fs/udf/Kconfig | 1 + + 4 files changed, 4 insertions(+) + -+diff --git a/fs/hfs/Kconfig b/fs/hfs/Kconfig -+index 129926b5142d..e0d2c647aa07 100644 +--- a/fs/hfs/Kconfig ++++ b/fs/hfs/Kconfig +@@ -2,6 +2,7 @@ @@ -4770,8 +4546,6 @@ index 0000000000..b46865fb55 + select NLS + help + If you say Y here, you will be able to mount Macintosh-formatted -+diff --git a/fs/hfsplus/Kconfig b/fs/hfsplus/Kconfig -+index 7d4229aecec0..648d91d1881f 100644 +--- a/fs/hfsplus/Kconfig ++++ b/fs/hfsplus/Kconfig +@@ -2,6 +2,7 @@ @@ -4782,8 +4556,6 @@ index 0000000000..b46865fb55 + select NLS + select NLS_UTF8 + help -+diff --git a/fs/isofs/Kconfig b/fs/isofs/Kconfig -+index 08ffd37b9bb8..f74680379207 100644 +--- a/fs/isofs/Kconfig ++++ b/fs/isofs/Kconfig +@@ -1,6 +1,7 @@ @@ -4794,8 +4566,6 @@ index 0000000000..b46865fb55 + help + This is the standard file system used on CD-ROMs. It was previously + known as "High Sierra File System" and is called "hsfs" on other -+diff --git a/fs/udf/Kconfig b/fs/udf/Kconfig -+index 26e1a49f3ba7..3f85a084d2b5 100644 +--- a/fs/udf/Kconfig ++++ b/fs/udf/Kconfig +@@ -1,6 +1,7 @@ @@ -4806,14 +4576,12 @@ index 0000000000..b46865fb55 + select CRC_ITU_T + select NLS + help -+-- -+ diff --git a/target/linux/generic/pending-5.15/530-jffs2_make_lzma_available.patch b/target/linux/generic/pending-5.15/530-jffs2_make_lzma_available.patch new file mode 100644 -index 0000000000..fd6ca784c0 +index 0000000000..ac784d0b0b --- /dev/null +++ b/target/linux/generic/pending-5.15/530-jffs2_make_lzma_available.patch -@@ -0,0 +1,5180 @@ +@@ -0,0 +1,4581 @@ +From: Alexandros C. Couloumbis <alex@ozo.com> +Subject: fs: add jffs2/lzma support (not activated by default yet) + @@ -5172,7 +4940,7 @@ index 0000000000..fd6ca784c0 ++#endif +--- /dev/null ++++ b/include/linux/lzma/LzFind.h -+@@ -0,0 +1,115 @@ ++@@ -0,0 +1,98 @@ ++/* LzFind.h -- Match finder for LZ algorithms ++2009-04-22 : Igor Pavlov : Public domain */ ++ @@ -5230,11 +4998,6 @@ index 0000000000..fd6ca784c0 ++ ++#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) ++ -++int MatchFinder_NeedMove(CMatchFinder *p); -++Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); -++void MatchFinder_MoveBlock(CMatchFinder *p); -++void MatchFinder_ReadIfRequired(CMatchFinder *p); -++ ++void MatchFinder_Construct(CMatchFinder *p); ++ ++/* Conditions: @@ -5245,12 +5008,6 @@ index 0000000000..fd6ca784c0 ++ UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ++ ISzAlloc *alloc); ++void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); -++void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems); -++void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); -++ -++UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, -++ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, -++ UInt32 *distances, UInt32 maxLen); ++ ++/* ++Conditions: @@ -5277,12 +5034,6 @@ index 0000000000..fd6ca784c0 ++ ++void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); ++ -++void MatchFinder_Init(CMatchFinder *p); -++UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); -++UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); -++void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); -++void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); -++ ++#ifdef __cplusplus ++} ++#endif @@ -5347,7 +5098,7 @@ index 0000000000..fd6ca784c0 ++#endif +--- /dev/null ++++ b/include/linux/lzma/LzmaDec.h -+@@ -0,0 +1,231 @@ ++@@ -0,0 +1,130 @@ ++/* LzmaDec.h -- LZMA Decoder ++2009-02-07 : Igor Pavlov : Public domain */ ++ @@ -5381,14 +5132,6 @@ index 0000000000..fd6ca784c0 ++ UInt32 dicSize; ++} CLzmaProps; ++ -++/* LzmaProps_Decode - decodes properties -++Returns: -++ SZ_OK -++ SZ_ERROR_UNSUPPORTED - Unsupported properties -++*/ -++ -++SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); -++ ++ ++/* ---------- LZMA Decoder state ---------- */ ++ @@ -5420,8 +5163,6 @@ index 0000000000..fd6ca784c0 ++ ++#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } ++ -++void LzmaDec_Init(CLzmaDec *p); -++ ++/* There are two types of LZMA streams: ++ 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. ++ 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ @@ -5458,97 +5199,6 @@ index 0000000000..fd6ca784c0 ++ ++/* ELzmaStatus is used only as output value for function call */ ++ -++ -++/* ---------- Interfaces ---------- */ -++ -++/* There are 3 levels of interfaces: -++ 1) Dictionary Interface -++ 2) Buffer Interface -++ 3) One Call Interface -++ You can select any of these interfaces, but don't mix functions from different -++ groups for same object. */ -++ -++ -++/* There are two variants to allocate state for Dictionary Interface: -++ 1) LzmaDec_Allocate / LzmaDec_Free -++ 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs -++ You can use variant 2, if you set dictionary buffer manually. -++ For Buffer Interface you must always use variant 1. -++ -++LzmaDec_Allocate* can return: -++ SZ_OK -++ SZ_ERROR_MEM - Memory allocation error -++ SZ_ERROR_UNSUPPORTED - Unsupported properties -++*/ -++ -++SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); -++void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); -++ -++SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); -++void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); -++ -++/* ---------- Dictionary Interface ---------- */ -++ -++/* You can use it, if you want to eliminate the overhead for data copying from -++ dictionary to some other external buffer. -++ You must work with CLzmaDec variables directly in this interface. -++ -++ STEPS: -++ LzmaDec_Constr() -++ LzmaDec_Allocate() -++ for (each new stream) -++ { -++ LzmaDec_Init() -++ while (it needs more decompression) -++ { -++ LzmaDec_DecodeToDic() -++ use data from CLzmaDec::dic and update CLzmaDec::dicPos -++ } -++ } -++ LzmaDec_Free() -++*/ -++ -++/* LzmaDec_DecodeToDic -++ -++ The decoding to internal dictionary buffer (CLzmaDec::dic). -++ You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! -++ -++finishMode: -++ It has meaning only if the decoding reaches output limit (dicLimit). -++ LZMA_FINISH_ANY - Decode just dicLimit bytes. -++ LZMA_FINISH_END - Stream must be finished after dicLimit. -++ -++Returns: -++ SZ_OK -++ status: -++ LZMA_STATUS_FINISHED_WITH_MARK -++ LZMA_STATUS_NOT_FINISHED -++ LZMA_STATUS_NEEDS_MORE_INPUT -++ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK -++ SZ_ERROR_DATA - Data error -++*/ -++ -++SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, -++ const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); -++ -++ -++/* ---------- Buffer Interface ---------- */ -++ -++/* It's zlib-like interface. -++ See LzmaDec_DecodeToDic description for information about STEPS and return results, -++ but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need -++ to work with CLzmaDec variables manually. -++ -++finishMode: -++ It has meaning only if the decoding reaches output limit (*destLen). -++ LZMA_FINISH_ANY - Decode just destLen bytes. -++ LZMA_FINISH_END - Stream must be finished after (*destLen). -++*/ -++ -++SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, -++ const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); -++ -++ ++/* ---------- One Call Interface ---------- */ ++ ++/* LzmaDecode @@ -5581,7 +5231,7 @@ index 0000000000..fd6ca784c0 ++#endif +--- /dev/null ++++ b/include/linux/lzma/LzmaEnc.h -+@@ -0,0 +1,80 @@ ++@@ -0,0 +1,60 @@ ++/* LzmaEnc.h -- LZMA Encoder ++2009-02-07 : Igor Pavlov : Public domain */ ++ @@ -5615,9 +5265,6 @@ index 0000000000..fd6ca784c0 ++} CLzmaEncProps; ++ ++void LzmaEncProps_Init(CLzmaEncProps *p); -++void LzmaEncProps_Normalize(CLzmaEncProps *p); -++UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2); -++ ++ ++/* ---------- CLzmaEncHandle Interface ---------- */ ++ @@ -5637,26 +5284,9 @@ index 0000000000..fd6ca784c0 ++void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig); ++SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props); ++SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size); -++SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, -++ ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); ++SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, ++ int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); ++ -++/* ---------- One Call Interface ---------- */ -++ -++/* LzmaEncode -++Return code: -++ SZ_OK - OK -++ SZ_ERROR_MEM - Memory allocation error -++ SZ_ERROR_PARAM - Incorrect paramater -++ SZ_ERROR_OUTPUT_EOF - output buffer overflow -++ SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) -++*/ -++ -++SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, -++ const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, -++ ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); -++ ++#ifdef __cplusplus ++} ++#endif @@ -5946,7 +5576,7 @@ index 0000000000..fd6ca784c0 + lib-$(CONFIG_DECOMPRESS_BZIP2) += decompress_bunzip2.o +--- /dev/null ++++ b/lib/lzma/LzFind.c -+@@ -0,0 +1,761 @@ ++@@ -0,0 +1,522 @@ ++/* LzFind.c -- Match finder for LZ algorithms ++2009-04-22 : Igor Pavlov : Public domain */ ++ @@ -5963,9 +5593,15 @@ index 0000000000..fd6ca784c0 ++ ++#define kStartMaxLen 3 ++ +++#if 0 +++#define DIRECT_INPUT p->directInput +++#else +++#define DIRECT_INPUT 1 +++#endif +++ ++static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) ++{ -++ if (!p->directInput) +++ if (!DIRECT_INPUT) ++ { ++ alloc->Free(alloc, p->bufferBase); ++ p->bufferBase = 0; @@ -5977,7 +5613,7 @@ index 0000000000..fd6ca784c0 ++static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) ++{ ++ UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; -++ if (p->directInput) +++ if (DIRECT_INPUT) ++ { ++ p->blockSize = blockSize; ++ return 1; @@ -5991,12 +5627,12 @@ index 0000000000..fd6ca784c0 ++ return (p->bufferBase != 0); ++} ++ -++Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } -++Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } +++static Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } +++static Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } ++ -++UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } +++static UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } ++ -++void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) +++static void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) ++{ ++ p->posLimit -= subValue; ++ p->pos -= subValue; @@ -6007,7 +5643,7 @@ index 0000000000..fd6ca784c0 ++{ ++ if (p->streamEndWasReached || p->result != SZ_OK) ++ return; -++ if (p->directInput) +++ if (DIRECT_INPUT) ++ { ++ UInt32 curSize = 0xFFFFFFFF - p->streamPos; ++ if (curSize > p->directInputRem) @@ -6038,7 +5674,7 @@ index 0000000000..fd6ca784c0 ++ } ++} ++ -++void MatchFinder_MoveBlock(CMatchFinder *p) +++static void MatchFinder_MoveBlock(CMatchFinder *p) ++{ ++ memmove(p->bufferBase, ++ p->buffer - p->keepSizeBefore, @@ -6046,22 +5682,14 @@ index 0000000000..fd6ca784c0 ++ p->buffer = p->bufferBase + p->keepSizeBefore; ++} ++ -++int MatchFinder_NeedMove(CMatchFinder *p) +++static int MatchFinder_NeedMove(CMatchFinder *p) ++{ -++ if (p->directInput) +++ if (DIRECT_INPUT) ++ return 0; ++ /* if (p->streamEndWasReached) return 0; */ ++ return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); ++} ++ -++void MatchFinder_ReadIfRequired(CMatchFinder *p) -++{ -++ if (p->streamEndWasReached) -++ return; -++ if (p->keepSizeAfter >= p->streamPos - p->pos) -++ MatchFinder_ReadBlock(p); -++} -++ ++static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) ++{ ++ if (MatchFinder_NeedMove(p)) @@ -6217,7 +5845,7 @@ index 0000000000..fd6ca784c0 ++ p->posLimit = p->pos + limit; ++} ++ -++void MatchFinder_Init(CMatchFinder *p) +++static void MatchFinder_Init(CMatchFinder *p) ++{ ++ UInt32 i; ++ for (i = 0; i < p->hashSizeSum; i++) @@ -6236,7 +5864,7 @@ index 0000000000..fd6ca784c0 ++ return (p->pos - p->historySize - 1) & kNormalizeMask; ++} ++ -++void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) +++static void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) ++{ ++ UInt32 i; ++ for (i = 0; i < numItems; i++) @@ -6268,38 +5896,7 @@ index 0000000000..fd6ca784c0 ++ MatchFinder_SetLimits(p); ++} ++ -++static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, -++ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, -++ UInt32 *distances, UInt32 maxLen) -++{ -++ son[_cyclicBufferPos] = curMatch; -++ for (;;) -++ { -++ UInt32 delta = pos - curMatch; -++ if (cutValue-- == 0 || delta >= _cyclicBufferSize) -++ return distances; -++ { -++ const Byte *pb = cur - delta; -++ curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; -++ if (pb[maxLen] == cur[maxLen] && *pb == *cur) -++ { -++ UInt32 len = 0; -++ while (++len != lenLimit) -++ if (pb[len] != cur[len]) -++ break; -++ if (maxLen < len) -++ { -++ *distances++ = maxLen = len; -++ *distances++ = delta - 1; -++ if (len == lenLimit) -++ return distances; -++ } -++ } -++ } -++ } -++} -++ -++UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, +++static UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, ++ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, ++ UInt32 *distances, UInt32 maxLen) ++{ @@ -6409,10 +6006,10 @@ index 0000000000..fd6ca784c0 ++ p->buffer++; \ ++ if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); ++ -++#define MOVE_POS_RET MOVE_POS return offset; -++ ++static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } ++ +++#define MOVE_POS_RET MatchFinder_MovePos(p); return offset; +++ ++#define GET_MATCHES_HEADER2(minLen, ret_op) \ ++ UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \ ++ lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ @@ -6428,62 +6025,7 @@ index 0000000000..fd6ca784c0 ++ distances + offset, maxLen) - distances); MOVE_POS_RET; ++ ++#define SKIP_FOOTER \ -++ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; -++ -++static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) -++{ -++ UInt32 offset; -++ GET_MATCHES_HEADER(2) -++ HASH2_CALC; -++ curMatch = p->hash[hashValue]; -++ p->hash[hashValue] = p->pos; -++ offset = 0; -++ GET_MATCHES_FOOTER(offset, 1) -++} -++ -++UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) -++{ -++ UInt32 offset; -++ GET_MATCHES_HEADER(3) -++ HASH_ZIP_CALC; -++ curMatch = p->hash[hashValue]; -++ p->hash[hashValue] = p->pos; -++ offset = 0; -++ GET_MATCHES_FOOTER(offset, 2) -++} -++ -++static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) -++{ -++ UInt32 hash2Value, delta2, maxLen, offset; -++ GET_MATCHES_HEADER(3) -++ -++ HASH3_CALC; -++ -++ delta2 = p->pos - p->hash[hash2Value]; -++ curMatch = p->hash[kFix3HashSize + hashValue]; -++ -++ p->hash[hash2Value] = -++ p->hash[kFix3HashSize + hashValue] = p->pos; -++ -++ -++ maxLen = 2; -++ offset = 0; -++ if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) -++ { -++ for (; maxLen != lenLimit; maxLen++) -++ if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) -++ break; -++ distances[0] = maxLen; -++ distances[1] = delta2 - 1; -++ offset = 2; -++ if (maxLen == lenLimit) -++ { -++ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); -++ MOVE_POS_RET; -++ } -++ } -++ GET_MATCHES_FOOTER(offset, maxLen) -++} +++ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MatchFinder_MovePos(p); ++ ++static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) ++{ @@ -6532,108 +6074,6 @@ index 0000000000..fd6ca784c0 ++ GET_MATCHES_FOOTER(offset, maxLen) ++} ++ -++static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) -++{ -++ UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; -++ GET_MATCHES_HEADER(4) -++ -++ HASH4_CALC; -++ -++ delta2 = p->pos - p->hash[ hash2Value]; -++ delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; -++ curMatch = p->hash[kFix4HashSize + hashValue]; -++ -++ p->hash[ hash2Value] = -++ p->hash[kFix3HashSize + hash3Value] = -++ p->hash[kFix4HashSize + hashValue] = p->pos; -++ -++ maxLen = 1; -++ offset = 0; -++ if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) -++ { -++ distances[0] = maxLen = 2; -++ distances[1] = delta2 - 1; -++ offset = 2; -++ } -++ if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) -++ { -++ maxLen = 3; -++ distances[offset + 1] = delta3 - 1; -++ offset += 2; -++ delta2 = delta3; -++ } -++ if (offset != 0) -++ { -++ for (; maxLen != lenLimit; maxLen++) -++ if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) -++ break; -++ distances[offset - 2] = maxLen; -++ if (maxLen == lenLimit) -++ { -++ p->son[p->cyclicBufferPos] = curMatch; -++ MOVE_POS_RET; -++ } -++ } -++ if (maxLen < 3) -++ maxLen = 3; -++ offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), -++ distances + offset, maxLen) - (distances)); -++ MOVE_POS_RET -++} -++ -++UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) -++{ -++ UInt32 offset; -++ GET_MATCHES_HEADER(3) -++ HASH_ZIP_CALC; -++ curMatch = p->hash[hashValue]; -++ p->hash[hashValue] = p->pos; -++ offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), -++ distances, 2) - (distances)); -++ MOVE_POS_RET -++} -++ -++static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) -++{ -++ do -++ { -++ SKIP_HEADER(2) -++ HASH2_CALC; -++ curMatch = p->hash[hashValue]; -++ p->hash[hashValue] = p->pos; -++ SKIP_FOOTER -++ } -++ while (--num != 0); -++} -++ -++void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) -++{ -++ do -++ { -++ SKIP_HEADER(3) -++ HASH_ZIP_CALC; -++ curMatch = p->hash[hashValue]; -++ p->hash[hashValue] = p->pos; -++ SKIP_FOOTER -++ } -++ while (--num != 0); -++} -++ -++static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) -++{ -++ do -++ { -++ UInt32 hash2Value; -++ SKIP_HEADER(3) -++ HASH3_CALC; -++ curMatch = p->hash[kFix3HashSize + hashValue]; -++ p->hash[hash2Value] = -++ p->hash[kFix3HashSize + hashValue] = p->pos; -++ SKIP_FOOTER -++ } -++ while (--num != 0); -++} -++ ++static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) ++{ ++ do @@ -6650,67 +6090,18 @@ index 0000000000..fd6ca784c0 ++ while (--num != 0); ++} ++ -++static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) -++{ -++ do -++ { -++ UInt32 hash2Value, hash3Value; -++ SKIP_HEADER(4) -++ HASH4_CALC; -++ curMatch = p->hash[kFix4HashSize + hashValue]; -++ p->hash[ hash2Value] = -++ p->hash[kFix3HashSize + hash3Value] = -++ p->hash[kFix4HashSize + hashValue] = p->pos; -++ p->son[p->cyclicBufferPos] = curMatch; -++ MOVE_POS -++ } -++ while (--num != 0); -++} -++ -++void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) -++{ -++ do -++ { -++ SKIP_HEADER(3) -++ HASH_ZIP_CALC; -++ curMatch = p->hash[hashValue]; -++ p->hash[hashValue] = p->pos; -++ p->son[p->cyclicBufferPos] = curMatch; -++ MOVE_POS -++ } -++ while (--num != 0); -++} -++ ++void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) ++{ ++ vTable->Init = (Mf_Init_Func)MatchFinder_Init; ++ vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte; ++ vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; ++ vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; -++ if (!p->btMode) -++ { -++ vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; -++ vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; -++ } -++ else if (p->numHashBytes == 2) -++ { -++ vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; -++ vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; -++ } -++ else if (p->numHashBytes == 3) -++ { -++ vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; -++ vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; -++ } -++ else -++ { -++ vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; -++ vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; -++ } +++ vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; +++ vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; ++} +--- /dev/null ++++ b/lib/lzma/LzmaDec.c -+@@ -0,0 +1,999 @@ ++@@ -0,0 +1,925 @@ ++/* LzmaDec.c -- LZMA Decoder ++2009-09-20 : Igor Pavlov : Public domain */ ++ @@ -7395,7 +6786,7 @@ index 0000000000..fd6ca784c0 ++ p->needFlush = 0; ++} ++ -++void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) +++static void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) ++{ ++ p->needFlush = 1; ++ p->remainLen = 0; @@ -7411,7 +6802,7 @@ index 0000000000..fd6ca784c0 ++ p->needInitState = 1; ++} ++ -++void LzmaDec_Init(CLzmaDec *p) +++static void LzmaDec_Init(CLzmaDec *p) ++{ ++ p->dicPos = 0; ++ LzmaDec_InitDicAndState(p, True, True); @@ -7429,7 +6820,7 @@ index 0000000000..fd6ca784c0 ++ p->needInitState = 0; ++} ++ -++SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, +++static SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ++ ELzmaFinishMode finishMode, ELzmaStatus *status) ++{ ++ SizeT inSize = *srcLen; @@ -7550,65 +6941,13 @@ index 0000000000..fd6ca784c0 ++ return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; ++} ++ -++SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) -++{ -++ SizeT outSize = *destLen; -++ SizeT inSize = *srcLen; -++ *srcLen = *destLen = 0; -++ for (;;) -++ { -++ SizeT inSizeCur = inSize, outSizeCur, dicPos; -++ ELzmaFinishMode curFinishMode; -++ SRes res; -++ if (p->dicPos == p->dicBufSize) -++ p->dicPos = 0; -++ dicPos = p->dicPos; -++ if (outSize > p->dicBufSize - dicPos) -++ { -++ outSizeCur = p->dicBufSize; -++ curFinishMode = LZMA_FINISH_ANY; -++ } -++ else -++ { -++ outSizeCur = dicPos + outSize; -++ curFinishMode = finishMode; -++ } -++ -++ res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); -++ src += inSizeCur; -++ inSize -= inSizeCur; -++ *srcLen += inSizeCur; -++ outSizeCur = p->dicPos - dicPos; -++ memcpy(dest, p->dic + dicPos, outSizeCur); -++ dest += outSizeCur; -++ outSize -= outSizeCur; -++ *destLen += outSizeCur; -++ if (res != 0) -++ return res; -++ if (outSizeCur == 0 || outSize == 0) -++ return SZ_OK; -++ } -++} -++ -++void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) +++static void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) ++{ ++ alloc->Free(alloc, p->probs); ++ p->probs = 0; ++} ++ -++static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) -++{ -++ alloc->Free(alloc, p->dic); -++ p->dic = 0; -++} -++ -++void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) -++{ -++ LzmaDec_FreeProbs(p, alloc); -++ LzmaDec_FreeDict(p, alloc); -++} -++ -++SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) +++static SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) ++{ ++ UInt32 dicSize; ++ Byte d; @@ -7648,33 +6987,11 @@ index 0000000000..fd6ca784c0 ++ return SZ_OK; ++} ++ -++SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) -++{ -++ CLzmaProps propNew; -++ RINOK(LzmaProps_Decode(&propNew, props, propsSize)); -++ RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); -++ p->prop = propNew; -++ return SZ_OK; -++} -++ -++SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) +++static SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) ++{ ++ CLzmaProps propNew; -++ SizeT dicBufSize; ++ RINOK(LzmaProps_Decode(&propNew, props, propsSize)); ++ RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); -++ dicBufSize = propNew.dicSize; -++ if (p->dic == 0 || dicBufSize != p->dicBufSize) -++ { -++ LzmaDec_FreeDict(p, alloc); -++ p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); -++ if (p->dic == 0) -++ { -++ LzmaDec_FreeProbs(p, alloc); -++ return SZ_ERROR_MEM; -++ } -++ } -++ p->dicBufSize = dicBufSize; ++ p->prop = propNew; ++ return SZ_OK; ++} @@ -7712,7 +7029,7 @@ index 0000000000..fd6ca784c0 ++} +--- /dev/null ++++ b/lib/lzma/LzmaEnc.c -+@@ -0,0 +1,2271 @@ ++@@ -0,0 +1,2123 @@ ++/* LzmaEnc.c -- LZMA Encoder ++2009-11-24 : Igor Pavlov : Public domain */ ++ @@ -7768,7 +7085,7 @@ index 0000000000..fd6ca784c0 ++ p->writeEndMark = 0; ++} ++ -++void LzmaEncProps_Normalize(CLzmaEncProps *p) +++static void LzmaEncProps_Normalize(CLzmaEncProps *p) ++{ ++ int level = p->level; ++ if (level < 0) level = 5; @@ -7791,7 +7108,7 @@ index 0000000000..fd6ca784c0 ++ #endif ++} ++ -++UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) +++static UInt32 __maybe_unused LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) ++{ ++ CLzmaEncProps props = *props2; ++ LzmaEncProps_Normalize(&props); @@ -7808,7 +7125,7 @@ index 0000000000..fd6ca784c0 ++ ++#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); } ++ -++UInt32 GetPosSlot1(UInt32 pos) +++static UInt32 GetPosSlot1(UInt32 pos) ++{ ++ UInt32 res; ++ BSR2_RET(pos, res); @@ -7822,7 +7139,7 @@ index 0000000000..fd6ca784c0 ++#define kNumLogBits (9 + (int)sizeof(size_t) / 2) ++#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) ++ -++void LzmaEnc_FastPosInit(Byte *g_FastPos) +++static void LzmaEnc_FastPosInit(Byte *g_FastPos) ++{ ++ int c = 2, slotFast; ++ g_FastPos[0] = 0; @@ -8054,59 +7371,7 @@ index 0000000000..fd6ca784c0 ++ CSaveState saveState; ++} CLzmaEnc; ++ -++void LzmaEnc_SaveState(CLzmaEncHandle pp) -++{ -++ CLzmaEnc *p = (CLzmaEnc *)pp; -++ CSaveState *dest = &p->saveState; -++ int i; -++ dest->lenEnc = p->lenEnc; -++ dest->repLenEnc = p->repLenEnc; -++ dest->state = p->state; -++ -++ for (i = 0; i < kNumStates; i++) -++ { -++ memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); -++ memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); -++ } -++ for (i = 0; i < kNumLenToPosStates; i++) -++ memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); -++ memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); -++ memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); -++ memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); -++ memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); -++ memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); -++ memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); -++ memcpy(dest->reps, p->reps, sizeof(p->reps)); -++ memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb)); -++} -++ -++void LzmaEnc_RestoreState(CLzmaEncHandle pp) -++{ -++ CLzmaEnc *dest = (CLzmaEnc *)pp; -++ const CSaveState *p = &dest->saveState; -++ int i; -++ dest->lenEnc = p->lenEnc; -++ dest->repLenEnc = p->repLenEnc; -++ dest->state = p->state; -++ -++ for (i = 0; i < kNumStates; i++) -++ { -++ memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); -++ memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); -++ } -++ for (i = 0; i < kNumLenToPosStates; i++) -++ memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); -++ memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); -++ memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); -++ memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); -++ memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); -++ memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); -++ memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); -++ memcpy(dest->reps, p->reps, sizeof(p->reps)); -++ memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb)); -++} -++ -++SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) +++SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) ++{ ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++ CLzmaEncProps props = *props2; @@ -8315,7 +7580,7 @@ index 0000000000..fd6ca784c0 ++ while (symbol < 0x10000); ++} ++ -++void LzmaEnc_InitPriceTables(UInt32 *ProbPrices) +++static void LzmaEnc_InitPriceTables(UInt32 *ProbPrices) ++{ ++ UInt32 i; ++ for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits)) @@ -9391,7 +8656,7 @@ index 0000000000..fd6ca784c0 ++ p->matchPriceCount = 0; ++} ++ -++void LzmaEnc_Construct(CLzmaEnc *p) +++static void LzmaEnc_Construct(CLzmaEnc *p) ++{ ++ RangeEnc_Construct(&p->rc); ++ MatchFinder_Construct(&p->matchFinderBase); @@ -9424,7 +8689,7 @@ index 0000000000..fd6ca784c0 ++ return p; ++} ++ -++void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) +++static void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) ++{ ++ alloc->Free(alloc, p->litProbs); ++ alloc->Free(alloc, p->saveState.litProbs); @@ -9432,7 +8697,7 @@ index 0000000000..fd6ca784c0 ++ p->saveState.litProbs = 0; ++} ++ -++void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) +++static void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ #ifndef _7ZIP_ST ++ MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); @@ -9662,7 +8927,7 @@ index 0000000000..fd6ca784c0 ++ return SZ_OK; ++} ++ -++void LzmaEnc_Init(CLzmaEnc *p) +++static void LzmaEnc_Init(CLzmaEnc *p) ++{ ++ UInt32 i; ++ p->state = 0; @@ -9720,7 +8985,7 @@ index 0000000000..fd6ca784c0 ++ p->lpMask = (1 << p->lp) - 1; ++} ++ -++void LzmaEnc_InitPrices(CLzmaEnc *p) +++static void LzmaEnc_InitPrices(CLzmaEnc *p) ++{ ++ if (!p->fastMode) ++ { @@ -9752,26 +9017,6 @@ index 0000000000..fd6ca784c0 ++ return SZ_OK; ++} ++ -++static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, -++ ISzAlloc *alloc, ISzAlloc *allocBig) -++{ -++ CLzmaEnc *p = (CLzmaEnc *)pp; -++ p->matchFinderBase.stream = inStream; -++ p->needInit = 1; -++ p->rc.outStream = outStream; -++ return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); -++} -++ -++SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, -++ ISeqInStream *inStream, UInt32 keepWindowSize, -++ ISzAlloc *alloc, ISzAlloc *allocBig) -++{ -++ CLzmaEnc *p = (CLzmaEnc *)pp; -++ p->matchFinderBase.stream = inStream; -++ p->needInit = 1; -++ return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); -++} -++ ++static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) ++{ ++ p->matchFinderBase.directInput = 1; @@ -9779,7 +9024,7 @@ index 0000000000..fd6ca784c0 ++ p->matchFinderBase.directInputRem = srcLen; ++} ++ -++SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, +++static SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, ++ UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ CLzmaEnc *p = (CLzmaEnc *)pp; @@ -9789,7 +9034,7 @@ index 0000000000..fd6ca784c0 ++ return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); ++} ++ -++void LzmaEnc_Finish(CLzmaEncHandle pp) +++static void LzmaEnc_Finish(CLzmaEncHandle pp) ++{ ++ #ifndef _7ZIP_ST ++ CLzmaEnc *p = (CLzmaEnc *)pp; @@ -9822,53 +9067,6 @@ index 0000000000..fd6ca784c0 ++ return size; ++} ++ -++ -++UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp) -++{ -++ const CLzmaEnc *p = (CLzmaEnc *)pp; -++ return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); -++} -++ -++const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) -++{ -++ const CLzmaEnc *p = (CLzmaEnc *)pp; -++ return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; -++} -++ -++SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, -++ Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) -++{ -++ CLzmaEnc *p = (CLzmaEnc *)pp; -++ UInt64 nowPos64; -++ SRes res; -++ CSeqOutStreamBuf outStream; -++ -++ outStream.funcTable.Write = MyWrite; -++ outStream.data = dest; -++ outStream.rem = *destLen; -++ outStream.overflow = False; -++ -++ p->writeEndMark = False; -++ p->finished = False; -++ p->result = SZ_OK; -++ -++ if (reInit) -++ LzmaEnc_Init(p); -++ LzmaEnc_InitPrices(p); -++ nowPos64 = p->nowPos64; -++ RangeEnc_Init(&p->rc); -++ p->rc.outStream = &outStream.funcTable; -++ -++ res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize); -++ -++ *unpackSize = (UInt32)(p->nowPos64 - nowPos64); -++ *destLen -= outStream.rem; -++ if (outStream.overflow) -++ return SZ_ERROR_OUTPUT_EOF; -++ -++ return res; -++} -++ ++static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress) ++{ ++ SRes res = SZ_OK; @@ -9899,13 +9097,6 @@ index 0000000000..fd6ca784c0 ++ return res; ++} ++ -++SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, -++ ISzAlloc *alloc, ISzAlloc *allocBig) -++{ -++ RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig)); -++ return LzmaEnc_Encode2((CLzmaEnc *)pp, progress); -++} -++ ++SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) ++{ ++ CLzmaEnc *p = (CLzmaEnc *)pp; @@ -9962,28 +9153,6 @@ index 0000000000..fd6ca784c0 ++ return SZ_ERROR_OUTPUT_EOF; ++ return res; ++} -++ -++SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, -++ const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, -++ ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) -++{ -++ CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc); -++ SRes res; -++ if (p == 0) -++ return SZ_ERROR_MEM; -++ -++ res = LzmaEnc_SetProps(p, props); -++ if (res == SZ_OK) -++ { -++ res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize); -++ if (res == SZ_OK) -++ res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen, -++ writeEndMark, progress, alloc, allocBig); -++ } -++ -++ LzmaEnc_Destroy(p, alloc, allocBig); -++ return res; -++} +--- /dev/null ++++ b/lib/lzma/Makefile +@@ -0,0 +1,7 @@ @@ -10417,7 +9586,7 @@ index 0000000000..79da6778b6 + diff --git a/target/linux/generic/pending-5.15/613-netfilter_optional_tcp_window_check.patch b/target/linux/generic/pending-5.15/613-netfilter_optional_tcp_window_check.patch new file mode 100644 -index 0000000000..fd9e63a613 +index 0000000000..93c52e8842 --- /dev/null +++ b/target/linux/generic/pending-5.15/613-netfilter_optional_tcp_window_check.patch @@ -0,0 +1,83 @@ @@ -10442,7 +9611,7 @@ index 0000000000..fd9e63a613 + /* + * Get the required data from the packet. + */ -+@@ -1160,7 +1163,7 @@ int nf_conntrack_tcp_packet(struct nf_co ++@@ -1191,7 +1194,7 @@ int nf_conntrack_tcp_packet(struct nf_co + IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED && + timeouts[new_state] > timeouts[TCP_CONNTRACK_UNACK]) + timeout = timeouts[TCP_CONNTRACK_UNACK]; @@ -10451,7 +9620,7 @@ index 0000000000..fd9e63a613 + timeouts[new_state] > timeouts[TCP_CONNTRACK_RETRANS]) + timeout = timeouts[TCP_CONNTRACK_RETRANS]; + else -+@@ -1476,6 +1479,9 @@ void nf_conntrack_tcp_init_net(struct ne ++@@ -1507,6 +1510,9 @@ void nf_conntrack_tcp_init_net(struct ne + */ + tn->tcp_be_liberal = 0; + @@ -10742,7 +9911,7 @@ index 0000000000..c61935ffb0 + static inline struct packet_sock *pkt_sk(struct sock *sk) diff --git a/target/linux/generic/pending-5.15/655-increase_skb_pad.patch b/target/linux/generic/pending-5.15/655-increase_skb_pad.patch new file mode 100644 -index 0000000000..9d03fe5c31 +index 0000000000..d1bb72d353 --- /dev/null +++ b/target/linux/generic/pending-5.15/655-increase_skb_pad.patch @@ -0,0 +1,20 @@ @@ -10757,7 +9926,7 @@ index 0000000000..9d03fe5c31 + +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h -+@@ -2737,7 +2737,7 @@ static inline int pskb_network_may_pull( ++@@ -2820,7 +2820,7 @@ static inline int pskb_network_may_pull( + * NET_IP_ALIGN(2) + ethernet_header(14) + IP_header(20/40) + ports(8) + */ + #ifndef NET_SKB_PAD @@ -10768,7 +9937,7 @@ index 0000000000..9d03fe5c31 + int ___pskb_trim(struct sk_buff *skb, unsigned int len); diff --git a/target/linux/generic/pending-5.15/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch b/target/linux/generic/pending-5.15/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch new file mode 100644 -index 0000000000..09efa1e72f +index 0000000000..2f6fbd59e4 --- /dev/null +++ b/target/linux/generic/pending-5.15/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch @@ -0,0 +1,511 @@ @@ -11112,7 +10281,7 @@ index 0000000000..09efa1e72f + if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6)) + return -1; + -+@@ -1525,6 +1686,14 @@ ip6_tnl_change(struct ip6_tnl *t, const ++@@ -1526,6 +1687,14 @@ ip6_tnl_change(struct ip6_tnl *t, const + t->parms.link = p->link; + t->parms.proto = p->proto; + t->parms.fwmark = p->fwmark; @@ -11127,7 +10296,7 @@ index 0000000000..09efa1e72f + dst_cache_reset(&t->dst_cache); + ip6_tnl_link_config(t); + return 0; -+@@ -1563,6 +1732,7 @@ ip6_tnl_parm_from_user(struct __ip6_tnl_ ++@@ -1564,6 +1733,7 @@ ip6_tnl_parm_from_user(struct __ip6_tnl_ + p->flowinfo = u->flowinfo; + p->link = u->link; + p->proto = u->proto; @@ -11135,7 +10304,7 @@ index 0000000000..09efa1e72f + memcpy(p->name, u->name, sizeof(u->name)); + } + -+@@ -1949,6 +2119,15 @@ static int ip6_tnl_validate(struct nlatt ++@@ -1950,6 +2120,15 @@ static int ip6_tnl_validate(struct nlatt + return 0; + } + @@ -11151,7 +10320,7 @@ index 0000000000..09efa1e72f + static void ip6_tnl_netlink_parms(struct nlattr *data[], + struct __ip6_tnl_parm *parms) + { -+@@ -1986,6 +2165,46 @@ static void ip6_tnl_netlink_parms(struct ++@@ -1987,6 +2166,46 @@ static void ip6_tnl_netlink_parms(struct + + if (data[IFLA_IPTUN_FWMARK]) + parms->fwmark = nla_get_u32(data[IFLA_IPTUN_FWMARK]); @@ -11198,7 +10367,7 @@ index 0000000000..09efa1e72f + } + + static bool ip6_tnl_netlink_encap_parms(struct nlattr *data[], -+@@ -2101,6 +2320,12 @@ static void ip6_tnl_dellink(struct net_d ++@@ -2102,6 +2321,12 @@ static void ip6_tnl_dellink(struct net_d + + static size_t ip6_tnl_get_size(const struct net_device *dev) + { @@ -11211,7 +10380,7 @@ index 0000000000..09efa1e72f + return + /* IFLA_IPTUN_LINK */ + nla_total_size(4) + -+@@ -2130,6 +2355,24 @@ static size_t ip6_tnl_get_size(const str ++@@ -2131,6 +2356,24 @@ static size_t ip6_tnl_get_size(const str + nla_total_size(0) + + /* IFLA_IPTUN_FWMARK */ + nla_total_size(4) + @@ -11236,7 +10405,7 @@ index 0000000000..09efa1e72f + 0; + } + -+@@ -2137,6 +2380,9 @@ static int ip6_tnl_fill_info(struct sk_b ++@@ -2138,6 +2381,9 @@ static int ip6_tnl_fill_info(struct sk_b + { + struct ip6_tnl *tunnel = netdev_priv(dev); + struct __ip6_tnl_parm *parm = &tunnel->parms; @@ -11246,7 +10415,7 @@ index 0000000000..09efa1e72f + + if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) || + nla_put_in6_addr(skb, IFLA_IPTUN_LOCAL, &parm->laddr) || -+@@ -2146,9 +2392,27 @@ static int ip6_tnl_fill_info(struct sk_b ++@@ -2147,9 +2393,27 @@ static int ip6_tnl_fill_info(struct sk_b + nla_put_be32(skb, IFLA_IPTUN_FLOWINFO, parm->flowinfo) || + nla_put_u32(skb, IFLA_IPTUN_FLAGS, parm->flags) || + nla_put_u8(skb, IFLA_IPTUN_PROTO, parm->proto) || @@ -11275,7 +10444,7 @@ index 0000000000..09efa1e72f + if (nla_put_u16(skb, IFLA_IPTUN_ENCAP_TYPE, tunnel->encap.type) || + nla_put_be16(skb, IFLA_IPTUN_ENCAP_SPORT, tunnel->encap.sport) || + nla_put_be16(skb, IFLA_IPTUN_ENCAP_DPORT, tunnel->encap.dport) || -+@@ -2188,6 +2452,7 @@ static const struct nla_policy ip6_tnl_p ++@@ -2189,6 +2453,7 @@ static const struct nla_policy ip6_tnl_p + [IFLA_IPTUN_ENCAP_DPORT] = { .type = NLA_U16 }, + [IFLA_IPTUN_COLLECT_METADATA] = { .type = NLA_FLAG }, + [IFLA_IPTUN_FWMARK] = { .type = NLA_U32 }, @@ -11285,7 +10454,7 @@ index 0000000000..09efa1e72f + static struct rtnl_link_ops ip6_link_ops __read_mostly = { diff --git a/target/linux/generic/pending-5.15/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch b/target/linux/generic/pending-5.15/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch new file mode 100644 -index 0000000000..68960765bb +index 0000000000..c58e6b545b --- /dev/null +++ b/target/linux/generic/pending-5.15/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch @@ -0,0 +1,263 @@ @@ -11357,7 +10526,7 @@ index 0000000000..68960765bb + static void rt_fibinfo_free(struct rtable __rcu **rtp) +--- a/net/ipv4/fib_trie.c ++++ b/net/ipv4/fib_trie.c -+@@ -2767,6 +2767,7 @@ static const char *const rtn_type_names[ ++@@ -2770,6 +2770,7 @@ static const char *const rtn_type_names[ + [RTN_THROW] = "THROW", + [RTN_NAT] = "NAT", + [RTN_XRESOLVE] = "XRESOLVE", @@ -11542,7 +10711,7 @@ index 0000000000..68960765bb + kfree(net->ipv6.ip6_blk_hole_entry); + #endif + dst_entries_destroy(&net->ipv6.ip6_dst_ops); -+@@ -6639,6 +6688,9 @@ void __init ip6_route_init_special_entri ++@@ -6645,6 +6694,9 @@ void __init ip6_route_init_special_entri + init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); + init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; + init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); @@ -11610,7 +10779,7 @@ index 0000000000..bea43b2bad + diff --git a/target/linux/generic/pending-5.15/680-NET-skip-GRO-for-foreign-MAC-addresses.patch b/target/linux/generic/pending-5.15/680-NET-skip-GRO-for-foreign-MAC-addresses.patch new file mode 100644 -index 0000000000..8b4cd10488 +index 0000000000..72938abd37 --- /dev/null +++ b/target/linux/generic/pending-5.15/680-NET-skip-GRO-for-foreign-MAC-addresses.patch @@ -0,0 +1,149 @@ @@ -11627,7 +10796,7 @@ index 0000000000..8b4cd10488 + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h -+@@ -2075,6 +2075,8 @@ struct net_device { ++@@ -2089,6 +2089,8 @@ struct net_device { + struct netdev_hw_addr_list mc; + struct netdev_hw_addr_list dev_addrs; + @@ -11638,7 +10807,7 @@ index 0000000000..8b4cd10488 + #endif +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h -+@@ -855,6 +855,7 @@ struct sk_buff { ++@@ -892,6 +892,7 @@ struct sk_buff { + #ifdef CONFIG_IPV6_NDISC_NODETYPE + __u8 ndisc_nodetype:2; + #endif @@ -11648,7 +10817,7 @@ index 0000000000..8b4cd10488 + __u8 inner_protocol_type:1; +--- a/net/core/dev.c ++++ b/net/core/dev.c -+@@ -6061,6 +6061,9 @@ static enum gro_result dev_gro_receive(s ++@@ -6063,6 +6063,9 @@ static enum gro_result dev_gro_receive(s + int same_flow; + int grow; + @@ -11658,7 +10827,7 @@ index 0000000000..8b4cd10488 + if (netif_elide_gro(skb->dev)) + goto normal; + -+@@ -8075,6 +8078,48 @@ static void __netdev_adjacent_dev_unlink ++@@ -8077,6 +8080,48 @@ static void __netdev_adjacent_dev_unlink + &upper_dev->adj_list.lower); + } + @@ -11707,7 +10876,7 @@ index 0000000000..8b4cd10488 + static int __netdev_upper_dev_link(struct net_device *dev, + struct net_device *upper_dev, bool master, + void *upper_priv, void *upper_info, -+@@ -8126,6 +8171,7 @@ static int __netdev_upper_dev_link(struc ++@@ -8128,6 +8173,7 @@ static int __netdev_upper_dev_link(struc + if (ret) + return ret; + @@ -11715,7 +10884,7 @@ index 0000000000..8b4cd10488 + ret = call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, + &changeupper_info.info); + ret = notifier_to_errno(ret); -+@@ -8222,6 +8268,7 @@ static void __netdev_upper_dev_unlink(st ++@@ -8224,6 +8270,7 @@ static void __netdev_upper_dev_unlink(st + + __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev); + @@ -11723,7 +10892,7 @@ index 0000000000..8b4cd10488 + call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, + &changeupper_info.info); + -+@@ -9041,6 +9088,7 @@ int dev_set_mac_address(struct net_devic ++@@ -9043,6 +9090,7 @@ int dev_set_mac_address(struct net_devic + if (err) + return err; + dev->addr_assign_type = NET_ADDR_SET; @@ -11860,10 +11029,10 @@ index 0000000000..fe6faddc7d + EXPORT_SYMBOL(of_get_mac_address); diff --git a/target/linux/generic/pending-5.15/683-of_net-add-mac-address-to-of-tree.patch b/target/linux/generic/pending-5.15/683-of_net-add-mac-address-to-of-tree.patch new file mode 100644 -index 0000000000..742d58b708 +index 0000000000..f7ef06a14a --- /dev/null +++ b/target/linux/generic/pending-5.15/683-of_net-add-mac-address-to-of-tree.patch -@@ -0,0 +1,59 @@ +@@ -0,0 +1,55 @@ +From 8585756342caa6d27008d1ad0c18023e4211a40a Mon Sep 17 00:00:00 2001 +From: OpenWrt community <openwrt-devel@lists.openwrt.org> +Date: Wed, 13 Jul 2022 12:22:48 +0200 @@ -11881,11 +11050,9 @@ index 0000000000..742d58b708 + net/core/of_net.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + -+diff --git a/net/core/of_net.c b/net/core/of_net.c -+index 71c38b532f72..43b28c8ddff9 100644 +--- a/net/core/of_net.c ++++ b/net/core/of_net.c -+@@ -95,6 +95,27 @@ static int of_get_mac_addr_nvmem(struct device_node *np, u8 *addr) ++@@ -95,6 +95,27 @@ static int of_get_mac_addr_nvmem(struct + return 0; + } + @@ -11913,7 +11080,7 @@ index 0000000000..742d58b708 + /** + * of_get_mac_address() + * @np: Caller's Device Node -+@@ -175,6 +196,7 @@ int of_get_mac_address(struct device_node *np, u8 *addr) ++@@ -175,6 +196,7 @@ found: + addr[5] = (mac_val >> 0) & 0xff; + } + @@ -11921,11 +11088,203 @@ index 0000000000..742d58b708 + return ret; + } + EXPORT_SYMBOL(of_get_mac_address); -+-- +diff --git a/target/linux/generic/pending-5.15/684-of_net-do-mac-address-increment-only-once.patch b/target/linux/generic/pending-5.15/684-of_net-do-mac-address-increment-only-once.patch +new file mode 100644 +index 0000000000..44d88e31a2 +--- /dev/null ++++ b/target/linux/generic/pending-5.15/684-of_net-do-mac-address-increment-only-once.patch +@@ -0,0 +1,31 @@ ++From dd07dd394d8bfdb5d527fab18ca54f20815ec4e4 Mon Sep 17 00:00:00 2001 ++From: Will Moss <willormos@gmail.com> ++Date: Wed, 3 Aug 2022 13:48:55 +0000 ++Subject: [PATCH] of_net: do mac-address-increment only once ++ ++Remove mac-address-increment and mac-address-increment-byte ++DT property after incrementing process to make sure MAC address ++would not get incremented more if this function is stared again. ++It could happen if device initialization is deferred after ++unsuccessful attempt. ++ ++Signed-off-by: Will Moss <willormos@gmail.com> ++--- ++ drivers/of/of_net.c | 6 ++++++ ++ 1 file changed, 6 insertions(+) ++ ++--- a/net/core/of_net.c +++++ b/net/core/of_net.c ++@@ -194,6 +194,12 @@ found: ++ addr[3] = (mac_val >> 16) & 0xff; ++ addr[4] = (mac_val >> 8) & 0xff; ++ addr[5] = (mac_val >> 0) & 0xff; +++ +++ /* Remove mac-address-increment and mac-address-increment-byte +++ * DT property to make sure MAC address would not get incremented +++ * more if this function is stared again. */ +++ of_remove_property(np, of_find_property(np, "mac-address-increment", NULL)); +++ of_remove_property(np, of_find_property(np, "mac-address-increment-byte", NULL)); ++ } ++ ++ of_add_mac_address(np, addr); +diff --git a/target/linux/generic/pending-5.15/700-netfilter-nft_flow_offload-handle-netdevice-events-f.patch b/target/linux/generic/pending-5.15/700-netfilter-nft_flow_offload-handle-netdevice-events-f.patch +new file mode 100644 +index 0000000000..488c6a8d92 +--- /dev/null ++++ b/target/linux/generic/pending-5.15/700-netfilter-nft_flow_offload-handle-netdevice-events-f.patch +@@ -0,0 +1,106 @@ ++From: Pablo Neira Ayuso <pablo@netfilter.org> ++Date: Thu, 25 Jan 2018 12:58:55 +0100 ++Subject: [PATCH] netfilter: nft_flow_offload: handle netdevice events from ++ nf_flow_table ++ ++Move the code that deals with device events to the core. ++ ++Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> ++--- ++ ++--- a/net/netfilter/nf_flow_table_core.c +++++ b/net/netfilter/nf_flow_table_core.c ++@@ -613,13 +613,41 @@ void nf_flow_table_free(struct nf_flowta ++ } ++ EXPORT_SYMBOL_GPL(nf_flow_table_free); ++ +++static int nf_flow_table_netdev_event(struct notifier_block *this, +++ unsigned long event, void *ptr) +++{ +++ struct net_device *dev = netdev_notifier_info_to_dev(ptr); +++ +++ if (event != NETDEV_DOWN) +++ return NOTIFY_DONE; +++ +++ nf_flow_table_cleanup(dev); +++ +++ return NOTIFY_DONE; +++} +++ +++static struct notifier_block flow_offload_netdev_notifier = { +++ .notifier_call = nf_flow_table_netdev_event, +++}; +++ ++ static int __init nf_flow_table_module_init(void) ++ { ++- return nf_flow_table_offload_init(); +++ int ret; +++ +++ ret = nf_flow_table_offload_init(); +++ if (ret) +++ return ret; +++ +++ ret = register_netdevice_notifier(&flow_offload_netdev_notifier); +++ if (ret) +++ nf_flow_table_offload_exit(); +++ +++ return ret; ++ } ++ ++ static void __exit nf_flow_table_module_exit(void) ++ { +++ unregister_netdevice_notifier(&flow_offload_netdev_notifier); ++ nf_flow_table_offload_exit(); ++ } ++ ++--- a/net/netfilter/nft_flow_offload.c +++++ b/net/netfilter/nft_flow_offload.c ++@@ -444,47 +444,14 @@ static struct nft_expr_type nft_flow_off ++ .owner = THIS_MODULE, ++ }; ++ ++-static int flow_offload_netdev_event(struct notifier_block *this, ++- unsigned long event, void *ptr) ++-{ ++- struct net_device *dev = netdev_notifier_info_to_dev(ptr); ++- ++- if (event != NETDEV_DOWN) ++- return NOTIFY_DONE; ++- ++- nf_flow_table_cleanup(dev); ++- ++- return NOTIFY_DONE; ++-} ++- ++-static struct notifier_block flow_offload_netdev_notifier = { ++- .notifier_call = flow_offload_netdev_event, ++-}; ++- ++ static int __init nft_flow_offload_module_init(void) ++ { ++- int err; ++- ++- err = register_netdevice_notifier(&flow_offload_netdev_notifier); ++- if (err) ++- goto err; ++- ++- err = nft_register_expr(&nft_flow_offload_type); ++- if (err < 0) ++- goto register_expr; ++- ++- return 0; ++- ++-register_expr: ++- unregister_netdevice_notifier(&flow_offload_netdev_notifier); ++-err: ++- return err; +++ return nft_register_expr(&nft_flow_offload_type); ++ } ++ ++ static void __exit nft_flow_offload_module_exit(void) ++ { ++ nft_unregister_expr(&nft_flow_offload_type); ++- unregister_netdevice_notifier(&flow_offload_netdev_notifier); ++ } ++ ++ module_init(nft_flow_offload_module_init); +diff --git a/target/linux/generic/pending-5.15/701-netfilter-nf_flow_table-add-missing-locking.patch b/target/linux/generic/pending-5.15/701-netfilter-nf_flow_table-add-missing-locking.patch +new file mode 100644 +index 0000000000..9ff393a8b7 +--- /dev/null ++++ b/target/linux/generic/pending-5.15/701-netfilter-nf_flow_table-add-missing-locking.patch +@@ -0,0 +1,39 @@ ++From: Felix Fietkau <nbd@nbd.name> ++Date: Sat, 19 Nov 2022 18:48:42 +0100 ++Subject: [PATCH] netfilter: nf_flow_table: add missing locking ++ ++nf_flow_table_block_setup and the driver TC_SETUP_FT call can modify the flow ++block cb list while they are being traversed elsewhere, causing a crash. ++Add a write lock around the calls to protect readers ++ ++Signed-off-by: Felix Fietkau <nbd@nbd.name> ++--- + ++--- a/net/netfilter/nf_flow_table_offload.c +++++ b/net/netfilter/nf_flow_table_offload.c ++@@ -1074,6 +1074,7 @@ static int nf_flow_table_block_setup(str ++ struct flow_block_cb *block_cb, *next; ++ int err = 0; ++ +++ down_write(&flowtable->flow_block_lock); ++ switch (cmd) { ++ case FLOW_BLOCK_BIND: ++ list_splice(&bo->cb_list, &flowtable->flow_block.cb_list); ++@@ -1088,6 +1089,7 @@ static int nf_flow_table_block_setup(str ++ WARN_ON_ONCE(1); ++ err = -EOPNOTSUPP; ++ } +++ up_write(&flowtable->flow_block_lock); ++ ++ return err; ++ } ++@@ -1144,7 +1146,9 @@ static int nf_flow_table_offload_cmd(str ++ ++ nf_flow_table_block_offload_init(bo, dev_net(dev), cmd, flowtable, ++ extack); +++ down_write(&flowtable->flow_block_lock); ++ err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_FT, bo); +++ up_write(&flowtable->flow_block_lock); ++ if (err < 0) ++ return err; ++ diff --git a/target/linux/generic/pending-5.15/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch b/target/linux/generic/pending-5.15/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch new file mode 100644 -index 0000000000..4b5c474204 +index 0000000000..3e1486962c --- /dev/null +++ b/target/linux/generic/pending-5.15/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch @@ -0,0 +1,41 @@ @@ -11941,7 +11300,7 @@ index 0000000000..4b5c474204 + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+@@ -2443,8 +2443,8 @@ static irqreturn_t mtk_handle_irq_rx(int ++@@ -2802,8 +2802,8 @@ static irqreturn_t mtk_handle_irq_rx(int + + eth->rx_events++; + if (likely(napi_schedule_prep(ð->rx_napi))) { @@ -11951,7 +11310,7 @@ index 0000000000..4b5c474204 + } + + return IRQ_HANDLED; -+@@ -2456,8 +2456,8 @@ static irqreturn_t mtk_handle_irq_tx(int ++@@ -2815,8 +2815,8 @@ static irqreturn_t mtk_handle_irq_tx(int + + eth->tx_events++; + if (likely(napi_schedule_prep(ð->tx_napi))) { @@ -11961,18 +11320,18 @@ index 0000000000..4b5c474204 + } + + return IRQ_HANDLED; -+@@ -3623,6 +3623,8 @@ static int mtk_probe(struct platform_dev ++@@ -4118,6 +4118,8 @@ static int mtk_probe(struct platform_dev + * for NAPI to work + */ + init_dummy_netdev(ð->dummy_dev); ++ eth->dummy_dev.threaded = 1; ++ strcpy(eth->dummy_dev.name, "mtk_eth"); + netif_napi_add(ð->dummy_dev, ð->tx_napi, mtk_napi_tx, -+ MTK_NAPI_WEIGHT); ++ NAPI_POLL_WEIGHT); + netif_napi_add(ð->dummy_dev, ð->rx_napi, mtk_napi_rx, diff --git a/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch b/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch new file mode 100644 -index 0000000000..21c322b4f1 +index 0000000000..976239c128 --- /dev/null +++ b/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch @@ -0,0 +1,38 @@ @@ -11989,7 +11348,7 @@ index 0000000000..21c322b4f1 + +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c -+@@ -1738,6 +1738,9 @@ void phy_detach(struct phy_device *phyde ++@@ -1746,6 +1746,9 @@ void phy_detach(struct phy_device *phyde + struct module *ndev_owner = NULL; + struct mii_bus *bus; + @@ -12001,7 +11360,7 @@ index 0000000000..21c322b4f1 + sysfs_remove_link(&dev->dev.kobj, "phydev"); +--- a/include/linux/phy.h ++++ b/include/linux/phy.h -+@@ -789,6 +789,12 @@ struct phy_driver { ++@@ -823,6 +823,12 @@ struct phy_driver { + /** @handle_interrupt: Override default interrupt handling */ + irqreturn_t (*handle_interrupt)(struct phy_device *phydev); + @@ -12229,3105 +11588,6639 @@ index 0000000000..2a2ca7f1fa + nla_nest_cancel(skb, protinfo); + goto nla_put_failure; + } -diff --git a/target/linux/generic/pending-5.15/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch b/target/linux/generic/pending-5.15/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch +diff --git a/target/linux/generic/pending-5.15/721-net-phy-realtek-rtl8221-allow-to-configure-SERDES-mo.patch b/target/linux/generic/pending-5.15/721-net-phy-realtek-rtl8221-allow-to-configure-SERDES-mo.patch new file mode 100644 -index 0000000000..662b956e4c +index 0000000000..703a0b8b72 --- /dev/null -+++ b/target/linux/generic/pending-5.15/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch -@@ -0,0 +1,27 @@ -+From: Tobias Waldekranz <tobias@waldekranz.com> -+Subject: [RFC net-next 7/7] net: dsa: mv88e6xxx: Request assisted learning on CPU port -+Date: Sat, 16 Jan 2021 02:25:15 +0100 -+Archived-At: <https://lore.kernel.org/netdev/20210116012515.3152-8-tobias@waldekranz.com/> ++++ b/target/linux/generic/pending-5.15/721-net-phy-realtek-rtl8221-allow-to-configure-SERDES-mo.patch +@@ -0,0 +1,101 @@ ++From ace6abaa0f9203083fe4c0a6a74da2d96410b625 Mon Sep 17 00:00:00 2001 ++From: Alexander Couzens <lynxis@fe80.eu> ++Date: Sat, 13 Aug 2022 12:49:33 +0200 ++Subject: [PATCH 01/10] net: phy: realtek: rtl8221: allow to configure SERDES ++ mode ++ ++The rtl8221 supports multiple SERDES modes: ++- SGMII ++- 2500base-x ++- HiSGMII ++ ++Further it supports rate adaption on SERDES links to allow ++slow ethernet speeds (10/100/1000mbit) to work on 2500base-x/HiSGMII ++links without reducing the SERDES speed. ++ ++When operating without rate adapters the SERDES link will follow the ++ethernet speed. ++ ++Signed-off-by: Alexander Couzens <lynxis@fe80.eu> ++--- ++ drivers/net/phy/realtek.c | 48 +++++++++++++++++++++++++++++++++++++++ ++ 1 file changed, 48 insertions(+) ++ ++--- a/drivers/net/phy/realtek.c +++++ b/drivers/net/phy/realtek.c ++@@ -53,6 +53,15 @@ ++ RTL8201F_ISR_LINK) ++ #define RTL8201F_IER 0x13 ++ +++#define RTL8221B_MMD_SERDES_CTRL MDIO_MMD_VEND1 +++#define RTL8221B_MMD_PHY_CTRL MDIO_MMD_VEND2 +++#define RTL8221B_SERDES_OPTION 0x697a +++#define RTL8221B_SERDES_OPTION_MODE_MASK GENMASK(5, 0) +++#define RTL8221B_SERDES_OPTION_MODE_2500BASEX_SGMII 0 +++#define RTL8221B_SERDES_OPTION_MODE_HISGMII_SGMII 1 +++#define RTL8221B_SERDES_OPTION_MODE_2500BASEX 2 +++#define RTL8221B_SERDES_OPTION_MODE_HISGMII 3 +++ ++ #define RTL8366RB_POWER_SAVE 0x15 ++ #define RTL8366RB_POWER_SAVE_ON BIT(12) ++ ++@@ -841,6 +850,43 @@ static irqreturn_t rtl9000a_handle_inter ++ return IRQ_HANDLED; ++ } ++ +++static int rtl8221b_config_init(struct phy_device *phydev) +++{ +++ u16 option_mode; +++ +++ switch (phydev->interface) { +++ case PHY_INTERFACE_MODE_SGMII: +++ case PHY_INTERFACE_MODE_2500BASEX: +++ option_mode = RTL8221B_SERDES_OPTION_MODE_2500BASEX_SGMII; +++ break; +++ default: +++ return 0; +++ } +++ +++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, +++ 0x75f3, 0); +++ +++ phy_modify_mmd_changed(phydev, RTL8221B_MMD_SERDES_CTRL, +++ RTL8221B_SERDES_OPTION, +++ RTL8221B_SERDES_OPTION_MODE_MASK, option_mode); +++ switch (option_mode) { +++ case RTL8221B_SERDES_OPTION_MODE_2500BASEX_SGMII: +++ case RTL8221B_SERDES_OPTION_MODE_2500BASEX: +++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6a04, 0x0503); +++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6f10, 0xd455); +++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6f11, 0x8020); +++ break; +++ case RTL8221B_SERDES_OPTION_MODE_HISGMII_SGMII: +++ case RTL8221B_SERDES_OPTION_MODE_HISGMII: +++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6a04, 0x0503); +++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6f10, 0xd433); +++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6f11, 0x8020); +++ break; +++ } +++ +++ return 0; +++} +++ ++ static struct phy_driver realtek_drvs[] = { ++ { ++ PHY_ID_MATCH_EXACT(0x00008201), ++@@ -981,6 +1027,7 @@ static struct phy_driver realtek_drvs[] ++ PHY_ID_MATCH_EXACT(0x001cc849), ++ .name = "RTL8221B-VB-CG 2.5Gbps PHY", ++ .get_features = rtl822x_get_features, +++ .config_init = rtl8221b_config_init, ++ .config_aneg = rtl822x_config_aneg, ++ .read_status = rtl822x_read_status, ++ .suspend = genphy_suspend, ++@@ -992,6 +1039,7 @@ static struct phy_driver realtek_drvs[] ++ .name = "RTL8221B-VM-CG 2.5Gbps PHY", ++ .get_features = rtl822x_get_features, ++ .config_aneg = rtl822x_config_aneg, +++ .config_init = rtl8221b_config_init, ++ .read_status = rtl822x_read_status, ++ .suspend = genphy_suspend, ++ .resume = rtlgen_resume, +diff --git a/target/linux/generic/pending-5.15/723-net-mt7531-ensure-all-MACs-are-powered-down-before-r.patch b/target/linux/generic/pending-5.15/723-net-mt7531-ensure-all-MACs-are-powered-down-before-r.patch +new file mode 100644 +index 0000000000..cc12d72110 +--- /dev/null ++++ b/target/linux/generic/pending-5.15/723-net-mt7531-ensure-all-MACs-are-powered-down-before-r.patch +@@ -0,0 +1,28 @@ ++From 3fb8841513c4ec3a2e5d366df86230c45f239a57 Mon Sep 17 00:00:00 2001 ++From: Alexander Couzens <lynxis@fe80.eu> ++Date: Sat, 13 Aug 2022 13:08:22 +0200 ++Subject: [PATCH 03/10] net: mt7531: ensure all MACs are powered down before ++ reset + -+While the hardware is capable of performing learning on the CPU port, -+it requires alot of additions to the bridge's forwarding path in order -+to handle multi-destination traffic correctly. ++The datasheet [1] explicit describes it as requirement for a reset. + -+Until that is in place, opt for the next best thing and let DSA sync -+the relevant addresses down to the hardware FDB. ++[1] MT7531 Reference Manual for Development Board rev 1.0, page 735 + -+Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com> ++Signed-off-by: Alexander Couzens <lynxis@fe80.eu> +--- -+ drivers/net/dsa/mv88e6xxx/chip.c | 1 + -+ 1 file changed, 1 insertion(+) ++ drivers/net/dsa/mt7530.c | 4 ++++ ++ 1 file changed, 4 insertions(+) + -+--- a/drivers/net/dsa/mv88e6xxx/chip.c -++++ b/drivers/net/dsa/mv88e6xxx/chip.c -+@@ -6320,6 +6320,7 @@ static int mv88e6xxx_register_switch(str -+ ds->ops = &mv88e6xxx_switch_ops; -+ ds->ageing_time_min = chip->info->age_time_coeff; -+ ds->ageing_time_max = chip->info->age_time_coeff * U8_MAX; -++ ds->assisted_learning_on_cpu_port = true; ++--- a/drivers/net/dsa/mt7530.c +++++ b/drivers/net/dsa/mt7530.c ++@@ -2324,6 +2324,10 @@ mt7531_setup(struct dsa_switch *ds) ++ return -ENODEV; ++ } + -+ /* Some chips support up to 32, but that requires enabling the -+ * 5-bit port mode, which we do not support. 640k^W16 ought to -diff --git a/target/linux/generic/pending-5.15/780-ARM-kirkwood-add-missing-linux-if_ether.h-for-ETH_AL.patch b/target/linux/generic/pending-5.15/780-ARM-kirkwood-add-missing-linux-if_ether.h-for-ETH_AL.patch +++ /* all MACs must be forced link-down before sw reset */ +++ for (i = 0; i < MT7530_NUM_PORTS; i++) +++ mt7530_write(priv, MT7530_PMCR_P(i), MT7531_FORCE_LNK); +++ ++ /* Reset the switch through internal reset */ ++ mt7530_write(priv, MT7530_SYS_CTRL, ++ SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST | +diff --git a/target/linux/generic/pending-5.15/724-net-mtk_sgmii-implement-mtk_pcs_ops.patch b/target/linux/generic/pending-5.15/724-net-mtk_sgmii-implement-mtk_pcs_ops.patch new file mode 100644 -index 0000000000..fcf7892c04 +index 0000000000..cd97706658 --- /dev/null -+++ b/target/linux/generic/pending-5.15/780-ARM-kirkwood-add-missing-linux-if_ether.h-for-ETH_AL.patch -@@ -0,0 +1,61 @@ -+From patchwork Thu Aug 5 22:23:30 2021 -+Content-Type: text/plain; charset="utf-8" -+MIME-Version: 1.0 -+Content-Transfer-Encoding: 7bit -+X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org> -+X-Patchwork-Id: 12422209 -+Date: Thu, 5 Aug 2021 23:23:30 +0100 -+From: Daniel Golle <daniel@makrotopia.org> -+To: linux-arm-kernel@lists.infradead.org, netdev@vger.kernel.org, -+ linux-kernel@vger.kernel.org -+Cc: "David S. Miller" <davem@davemloft.net>, Andrew Lunn <andrew@lunn.ch>, -+ Michael Walle <michael@walle.cc> -+Subject: [PATCH] ARM: kirkwood: add missing <linux/if_ether.h> for ETH_ALEN -+Message-ID: <YQxk4jrbm31NM1US@makrotopia.org> -+MIME-Version: 1.0 -+Content-Disposition: inline -+X-BeenThere: linux-arm-kernel@lists.infradead.org -+X-Mailman-Version: 2.1.34 -+Precedence: list -+List-Id: <linux-arm-kernel.lists.infradead.org> -+List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/> -+Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org> ++++ b/target/linux/generic/pending-5.15/724-net-mtk_sgmii-implement-mtk_pcs_ops.patch +@@ -0,0 +1,46 @@ ++From cbfed00575d15eafd85efd9619b7ecc0836a4aa7 Mon Sep 17 00:00:00 2001 ++From: Alexander Couzens <lynxis@fe80.eu> ++Date: Sat, 13 Aug 2022 14:42:12 +0200 ++Subject: [PATCH 04/10] net: mtk_sgmii: implement mtk_pcs_ops ++ ++Implement mtk_pcs_ops for the SGMII pcs to read the current state ++of the hardware. ++ ++Signed-off-by: Alexander Couzens <lynxis@fe80.eu> ++[added DUPLEX_FULL] ++Signed-off-by: Daniel Golle <daniel@makrotopia.org> ++--- ++ drivers/net/ethernet/mediatek/mtk_sgmii.c | 15 +++++++++++++++ ++ 1 file changed, 15 insertions(+) + -+After commit 83216e3988cd1 ("of: net: pass the dst buffer to -+of_get_mac_address()") build fails for kirkwood as ETH_ALEN is not -+defined. ++--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c +++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c ++@@ -122,10 +122,28 @@ static void mtk_pcs_link_up(struct phyli ++ regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val); ++ } ++ +++static void mtk_pcs_get_state(struct phylink_pcs *pcs, struct phylink_link_state *state) +++{ +++ struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); +++ unsigned int val; +++ +++ regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val); +++ state->an_complete = !!(val & SGMII_AN_COMPLETE); +++ state->link = !!(val & SGMII_LINK_STATYS); +++ if (!state->link) +++ return; +++ +++ regmap_read(mpcs->regmap, mpcs->ana_rgc3, &val); +++ state->speed = val & RG_PHY_SPEED_3_125G ? SPEED_2500 : SPEED_1000; +++ state->duplex = DUPLEX_FULL; +++ state->pause = 0; +++} +++ ++ static const struct phylink_pcs_ops mtk_pcs_ops = { ++ .pcs_config = mtk_pcs_config, ++ .pcs_an_restart = mtk_pcs_restart_an, ++ .pcs_link_up = mtk_pcs_link_up, +++ .pcs_get_state = mtk_pcs_get_state, ++ }; ++ ++ int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3) +diff --git a/target/linux/generic/pending-5.15/725-net-mtk_sgmii-fix-powering-up-the-SGMII-phy.patch b/target/linux/generic/pending-5.15/725-net-mtk_sgmii-fix-powering-up-the-SGMII-phy.patch +new file mode 100644 +index 0000000000..0fa357d48f +--- /dev/null ++++ b/target/linux/generic/pending-5.15/725-net-mtk_sgmii-fix-powering-up-the-SGMII-phy.patch +@@ -0,0 +1,39 @@ ++From 7f75f43fe2159123baa101fcc8c6faa0b0a4c598 Mon Sep 17 00:00:00 2001 ++From: Alexander Couzens <lynxis@fe80.eu> ++Date: Sat, 13 Aug 2022 14:48:51 +0200 ++Subject: [PATCH 05/10] net: mtk_sgmii: fix powering up the SGMII phy + -+arch/arm/mach-mvebu/kirkwood.c: In function 'kirkwood_dt_eth_fixup': -+arch/arm/mach-mvebu/kirkwood.c:87:13: error: 'ETH_ALEN' undeclared (first use in this function); did you mean 'ESTALE'? -+ u8 tmpmac[ETH_ALEN]; -+ ^~~~~~~~ -+ ESTALE -+arch/arm/mach-mvebu/kirkwood.c:87:13: note: each undeclared identifier is reported only once for each function it appears in -+arch/arm/mach-mvebu/kirkwood.c:87:6: warning: unused variable 'tmpmac' [-Wunused-variable] -+ u8 tmpmac[ETH_ALEN]; -+ ^~~~~~ -+make[5]: *** [scripts/Makefile.build:262: arch/arm/mach-mvebu/kirkwood.o] Error 1 -+make[5]: *** Waiting for unfinished jobs.... ++There are certain race condition when the SGMII_PHYA_PWD register still ++contains 0x9 which prevents the SGMII from working properly. + -+Add missing #include <linux/if_ether.h> to fix this. ++The SGMII still shows link but no traffic can flow. + -+Cc: David S. Miller <davem@davemloft.net> -+Cc: Andrew Lunn <andrew@lunn.ch> -+Cc: Michael Walle <michael@walle.cc> -+Reported-by: https://buildbot.openwrt.org/master/images/#/builders/56/builds/220/steps/44/logs/stdio -+Fixes: 83216e3988cd1 ("of: net: pass the dst buffer to of_get_mac_address()") -+Signed-off-by: Daniel Golle <daniel@makrotopia.org> ++Signed-off-by: Alexander Couzens <lynxis@fe80.eu> +--- -+ arch/arm/mach-mvebu/kirkwood.c | 1 + -+ 1 file changed, 1 insertion(+) ++ drivers/net/ethernet/mediatek/mtk_sgmii.c | 8 ++------ ++ 1 file changed, 2 insertions(+), 6 deletions(-) + -+--- a/arch/arm/mach-mvebu/kirkwood.c -++++ b/arch/arm/mach-mvebu/kirkwood.c -+@@ -14,6 +14,7 @@ -+ #include <linux/kernel.h> -+ #include <linux/init.h> -+ #include <linux/mbus.h> -++#include <linux/if_ether.h> -+ #include <linux/of.h> -+ #include <linux/of_address.h> -+ #include <linux/of_net.h> -diff --git a/target/linux/generic/pending-5.15/800-bcma-get-SoC-device-struct-copy-its-DMA-params-to-th.patch b/target/linux/generic/pending-5.15/800-bcma-get-SoC-device-struct-copy-its-DMA-params-to-th.patch ++--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c +++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c ++@@ -36,9 +36,7 @@ static int mtk_pcs_setup_mode_an(struct ++ val |= SGMII_AN_RESTART; ++ regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val); ++ ++- regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val); ++- val &= ~SGMII_PHYA_PWD; ++- regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val); +++ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0); ++ ++ return 0; ++ ++@@ -70,9 +68,7 @@ static int mtk_pcs_setup_mode_force(stru ++ regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val); ++ ++ /* Release PHYA power down state */ ++- regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val); ++- val &= ~SGMII_PHYA_PWD; ++- regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val); +++ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0); ++ ++ return 0; ++ } +diff --git a/target/linux/generic/pending-5.15/726-net-mtk_sgmii-ensure-the-SGMII-PHY-is-powered-down-o.patch b/target/linux/generic/pending-5.15/726-net-mtk_sgmii-ensure-the-SGMII-PHY-is-powered-down-o.patch new file mode 100644 -index 0000000000..478a2cb27d +index 0000000000..329b41cf03 --- /dev/null -+++ b/target/linux/generic/pending-5.15/800-bcma-get-SoC-device-struct-copy-its-DMA-params-to-th.patch -@@ -0,0 +1,73 @@ -+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl> -+Subject: [PATCH] bcma: get SoC device struct & copy its DMA params to the -+ subdevices -+MIME-Version: 1.0 -+Content-Type: text/plain; charset=UTF-8 -+Content-Transfer-Encoding: 8bit -+ -+For bus devices to be fully usable it's required to set their DMA -+parameters. -+ -+For years it has been missing and remained unnoticed because of -+mips_dma_alloc_coherent() silently handling the empty coherent_dma_mask. -+Kernel 4.19 came with a lot of DMA changes and caused a regression on -+the bcm47xx. Starting with the commit f8c55dc6e828 ("MIPS: use generic -+dma noncoherent ops for simple noncoherent platforms") DMA coherent -+allocations just fail. Example: -+[ 1.114914] bgmac_bcma bcma0:2: Allocation of TX ring 0x200 failed -+[ 1.121215] bgmac_bcma bcma0:2: Unable to alloc memory for DMA -+[ 1.127626] bgmac_bcma: probe of bcma0:2 failed with error -12 -+[ 1.133838] bgmac_bcma: Broadcom 47xx GBit MAC driver loaded -+ -+This change fixes above regression in addition to the MIPS bcm47xx -+commit 321c46b91550 ("MIPS: BCM47XX: Setup struct device for the SoC"). -+ -+It also fixes another *old* GPIO regression caused by a parent pointing -+to the NULL: -+[ 0.157054] missing gpiochip .dev parent pointer -+[ 0.157287] bcma: bus0: Error registering GPIO driver: -22 -+introduced by the commit 74f4e0cc6108 ("bcma: switch GPIO portions to -+use GPIOLIB_IRQCHIP"). ++++ b/target/linux/generic/pending-5.15/726-net-mtk_sgmii-ensure-the-SGMII-PHY-is-powered-down-o.patch +@@ -0,0 +1,65 @@ ++From 9daea9b71d060d93d7394ac465b2e5ee0b7e7bca Mon Sep 17 00:00:00 2001 ++From: Alexander Couzens <lynxis@fe80.eu> ++Date: Mon, 15 Aug 2022 16:02:01 +0200 ++Subject: [PATCH 06/10] net: mtk_sgmii: ensure the SGMII PHY is powered down on ++ configuration + -+Fixes: f8c55dc6e828 ("MIPS: use generic dma noncoherent ops for simple noncoherent platforms") -+Fixes: 74f4e0cc6108 ("bcma: switch GPIO portions to use GPIOLIB_IRQCHIP") -+Cc: linux-mips@linux-mips.org -+Cc: Christoph Hellwig <hch@lst.de> -+Cc: Linus Walleij <linus.walleij@linaro.org> -+Signed-off-by: RafaÅ‚ MiÅ‚ecki <rafal@milecki.pl> ++The code expect the PHY to be in power down (which is only true after reset). ++Allow the changes of SGMII parameters more than once. +--- ++ drivers/net/ethernet/mediatek/mtk_sgmii.c | 16 +++++++++++++++- ++ 1 file changed, 15 insertions(+), 1 deletion(-) + -+--- a/drivers/bcma/host_soc.c -++++ b/drivers/bcma/host_soc.c -+@@ -191,6 +191,8 @@ int __init bcma_host_soc_init(struct bcm -+ struct bcma_bus *bus = &soc->bus; -+ int err; ++--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c +++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c ++@@ -7,6 +7,7 @@ ++ * ++ */ + -++ bus->dev = soc->dev; +++#include <linux/delay.h> ++ #include <linux/mfd/syscon.h> ++ #include <linux/of.h> ++ #include <linux/phylink.h> ++@@ -24,6 +25,9 @@ static int mtk_pcs_setup_mode_an(struct ++ { ++ unsigned int val; ++ +++ /* PHYA power down */ +++ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, SGMII_PHYA_PWD); ++ -+ /* Scan bus and initialize it */ -+ err = bcma_bus_early_register(bus); -+ if (err) -+--- a/drivers/bcma/main.c -++++ b/drivers/bcma/main.c -+@@ -236,13 +236,17 @@ EXPORT_SYMBOL(bcma_core_irq); ++ /* Setup the link timer and QPHY power up inside SGMIISYS */ ++ regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, ++ SGMII_LINK_TIMER_DEFAULT); ++@@ -36,6 +40,10 @@ static int mtk_pcs_setup_mode_an(struct ++ val |= SGMII_AN_RESTART; ++ regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val); + -+ void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core) +++ /* Release PHYA power down state +++ * unknown how much the QPHY needs but it is racy without a sleep +++ */ +++ usleep_range(50, 100); ++ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0); ++ ++ return 0; ++@@ -50,6 +58,9 @@ static int mtk_pcs_setup_mode_force(stru + { -+- device_initialize(&core->dev); -++ struct device *dev = &core->dev; ++ unsigned int val; ++ +++ /* PHYA power down */ +++ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, SGMII_PHYA_PWD); ++ -++ device_initialize(dev); -+ core->dev.release = bcma_release_core_dev; -+ core->dev.bus = &bcma_bus_type; -+- dev_set_name(&core->dev, "bcma%d:%d", bus->num, core->core_index); -++ dev_set_name(dev, "bcma%d:%d", bus->num, core->core_index); -+ core->dev.parent = bus->dev; -+- if (bus->dev) -++ if (bus->dev) { -+ bcma_of_fill_device(bus->dev, core); -++ dma_coerce_mask_and_coherent(dev, bus->dev->coherent_dma_mask); -++ } ++ regmap_read(mpcs->regmap, mpcs->ana_rgc3, &val); ++ val &= ~RG_PHY_SPEED_MASK; ++ if (interface == PHY_INTERFACE_MODE_2500BASEX) ++@@ -67,7 +78,10 @@ static int mtk_pcs_setup_mode_force(stru ++ val |= SGMII_SPEED_1000; ++ regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val); + -+ switch (bus->hosttype) { -+ case BCMA_HOSTTYPE_PCI: -diff --git a/target/linux/generic/pending-5.15/801-gpio-gpio-cascade-add-generic-GPIO-cascade.patch b/target/linux/generic/pending-5.15/801-gpio-gpio-cascade-add-generic-GPIO-cascade.patch ++- /* Release PHYA power down state */ +++ /* Release PHYA power down state +++ * unknown how much the QPHY needs but it is racy without a sleep +++ */ +++ usleep_range(50, 100); ++ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0); ++ ++ return 0; +diff --git a/target/linux/generic/pending-5.15/727-net-mtk_sgmii-mtk_pcs_setup_mode_an-don-t-rely-on-re.patch b/target/linux/generic/pending-5.15/727-net-mtk_sgmii-mtk_pcs_setup_mode_an-don-t-rely-on-re.patch new file mode 100644 -index 0000000000..c1e14b9271 +index 0000000000..5bc187cfc8 --- /dev/null -+++ b/target/linux/generic/pending-5.15/801-gpio-gpio-cascade-add-generic-GPIO-cascade.patch -@@ -0,0 +1,222 @@ -+From fc23ea48ba52c24f201fe5ca0132ee1a3de5a70a Mon Sep 17 00:00:00 2001 -+From: Mauri Sandberg <maukka@ext.kapsi.fi> -+Date: Thu, 25 Mar 2021 11:48:05 +0200 -+Subject: [PATCH 2/2] gpio: gpio-cascade: add generic GPIO cascade ++++ b/target/linux/generic/pending-5.15/727-net-mtk_sgmii-mtk_pcs_setup_mode_an-don-t-rely-on-re.patch +@@ -0,0 +1,31 @@ ++From e4dca7affb8c03438b63bdb5fddefd6ad2431cfd Mon Sep 17 00:00:00 2001 ++From: Alexander Couzens <lynxis@fe80.eu> ++Date: Mon, 15 Aug 2022 14:59:29 +0200 ++Subject: [PATCH 07/10] net: mtk_sgmii: mtk_pcs_setup_mode_an: don't rely on ++ register defaults + -+Adds support for building cascades of GPIO lines. That is, it allows -+setups when there is one upstream line and multiple cascaded lines, out -+of which one can be chosen at a time. The status of the upstream line -+can be conveyed to the selected cascaded line or, vice versa, the status -+of the cascaded line can be conveyed to the upstream line. ++Ensure autonegotiation is enabled. + -+A multiplexer is being used to select, which cascaded GPIO line is being -+used at any given time. ++Signed-off-by: Alexander Couzens <lynxis@fe80.eu> ++--- ++ drivers/net/ethernet/mediatek/mtk_sgmii.c | 5 +++-- ++ 1 file changed, 3 insertions(+), 2 deletions(-) ++ ++--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c +++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c ++@@ -32,12 +32,13 @@ static int mtk_pcs_setup_mode_an(struct ++ regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, ++ SGMII_LINK_TIMER_DEFAULT); ++ +++ /* disable remote fault & enable auto neg */ ++ regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val); ++- val |= SGMII_REMOTE_FAULT_DIS; +++ val |= SGMII_REMOTE_FAULT_DIS | SGMII_SPEED_DUPLEX_AN; ++ regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val); ++ ++ regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val); ++- val |= SGMII_AN_RESTART; +++ val |= SGMII_AN_RESTART | SGMII_AN_ENABLE; ++ regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val); ++ ++ /* Release PHYA power down state +diff --git a/target/linux/generic/pending-5.15/728-net-mtk_sgmii-set-the-speed-according-to-the-phy-int.patch b/target/linux/generic/pending-5.15/728-net-mtk_sgmii-set-the-speed-according-to-the-phy-int.patch +new file mode 100644 +index 0000000000..0b17f77eef +--- /dev/null ++++ b/target/linux/generic/pending-5.15/728-net-mtk_sgmii-set-the-speed-according-to-the-phy-int.patch +@@ -0,0 +1,47 @@ ++From 952b64575613d26163a5afa5ff8bfdb57840091b Mon Sep 17 00:00:00 2001 ++From: Alexander Couzens <lynxis@fe80.eu> ++Date: Mon, 15 Aug 2022 15:00:14 +0200 ++Subject: [PATCH 08/10] net: mtk_sgmii: set the speed according to the phy ++ interface in AN ++ ++The non auto-negotioting code path is setting the correct speed for the ++interface. Ensure auto-negotiation code path is doing it as well. ++ ++Signed-off-by: Alexander Couzens <lynxis@fe80.eu> ++--- ++ drivers/net/ethernet/mediatek/mtk_sgmii.c | 11 +++++++++-- ++ 1 file changed, 9 insertions(+), 2 deletions(-) + -+At the moment only input direction is supported. In future it should be -+possible to add support for output direction, too. ++--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c +++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c ++@@ -21,13 +21,20 @@ static struct mtk_pcs *pcs_to_mtk_pcs(st ++ } ++ ++ /* For SGMII interface mode */ ++-static int mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs) +++static int mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs, phy_interface_t interface) ++ { ++ unsigned int val; ++ ++ /* PHYA power down */ ++ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, SGMII_PHYA_PWD); ++ +++ /* Set SGMII phy speed */ +++ regmap_read(mpcs->regmap, mpcs->ana_rgc3, &val); +++ val &= ~RG_PHY_SPEED_MASK; +++ if (interface == PHY_INTERFACE_MODE_2500BASEX) +++ val |= RG_PHY_SPEED_3_125G; +++ regmap_write(mpcs->regmap, mpcs->ana_rgc3, val); +++ ++ /* Setup the link timer and QPHY power up inside SGMIISYS */ ++ regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, ++ SGMII_LINK_TIMER_DEFAULT); ++@@ -100,7 +107,7 @@ static int mtk_pcs_config(struct phylink ++ if (interface != PHY_INTERFACE_MODE_SGMII) ++ err = mtk_pcs_setup_mode_force(mpcs, interface); ++ else if (phylink_autoneg_inband(mode)) ++- err = mtk_pcs_setup_mode_an(mpcs); +++ err = mtk_pcs_setup_mode_an(mpcs, interface); ++ ++ return err; ++ } +diff --git a/target/linux/generic/pending-5.15/729-net-mtk_eth_soc-improve-comment.patch b/target/linux/generic/pending-5.15/729-net-mtk_eth_soc-improve-comment.patch +new file mode 100644 +index 0000000000..80144850ec +--- /dev/null ++++ b/target/linux/generic/pending-5.15/729-net-mtk_eth_soc-improve-comment.patch +@@ -0,0 +1,22 @@ ++From 06773f19cffd6c9d34dcbc8320169afef5ab60ba Mon Sep 17 00:00:00 2001 ++From: Alexander Couzens <lynxis@fe80.eu> ++Date: Mon, 15 Aug 2022 13:58:07 +0200 ++Subject: [PATCH 09/10] net: mtk_eth_soc: improve comment + -+Signed-off-by: Mauri Sandberg <maukka@ext.kapsi.fi> -+Reviewed-by: Linus Walleij <linus.walleij@linaro.org> -+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com> ++Signed-off-by: Alexander Couzens <lynxis@fe80.eu> +--- -+v7 -> v8: -+ - rearrange members in struct gpio_cascade -+ - cosmetic changes in file header and in one function declaration -+ - added Reviewed-by tags by Linus and Andy -+v6 -> v7: -+ - In Kconfig add info about module name -+ - adhere to new convention that allows lines longer than 80 chars -+ - use dev_probe_err with upstream gpio line too -+ - refactor for cleaner exit of probe function. -+v5 -> v6: -+ - In Kconfig, remove dependency to OF_GPIO and select only MULTIPLEXER -+ - refactor code preferring one-liners -+ - clean up prints, removing them from success-path. -+ - don't explicitly set gpio_chip.of_node as it's done in the GPIO library -+ - use devm_gpiochip_add_data instead of gpiochip_add -+v4 -> v5: -+ - renamed gpio-mux-input -> gpio-cascade. refactored code accordingly -+ here and there and changed to use new bindings and compatible string -+ - ambigious and vague 'pin' was rename to 'upstream_line' -+ - dropped Tested-by and Reviewed-by due to changes in bindings -+ - dropped Reported-by suggested by an automatic bot as it was not really -+ appropriate to begin with -+ - functionally it's the same as v4 -+v3 -> v4: -+ - Changed author email -+ - Included Tested-by and Reviewed-by from Drew -+v2 -> v3: -+ - use managed device resources -+ - update Kconfig description -+v1 -> v2: -+ - removed .owner from platform_driver as per test bot's instruction -+ - added MODULE_AUTHOR, MODULE_DESCRIPTION, MODULE_LICENSE -+ - added gpio_mux_input_get_direction as it's recommended for all chips -+ - removed because this is input only chip: gpio_mux_input_set_value -+ - removed because they are not needed for input/output only chips: -+ gpio_mux_input_direction_input -+ gpio_mux_input_direction_output -+ - fixed typo in an error message -+ - added info message about successful registration -+ - removed can_sleep flag as this does not sleep while getting GPIO value -+ like I2C or SPI do -+ - Updated description in Kconfig ++ drivers/net/ethernet/mediatek/mtk_sgmii.c | 3 ++- ++ 1 file changed, 2 insertions(+), 1 deletion(-) ++ ++--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c +++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c ++@@ -80,7 +80,8 @@ static int mtk_pcs_setup_mode_force(stru ++ val &= ~SGMII_AN_ENABLE; ++ regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val); ++ ++- /* Set the speed etc but leave the duplex unchanged */ +++ /* Set the speed etc but leave the duplex unchanged. +++ * The SGMII mode for 2.5gbit is the same as for 1gbit, expect the speed in ANA_RGC3 */ ++ regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val); ++ val &= SGMII_DUPLEX_FULL | ~SGMII_IF_MODE_MASK; ++ val |= SGMII_SPEED_1000; +diff --git a/target/linux/generic/pending-5.15/730-mtk_sgmii-enable-PCS-polling-to-allow-SFP-work.patch b/target/linux/generic/pending-5.15/730-mtk_sgmii-enable-PCS-polling-to-allow-SFP-work.patch +new file mode 100644 +index 0000000000..d185aed7bd +--- /dev/null ++++ b/target/linux/generic/pending-5.15/730-mtk_sgmii-enable-PCS-polling-to-allow-SFP-work.patch +@@ -0,0 +1,23 @@ ++From 95dcd0f223d7cab6e25bc19088016e5eb4ca1804 Mon Sep 17 00:00:00 2001 ++From: Alexander Couzens <lynxis@fe80.eu> ++Date: Tue, 16 Aug 2022 00:22:11 +0200 ++Subject: [PATCH 10/10] mtk_sgmii: enable PCS polling to allow SFP work ++ ++Currently there is no IRQ handling (even the SGMII supports it). ++Enable polling to support SFP ports. ++ ++Signed-off-by: Alexander Couzens <lynxis@fe80.eu> +--- -+ drivers/gpio/Kconfig | 15 +++++ -+ drivers/gpio/Makefile | 1 + -+ drivers/gpio/gpio-cascade.c | 117 ++++++++++++++++++++++++++++++++++++ -+ 3 files changed, 133 insertions(+) -+ create mode 100644 drivers/gpio/gpio-cascade.c ++ drivers/net/ethernet/mediatek/mtk_sgmii.c | 1 + ++ 1 file changed, 1 insertion(+) + -+--- a/drivers/gpio/Kconfig -++++ b/drivers/gpio/Kconfig -+@@ -1683,4 +1683,19 @@ config GPIO_VIRTIO ++--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c +++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c ++@@ -182,6 +182,7 @@ int mtk_sgmii_init(struct mtk_sgmii *ss, ++ return PTR_ERR(ss->pcs[i].regmap); + -+ endmenu ++ ss->pcs[i].pcs.ops = &mtk_pcs_ops; +++ ss->pcs[i].pcs.poll = 1; ++ } + -++comment "Other GPIO expanders" ++ return 0; +diff --git a/target/linux/generic/pending-5.15/731-net-ethernet-mediatek-ppe-add-support-for-flow-accou.patch b/target/linux/generic/pending-5.15/731-net-ethernet-mediatek-ppe-add-support-for-flow-accou.patch +new file mode 100644 +index 0000000000..8bf036d006 +--- /dev/null ++++ b/target/linux/generic/pending-5.15/731-net-ethernet-mediatek-ppe-add-support-for-flow-accou.patch +@@ -0,0 +1,409 @@ ++From patchwork Wed Nov 2 00:58:01 2022 ++Content-Type: text/plain; charset="utf-8" ++MIME-Version: 1.0 ++Content-Transfer-Encoding: 7bit ++X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org> ++X-Patchwork-Id: 13027653 ++X-Patchwork-Delegate: kuba@kernel.org ++Return-Path: <netdev-owner@kernel.org> ++Date: Wed, 2 Nov 2022 00:58:01 +0000 ++From: Daniel Golle <daniel@makrotopia.org> ++To: Felix Fietkau <nbd@nbd.name>, John Crispin <john@phrozen.org>, ++ Sean Wang <sean.wang@mediatek.com>, ++ Mark Lee <Mark-MC.Lee@mediatek.com>, ++ "David S. Miller" <davem@davemloft.net>, ++ Eric Dumazet <edumazet@google.com>, ++ Jakub Kicinski <kuba@kernel.org>, ++ Paolo Abeni <pabeni@redhat.com>, ++ Matthias Brugger <matthias.bgg@gmail.com>, ++ netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, ++ linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org ++Subject: [PATCH v4] net: ethernet: mediatek: ppe: add support for flow ++ accounting ++Message-ID: <Y2HAmYYPd77dz+K5@makrotopia.org> ++MIME-Version: 1.0 ++Content-Disposition: inline ++Precedence: bulk ++List-ID: <netdev.vger.kernel.org> ++X-Mailing-List: netdev@vger.kernel.org ++X-Patchwork-Delegate: kuba@kernel.org ++ ++The PPE units found in MT7622 and newer support packet and byte ++accounting of hw-offloaded flows. Add support for reading those ++counters as found in MediaTek's SDK[1]. ++ ++[1]: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/bc6a6a375c800dc2b80e1a325a2c732d1737df92 ++Signed-off-by: Daniel Golle <daniel@makrotopia.org> ++--- ++v4: declare function mtk_mib_entry_read as static ++v3: don't bother to set 'false' values in any zero-initialized struct ++ use mtk_foe_entry_ib2 ++ both changes were requested by Felix Fietkau ++ ++v2: fix wrong variable name in return value check spotted by Denis Kirjanov ++ ++ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 7 +- ++ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 + ++ drivers/net/ethernet/mediatek/mtk_ppe.c | 110 +++++++++++++++++- ++ drivers/net/ethernet/mediatek/mtk_ppe.h | 23 +++- ++ .../net/ethernet/mediatek/mtk_ppe_debugfs.c | 9 +- ++ .../net/ethernet/mediatek/mtk_ppe_offload.c | 7 ++ ++ drivers/net/ethernet/mediatek/mtk_ppe_regs.h | 14 +++ ++ 7 files changed, 166 insertions(+), 5 deletions(-) ++ ++--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++@@ -4088,7 +4088,9 @@ static int mtk_probe(struct platform_dev ++ u32 ppe_addr = eth->soc->reg_map->ppe_base + i * 0x400; ++ ++ eth->ppe[i] = mtk_ppe_init(eth, eth->base + ppe_addr, ++- eth->soc->offload_version, i); +++ eth->soc->offload_version, i, +++ eth->soc->has_accounting); +++ ++ if (!eth->ppe[i]) { ++ err = -ENOMEM; ++ goto err_free_dev; ++@@ -4211,6 +4213,7 @@ static const struct mtk_soc_data mt7622_ ++ .required_pctl = false, ++ .offload_version = 2, ++ .hash_offset = 2, +++ .has_accounting = true, ++ .foe_entry_size = sizeof(struct mtk_foe_entry) - 16, ++ .txrx = { ++ .txd_size = sizeof(struct mtk_tx_dma), ++@@ -4248,6 +4251,7 @@ static const struct mtk_soc_data mt7629_ ++ .hw_features = MTK_HW_FEATURES, ++ .required_clks = MT7629_CLKS_BITMAP, ++ .required_pctl = false, +++ .has_accounting = true, ++ .txrx = { ++ .txd_size = sizeof(struct mtk_tx_dma), ++ .rxd_size = sizeof(struct mtk_rx_dma), ++@@ -4268,6 +4272,7 @@ static const struct mtk_soc_data mt7986_ ++ .offload_version = 2, ++ .hash_offset = 4, ++ .foe_entry_size = sizeof(struct mtk_foe_entry), +++ .has_accounting = true, ++ .txrx = { ++ .txd_size = sizeof(struct mtk_tx_dma_v2), ++ .rxd_size = sizeof(struct mtk_rx_dma_v2), ++--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++@@ -983,6 +983,7 @@ struct mtk_soc_data { ++ u8 hash_offset; ++ u16 foe_entry_size; ++ netdev_features_t hw_features; +++ bool has_accounting; ++ struct { ++ u32 txd_size; ++ u32 rxd_size; ++--- a/drivers/net/ethernet/mediatek/mtk_ppe.c +++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c ++@@ -74,6 +74,46 @@ static int mtk_ppe_wait_busy(struct mtk_ ++ return ret; ++ } ++ +++static int mtk_ppe_mib_wait_busy(struct mtk_ppe *ppe) +++{ +++ int ret; +++ u32 val; ++ -++config GPIO_CASCADE -++ tristate "General GPIO cascade" -++ select MULTIPLEXER -++ help -++ Say yes here to enable support for generic GPIO cascade. +++ ret = readl_poll_timeout(ppe->base + MTK_PPE_MIB_SER_CR, val, +++ !(val & MTK_PPE_MIB_SER_CR_ST), +++ 20, MTK_PPE_WAIT_TIMEOUT_US); ++ -++ This allows building one-to-many cascades of GPIO lines using -++ different types of multiplexers readily available. At the -++ moment only input lines are supported. +++ if (ret) +++ dev_err(ppe->dev, "MIB table busy"); ++ -++ To build the driver as a module choose 'm' and the resulting module -++ will be called 'gpio-cascade'. +++ return ret; +++} ++ -+ endif -+--- a/drivers/gpio/Makefile -++++ b/drivers/gpio/Makefile -+@@ -45,6 +45,7 @@ obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd -+ obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o -+ obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o -+ obj-$(CONFIG_GPIO_CADENCE) += gpio-cadence.o -++obj-$(CONFIG_GPIO_CASCADE) += gpio-cascade.o -+ obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o -+ obj-$(CONFIG_GPIO_SNPS_CREG) += gpio-creg-snps.o -+ obj-$(CONFIG_GPIO_CRYSTAL_COVE) += gpio-crystalcove.o -+--- /dev/null -++++ b/drivers/gpio/gpio-cascade.c -+@@ -0,0 +1,117 @@ -++// SPDX-License-Identifier: GPL-2.0-only -++/* -++ * A generic GPIO cascade driver -++ * -++ * Copyright (C) 2021 Mauri Sandberg <maukka@ext.kapsi.fi> -++ * -++ * This allows building cascades of GPIO lines in a manner illustrated -++ * below: -++ * -++ * /|---- Cascaded GPIO line 0 -++ * Upstream | |---- Cascaded GPIO line 1 -++ * GPIO line ----+ | . -++ * | | . -++ * \|---- Cascaded GPIO line n -++ * -++ * A multiplexer is being used to select, which cascaded line is being -++ * addressed at any given time. -++ * -++ * At the moment only input mode is supported due to lack of means for -++ * testing output functionality. At least theoretically output should be -++ * possible with open drain constructions. -++ */ +++static int mtk_mib_entry_read(struct mtk_ppe *ppe, u16 index, u64 *bytes, u64 *packets) +++{ +++ u32 val, cnt_r0, cnt_r1, cnt_r2; +++ u32 byte_cnt_low, byte_cnt_high, pkt_cnt_low, pkt_cnt_high; ++ -++#include <linux/module.h> -++#include <linux/slab.h> -++#include <linux/platform_device.h> -++#include <linux/mux/consumer.h> +++ val = FIELD_PREP(MTK_PPE_MIB_SER_CR_ADDR, index) | MTK_PPE_MIB_SER_CR_ST; +++ ppe_w32(ppe, MTK_PPE_MIB_SER_CR, val); ++ -++#include <linux/gpio/consumer.h> -++#include <linux/gpio/driver.h> +++ if (mtk_ppe_mib_wait_busy(ppe)) +++ return -ETIMEDOUT; ++ -++struct gpio_cascade { -++ struct gpio_chip gpio_chip; -++ struct device *parent; -++ struct mux_control *mux_control; -++ struct gpio_desc *upstream_line; -++}; +++ cnt_r0 = readl(ppe->base + MTK_PPE_MIB_SER_R0); +++ cnt_r1 = readl(ppe->base + MTK_PPE_MIB_SER_R1); +++ cnt_r2 = readl(ppe->base + MTK_PPE_MIB_SER_R2); ++ -++static struct gpio_cascade *chip_to_cascade(struct gpio_chip *gc) -++{ -++ return container_of(gc, struct gpio_cascade, gpio_chip); -++} +++ byte_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW, cnt_r0); +++ byte_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH, cnt_r1); +++ pkt_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R1_PKT_CNT_LOW, cnt_r1); +++ pkt_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH, cnt_r2); +++ *bytes = ((u64)byte_cnt_high << 32) | byte_cnt_low; +++ *packets = (pkt_cnt_high << 16) | pkt_cnt_low; ++ -++static int gpio_cascade_get_direction(struct gpio_chip *gc, unsigned int offset) -++{ -++ return GPIO_LINE_DIRECTION_IN; +++ return 0; ++} ++ -++static int gpio_cascade_get_value(struct gpio_chip *gc, unsigned int offset) ++ static void mtk_ppe_cache_clear(struct mtk_ppe *ppe) ++ { ++ ppe_set(ppe, MTK_PPE_CACHE_CTL, MTK_PPE_CACHE_CTL_CLEAR); ++@@ -444,6 +484,13 @@ __mtk_foe_entry_clear(struct mtk_ppe *pp ++ hwe->ib1 &= ~MTK_FOE_IB1_STATE; ++ hwe->ib1 |= FIELD_PREP(MTK_FOE_IB1_STATE, MTK_FOE_STATE_INVALID); ++ dma_wmb(); +++ if (ppe->accounting) { +++ struct mtk_foe_accounting *acct; +++ +++ acct = ppe->acct_table + entry->hash * sizeof(*acct); +++ acct->packets = 0; +++ acct->bytes = 0; +++ } ++ } ++ entry->hash = 0xffff; ++ ++@@ -551,6 +598,9 @@ __mtk_foe_entry_commit(struct mtk_ppe *p ++ wmb(); ++ hwe->ib1 = entry->ib1; ++ +++ if (ppe->accounting) +++ *mtk_foe_entry_ib2(eth, hwe) |= MTK_FOE_IB2_MIB_CNT; +++ ++ dma_wmb(); ++ ++ mtk_ppe_cache_clear(ppe); ++@@ -716,14 +766,42 @@ int mtk_foe_entry_idle_time(struct mtk_p ++ return __mtk_foe_entry_idle_time(ppe, entry->data.ib1); ++ } ++ +++struct mtk_foe_accounting *mtk_foe_entry_get_mib(struct mtk_ppe *ppe, u32 index, +++ struct mtk_foe_accounting *diff) ++{ -++ struct gpio_cascade *cas = chip_to_cascade(gc); -++ int ret; +++ struct mtk_foe_accounting *acct; +++ int size = sizeof(struct mtk_foe_accounting); +++ u64 bytes, packets; ++ -++ ret = mux_control_select(cas->mux_control, offset); -++ if (ret) -++ return ret; +++ if (!ppe->accounting) +++ return NULL; ++ -++ ret = gpiod_get_value(cas->upstream_line); -++ mux_control_deselect(cas->mux_control); -++ return ret; +++ if (mtk_mib_entry_read(ppe, index, &bytes, &packets)) +++ return NULL; +++ +++ acct = ppe->acct_table + index * size; +++ +++ acct->bytes += bytes; +++ acct->packets += packets; +++ +++ if (diff) { +++ diff->bytes = bytes; +++ diff->packets = packets; +++ } +++ +++ return acct; ++} ++ -++static int gpio_cascade_probe(struct platform_device *pdev) -++{ -++ struct device *dev = &pdev->dev; -++ struct gpio_cascade *cas; -++ struct mux_control *mc; -++ struct gpio_desc *upstream; -++ struct gpio_chip *gc; ++ struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, ++- int version, int index) +++ int version, int index, bool accounting) ++ { ++ const struct mtk_soc_data *soc = eth->soc; ++ struct device *dev = eth->dev; ++ struct mtk_ppe *ppe; ++ u32 foe_flow_size; ++ void *foe; +++ struct mtk_mib_entry *mib; +++ struct mtk_foe_accounting *acct; ++ ++ ppe = devm_kzalloc(dev, sizeof(*ppe), GFP_KERNEL); ++ if (!ppe) ++@@ -738,6 +816,7 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_ ++ ppe->eth = eth; ++ ppe->dev = dev; ++ ppe->version = version; +++ ppe->accounting = accounting; ++ ++ foe = dmam_alloc_coherent(ppe->dev, ++ MTK_PPE_ENTRIES * soc->foe_entry_size, ++@@ -753,6 +832,25 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_ ++ if (!ppe->foe_flow) ++ return NULL; ++ +++ if (accounting) { +++ mib = dmam_alloc_coherent(ppe->dev, MTK_PPE_ENTRIES * sizeof(*mib), +++ &ppe->mib_phys, GFP_KERNEL); +++ if (!mib) +++ return NULL; +++ +++ memset(mib, 0, MTK_PPE_ENTRIES * sizeof(*mib)); +++ +++ ppe->mib_table = mib; +++ +++ acct = devm_kzalloc(dev, MTK_PPE_ENTRIES * sizeof(*acct), +++ GFP_KERNEL); +++ +++ if (!acct) +++ return NULL; +++ +++ ppe->acct_table = acct; +++ } ++ -++ cas = devm_kzalloc(dev, sizeof(*cas), GFP_KERNEL); -++ if (!cas) -++ return -ENOMEM; ++ mtk_ppe_debugfs_init(ppe, index); ++ ++ return ppe; ++@@ -867,6 +965,16 @@ void mtk_ppe_start(struct mtk_ppe *ppe) ++ ppe_w32(ppe, MTK_PPE_DEFAULT_CPU_PORT1, 0xcb777); ++ ppe_w32(ppe, MTK_PPE_SBW_CTRL, 0x7f); ++ } ++ -++ mc = devm_mux_control_get(dev, NULL); -++ if (IS_ERR(mc)) -++ return dev_err_probe(dev, PTR_ERR(mc), "unable to get mux-control\n"); +++ if (ppe->accounting && ppe->mib_phys) { +++ ppe_w32(ppe, MTK_PPE_MIB_TB_BASE, ppe->mib_phys); +++ ppe_m32(ppe, MTK_PPE_MIB_CFG, MTK_PPE_MIB_CFG_EN, +++ MTK_PPE_MIB_CFG_EN); +++ ppe_m32(ppe, MTK_PPE_MIB_CFG, MTK_PPE_MIB_CFG_RD_CLR, +++ MTK_PPE_MIB_CFG_RD_CLR); +++ ppe_m32(ppe, MTK_PPE_MIB_CACHE_CTL, MTK_PPE_MIB_CACHE_CTL_EN, +++ MTK_PPE_MIB_CFG_RD_CLR); +++ } ++ } ++ ++ int mtk_ppe_stop(struct mtk_ppe *ppe) ++--- a/drivers/net/ethernet/mediatek/mtk_ppe.h +++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h ++@@ -57,6 +57,7 @@ enum { ++ #define MTK_FOE_IB2_MULTICAST BIT(8) ++ ++ #define MTK_FOE_IB2_WDMA_QID2 GENMASK(13, 12) +++#define MTK_FOE_IB2_MIB_CNT BIT(15) ++ #define MTK_FOE_IB2_WDMA_DEVIDX BIT(16) ++ #define MTK_FOE_IB2_WDMA_WINFO BIT(17) ++ ++@@ -284,16 +285,34 @@ struct mtk_flow_entry { ++ unsigned long cookie; ++ }; ++ +++struct mtk_mib_entry { +++ u32 byt_cnt_l; +++ u16 byt_cnt_h; +++ u32 pkt_cnt_l; +++ u8 pkt_cnt_h; +++ u8 _rsv0; +++ u32 _rsv1; +++} __packed; +++ +++struct mtk_foe_accounting { +++ u64 bytes; +++ u64 packets; +++}; ++ -++ cas->mux_control = mc; -++ upstream = devm_gpiod_get(dev, "upstream", GPIOD_IN); -++ if (IS_ERR(upstream)) -++ return dev_err_probe(dev, PTR_ERR(upstream), "unable to claim upstream GPIO line\n"); ++ struct mtk_ppe { ++ struct mtk_eth *eth; ++ struct device *dev; ++ void __iomem *base; ++ int version; ++ char dirname[5]; +++ bool accounting; ++ ++ void *foe_table; ++ dma_addr_t foe_phys; ++ +++ struct mtk_mib_entry *mib_table; +++ dma_addr_t mib_phys; ++ -++ cas->upstream_line = upstream; -++ cas->parent = dev; ++ u16 foe_check_time[MTK_PPE_ENTRIES]; ++ struct hlist_head *foe_flow; ++ ++@@ -303,7 +322,7 @@ struct mtk_ppe { ++ }; ++ ++ struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, ++- int version, int index); +++ int version, int index, bool accounting); ++ void mtk_ppe_start(struct mtk_ppe *ppe); ++ int mtk_ppe_stop(struct mtk_ppe *ppe); ++ ++@@ -354,5 +373,7 @@ int mtk_foe_entry_commit(struct mtk_ppe ++ void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); ++ int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); ++ int mtk_ppe_debugfs_init(struct mtk_ppe *ppe, int index); +++struct mtk_foe_accounting *mtk_foe_entry_get_mib(struct mtk_ppe *ppe, u32 index, +++ struct mtk_foe_accounting *diff); ++ ++ #endif ++--- a/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c +++++ b/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c ++@@ -82,6 +82,7 @@ mtk_ppe_debugfs_foe_show(struct seq_file ++ struct mtk_foe_entry *entry = mtk_foe_get_entry(ppe, i); ++ struct mtk_foe_mac_info *l2; ++ struct mtk_flow_addr_info ai = {}; +++ struct mtk_foe_accounting *acct; ++ unsigned char h_source[ETH_ALEN]; ++ unsigned char h_dest[ETH_ALEN]; ++ int type, state; ++@@ -95,6 +96,8 @@ mtk_ppe_debugfs_foe_show(struct seq_file ++ if (bind && state != MTK_FOE_STATE_BIND) ++ continue; ++ +++ acct = mtk_foe_entry_get_mib(ppe, i, NULL); +++ ++ type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1); ++ seq_printf(m, "%05x %s %7s", i, ++ mtk_foe_entry_state_str(state), ++@@ -153,9 +156,11 @@ mtk_ppe_debugfs_foe_show(struct seq_file ++ *((__be16 *)&h_dest[4]) = htons(l2->dest_mac_lo); ++ ++ seq_printf(m, " eth=%pM->%pM etype=%04x" ++- " vlan=%d,%d ib1=%08x ib2=%08x\n", +++ " vlan=%d,%d ib1=%08x ib2=%08x" +++ " packets=%lld bytes=%lld\n", ++ h_source, h_dest, ntohs(l2->etype), ++- l2->vlan1, l2->vlan2, entry->ib1, ib2); +++ l2->vlan1, l2->vlan2, entry->ib1, ib2, +++ acct->packets, acct->bytes); ++ } ++ ++ return 0; ++--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++@@ -491,6 +491,7 @@ static int ++ mtk_flow_offload_stats(struct mtk_eth *eth, struct flow_cls_offload *f) ++ { ++ struct mtk_flow_entry *entry; +++ struct mtk_foe_accounting diff; ++ u32 idle; ++ ++ entry = rhashtable_lookup(ð->flow_table, &f->cookie, ++@@ -501,6 +502,12 @@ mtk_flow_offload_stats(struct mtk_eth *e ++ idle = mtk_foe_entry_idle_time(eth->ppe[entry->ppe_index], entry); ++ f->stats.lastused = jiffies - idle * HZ; ++ +++ if (entry->hash != 0xFFFF) { +++ mtk_foe_entry_get_mib(eth->ppe[entry->ppe_index], entry->hash, &diff); +++ f->stats.pkts += diff.packets; +++ f->stats.bytes += diff.bytes; +++ } ++ -++ gc = &cas->gpio_chip; -++ gc->get = gpio_cascade_get_value; -++ gc->get_direction = gpio_cascade_get_direction; -++ gc->base = -1; -++ gc->ngpio = mux_control_states(mc); -++ gc->label = dev_name(cas->parent); -++ gc->parent = cas->parent; -++ gc->owner = THIS_MODULE; ++ return 0; ++ } ++ ++--- a/drivers/net/ethernet/mediatek/mtk_ppe_regs.h +++++ b/drivers/net/ethernet/mediatek/mtk_ppe_regs.h ++@@ -143,6 +143,20 @@ enum { ++ ++ #define MTK_PPE_MIB_TB_BASE 0x338 ++ +++#define MTK_PPE_MIB_SER_CR 0x33C +++#define MTK_PPE_MIB_SER_CR_ST BIT(16) +++#define MTK_PPE_MIB_SER_CR_ADDR GENMASK(13, 0) ++ -++ platform_set_drvdata(pdev, cas); -++ return devm_gpiochip_add_data(dev, &cas->gpio_chip, NULL); -++} +++#define MTK_PPE_MIB_SER_R0 0x340 +++#define MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW GENMASK(31, 0) ++ -++static const struct of_device_id gpio_cascade_id[] = { -++ { .compatible = "gpio-cascade" }, -++ { /* sentinel */ } -++}; -++MODULE_DEVICE_TABLE(of, gpio_cascade_id); +++#define MTK_PPE_MIB_SER_R1 0x344 +++#define MTK_PPE_MIB_SER_R1_PKT_CNT_LOW GENMASK(31, 16) +++#define MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH GENMASK(15, 0) ++ -++static struct platform_driver gpio_cascade_driver = { -++ .driver = { -++ .name = "gpio-cascade", -++ .of_match_table = gpio_cascade_id, -++ }, -++ .probe = gpio_cascade_probe, -++}; -++module_platform_driver(gpio_cascade_driver); +++#define MTK_PPE_MIB_SER_R2 0x348 +++#define MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH GENMASK(23, 0) ++ -++MODULE_AUTHOR("Mauri Sandberg <maukka@ext.kapsi.fi>"); -++MODULE_DESCRIPTION("Generic GPIO cascade"); -++MODULE_LICENSE("GPL"); -diff --git a/target/linux/generic/pending-5.15/810-pci_disable_common_quirks.patch b/target/linux/generic/pending-5.15/810-pci_disable_common_quirks.patch ++ #define MTK_PPE_MIB_CACHE_CTL 0x350 ++ #define MTK_PPE_MIB_CACHE_CTL_EN BIT(0) ++ #define MTK_PPE_MIB_CACHE_CTL_FLUSH BIT(2) +diff --git a/target/linux/generic/pending-5.15/732-01-net-ethernet-mtk_eth_soc-account-for-vlan-in-rx-head.patch b/target/linux/generic/pending-5.15/732-01-net-ethernet-mtk_eth_soc-account-for-vlan-in-rx-head.patch new file mode 100644 -index 0000000000..7edbd94f76 +index 0000000000..45af898cf0 --- /dev/null -+++ b/target/linux/generic/pending-5.15/810-pci_disable_common_quirks.patch -@@ -0,0 +1,62 @@ -+From: Gabor Juhos <juhosg@openwrt.org> -+Subject: debloat: add kernel config option to disabling common PCI quirks ++++ b/target/linux/generic/pending-5.15/732-01-net-ethernet-mtk_eth_soc-account-for-vlan-in-rx-head.patch +@@ -0,0 +1,22 @@ ++From: Felix Fietkau <nbd@nbd.name> ++Date: Thu, 27 Oct 2022 19:50:31 +0200 ++Subject: [PATCH] net: ethernet: mtk_eth_soc: account for vlan in rx ++ header length + -+Signed-off-by: Gabor Juhos <juhosg@openwrt.org> ++The network stack assumes that devices can handle an extra VLAN tag without ++increasing the MTU ++ ++Signed-off-by: Felix Fietkau <nbd@nbd.name> +--- -+ drivers/pci/Kconfig | 6 ++++++ -+ drivers/pci/quirks.c | 6 ++++++ -+ 2 files changed, 12 insertions(+) + -+--- a/drivers/pci/Kconfig -++++ b/drivers/pci/Kconfig -+@@ -118,6 +118,13 @@ config XEN_PCIDEV_FRONTEND -+ The PCI device frontend driver allows the kernel to import arbitrary -+ PCI devices from a PCI backend to support PCI driver domains. ++--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++@@ -29,7 +29,7 @@ ++ #define MTK_TX_DMA_BUF_LEN_V2 0xffff ++ #define MTK_DMA_SIZE 512 ++ #define MTK_MAC_COUNT 2 ++-#define MTK_RX_ETH_HLEN (ETH_HLEN + ETH_FCS_LEN) +++#define MTK_RX_ETH_HLEN (VLAN_ETH_HLEN + ETH_FCS_LEN) ++ #define MTK_RX_HLEN (NET_SKB_PAD + MTK_RX_ETH_HLEN + NET_IP_ALIGN) ++ #define MTK_DMA_DUMMY_DESC 0xffffffff ++ #define MTK_DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | \ +diff --git a/target/linux/generic/pending-5.15/732-02-net-ethernet-mtk_eth_soc-increase-tx-ring-side-for-Q.patch b/target/linux/generic/pending-5.15/732-02-net-ethernet-mtk_eth_soc-increase-tx-ring-side-for-Q.patch +new file mode 100644 +index 0000000000..c6526a39a8 +--- /dev/null ++++ b/target/linux/generic/pending-5.15/732-02-net-ethernet-mtk_eth_soc-increase-tx-ring-side-for-Q.patch +@@ -0,0 +1,143 @@ ++From: Felix Fietkau <nbd@nbd.name> ++Date: Thu, 27 Oct 2022 19:53:57 +0200 ++Subject: [PATCH] net: ethernet: mtk_eth_soc: increase tx ring side for ++ QDMA devices ++ ++In order to use the hardware traffic shaper feature, a larger tx ring is ++needed, especially for the scratch ring, which the hardware shaper uses to ++reorder packets. ++ ++Signed-off-by: Felix Fietkau <nbd@nbd.name> ++--- ++ ++--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++@@ -894,7 +894,7 @@ static int mtk_init_fq_dma(struct mtk_et ++ { ++ const struct mtk_soc_data *soc = eth->soc; ++ dma_addr_t phy_ring_tail; ++- int cnt = MTK_DMA_SIZE; +++ int cnt = MTK_QDMA_RING_SIZE; ++ dma_addr_t dma_addr; ++ int i; + -++config PCI_DISABLE_COMMON_QUIRKS -++ bool "PCI disable common quirks" -++ depends on PCI -++ help -++ If you don't know what to do here, say N. -++ -++ -+ config PCI_ATS -+ bool ++@@ -2148,19 +2148,25 @@ static int mtk_tx_alloc(struct mtk_eth * ++ struct mtk_tx_ring *ring = ð->tx_ring; ++ int i, sz = soc->txrx.txd_size; ++ struct mtk_tx_dma_v2 *txd; +++ int ring_size; + -+--- a/drivers/pci/quirks.c -++++ b/drivers/pci/quirks.c -+@@ -206,6 +206,7 @@ static void quirk_mmio_always_on(struct -+ DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_ANY_ID, PCI_ANY_ID, -+ PCI_CLASS_BRIDGE_HOST, 8, quirk_mmio_always_on); ++- ring->buf = kcalloc(MTK_DMA_SIZE, sizeof(*ring->buf), +++ if (MTK_HAS_CAPS(soc->caps, MTK_QDMA)) +++ ring_size = MTK_QDMA_RING_SIZE; +++ else +++ ring_size = MTK_DMA_SIZE; +++ +++ ring->buf = kcalloc(ring_size, sizeof(*ring->buf), ++ GFP_KERNEL); ++ if (!ring->buf) ++ goto no_tx_mem; ++ ++- ring->dma = dma_alloc_coherent(eth->dma_dev, MTK_DMA_SIZE * sz, +++ ring->dma = dma_alloc_coherent(eth->dma_dev, ring_size * sz, ++ &ring->phys, GFP_KERNEL); ++ if (!ring->dma) ++ goto no_tx_mem; ++ ++- for (i = 0; i < MTK_DMA_SIZE; i++) { ++- int next = (i + 1) % MTK_DMA_SIZE; +++ for (i = 0; i < ring_size; i++) { +++ int next = (i + 1) % ring_size; ++ u32 next_ptr = ring->phys + next * sz; ++ ++ txd = ring->dma + i * sz; ++@@ -2180,22 +2186,22 @@ static int mtk_tx_alloc(struct mtk_eth * ++ * descriptors in ring->dma_pdma. ++ */ ++ if (!MTK_HAS_CAPS(soc->caps, MTK_QDMA)) { ++- ring->dma_pdma = dma_alloc_coherent(eth->dma_dev, MTK_DMA_SIZE * sz, +++ ring->dma_pdma = dma_alloc_coherent(eth->dma_dev, ring_size * sz, ++ &ring->phys_pdma, GFP_KERNEL); ++ if (!ring->dma_pdma) ++ goto no_tx_mem; ++ ++- for (i = 0; i < MTK_DMA_SIZE; i++) { +++ for (i = 0; i < ring_size; i++) { ++ ring->dma_pdma[i].txd2 = TX_DMA_DESP2_DEF; ++ ring->dma_pdma[i].txd4 = 0; ++ } ++ } + -++#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS -+ /* -+ * The Mellanox Tavor device gives false positive parity errors. Disable -+ * parity error reporting. -+@@ -3363,6 +3364,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I -+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65f9, quirk_intel_mc_errata); -+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65fa, quirk_intel_mc_errata); ++- ring->dma_size = MTK_DMA_SIZE; ++- atomic_set(&ring->free_count, MTK_DMA_SIZE - 2); +++ ring->dma_size = ring_size; +++ atomic_set(&ring->free_count, ring_size - 2); ++ ring->next_free = ring->dma; ++ ring->last_free = (void *)txd; ++- ring->last_free_ptr = (u32)(ring->phys + ((MTK_DMA_SIZE - 1) * sz)); +++ ring->last_free_ptr = (u32)(ring->phys + ((ring_size - 1) * sz)); ++ ring->thresh = MAX_SKB_FRAGS; ++ ++ /* make sure that all changes to the dma ring are flushed before we ++@@ -2207,14 +2213,14 @@ static int mtk_tx_alloc(struct mtk_eth * ++ mtk_w32(eth, ring->phys, soc->reg_map->qdma.ctx_ptr); ++ mtk_w32(eth, ring->phys, soc->reg_map->qdma.dtx_ptr); ++ mtk_w32(eth, ++- ring->phys + ((MTK_DMA_SIZE - 1) * sz), +++ ring->phys + ((ring_size - 1) * sz), ++ soc->reg_map->qdma.crx_ptr); ++ mtk_w32(eth, ring->last_free_ptr, soc->reg_map->qdma.drx_ptr); ++ mtk_w32(eth, (QDMA_RES_THRES << 8) | QDMA_RES_THRES, ++ soc->reg_map->qdma.qtx_cfg); ++ } else { ++ mtk_w32(eth, ring->phys_pdma, MT7628_TX_BASE_PTR0); ++- mtk_w32(eth, MTK_DMA_SIZE, MT7628_TX_MAX_CNT0); +++ mtk_w32(eth, ring_size, MT7628_TX_MAX_CNT0); ++ mtk_w32(eth, 0, MT7628_TX_CTX_IDX0); ++ mtk_w32(eth, MT7628_PST_DTX_IDX0, soc->reg_map->pdma.rst_idx); ++ } ++@@ -2232,7 +2238,7 @@ static void mtk_tx_clean(struct mtk_eth ++ int i; + -++#endif /* !CONFIG_PCI_DISABLE_COMMON_QUIRKS */ -++ -+ /* -+ * Ivytown NTB BAR sizes are misreported by the hardware due to an erratum. -+ * To work around this, query the size it should be configured to by the -+@@ -3388,6 +3391,8 @@ static void quirk_intel_ntb(struct pci_d -+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0e08, quirk_intel_ntb); -+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0e0d, quirk_intel_ntb); ++ if (ring->buf) { ++- for (i = 0; i < MTK_DMA_SIZE; i++) +++ for (i = 0; i < ring->dma_size; i++) ++ mtk_tx_unmap(eth, &ring->buf[i], false); ++ kfree(ring->buf); ++ ring->buf = NULL; ++@@ -2240,14 +2246,14 @@ static void mtk_tx_clean(struct mtk_eth ++ ++ if (ring->dma) { ++ dma_free_coherent(eth->dma_dev, ++- MTK_DMA_SIZE * soc->txrx.txd_size, +++ ring->dma_size * soc->txrx.txd_size, ++ ring->dma, ring->phys); ++ ring->dma = NULL; ++ } + -++#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS -++ -+ /* -+ * Some BIOS implementations leave the Intel GPU interrupts enabled, even -+ * though no one is handling them (e.g., if the i915 driver is never -+@@ -3426,6 +3431,8 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IN -+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq); -+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0152, disable_igfx_irq); ++ if (ring->dma_pdma) { ++ dma_free_coherent(eth->dma_dev, ++- MTK_DMA_SIZE * soc->txrx.txd_size, +++ ring->dma_size * soc->txrx.txd_size, ++ ring->dma_pdma, ring->phys_pdma); ++ ring->dma_pdma = NULL; ++ } ++@@ -2767,7 +2773,7 @@ static void mtk_dma_free(struct mtk_eth ++ netdev_reset_queue(eth->netdev[i]); ++ if (eth->scratch_ring) { ++ dma_free_coherent(eth->dma_dev, ++- MTK_DMA_SIZE * soc->txrx.txd_size, +++ MTK_QDMA_RING_SIZE * soc->txrx.txd_size, ++ eth->scratch_ring, eth->phy_scratch_ring); ++ eth->scratch_ring = NULL; ++ eth->phy_scratch_ring = 0; ++--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++@@ -27,6 +27,7 @@ ++ #define MTK_MAX_RX_LENGTH_2K 2048 ++ #define MTK_TX_DMA_BUF_LEN 0x3fff ++ #define MTK_TX_DMA_BUF_LEN_V2 0xffff +++#define MTK_QDMA_RING_SIZE 2048 ++ #define MTK_DMA_SIZE 512 ++ #define MTK_MAC_COUNT 2 ++ #define MTK_RX_ETH_HLEN (VLAN_ETH_HLEN + ETH_FCS_LEN) +diff --git a/target/linux/generic/pending-5.15/732-03-net-ethernet-mtk_eth_soc-avoid-port_mg-assignment-on.patch b/target/linux/generic/pending-5.15/732-03-net-ethernet-mtk_eth_soc-avoid-port_mg-assignment-on.patch +new file mode 100644 +index 0000000000..116ae011f0 +--- /dev/null ++++ b/target/linux/generic/pending-5.15/732-03-net-ethernet-mtk_eth_soc-avoid-port_mg-assignment-on.patch +@@ -0,0 +1,52 @@ ++From: Felix Fietkau <nbd@nbd.name> ++Date: Fri, 4 Nov 2022 19:49:08 +0100 ++Subject: [PATCH] net: ethernet: mtk_eth_soc: avoid port_mg assignment on ++ MT7622 and newer ++ ++On newer chips, this field is unused and contains some bits related to queue ++assignment. Initialize it to 0 in those cases. ++Fix offload_version on MT7621 and MT7623, which still need the previous value. ++ ++Signed-off-by: Felix Fietkau <nbd@nbd.name> ++--- ++ ++--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++@@ -4197,7 +4197,7 @@ static const struct mtk_soc_data mt7621_ ++ .hw_features = MTK_HW_FEATURES, ++ .required_clks = MT7621_CLKS_BITMAP, ++ .required_pctl = false, ++- .offload_version = 2, +++ .offload_version = 1, ++ .hash_offset = 2, ++ .foe_entry_size = sizeof(struct mtk_foe_entry) - 16, ++ .txrx = { ++@@ -4237,7 +4237,7 @@ static const struct mtk_soc_data mt7623_ ++ .hw_features = MTK_HW_FEATURES, ++ .required_clks = MT7623_CLKS_BITMAP, ++ .required_pctl = true, ++- .offload_version = 2, +++ .offload_version = 1, ++ .hash_offset = 2, ++ .foe_entry_size = sizeof(struct mtk_foe_entry) - 16, ++ .txrx = { ++--- a/drivers/net/ethernet/mediatek/mtk_ppe.c +++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c ++@@ -215,6 +215,8 @@ int mtk_foe_entry_prepare(struct mtk_eth ++ val = FIELD_PREP(MTK_FOE_IB2_DEST_PORT_V2, pse_port) | ++ FIELD_PREP(MTK_FOE_IB2_PORT_AG_V2, 0xf); ++ } else { +++ int port_mg = eth->soc->offload_version > 1 ? 0 : 0x3f; +++ ++ val = FIELD_PREP(MTK_FOE_IB1_STATE, MTK_FOE_STATE_BIND) | ++ FIELD_PREP(MTK_FOE_IB1_PACKET_TYPE, type) | ++ FIELD_PREP(MTK_FOE_IB1_UDP, l4proto == IPPROTO_UDP) | ++@@ -222,7 +224,7 @@ int mtk_foe_entry_prepare(struct mtk_eth ++ entry->ib1 = val; ++ ++ val = FIELD_PREP(MTK_FOE_IB2_DEST_PORT, pse_port) | ++- FIELD_PREP(MTK_FOE_IB2_PORT_MG, 0x3f) | +++ FIELD_PREP(MTK_FOE_IB2_PORT_MG, port_mg) | ++ FIELD_PREP(MTK_FOE_IB2_PORT_AG, 0x1f); ++ } + -++#endif /* !CONFIG_PCI_DISABLE_COMMON_QUIRKS */ -++ -+ /* -+ * PCI devices which are on Intel chips can skip the 10ms delay -+ * before entering D3 mode. -diff --git a/target/linux/generic/pending-5.15/811-pci_disable_usb_common_quirks.patch b/target/linux/generic/pending-5.15/811-pci_disable_usb_common_quirks.patch +diff --git a/target/linux/generic/pending-5.15/732-04-net-ethernet-mtk_eth_soc-implement-multi-queue-suppo.patch b/target/linux/generic/pending-5.15/732-04-net-ethernet-mtk_eth_soc-implement-multi-queue-suppo.patch new file mode 100644 -index 0000000000..67406bac84 +index 0000000000..fd1898586f --- /dev/null -+++ b/target/linux/generic/pending-5.15/811-pci_disable_usb_common_quirks.patch -@@ -0,0 +1,115 @@ ++++ b/target/linux/generic/pending-5.15/732-04-net-ethernet-mtk_eth_soc-implement-multi-queue-suppo.patch +@@ -0,0 +1,654 @@ +From: Felix Fietkau <nbd@nbd.name> -+Subject: debloat: disable common USB quirks ++Date: Thu, 27 Oct 2022 20:17:27 +0200 ++Subject: [PATCH] net: ethernet: mtk_eth_soc: implement multi-queue ++ support for per-port queues ++ ++When sending traffic to multiple ports with different link speeds, queued ++packets to one port can drown out tx to other ports. ++In order to better handle transmission to multiple ports, use the hardware ++shaper feature to implement weighted fair queueing between ports. ++Weight and maximum rate are automatically adjusted based on the link speed ++of the port. ++The first 3 queues are unrestricted and reserved for non-DSA direct tx on ++GMAC ports. The following queues are automatically assigned by the MTK DSA ++tag driver based on the target port number. ++The PPE offload code configures the queues for offloaded traffic in the same ++way. ++This feature is only supported on devices supporting QDMA. All queues still ++share the same DMA ring and descriptor pool. + +Signed-off-by: Felix Fietkau <nbd@nbd.name> +--- -+ drivers/usb/host/pci-quirks.c | 16 ++++++++++++++++ -+ drivers/usb/host/pci-quirks.h | 18 +++++++++++++++++- -+ include/linux/usb/hcd.h | 7 +++++++ -+ 3 files changed, 40 insertions(+), 1 deletion(-) + -+--- a/drivers/usb/host/pci-quirks.c -++++ b/drivers/usb/host/pci-quirks.c -+@@ -128,6 +128,8 @@ struct amd_chipset_type { -+ u8 rev; -+ }; ++--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++@@ -54,6 +54,7 @@ static const struct mtk_reg_map mtk_reg_ ++ }, ++ .qdma = { ++ .qtx_cfg = 0x1800, +++ .qtx_sch = 0x1804, ++ .rx_ptr = 0x1900, ++ .rx_cnt_cfg = 0x1904, ++ .qcrx_ptr = 0x1908, ++@@ -61,6 +62,7 @@ static const struct mtk_reg_map mtk_reg_ ++ .rst_idx = 0x1a08, ++ .delay_irq = 0x1a0c, ++ .fc_th = 0x1a10, +++ .tx_sch_rate = 0x1a14, ++ .int_grp = 0x1a20, ++ .hred = 0x1a44, ++ .ctx_ptr = 0x1b00, ++@@ -113,6 +115,7 @@ static const struct mtk_reg_map mt7986_r ++ }, ++ .qdma = { ++ .qtx_cfg = 0x4400, +++ .qtx_sch = 0x4404, ++ .rx_ptr = 0x4500, ++ .rx_cnt_cfg = 0x4504, ++ .qcrx_ptr = 0x4508, ++@@ -130,6 +133,7 @@ static const struct mtk_reg_map mt7986_r ++ .fq_tail = 0x4724, ++ .fq_count = 0x4728, ++ .fq_blen = 0x472c, +++ .tx_sch_rate = 0x4798, ++ }, ++ .gdm1_cnt = 0x1c00, ++ .gdma_to_ppe0 = 0x3333, ++@@ -570,6 +574,75 @@ static void mtk_mac_link_down(struct phy ++ mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); ++ } + -++#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS +++static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx, +++ int speed) +++{ +++ const struct mtk_soc_data *soc = eth->soc; +++ u32 ofs, val; ++ -+ static struct amd_chipset_info { -+ struct pci_dev *nb_dev; -+ struct pci_dev *smbus_dev; -+@@ -633,6 +635,10 @@ bool usb_amd_pt_check_port(struct device -+ } -+ EXPORT_SYMBOL_GPL(usb_amd_pt_check_port); -+ -++#endif /* CONFIG_PCI_DISABLE_COMMON_QUIRKS */ +++ if (!MTK_HAS_CAPS(soc->caps, MTK_QDMA)) +++ return; ++ -++#if IS_ENABLED(CONFIG_USB_UHCI_HCD) +++ val = MTK_QTX_SCH_MIN_RATE_EN | +++ /* minimum: 10 Mbps */ +++ FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, 1) | +++ FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, 4) | +++ MTK_QTX_SCH_LEAKY_BUCKET_SIZE; +++ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) +++ val |= MTK_QTX_SCH_LEAKY_BUCKET_EN; +++ +++ if (IS_ENABLED(CONFIG_SOC_MT7621)) { +++ switch (speed) { +++ case SPEED_10: +++ val |= MTK_QTX_SCH_MAX_RATE_EN | +++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 103) | +++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 2) | +++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1); +++ break; +++ case SPEED_100: +++ val |= MTK_QTX_SCH_MAX_RATE_EN | +++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 103) | +++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 3); +++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1); +++ break; +++ case SPEED_1000: +++ val |= MTK_QTX_SCH_MAX_RATE_EN | +++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 105) | +++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 4) | +++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 10); +++ break; +++ default: +++ break; +++ } +++ } else { +++ switch (speed) { +++ case SPEED_10: +++ val |= MTK_QTX_SCH_MAX_RATE_EN | +++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 1) | +++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 4) | +++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1); +++ break; +++ case SPEED_100: +++ val |= MTK_QTX_SCH_MAX_RATE_EN | +++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 1) | +++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5); +++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1); +++ break; +++ case SPEED_1000: +++ val |= MTK_QTX_SCH_MAX_RATE_EN | +++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 10) | +++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5) | +++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 10); +++ break; +++ default: +++ break; +++ } +++ } ++ -+ /* -+ * Make sure the controller is completely inactive, unable to -+ * generate interrupts or do DMA. -+@@ -712,8 +718,17 @@ reset_needed: -+ uhci_reset_hc(pdev, base); -+ return 1; -+ } -++#else -++int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base) -++{ -++ return 0; +++ ofs = MTK_QTX_OFFSET * idx; +++ mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs); ++} ++ -++#endif -+ EXPORT_SYMBOL_GPL(uhci_check_and_reset_hc); ++ static void mtk_mac_link_up(struct phylink_config *config, ++ struct phy_device *phy, ++ unsigned int mode, phy_interface_t interface, ++@@ -595,6 +668,8 @@ static void mtk_mac_link_up(struct phyli ++ break; ++ } + -++#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS +++ mtk_set_queue_speed(mac->hw, mac->id, speed); ++ -+ static inline int io_type_enabled(struct pci_dev *pdev, unsigned int mask) -+ { -+ u16 cmd; -+@@ -1285,3 +1300,4 @@ static void quirk_usb_early_handoff(stru ++ /* Configure duplex */ ++ if (duplex == DUPLEX_FULL) ++ mcr |= MAC_MCR_FORCE_DPX; ++@@ -1053,7 +1128,8 @@ static void mtk_tx_set_dma_desc_v1(struc ++ ++ WRITE_ONCE(desc->txd1, info->addr); ++ ++- data = TX_DMA_SWC | TX_DMA_PLEN0(info->size); +++ data = TX_DMA_SWC | TX_DMA_PLEN0(info->size) | +++ FIELD_PREP(TX_DMA_PQID, info->qid); ++ if (info->last) ++ data |= TX_DMA_LS0; ++ WRITE_ONCE(desc->txd3, data); ++@@ -1087,9 +1163,6 @@ static void mtk_tx_set_dma_desc_v2(struc ++ data |= TX_DMA_LS0; ++ WRITE_ONCE(desc->txd3, data); ++ ++- if (!info->qid && mac->id) ++- info->qid = MTK_QDMA_GMAC2_QID; ++- ++ data = (mac->id + 1) << TX_DMA_FPORT_SHIFT_V2; /* forward port */ ++ data |= TX_DMA_SWC_V2 | QID_BITS_V2(info->qid); ++ WRITE_ONCE(desc->txd4, data); ++@@ -1133,11 +1206,12 @@ static int mtk_tx_map(struct sk_buff *sk ++ .gso = gso, ++ .csum = skb->ip_summed == CHECKSUM_PARTIAL, ++ .vlan = skb_vlan_tag_present(skb), ++- .qid = skb->mark & MTK_QDMA_TX_MASK, +++ .qid = skb_get_queue_mapping(skb), ++ .vlan_tci = skb_vlan_tag_get(skb), ++ .first = true, ++ .last = !skb_is_nonlinear(skb), ++ }; +++ struct netdev_queue *txq; ++ struct mtk_mac *mac = netdev_priv(dev); ++ struct mtk_eth *eth = mac->hw; ++ const struct mtk_soc_data *soc = eth->soc; ++@@ -1145,8 +1219,10 @@ static int mtk_tx_map(struct sk_buff *sk ++ struct mtk_tx_dma *itxd_pdma, *txd_pdma; ++ struct mtk_tx_buf *itx_buf, *tx_buf; ++ int i, n_desc = 1; +++ int queue = skb_get_queue_mapping(skb); ++ int k = 0; ++ +++ txq = netdev_get_tx_queue(dev, queue); ++ itxd = ring->next_free; ++ itxd_pdma = qdma_to_pdma(ring, itxd); ++ if (itxd == ring->last_free) ++@@ -1195,7 +1271,7 @@ static int mtk_tx_map(struct sk_buff *sk ++ memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info)); ++ txd_info.size = min_t(unsigned int, frag_size, ++ soc->txrx.dma_max_len); ++- txd_info.qid = skb->mark & MTK_QDMA_TX_MASK; +++ txd_info.qid = queue; ++ txd_info.last = i == skb_shinfo(skb)->nr_frags - 1 && ++ !(frag_size - txd_info.size); ++ txd_info.addr = skb_frag_dma_map(eth->dma_dev, frag, ++@@ -1234,7 +1310,7 @@ static int mtk_tx_map(struct sk_buff *sk ++ txd_pdma->txd2 |= TX_DMA_LS1; ++ } ++ ++- netdev_sent_queue(dev, skb->len); +++ netdev_tx_sent_queue(txq, skb->len); ++ skb_tx_timestamp(skb); ++ ++ ring->next_free = mtk_qdma_phys_to_virt(ring, txd->txd2); ++@@ -1246,8 +1322,7 @@ static int mtk_tx_map(struct sk_buff *sk ++ wmb(); ++ ++ if (MTK_HAS_CAPS(soc->caps, MTK_QDMA)) { ++- if (netif_xmit_stopped(netdev_get_tx_queue(dev, 0)) || ++- !netdev_xmit_more()) +++ if (netif_xmit_stopped(txq) || !netdev_xmit_more()) ++ mtk_w32(eth, txd->txd2, soc->reg_map->qdma.ctx_ptr); ++ } else { ++ int next_idx; ++@@ -1316,7 +1391,7 @@ static void mtk_wake_queue(struct mtk_et ++ for (i = 0; i < MTK_MAC_COUNT; i++) { ++ if (!eth->netdev[i]) ++ continue; ++- netif_wake_queue(eth->netdev[i]); +++ netif_tx_wake_all_queues(eth->netdev[i]); ++ } + } -+ DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID, -+ PCI_CLASS_SERIAL_USB, 8, quirk_usb_early_handoff); -++#endif -+--- a/drivers/usb/host/pci-quirks.h -++++ b/drivers/usb/host/pci-quirks.h -+@@ -5,6 +5,9 @@ -+ #ifdef CONFIG_USB_PCI -+ void uhci_reset_hc(struct pci_dev *pdev, unsigned long base); -+ int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base); -++#endif /* CONFIG_USB_PCI */ ++ ++@@ -1340,7 +1415,7 @@ static netdev_tx_t mtk_start_xmit(struct ++ ++ tx_num = mtk_cal_txd_req(eth, skb); ++ if (unlikely(atomic_read(&ring->free_count) <= tx_num)) { ++- netif_stop_queue(dev); +++ netif_tx_stop_all_queues(dev); ++ netif_err(eth, tx_queued, dev, ++ "Tx Ring full when queue awake!\n"); ++ spin_unlock(ð->page_lock); ++@@ -1366,7 +1441,7 @@ static netdev_tx_t mtk_start_xmit(struct ++ goto drop; ++ ++ if (unlikely(atomic_read(&ring->free_count) <= ring->thresh)) ++- netif_stop_queue(dev); +++ netif_tx_stop_all_queues(dev); ++ ++ spin_unlock(ð->page_lock); ++ ++@@ -1533,10 +1608,12 @@ static int mtk_xdp_submit_frame(struct m ++ struct skb_shared_info *sinfo = xdp_get_shared_info_from_frame(xdpf); ++ const struct mtk_soc_data *soc = eth->soc; ++ struct mtk_tx_ring *ring = ð->tx_ring; +++ struct mtk_mac *mac = netdev_priv(dev); ++ struct mtk_tx_dma_desc_info txd_info = { ++ .size = xdpf->len, ++ .first = true, ++ .last = !xdp_frame_has_frags(xdpf), +++ .qid = mac->id, ++ }; ++ int err, index = 0, n_desc = 1, nr_frags; ++ struct mtk_tx_dma *htxd, *txd, *txd_pdma; ++@@ -1587,6 +1664,7 @@ static int mtk_xdp_submit_frame(struct m ++ memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info)); ++ txd_info.size = skb_frag_size(&sinfo->frags[index]); ++ txd_info.last = index + 1 == nr_frags; +++ txd_info.qid = mac->id; ++ data = skb_frag_address(&sinfo->frags[index]); ++ ++ index++; ++@@ -1938,8 +2016,46 @@ rx_done: ++ return done; ++ } ++ +++struct mtk_poll_state { +++ struct netdev_queue *txq; +++ unsigned int total; +++ unsigned int done; +++ unsigned int bytes; +++}; ++ -++#if defined(CONFIG_USB_PCI) && !defined(CONFIG_PCI_DISABLE_COMMON_QUIRKS) -+ int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *pdev); -+ bool usb_amd_hang_symptom_quirk(void); -+ bool usb_amd_prefetch_quirk(void); -+@@ -19,6 +22,18 @@ void sb800_prefetch(struct device *dev, -+ bool usb_amd_pt_check_port(struct device *device, int port); -+ #else -+ struct pci_dev; -++static inline int usb_amd_quirk_pll_check(void) -++{ -++ return 0; -++} -++static inline bool usb_amd_hang_symptom_quirk(void) -++{ -++ return false; -++} -++static inline bool usb_amd_prefetch_quirk(void) +++static void +++mtk_poll_tx_done(struct mtk_eth *eth, struct mtk_poll_state *state, u8 mac, +++ struct sk_buff *skb) ++{ -++ return false; +++ struct netdev_queue *txq; +++ struct net_device *dev; +++ unsigned int bytes = skb->len; +++ +++ state->total++; +++ eth->tx_packets++; +++ eth->tx_bytes += bytes; +++ +++ dev = eth->netdev[mac]; +++ if (!dev) +++ return; +++ +++ txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); +++ if (state->txq == txq) { +++ state->done++; +++ state->bytes += bytes; +++ return; +++ } +++ +++ if (state->txq) +++ netdev_tx_completed_queue(state->txq, state->done, state->bytes); +++ +++ state->txq = txq; +++ state->done = 1; +++ state->bytes = bytes; ++} -+ static inline void usb_amd_quirk_pll_disable(void) {} -+ static inline void usb_amd_quirk_pll_enable(void) {} -+ static inline void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev) {} -+@@ -29,6 +44,11 @@ static inline bool usb_amd_pt_check_port +++ ++ static int mtk_poll_tx_qdma(struct mtk_eth *eth, int budget, ++- unsigned int *done, unsigned int *bytes) +++ struct mtk_poll_state *state) + { -+ return false; ++ const struct mtk_reg_map *reg_map = eth->soc->reg_map; ++ struct mtk_tx_ring *ring = ð->tx_ring; ++@@ -1969,12 +2085,9 @@ static int mtk_poll_tx_qdma(struct mtk_e ++ break; ++ ++ if (tx_buf->data != (void *)MTK_DMA_DUMMY_DESC) { ++- if (tx_buf->type == MTK_TYPE_SKB) { ++- struct sk_buff *skb = tx_buf->data; +++ if (tx_buf->type == MTK_TYPE_SKB) +++ mtk_poll_tx_done(eth, state, mac, tx_buf->data); ++ ++- bytes[mac] += skb->len; ++- done[mac]++; ++- } ++ budget--; ++ } ++ mtk_tx_unmap(eth, tx_buf, true); ++@@ -1992,7 +2105,7 @@ static int mtk_poll_tx_qdma(struct mtk_e + } -++static inline void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev) {} -++static inline bool usb_xhci_needs_pci_reset(struct pci_dev *pdev) ++ ++ static int mtk_poll_tx_pdma(struct mtk_eth *eth, int budget, ++- unsigned int *done, unsigned int *bytes) +++ struct mtk_poll_state *state) ++ { ++ struct mtk_tx_ring *ring = ð->tx_ring; ++ struct mtk_tx_buf *tx_buf; ++@@ -2008,12 +2121,8 @@ static int mtk_poll_tx_pdma(struct mtk_e ++ break; ++ ++ if (tx_buf->data != (void *)MTK_DMA_DUMMY_DESC) { ++- if (tx_buf->type == MTK_TYPE_SKB) { ++- struct sk_buff *skb = tx_buf->data; ++- ++- bytes[0] += skb->len; ++- done[0]++; ++- } +++ if (tx_buf->type == MTK_TYPE_SKB) +++ mtk_poll_tx_done(eth, state, 0, tx_buf->data); ++ budget--; ++ } ++ mtk_tx_unmap(eth, tx_buf, true); ++@@ -2034,26 +2143,15 @@ static int mtk_poll_tx(struct mtk_eth *e ++ { ++ struct mtk_tx_ring *ring = ð->tx_ring; ++ struct dim_sample dim_sample = {}; ++- unsigned int done[MTK_MAX_DEVS]; ++- unsigned int bytes[MTK_MAX_DEVS]; ++- int total = 0, i; ++- ++- memset(done, 0, sizeof(done)); ++- memset(bytes, 0, sizeof(bytes)); +++ struct mtk_poll_state state = {}; ++ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) ++- budget = mtk_poll_tx_qdma(eth, budget, done, bytes); +++ budget = mtk_poll_tx_qdma(eth, budget, &state); ++ else ++- budget = mtk_poll_tx_pdma(eth, budget, done, bytes); +++ budget = mtk_poll_tx_pdma(eth, budget, &state); ++ ++- for (i = 0; i < MTK_MAC_COUNT; i++) { ++- if (!eth->netdev[i] || !done[i]) ++- continue; ++- netdev_completed_queue(eth->netdev[i], done[i], bytes[i]); ++- total += done[i]; ++- eth->tx_packets += done[i]; ++- eth->tx_bytes += bytes[i]; ++- } +++ if (state.txq) +++ netdev_tx_completed_queue(state.txq, state.done, state.bytes); ++ ++ dim_update_sample(eth->tx_events, eth->tx_packets, eth->tx_bytes, ++ &dim_sample); ++@@ -2063,7 +2161,7 @@ static int mtk_poll_tx(struct mtk_eth *e ++ (atomic_read(&ring->free_count) > ring->thresh)) ++ mtk_wake_queue(eth); ++ ++- return total; +++ return state.total; ++ } ++ ++ static void mtk_handle_status_irq(struct mtk_eth *eth) ++@@ -2149,6 +2247,7 @@ static int mtk_tx_alloc(struct mtk_eth * ++ int i, sz = soc->txrx.txd_size; ++ struct mtk_tx_dma_v2 *txd; ++ int ring_size; +++ u32 ofs, val; ++ ++ if (MTK_HAS_CAPS(soc->caps, MTK_QDMA)) ++ ring_size = MTK_QDMA_RING_SIZE; ++@@ -2216,8 +2315,25 @@ static int mtk_tx_alloc(struct mtk_eth * ++ ring->phys + ((ring_size - 1) * sz), ++ soc->reg_map->qdma.crx_ptr); ++ mtk_w32(eth, ring->last_free_ptr, soc->reg_map->qdma.drx_ptr); ++- mtk_w32(eth, (QDMA_RES_THRES << 8) | QDMA_RES_THRES, ++- soc->reg_map->qdma.qtx_cfg); +++ +++ for (i = 0, ofs = 0; i < MTK_QDMA_NUM_QUEUES; i++) { +++ val = (QDMA_RES_THRES << 8) | QDMA_RES_THRES; +++ mtk_w32(eth, val, soc->reg_map->qdma.qtx_cfg + ofs); +++ +++ val = MTK_QTX_SCH_MIN_RATE_EN | +++ /* minimum: 10 Mbps */ +++ FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, 1) | +++ FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, 4) | +++ MTK_QTX_SCH_LEAKY_BUCKET_SIZE; +++ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) +++ val |= MTK_QTX_SCH_LEAKY_BUCKET_EN; +++ mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs); +++ ofs += MTK_QTX_OFFSET; +++ } +++ val = MTK_QDMA_TX_SCH_MAX_WFQ | (MTK_QDMA_TX_SCH_MAX_WFQ << 16); +++ mtk_w32(eth, val, soc->reg_map->qdma.tx_sch_rate); +++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) +++ mtk_w32(eth, val, soc->reg_map->qdma.tx_sch_rate + 4); ++ } else { ++ mtk_w32(eth, ring->phys_pdma, MT7628_TX_BASE_PTR0); ++ mtk_w32(eth, ring_size, MT7628_TX_MAX_CNT0); ++@@ -2882,7 +2998,7 @@ static int mtk_start_dma(struct mtk_eth ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ++ val |= MTK_MUTLI_CNT | MTK_RESV_BUF | ++ MTK_WCOMP_EN | MTK_DMAD_WR_WDONE | ++- MTK_CHK_DDONE_EN; +++ MTK_CHK_DDONE_EN | MTK_LEAKY_BUCKET_EN; ++ else ++ val |= MTK_RX_BT_32DWORDS; ++ mtk_w32(eth, val, reg_map->qdma.glo_cfg); ++@@ -2928,6 +3044,45 @@ static void mtk_gdm_config(struct mtk_et ++ mtk_w32(eth, 0, MTK_RST_GL); ++ } ++ +++static int mtk_device_event(struct notifier_block *n, unsigned long event, void *ptr) ++{ -++ return false; +++ struct mtk_mac *mac = container_of(n, struct mtk_mac, device_notifier); +++ struct mtk_eth *eth = mac->hw; +++ struct net_device *dev = netdev_notifier_info_to_dev(ptr); +++ struct ethtool_link_ksettings s; +++ struct net_device *ldev; +++ struct list_head *iter; +++ struct dsa_port *dp; +++ +++ if (event != NETDEV_CHANGE) +++ return NOTIFY_DONE; +++ +++ netdev_for_each_lower_dev(dev, ldev, iter) { +++ if (netdev_priv(ldev) == mac) +++ goto found; +++ } +++ +++ return NOTIFY_DONE; +++ +++found: +++ if (!dsa_slave_dev_check(dev)) +++ return NOTIFY_DONE; +++ +++ if (__ethtool_get_link_ksettings(dev, &s)) +++ return NOTIFY_DONE; +++ +++ if (s.base.speed == 0 || s.base.speed == ((__u32)-1)) +++ return NOTIFY_DONE; +++ +++ dp = dsa_port_from_netdev(dev); +++ if (dp->index >= MTK_QDMA_NUM_QUEUES) +++ return NOTIFY_DONE; +++ +++ mtk_set_queue_speed(eth, dp->index + 3, s.base.speed); +++ +++ return NOTIFY_DONE; ++} -+ #endif /* CONFIG_USB_PCI */ +++ ++ static int mtk_open(struct net_device *dev) ++ { ++ struct mtk_mac *mac = netdev_priv(dev); ++@@ -2970,7 +3125,8 @@ static int mtk_open(struct net_device *d ++ refcount_inc(ð->dma_refcnt); + -+ #endif /* __LINUX_USB_PCI_QUIRKS_H */ -+--- a/include/linux/usb/hcd.h -++++ b/include/linux/usb/hcd.h -+@@ -497,7 +497,14 @@ extern int usb_hcd_pci_probe(struct pci_ -+ extern void usb_hcd_pci_remove(struct pci_dev *dev); -+ extern void usb_hcd_pci_shutdown(struct pci_dev *dev); ++ phylink_start(mac->phylink); ++- netif_start_queue(dev); +++ netif_tx_start_all_queues(dev); +++ ++ return 0; ++ } + -++#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS -+ extern int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *dev); -++#else -++static inline int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *dev) ++@@ -3486,8 +3642,12 @@ static int mtk_unreg_dev(struct mtk_eth ++ int i; ++ ++ for (i = 0; i < MTK_MAC_COUNT; i++) { +++ struct mtk_mac *mac; ++ if (!eth->netdev[i]) ++ continue; +++ mac = netdev_priv(eth->netdev[i]); +++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) +++ unregister_netdevice_notifier(&mac->device_notifier); ++ unregister_netdev(eth->netdev[i]); ++ } ++ ++@@ -3703,6 +3863,23 @@ static int mtk_set_rxnfc(struct net_devi ++ return ret; ++ } ++ +++static u16 mtk_select_queue(struct net_device *dev, struct sk_buff *skb, +++ struct net_device *sb_dev) ++{ -++ return 0; +++ struct mtk_mac *mac = netdev_priv(dev); +++ unsigned int queue = 0; +++ +++ if (netdev_uses_dsa(dev)) +++ queue = skb_get_queue_mapping(skb) + 3; +++ else +++ queue = mac->id; +++ +++ if (queue >= dev->num_tx_queues) +++ queue = 0; +++ +++ return queue; ++} -++#endif +++ ++ static const struct ethtool_ops mtk_ethtool_ops = { ++ .get_link_ksettings = mtk_get_link_ksettings, ++ .set_link_ksettings = mtk_set_link_ksettings, ++@@ -3738,6 +3915,7 @@ static const struct net_device_ops mtk_n ++ .ndo_setup_tc = mtk_eth_setup_tc, ++ .ndo_bpf = mtk_xdp, ++ .ndo_xdp_xmit = mtk_xdp_xmit, +++ .ndo_select_queue = mtk_select_queue, ++ }; + -+ #ifdef CONFIG_PM -+ extern const struct dev_pm_ops usb_hcd_pci_pm_ops; -diff --git a/target/linux/generic/pending-5.15/820-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch b/target/linux/generic/pending-5.15/820-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch ++ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) ++@@ -3747,6 +3925,7 @@ static int mtk_add_mac(struct mtk_eth *e ++ struct phylink *phylink; ++ struct mtk_mac *mac; ++ int id, err; +++ int txqs = 1; ++ ++ if (!_id) { ++ dev_err(eth->dev, "missing mac id\n"); ++@@ -3764,7 +3943,10 @@ static int mtk_add_mac(struct mtk_eth *e ++ return -EINVAL; ++ } ++ ++- eth->netdev[id] = alloc_etherdev(sizeof(*mac)); +++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) +++ txqs = MTK_QDMA_NUM_QUEUES; +++ +++ eth->netdev[id] = alloc_etherdev_mqs(sizeof(*mac), txqs, 1); ++ if (!eth->netdev[id]) { ++ dev_err(eth->dev, "alloc_etherdev failed\n"); ++ return -ENOMEM; ++@@ -3861,6 +4043,11 @@ static int mtk_add_mac(struct mtk_eth *e ++ else ++ eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH_2K - MTK_RX_ETH_HLEN; ++ +++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) { +++ mac->device_notifier.notifier_call = mtk_device_event; +++ register_netdevice_notifier(&mac->device_notifier); +++ } +++ ++ return 0; ++ ++ free_netdev: ++--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++@@ -22,6 +22,7 @@ ++ #include <linux/bpf_trace.h> ++ #include "mtk_ppe.h" ++ +++#define MTK_QDMA_NUM_QUEUES 16 ++ #define MTK_QDMA_PAGE_SIZE 2048 ++ #define MTK_MAX_RX_LENGTH 1536 ++ #define MTK_MAX_RX_LENGTH_2K 2048 ++@@ -203,8 +204,26 @@ ++ #define MTK_RING_MAX_AGG_CNT_H ((MTK_HW_LRO_MAX_AGG_CNT >> 6) & 0x3) ++ ++ /* QDMA TX Queue Configuration Registers */ +++#define MTK_QTX_OFFSET 0x10 ++ #define QDMA_RES_THRES 4 ++ +++/* QDMA Tx Queue Scheduler Configuration Registers */ +++#define MTK_QTX_SCH_TX_SEL BIT(31) +++#define MTK_QTX_SCH_TX_SEL_V2 GENMASK(31, 30) +++ +++#define MTK_QTX_SCH_LEAKY_BUCKET_EN BIT(30) +++#define MTK_QTX_SCH_LEAKY_BUCKET_SIZE GENMASK(29, 28) +++#define MTK_QTX_SCH_MIN_RATE_EN BIT(27) +++#define MTK_QTX_SCH_MIN_RATE_MAN GENMASK(26, 20) +++#define MTK_QTX_SCH_MIN_RATE_EXP GENMASK(19, 16) +++#define MTK_QTX_SCH_MAX_RATE_WEIGHT GENMASK(15, 12) +++#define MTK_QTX_SCH_MAX_RATE_EN BIT(11) +++#define MTK_QTX_SCH_MAX_RATE_MAN GENMASK(10, 4) +++#define MTK_QTX_SCH_MAX_RATE_EXP GENMASK(3, 0) +++ +++/* QDMA TX Scheduler Rate Control Register */ +++#define MTK_QDMA_TX_SCH_MAX_WFQ BIT(15) +++ ++ /* QDMA Global Configuration Register */ ++ #define MTK_RX_2B_OFFSET BIT(31) ++ #define MTK_RX_BT_32DWORDS (3 << 11) ++@@ -223,6 +242,7 @@ ++ #define MTK_WCOMP_EN BIT(24) ++ #define MTK_RESV_BUF (0x40 << 16) ++ #define MTK_MUTLI_CNT (0x4 << 12) +++#define MTK_LEAKY_BUCKET_EN BIT(11) ++ ++ /* QDMA Flow Control Register */ ++ #define FC_THRES_DROP_MODE BIT(20) ++@@ -251,8 +271,6 @@ ++ #define MTK_STAT_OFFSET 0x40 ++ ++ /* QDMA TX NUM */ ++-#define MTK_QDMA_TX_NUM 16 ++-#define MTK_QDMA_TX_MASK (MTK_QDMA_TX_NUM - 1) ++ #define QID_BITS_V2(x) (((x) & 0x3f) << 16) ++ #define MTK_QDMA_GMAC2_QID 8 ++ ++@@ -282,6 +300,7 @@ ++ #define TX_DMA_PLEN0(x) (((x) & eth->soc->txrx.dma_max_len) << eth->soc->txrx.dma_len_offset) ++ #define TX_DMA_PLEN1(x) ((x) & eth->soc->txrx.dma_max_len) ++ #define TX_DMA_SWC BIT(14) +++#define TX_DMA_PQID GENMASK(3, 0) ++ ++ /* PDMA on MT7628 */ ++ #define TX_DMA_DONE BIT(31) ++@@ -930,6 +949,7 @@ struct mtk_reg_map { ++ } pdma; ++ struct { ++ u32 qtx_cfg; /* tx queue configuration */ +++ u32 qtx_sch; /* tx queue scheduler configuration */ ++ u32 rx_ptr; /* rx base pointer */ ++ u32 rx_cnt_cfg; /* rx max count configuration */ ++ u32 qcrx_ptr; /* rx cpu pointer */ ++@@ -947,6 +967,7 @@ struct mtk_reg_map { ++ u32 fq_tail; /* fq tail pointer */ ++ u32 fq_count; /* fq free page count */ ++ u32 fq_blen; /* fq free page buffer length */ +++ u32 tx_sch_rate; /* tx scheduler rate control registers */ ++ } qdma; ++ u32 gdm1_cnt; ++ u32 gdma_to_ppe0; ++@@ -1139,6 +1160,7 @@ struct mtk_mac { ++ __be32 hwlro_ip[MTK_MAX_LRO_IP_CNT]; ++ int hwlro_ip_cnt; ++ unsigned int syscfg0; +++ struct notifier_block device_notifier; ++ }; ++ ++ /* the struct describing the SoC. these are declared in the soc_xyz.c files */ +diff --git a/target/linux/generic/pending-5.15/732-05-net-dsa-tag_mtk-assign-per-port-queues.patch b/target/linux/generic/pending-5.15/732-05-net-dsa-tag_mtk-assign-per-port-queues.patch new file mode 100644 -index 0000000000..33eb34c913 +index 0000000000..7739366ade --- /dev/null -+++ b/target/linux/generic/pending-5.15/820-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch -@@ -0,0 +1,26 @@ -+From d9c8bc8c1408f3e8529db6e4e04017b4c579c342 Mon Sep 17 00:00:00 2001 -+From: Pawel Dembicki <paweldembicki@gmail.com> -+Date: Sun, 18 Feb 2018 17:08:04 +0100 -+Subject: [PATCH] w1: gpio: fix problem with platfom data in w1-gpio -+ -+In devices, where fdt is used, is impossible to apply platform data -+without proper fdt node. ++++ b/target/linux/generic/pending-5.15/732-05-net-dsa-tag_mtk-assign-per-port-queues.patch +@@ -0,0 +1,20 @@ ++From: Felix Fietkau <nbd@nbd.name> ++Date: Fri, 28 Oct 2022 18:16:03 +0200 ++Subject: [PATCH] net: dsa: tag_mtk: assign per-port queues + -+This patch allow to use platform data in devices with fdt. ++Keeps traffic sent to the switch within link speed limits + -+Signed-off-by: Pawel Dembicki <paweldembicki@gmail.com> ++Signed-off-by: Felix Fietkau <nbd@nbd.name> +--- -+ drivers/w1/masters/w1-gpio.c | 7 +++---- -+ 1 file changed, 3 insertions(+), 4 deletions(-) + -+--- a/drivers/w1/masters/w1-gpio.c -++++ b/drivers/w1/masters/w1-gpio.c -+@@ -76,7 +76,7 @@ static int w1_gpio_probe(struct platform -+ enum gpiod_flags gflags = GPIOD_OUT_LOW_OPEN_DRAIN; -+ int err; ++--- a/net/dsa/tag_mtk.c +++++ b/net/dsa/tag_mtk.c ++@@ -33,6 +33,8 @@ static struct sk_buff *mtk_tag_xmit(stru ++ if (__skb_put_padto(skb, ETH_ZLEN + MTK_HDR_LEN, false)) ++ return NULL; + -+- if (of_have_populated_dt()) { -++ if (of_have_populated_dt() && !dev_get_platdata(&pdev->dev)) { -+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); -+ if (!pdata) -+ return -ENOMEM; -diff --git a/target/linux/generic/pending-5.15/834-ledtrig-libata.patch b/target/linux/generic/pending-5.15/834-ledtrig-libata.patch +++ skb_set_queue_mapping(skb, dp->index); +++ ++ /* Build the special tag after the MAC Source Address. If VLAN header ++ * is present, it's required that VLAN header and special tag is ++ * being combined. Only in this way we can allow the switch can parse +diff --git a/target/linux/generic/pending-5.15/732-06-net-ethernet-mediatek-ppe-assign-per-port-queues-for.patch b/target/linux/generic/pending-5.15/732-06-net-ethernet-mediatek-ppe-assign-per-port-queues-for.patch new file mode 100644 -index 0000000000..3977b57d9f +index 0000000000..05161c3479 --- /dev/null -+++ b/target/linux/generic/pending-5.15/834-ledtrig-libata.patch -@@ -0,0 +1,149 @@ -+From: Daniel Golle <daniel@makrotopia.org> -+Subject: libata: add ledtrig support -+ -+This adds a LED trigger for each ATA port indicating disk activity. ++++ b/target/linux/generic/pending-5.15/732-06-net-ethernet-mediatek-ppe-assign-per-port-queues-for.patch +@@ -0,0 +1,93 @@ ++From: Felix Fietkau <nbd@nbd.name> ++Date: Thu, 3 Nov 2022 17:49:44 +0100 ++Subject: [PATCH] net: ethernet: mediatek: ppe: assign per-port queues ++ for offloaded traffic + -+As this is needed only on specific platforms (NAS SoCs and such), -+these platforms should define ARCH_WANTS_LIBATA_LEDS if there -+are boards with LED(s) intended to indicate ATA disk activity and -+need the OS to take care of that. -+In that way, if not selected, LED trigger support not will be -+included in libata-core and both, codepaths and structures remain -+untouched. ++Keeps traffic sent to the switch within link speed limits + -+Signed-off-by: Daniel Golle <daniel@makrotopia.org> ++Signed-off-by: Felix Fietkau <nbd@nbd.name> +--- -+ drivers/ata/Kconfig | 16 ++++++++++++++++ -+ drivers/ata/libata-core.c | 41 +++++++++++++++++++++++++++++++++++++++++ -+ include/linux/libata.h | 9 +++++++++ -+ 3 files changed, 66 insertions(+) + -+--- a/drivers/ata/Kconfig -++++ b/drivers/ata/Kconfig -+@@ -67,6 +67,22 @@ config ATA_FORCE -+ -+ If unsure, say Y. ++--- a/drivers/net/ethernet/mediatek/mtk_ppe.c +++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c ++@@ -445,6 +445,24 @@ static inline bool mtk_foe_entry_usable( ++ FIELD_GET(MTK_FOE_IB1_STATE, entry->ib1) != MTK_FOE_STATE_BIND; ++ } + -++config ARCH_WANT_LIBATA_LEDS -++ bool +++int mtk_foe_entry_set_queue(struct mtk_eth *eth, struct mtk_foe_entry *entry, +++ unsigned int queue) +++{ +++ u32 *ib2 = mtk_foe_entry_ib2(eth, entry); ++ -++config ATA_LEDS -++ bool "support ATA port LED triggers" -++ depends on ARCH_WANT_LIBATA_LEDS -++ select NEW_LEDS -++ select LEDS_CLASS -++ select LEDS_TRIGGERS -++ default y -++ help -++ This option adds a LED trigger for each registered ATA port. -++ It is used to drive disk activity leds connected via GPIO. -++ -++ If unsure, say N. -++ -+ config ATA_ACPI -+ bool "ATA ACPI Support" -+ depends on ACPI -+--- a/drivers/ata/libata-core.c -++++ b/drivers/ata/libata-core.c -+@@ -656,6 +656,19 @@ u64 ata_tf_read_block(const struct ata_t -+ return block; -+ } -+ -++#ifdef CONFIG_ATA_LEDS -++#define LIBATA_BLINK_DELAY 20 /* ms */ -++static inline void ata_led_act(struct ata_port *ap) -++{ -++ unsigned long led_delay = LIBATA_BLINK_DELAY; -++ -++ if (unlikely(!ap->ledtrig)) -++ return; +++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { +++ *ib2 &= ~MTK_FOE_IB2_QID_V2; +++ *ib2 |= FIELD_PREP(MTK_FOE_IB2_QID_V2, queue); +++ *ib2 |= MTK_FOE_IB2_PSE_QOS_V2; +++ } else { +++ *ib2 &= ~MTK_FOE_IB2_QID; +++ *ib2 |= FIELD_PREP(MTK_FOE_IB2_QID, queue); +++ *ib2 |= MTK_FOE_IB2_PSE_QOS; +++ } ++ -++ led_trigger_blink_oneshot(ap->ledtrig, &led_delay, &led_delay, 0); +++ return 0; ++} -++#endif ++ -+ /** -+ * ata_build_rw_tf - Build ATA taskfile for given read/write request -+ * @tf: Target ATA taskfile -+@@ -4576,6 +4589,9 @@ struct ata_queued_cmd *ata_qc_new_init(s -+ if (tag < 0) -+ return NULL; -+ } -++#ifdef CONFIG_ATA_LEDS -++ ata_led_act(ap); -++#endif ++ static bool ++ mtk_flow_entry_match(struct mtk_eth *eth, struct mtk_flow_entry *entry, ++ struct mtk_foe_entry *data) ++--- a/drivers/net/ethernet/mediatek/mtk_ppe.h +++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h ++@@ -69,7 +69,9 @@ enum { ++ #define MTK_FOE_IB2_DSCP GENMASK(31, 24) ++ ++ /* CONFIG_MEDIATEK_NETSYS_V2 */ +++#define MTK_FOE_IB2_QID_V2 GENMASK(6, 0) ++ #define MTK_FOE_IB2_PORT_MG_V2 BIT(7) +++#define MTK_FOE_IB2_PSE_QOS_V2 BIT(8) ++ #define MTK_FOE_IB2_DEST_PORT_V2 GENMASK(12, 9) ++ #define MTK_FOE_IB2_MULTICAST_V2 BIT(13) ++ #define MTK_FOE_IB2_WDMA_WINFO_V2 BIT(19) ++@@ -369,6 +371,8 @@ int mtk_foe_entry_set_pppoe(struct mtk_e ++ int sid); ++ int mtk_foe_entry_set_wdma(struct mtk_eth *eth, struct mtk_foe_entry *entry, ++ int wdma_idx, int txq, int bss, int wcid); +++int mtk_foe_entry_set_queue(struct mtk_eth *eth, struct mtk_foe_entry *entry, +++ unsigned int queue); ++ int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); ++ void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); ++ int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); ++--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++@@ -188,7 +188,7 @@ mtk_flow_set_output_device(struct mtk_et ++ int *wed_index) ++ { ++ struct mtk_wdma_info info = {}; ++- int pse_port, dsa_port; +++ int pse_port, dsa_port, queue; + -+ qc = __ata_qc_from_tag(ap, tag); -+ qc->tag = qc->hw_tag = tag; -+@@ -5354,6 +5370,9 @@ struct ata_port *ata_port_alloc(struct a -+ ap->stats.unhandled_irq = 1; -+ ap->stats.idle_irq = 1; -+ #endif -++#ifdef CONFIG_ATA_LEDS -++ ap->ledtrig = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); -++#endif -+ ata_sff_port_init(ap); ++ if (mtk_flow_get_wdma_info(dev, dest_mac, &info) == 0) { ++ mtk_foe_entry_set_wdma(eth, foe, info.wdma_idx, info.queue, ++@@ -212,8 +212,6 @@ mtk_flow_set_output_device(struct mtk_et ++ } + -+ return ap; -+@@ -5389,6 +5408,12 @@ static void ata_host_release(struct kref ++ dsa_port = mtk_flow_get_dsa_port(&dev); ++- if (dsa_port >= 0) ++- mtk_foe_entry_set_dsa(eth, foe, dsa_port); + -+ kfree(ap->pmp_link); -+ kfree(ap->slave_link); -++#ifdef CONFIG_ATA_LEDS -++ if (ap->ledtrig) { -++ led_trigger_unregister(ap->ledtrig); -++ kfree(ap->ledtrig); -++ }; -++#endif -+ kfree(ap); -+ host->ports[i] = NULL; -+ } -+@@ -5795,7 +5820,23 @@ int ata_host_register(struct ata_host *h -+ host->ports[i]->print_id = atomic_inc_return(&ata_print_id); -+ host->ports[i]->local_port_no = i + 1; -+ } -++#ifdef CONFIG_ATA_LEDS -++ for (i = 0; i < host->n_ports; i++) { -++ if (unlikely(!host->ports[i]->ledtrig)) -++ continue; ++ if (dev == eth->netdev[0]) ++ pse_port = 1; ++@@ -222,6 +220,14 @@ mtk_flow_set_output_device(struct mtk_et ++ else ++ return -EOPNOTSUPP; + -++ snprintf(host->ports[i]->ledtrig_name, -++ sizeof(host->ports[i]->ledtrig_name), "ata%u", -++ host->ports[i]->print_id); -++ -++ host->ports[i]->ledtrig->name = host->ports[i]->ledtrig_name; -++ -++ if (led_trigger_register(host->ports[i]->ledtrig)) { -++ kfree(host->ports[i]->ledtrig); -++ host->ports[i]->ledtrig = NULL; -++ } +++ if (dsa_port >= 0) { +++ mtk_foe_entry_set_dsa(eth, foe, dsa_port); +++ queue = 3 + dsa_port; +++ } else { +++ queue = pse_port - 1; ++ } -++#endif -+ /* Create associated sysfs transport objects */ -+ for (i = 0; i < host->n_ports; i++) { -+ rc = ata_tport_add(host->dev,host->ports[i]); -+--- a/include/linux/libata.h -++++ b/include/linux/libata.h -+@@ -23,6 +23,9 @@ -+ #include <linux/cdrom.h> -+ #include <linux/sched.h> -+ #include <linux/async.h> -++#ifdef CONFIG_ATA_LEDS -++#include <linux/leds.h> -++#endif -+ -+ /* -+ * Define if arch has non-standard setup. This is a _PCI_ standard -+@@ -888,6 +891,12 @@ struct ata_port { -+ #ifdef CONFIG_ATA_ACPI -+ struct ata_acpi_gtm __acpi_init_gtm; /* use ata_acpi_init_gtm() */ -+ #endif -++ -++#ifdef CONFIG_ATA_LEDS -++ struct led_trigger *ledtrig; -++ char ledtrig_name[8]; -++#endif +++ mtk_foe_entry_set_queue(eth, foe, queue); ++ -+ /* owned by EH */ -+ u8 sector_buf[ATA_SECT_SIZE] ____cacheline_aligned; -+ }; -diff --git a/target/linux/generic/pending-5.15/840-hwrng-bcm2835-set-quality-to-1000.patch b/target/linux/generic/pending-5.15/840-hwrng-bcm2835-set-quality-to-1000.patch ++ out: ++ mtk_foe_entry_set_pse_port(eth, foe, pse_port); ++ +diff --git a/target/linux/generic/pending-5.15/732-07-net-ethernet-mtk_eth_soc-compile-out-netsys-v2-code-.patch b/target/linux/generic/pending-5.15/732-07-net-ethernet-mtk_eth_soc-compile-out-netsys-v2-code-.patch new file mode 100644 -index 0000000000..5ca8933d6f +index 0000000000..8c711ba802 --- /dev/null -+++ b/target/linux/generic/pending-5.15/840-hwrng-bcm2835-set-quality-to-1000.patch -@@ -0,0 +1,26 @@ -+From d6988cf1d16faac56899918bb2b1be8d85155e3f Mon Sep 17 00:00:00 2001 -+From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com> -+Date: Sat, 20 Feb 2021 18:36:38 +0100 -+Subject: [PATCH] hwrng: bcm2835: set quality to 1000 -+MIME-Version: 1.0 -+Content-Type: text/plain; charset=UTF-8 -+Content-Transfer-Encoding: 8bit ++++ b/target/linux/generic/pending-5.15/732-07-net-ethernet-mtk_eth_soc-compile-out-netsys-v2-code-.patch +@@ -0,0 +1,28 @@ ++From: Felix Fietkau <nbd@nbd.name> ++Date: Thu, 27 Oct 2022 23:39:52 +0200 ++Subject: [PATCH] net: ethernet: mtk_eth_soc: compile out netsys v2 code ++ on mt7621 + -+This allows devices without a high precission timer to reduce boot from >100s -+to <30s. ++Avoid some branches in the hot path on low-end devices with limited CPU power, ++and reduce code size + -+Signed-off-by: Ãlvaro Fernández Rojas <noltari@gmail.com> ++Signed-off-by: Felix Fietkau <nbd@nbd.name> +--- -+ drivers/char/hw_random/bcm2835-rng.c | 1 + -+ 1 file changed, 1 insertion(+) + -+--- a/drivers/char/hw_random/bcm2835-rng.c -++++ b/drivers/char/hw_random/bcm2835-rng.c -+@@ -170,6 +170,7 @@ static int bcm2835_rng_probe(struct plat -+ priv->rng.init = bcm2835_rng_init; -+ priv->rng.read = bcm2835_rng_read; -+ priv->rng.cleanup = bcm2835_rng_cleanup; -++ priv->rng.quality = 1000; ++--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++@@ -895,7 +895,13 @@ enum mkt_eth_capabilities { ++ #define MTK_MUX_GMAC12_TO_GEPHY_SGMII \ ++ (MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII | MTK_MUX) + -+ if (dev_of_node(dev)) { -+ rng_id = of_match_node(bcm2835_rng_of_match, dev->of_node); -diff --git a/target/linux/generic/pending-5.15/842-net-qmi_wwan-add-ZTE-MF286D-modem-19d2-1485.patch b/target/linux/generic/pending-5.15/842-net-qmi_wwan-add-ZTE-MF286D-modem-19d2-1485.patch ++-#define MTK_HAS_CAPS(caps, _x) (((caps) & (_x)) == (_x)) +++#ifdef CONFIG_SOC_MT7621 +++#define MTK_CAP_MASK MTK_NETSYS_V2 +++#else +++#define MTK_CAP_MASK 0 +++#endif +++ +++#define MTK_HAS_CAPS(caps, _x) (((caps) & (_x) & ~(MTK_CAP_MASK)) == (_x)) ++ ++ #define MT7621_CAPS (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII | \ ++ MTK_GMAC2_RGMII | MTK_SHARED_INT | \ +diff --git a/target/linux/generic/pending-5.15/732-08-net-dsa-add-support-for-DSA-rx-offloading-via-metada.patch b/target/linux/generic/pending-5.15/732-08-net-dsa-add-support-for-DSA-rx-offloading-via-metada.patch new file mode 100644 -index 0000000000..530ab9ba13 +index 0000000000..0478cb528e --- /dev/null -+++ b/target/linux/generic/pending-5.15/842-net-qmi_wwan-add-ZTE-MF286D-modem-19d2-1485.patch -@@ -0,0 +1,59 @@ -+From 078c6a1cbd4cd7496048786beec2e312577bebbf Mon Sep 17 00:00:00 2001 -+From: Pawel Dembicki <paweldembicki@gmail.com> -+Date: Tue, 11 Jan 2022 23:11:32 +0100 -+Subject: [PATCH] net: qmi_wwan: add ZTE MF286D modem 19d2:1485 -+MIME-Version: 1.0 -+Content-Type: text/plain; charset=UTF-8 -+Content-Transfer-Encoding: 8bit ++++ b/target/linux/generic/pending-5.15/732-08-net-dsa-add-support-for-DSA-rx-offloading-via-metada.patch +@@ -0,0 +1,72 @@ ++From: Felix Fietkau <nbd@nbd.name> ++Date: Tue, 8 Nov 2022 15:03:15 +0100 ++Subject: [PATCH] net: dsa: add support for DSA rx offloading via ++ metadata dst + -+Modem from ZTE MF286D is an Qualcomm MDM9250 based 3G/4G modem. -+ -+T: Bus=02 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 3 Spd=5000 MxCh= 0 -+D: Ver= 3.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 9 #Cfgs= 1 -+P: Vendor=19d2 ProdID=1485 Rev=52.87 -+S: Manufacturer=ZTE,Incorporated -+S: Product=ZTE Technologies MSM -+S: SerialNumber=MF286DZTED000000 -+C:* #Ifs= 7 Cfg#= 1 Atr=80 MxPwr=896mA -+A: FirstIf#= 0 IfCount= 2 Cls=02(comm.) Sub=06 Prot=00 -+I:* If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=02 Prot=ff Driver=rndis_host -+E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl=32ms -+I:* If#= 1 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=rndis_host -+E: Ad=81(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms -+E: Ad=01(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms -+I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option -+E: Ad=83(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms -+E: Ad=02(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms -+I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=option -+E: Ad=85(I) Atr=03(Int.) MxPS= 10 Ivl=32ms -+E: Ad=84(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms -+E: Ad=03(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms -+I:* If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=option -+E: Ad=87(I) Atr=03(Int.) MxPS= 10 Ivl=32ms -+E: Ad=86(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms -+E: Ad=04(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms -+I:* If#= 5 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan -+E: Ad=88(I) Atr=03(Int.) MxPS= 8 Ivl=32ms -+E: Ad=8e(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms -+E: Ad=0f(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms -+I:* If#= 6 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=usbfs -+E: Ad=05(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms -+E: Ad=89(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms ++If a metadata dst is present with the type METADATA_HW_PORT_MUX on a dsa cpu ++port netdev, assume that it carries the port number and that there is no DSA ++tag present in the skb data. + -+Signed-off-by: Pawel Dembicki <paweldembicki@gmail.com> -+Acked-by: Bjørn Mork <bjorn@mork.no> -+Signed-off-by: David S. Miller <davem@davemloft.net> ++Signed-off-by: Felix Fietkau <nbd@nbd.name> +--- -+ drivers/net/usb/qmi_wwan.c | 1 + -+ 1 file changed, 1 insertion(+) + -+--- a/drivers/net/usb/qmi_wwan.c -++++ b/drivers/net/usb/qmi_wwan.c -+@@ -1313,6 +1313,7 @@ static const struct usb_device_id produc -+ {QMI_FIXED_INTF(0x19d2, 0x1426, 2)}, /* ZTE MF91 */ -+ {QMI_FIXED_INTF(0x19d2, 0x1428, 2)}, /* Telewell TW-LTE 4G v2 */ -+ {QMI_FIXED_INTF(0x19d2, 0x1432, 3)}, /* ZTE ME3620 */ -++ {QMI_FIXED_INTF(0x19d2, 0x1485, 5)}, /* ZTE MF286D */ -+ {QMI_FIXED_INTF(0x19d2, 0x2002, 4)}, /* ZTE (Vodafone) K3765-Z */ -+ {QMI_FIXED_INTF(0x2001, 0x7e16, 3)}, /* D-Link DWM-221 */ -+ {QMI_FIXED_INTF(0x2001, 0x7e19, 4)}, /* D-Link DWM-221 B1 */ -diff --git a/target/linux/generic/pending-5.15/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch b/target/linux/generic/pending-5.15/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch ++--- a/net/core/flow_dissector.c +++++ b/net/core/flow_dissector.c ++@@ -940,12 +940,14 @@ bool __skb_flow_dissect(const struct net ++ #if IS_ENABLED(CONFIG_NET_DSA) ++ if (unlikely(skb->dev && netdev_uses_dsa(skb->dev) && ++ proto == htons(ETH_P_XDSA))) { +++ struct metadata_dst *md_dst = skb_metadata_dst(skb); ++ const struct dsa_device_ops *ops; ++ int offset = 0; ++ ++ ops = skb->dev->dsa_ptr->tag_ops; ++ /* Only DSA header taggers break flow dissection */ ++- if (ops->needed_headroom) { +++ if (ops->needed_headroom && +++ (!md_dst || md_dst->type != METADATA_HW_PORT_MUX)) { ++ if (ops->flow_dissect) ++ ops->flow_dissect(skb, &proto, &offset); ++ else ++--- a/net/dsa/dsa.c +++++ b/net/dsa/dsa.c ++@@ -20,6 +20,7 @@ ++ #include <linux/phy_fixed.h> ++ #include <linux/ptp_classify.h> ++ #include <linux/etherdevice.h> +++#include <net/dst_metadata.h> ++ ++ #include "dsa_priv.h" ++ ++@@ -225,6 +226,7 @@ static bool dsa_skb_defer_rx_timestamp(s ++ static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev, ++ struct packet_type *pt, struct net_device *unused) ++ { +++ struct metadata_dst *md_dst = skb_metadata_dst(skb); ++ struct dsa_port *cpu_dp = dev->dsa_ptr; ++ struct sk_buff *nskb = NULL; ++ struct dsa_slave_priv *p; ++@@ -238,7 +240,22 @@ static int dsa_switch_rcv(struct sk_buff ++ if (!skb) ++ return 0; ++ ++- nskb = cpu_dp->rcv(skb, dev); +++ if (md_dst && md_dst->type == METADATA_HW_PORT_MUX) { +++ unsigned int port = md_dst->u.port_info.port_id; +++ +++ skb_dst_drop(skb); +++ if (!skb_has_extensions(skb)) +++ skb->slow_gro = 0; +++ +++ skb->dev = dsa_master_find_slave(dev, 0, port); +++ if (likely(skb->dev)) { +++ dsa_default_offload_fwd_mark(skb); +++ nskb = skb; +++ } +++ } else { +++ nskb = cpu_dp->rcv(skb, dev); +++ } +++ ++ if (!nskb) { ++ kfree_skb(skb); ++ return 0; +diff --git a/target/linux/generic/pending-5.15/732-09-net-ethernet-mtk_eth_soc-fix-VLAN-rx-hardware-accele.patch b/target/linux/generic/pending-5.15/732-09-net-ethernet-mtk_eth_soc-fix-VLAN-rx-hardware-accele.patch new file mode 100644 -index 0000000000..de28ebe73a +index 0000000000..c109067802 --- /dev/null -+++ b/target/linux/generic/pending-5.15/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch -@@ -0,0 +1,102 @@ -+From 663b9f99bb35dbc0c7b685f71ee3668a60d31320 Mon Sep 17 00:00:00 2001 -+From: =?UTF-8?q?Marek=20Beh=C3=BAn?= <kabel@kernel.org> -+Date: Mon, 10 Jan 2022 02:02:00 +0100 -+Subject: [PATCH] PCI: aardvark: Make main irq_chip structure a static driver -+ structure -+MIME-Version: 1.0 -+Content-Type: text/plain; charset=UTF-8 -+Content-Transfer-Encoding: 8bit -+ -+Marc Zyngier says [1] that we should use struct irq_chip as a global -+static struct in the driver. Even though the structure currently -+contains a dynamic member (parent_device), Marc says [2] that he plans -+to kill it and make the structure completely static. -+ -+We have already converted others irq_chip structures in this driver in -+this way, but we omitted this one because the .name member is -+dynamically created from device's name, and the name is displayed in -+sysfs, so changing it would break sysfs ABI. -+ -+The rationale for changing the name (to "advk-INT") in spite of sysfs -+ABI, and thus allowing to convert to a static structure, is that after -+the other changes we made in this series, the IRQ chip is basically -+something different: it no logner generates ERR and PME interrupts (they -+are generated by emulated bridge's rp_irq_chip). ++++ b/target/linux/generic/pending-5.15/732-09-net-ethernet-mtk_eth_soc-fix-VLAN-rx-hardware-accele.patch +@@ -0,0 +1,192 @@ ++From: Felix Fietkau <nbd@nbd.name> ++Date: Fri, 28 Oct 2022 11:01:12 +0200 ++Subject: [PATCH] net: ethernet: mtk_eth_soc: fix VLAN rx hardware ++ acceleration + -+[1] https://lore.kernel.org/linux-pci/877dbcvngf.wl-maz@kernel.org/ -+[2] https://lore.kernel.org/linux-pci/874k6gvkhz.wl-maz@kernel.org/ ++- enable VLAN untagging for PDMA rx ++- make it possible to disable the feature via ethtool ++- pass VLAN tag to the DSA driver ++- untag special tag on PDMA only if no non-DSA devices are in use ++- disable special tag untagging on 7986 for now, since it's not working yet + -+Signed-off-by: Marek Behún <kabel@kernel.org> ++Signed-off-by: Felix Fietkau <nbd@nbd.name> +--- -+ drivers/pci/controller/pci-aardvark.c | 25 +++++++------------------ -+ 1 file changed, 7 insertions(+), 18 deletions(-) + -+--- a/drivers/pci/controller/pci-aardvark.c -++++ b/drivers/pci/controller/pci-aardvark.c -+@@ -274,7 +274,6 @@ struct advk_pcie { -+ u8 wins_count; -+ struct irq_domain *rp_irq_domain; -+ struct irq_domain *irq_domain; -+- struct irq_chip irq_chip; -+ raw_spinlock_t irq_lock; -+ struct irq_domain *msi_domain; -+ struct irq_domain *msi_inner_domain; -+@@ -1330,14 +1329,19 @@ static void advk_pcie_irq_unmask(struct -+ raw_spin_unlock_irqrestore(&pcie->irq_lock, flags); -+ } -+ -++static struct irq_chip advk_irq_chip = { -++ .name = "advk-INT", -++ .irq_mask = advk_pcie_irq_mask, -++ .irq_unmask = advk_pcie_irq_unmask, -++}; ++--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++@@ -23,6 +23,7 @@ ++ #include <linux/jhash.h> ++ #include <linux/bitfield.h> ++ #include <net/dsa.h> +++#include <net/dst_metadata.h> ++ ++ #include "mtk_eth_soc.h" ++ #include "mtk_wed.h" ++@@ -1967,16 +1968,22 @@ static int mtk_poll_rx(struct napi_struc ++ htons(RX_DMA_VPID(trxd.rxd4)), ++ RX_DMA_VID(trxd.rxd4)); ++ } else if (trxd.rxd2 & RX_DMA_VTAG) { ++- __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), +++ __vlan_hwaccel_put_tag(skb, htons(RX_DMA_VPID(trxd.rxd3)), ++ RX_DMA_VID(trxd.rxd3)); ++ } +++ } ++ -+ static int advk_pcie_irq_map(struct irq_domain *h, -+ unsigned int virq, irq_hw_number_t hwirq) +++ /* When using VLAN untagging in combination with DSA, the +++ * hardware treats the MTK special tag as a VLAN and untags it. +++ */ +++ if (skb_vlan_tag_present(skb) && netdev_uses_dsa(netdev)) { +++ unsigned int port = ntohs(skb->vlan_proto) & GENMASK(2, 0); ++ ++- /* If the device is attached to a dsa switch, the special ++- * tag inserted in VLAN field by hw switch can * be offloaded ++- * by RX HW VLAN offload. Clear vlan info. ++- */ ++- if (netdev_uses_dsa(netdev)) ++- __vlan_hwaccel_clear_tag(skb); +++ if (port < ARRAY_SIZE(eth->dsa_meta) && +++ eth->dsa_meta[port]) +++ skb_dst_set_noref(skb, ð->dsa_meta[port]->dst); +++ +++ __vlan_hwaccel_clear_tag(skb); ++ } ++ ++ skb_record_rx_queue(skb, 0); ++@@ -2793,15 +2800,30 @@ static netdev_features_t mtk_fix_feature ++ ++ static int mtk_set_features(struct net_device *dev, netdev_features_t features) + { -+ struct advk_pcie *pcie = h->host_data; ++- int err = 0; +++ struct mtk_mac *mac = netdev_priv(dev); +++ struct mtk_eth *eth = mac->hw; +++ netdev_features_t diff = dev->features ^ features; +++ int i; +++ +++ if ((diff & NETIF_F_LRO) && !(features & NETIF_F_LRO)) +++ mtk_hwlro_netdev_disable(dev); + -+ irq_set_status_flags(virq, IRQ_LEVEL); -+- irq_set_chip_and_handler(virq, &pcie->irq_chip, -+- handle_level_irq); -++ irq_set_chip_and_handler(virq, &advk_irq_chip, handle_level_irq); -+ irq_set_chip_data(virq, pcie); ++- if (!((dev->features ^ features) & NETIF_F_LRO)) +++ /* Set RX VLAN offloading */ +++ if (!(diff & NETIF_F_HW_VLAN_CTAG_RX)) ++ return 0; + -+ return 0; -+@@ -1396,7 +1400,6 @@ static int advk_pcie_init_irq_domain(str -+ struct device *dev = &pcie->pdev->dev; -+ struct device_node *node = dev->of_node; -+ struct device_node *pcie_intc_node; -+- struct irq_chip *irq_chip; -+ int ret = 0; ++- if (!(features & NETIF_F_LRO)) ++- mtk_hwlro_netdev_disable(dev); +++ mtk_w32(eth, !!(features & NETIF_F_HW_VLAN_CTAG_RX), +++ MTK_CDMP_EG_CTRL); + -+ raw_spin_lock_init(&pcie->irq_lock); -+@@ -1407,28 +1410,14 @@ static int advk_pcie_init_irq_domain(str -+ return -ENODEV; -+ } ++- return err; +++ /* sync features with other MAC */ +++ for (i = 0; i < MTK_MAC_COUNT; i++) { +++ if (!eth->netdev[i] || eth->netdev[i] == dev) +++ continue; +++ eth->netdev[i]->features &= ~NETIF_F_HW_VLAN_CTAG_RX; +++ eth->netdev[i]->features |= features & NETIF_F_HW_VLAN_CTAG_RX; +++ } +++ +++ return 0; ++ } + -+- irq_chip = &pcie->irq_chip; -+- -+- irq_chip->name = devm_kasprintf(dev, GFP_KERNEL, "%s-irq", -+- dev_name(dev)); -+- if (!irq_chip->name) { -+- ret = -ENOMEM; -+- goto out_put_node; -+- } -+- -+- irq_chip->irq_mask = advk_pcie_irq_mask; -+- irq_chip->irq_unmask = advk_pcie_irq_unmask; -+- -+ pcie->irq_domain = -+ irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX, -+ &advk_pcie_irq_domain_ops, pcie); -+ if (!pcie->irq_domain) { -+ dev_err(dev, "Failed to get a INTx IRQ domain\n"); -+ ret = -ENOMEM; -+- goto out_put_node; -+ } -+ -+-out_put_node: -+ of_node_put(pcie_intc_node); -+ return ret; ++ /* wait for DMA to finish whatever it is doing before we start using it again */ ++@@ -3083,11 +3105,45 @@ found: ++ return NOTIFY_DONE; + } -diff --git a/target/linux/generic/pending-5.15/851-0001-phy-marvell-phy-mvebu-a3700-comphy-Remove-port-from-.patch b/target/linux/generic/pending-5.15/851-0001-phy-marvell-phy-mvebu-a3700-comphy-Remove-port-from-.patch -new file mode 100644 -index 0000000000..4a963be952 ---- /dev/null -+++ b/target/linux/generic/pending-5.15/851-0001-phy-marvell-phy-mvebu-a3700-comphy-Remove-port-from-.patch -@@ -0,0 +1,217 @@ -+From a719f7ba7fcba05d85801c6f0267f389a21627c1 Mon Sep 17 00:00:00 2001 -+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org> -+Date: Fri, 24 Sep 2021 13:03:02 +0200 -+Subject: [PATCH] phy: marvell: phy-mvebu-a3700-comphy: Remove port from driver -+ configuration -+MIME-Version: 1.0 -+Content-Type: text/plain; charset=UTF-8 -+Content-Transfer-Encoding: 8bit -+ -+Port number is encoded into argument for SMC call. It is zero for SATA, -+PCIe and also both USB 3.0 PHYs. It is non-zero only for Ethernet PHY -+(incorrectly called SGMII) on lane 0. Ethernet PHY on lane 1 also uses zero -+port number. -+ -+So construct "port" bits for SMC call argument can be constructed directly -+from PHY type and lane number. -+ -+Change driver code to always pass zero port number for non-ethernet PHYs -+and for ethernet PHYs determinate port number from lane number. This -+simplifies the driver. -+ -+As port number from DT PHY configuration is not used anymore, remove whole -+driver code which parses it. This also simplifies the driver. -+ -+Signed-off-by: Pali Rohár <pali@kernel.org> -+Signed-off-by: Marek Behún <kabel@kernel.org> -+Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com> -+--- -+ drivers/phy/marvell/phy-mvebu-a3700-comphy.c | 62 +++++++++----------- -+ 1 file changed, 29 insertions(+), 33 deletions(-) -+ -+--- a/drivers/phy/marvell/phy-mvebu-a3700-comphy.c -++++ b/drivers/phy/marvell/phy-mvebu-a3700-comphy.c -+@@ -20,7 +20,6 @@ -+ #include <linux/platform_device.h> -+ -+ #define MVEBU_A3700_COMPHY_LANES 3 -+-#define MVEBU_A3700_COMPHY_PORTS 2 -+ -+ /* COMPHY Fast SMC function identifiers */ -+ #define COMPHY_SIP_POWER_ON 0x82000001 -+@@ -45,51 +44,47 @@ -+ #define COMPHY_FW_NET(mode, idx, speed) (COMPHY_FW_MODE(mode) | \ -+ ((idx) << 8) | \ -+ ((speed) << 2)) -+-#define COMPHY_FW_PCIE(mode, idx, speed, width) (COMPHY_FW_NET(mode, idx, speed) | \ -++#define COMPHY_FW_PCIE(mode, speed, width) (COMPHY_FW_NET(mode, 0, speed) | \ -+ ((width) << 18)) -+ -+ struct mvebu_a3700_comphy_conf { -+ unsigned int lane; -+ enum phy_mode mode; -+ int submode; -+- unsigned int port; -+ u32 fw_mode; -+ }; -+ -+-#define MVEBU_A3700_COMPHY_CONF(_lane, _mode, _smode, _port, _fw) \ -++#define MVEBU_A3700_COMPHY_CONF(_lane, _mode, _smode, _fw) \ -+ { \ -+ .lane = _lane, \ -+ .mode = _mode, \ -+ .submode = _smode, \ -+- .port = _port, \ -+ .fw_mode = _fw, \ -+ } + -+-#define MVEBU_A3700_COMPHY_CONF_GEN(_lane, _mode, _port, _fw) \ -+- MVEBU_A3700_COMPHY_CONF(_lane, _mode, PHY_INTERFACE_MODE_NA, _port, _fw) -++#define MVEBU_A3700_COMPHY_CONF_GEN(_lane, _mode, _fw) \ -++ MVEBU_A3700_COMPHY_CONF(_lane, _mode, PHY_INTERFACE_MODE_NA, _fw) -+ -+-#define MVEBU_A3700_COMPHY_CONF_ETH(_lane, _smode, _port, _fw) \ -+- MVEBU_A3700_COMPHY_CONF(_lane, PHY_MODE_ETHERNET, _smode, _port, _fw) -++#define MVEBU_A3700_COMPHY_CONF_ETH(_lane, _smode, _fw) \ -++ MVEBU_A3700_COMPHY_CONF(_lane, PHY_MODE_ETHERNET, _smode, _fw) -+ -+ static const struct mvebu_a3700_comphy_conf mvebu_a3700_comphy_modes[] = { -+ /* lane 0 */ -+- MVEBU_A3700_COMPHY_CONF_GEN(0, PHY_MODE_USB_HOST_SS, 0, -++ MVEBU_A3700_COMPHY_CONF_GEN(0, PHY_MODE_USB_HOST_SS, -+ COMPHY_FW_MODE_USB3H), -+- MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_SGMII, 1, -++ MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_SGMII, -+ COMPHY_FW_MODE_SGMII), -+- MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_2500BASEX, 1, -++ MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_2500BASEX, -+ COMPHY_FW_MODE_2500BASEX), -+ /* lane 1 */ -+- MVEBU_A3700_COMPHY_CONF_GEN(1, PHY_MODE_PCIE, 0, -+- COMPHY_FW_MODE_PCIE), -+- MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_SGMII, 0, -++ MVEBU_A3700_COMPHY_CONF_GEN(1, PHY_MODE_PCIE, COMPHY_FW_MODE_PCIE), -++ MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_SGMII, -+ COMPHY_FW_MODE_SGMII), -+- MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_2500BASEX, 0, -++ MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_2500BASEX, -+ COMPHY_FW_MODE_2500BASEX), -+ /* lane 2 */ -+- MVEBU_A3700_COMPHY_CONF_GEN(2, PHY_MODE_SATA, 0, -+- COMPHY_FW_MODE_SATA), -+- MVEBU_A3700_COMPHY_CONF_GEN(2, PHY_MODE_USB_HOST_SS, 0, -++ MVEBU_A3700_COMPHY_CONF_GEN(2, PHY_MODE_SATA, COMPHY_FW_MODE_SATA), -++ MVEBU_A3700_COMPHY_CONF_GEN(2, PHY_MODE_USB_HOST_SS, -+ COMPHY_FW_MODE_USB3H), -+ }; +++static bool mtk_uses_dsa(struct net_device *dev) +++{ +++#if IS_ENABLED(CONFIG_NET_DSA) +++ return netdev_uses_dsa(dev) && +++ dev->dsa_ptr->tag_ops->proto == DSA_TAG_PROTO_MTK; +++#else +++ return false; +++#endif +++} +++ ++ static int mtk_open(struct net_device *dev) ++ { ++ struct mtk_mac *mac = netdev_priv(dev); ++ struct mtk_eth *eth = mac->hw; ++- int err; +++ int i, err; +++ +++ if (mtk_uses_dsa(dev) && !eth->prog) { +++ for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) { +++ struct metadata_dst *md_dst = eth->dsa_meta[i]; +++ +++ if (md_dst) +++ continue; +++ +++ md_dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, +++ GFP_KERNEL); +++ if (!md_dst) +++ return -ENOMEM; +++ +++ md_dst->u.port_info.port_id = i; +++ eth->dsa_meta[i] = md_dst; +++ } +++ } else { +++ /* Hardware special tag parsing needs to be disabled if at least +++ * one MAC does not use DSA. +++ */ +++ u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL); +++ val &= ~MTK_CDMP_STAG_EN; +++ mtk_w32(eth, val, MTK_CDMP_IG_CTRL); +++ } + -+@@ -98,7 +93,6 @@ struct mvebu_a3700_comphy_lane { -+ unsigned int id; -+ enum phy_mode mode; -+ int submode; -+- int port; -+ }; ++ err = phylink_of_phy_connect(mac->phylink, mac->of_node, 0); ++ if (err) { ++@@ -3417,6 +3473,10 @@ static int mtk_hw_init(struct mtk_eth *e ++ */ ++ val = mtk_r32(eth, MTK_CDMQ_IG_CTRL); ++ mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL); +++ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { +++ val = mtk_r32(eth, MTK_CDMP_IG_CTRL); +++ mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL); +++ } + -+ static int mvebu_a3700_comphy_smc(unsigned long function, unsigned long lane, -+@@ -120,7 +114,7 @@ static int mvebu_a3700_comphy_smc(unsign ++ /* Enable RX VLan Offloading */ ++ mtk_w32(eth, 1, MTK_CDMP_EG_CTRL); ++@@ -3634,6 +3694,12 @@ static int mtk_free_dev(struct mtk_eth * ++ free_netdev(eth->netdev[i]); + } ++ +++ for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) { +++ if (!eth->dsa_meta[i]) +++ break; +++ metadata_dst_free(eth->dsa_meta[i]); +++ } +++ ++ return 0; + } + -+-static int mvebu_a3700_comphy_get_fw_mode(int lane, int port, -++static int mvebu_a3700_comphy_get_fw_mode(int lane, -+ enum phy_mode mode, -+ int submode) -+ { -+@@ -132,7 +126,6 @@ static int mvebu_a3700_comphy_get_fw_mod ++--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++@@ -22,6 +22,9 @@ ++ #include <linux/bpf_trace.h> ++ #include "mtk_ppe.h" + -+ for (i = 0; i < n; i++) { -+ if (mvebu_a3700_comphy_modes[i].lane == lane && -+- mvebu_a3700_comphy_modes[i].port == port && -+ mvebu_a3700_comphy_modes[i].mode == mode && -+ mvebu_a3700_comphy_modes[i].submode == submode) -+ break; -+@@ -153,7 +146,7 @@ static int mvebu_a3700_comphy_set_mode(s -+ if (submode == PHY_INTERFACE_MODE_1000BASEX) -+ submode = PHY_INTERFACE_MODE_SGMII; -+ -+- fw_mode = mvebu_a3700_comphy_get_fw_mode(lane->id, lane->port, mode, -++ fw_mode = mvebu_a3700_comphy_get_fw_mode(lane->id, mode, -+ submode); -+ if (fw_mode < 0) { -+ dev_err(lane->dev, "invalid COMPHY mode\n"); -+@@ -172,9 +165,10 @@ static int mvebu_a3700_comphy_power_on(s -+ struct mvebu_a3700_comphy_lane *lane = phy_get_drvdata(phy); -+ u32 fw_param; -+ int fw_mode; -++ int fw_port; -+ int ret; +++#define MTK_MAX_DSA_PORTS 7 +++#define MTK_DSA_PORT_MASK GENMASK(2, 0) +++ ++ #define MTK_QDMA_NUM_QUEUES 16 ++ #define MTK_QDMA_PAGE_SIZE 2048 ++ #define MTK_MAX_RX_LENGTH 1536 ++@@ -93,6 +96,9 @@ ++ #define MTK_CDMQ_IG_CTRL 0x1400 ++ #define MTK_CDMQ_STAG_EN BIT(0) + -+- fw_mode = mvebu_a3700_comphy_get_fw_mode(lane->id, lane->port, -++ fw_mode = mvebu_a3700_comphy_get_fw_mode(lane->id, -+ lane->mode, lane->submode); -+ if (fw_mode < 0) { -+ dev_err(lane->dev, "invalid COMPHY mode\n"); -+@@ -191,17 +185,18 @@ static int mvebu_a3700_comphy_power_on(s -+ fw_param = COMPHY_FW_MODE(fw_mode); -+ break; -+ case PHY_MODE_ETHERNET: -++ fw_port = (lane->id == 0) ? 1 : 0; -+ switch (lane->submode) { -+ case PHY_INTERFACE_MODE_SGMII: -+ dev_dbg(lane->dev, "set lane %d to SGMII mode\n", -+ lane->id); -+- fw_param = COMPHY_FW_NET(fw_mode, lane->port, -++ fw_param = COMPHY_FW_NET(fw_mode, fw_port, -+ COMPHY_FW_SPEED_1_25G); -+ break; -+ case PHY_INTERFACE_MODE_2500BASEX: -+ dev_dbg(lane->dev, "set lane %d to 2500BASEX mode\n", -+ lane->id); -+- fw_param = COMPHY_FW_NET(fw_mode, lane->port, -++ fw_param = COMPHY_FW_NET(fw_mode, fw_port, -+ COMPHY_FW_SPEED_3_125G); -+ break; -+ default: -+@@ -212,8 +207,7 @@ static int mvebu_a3700_comphy_power_on(s -+ break; -+ case PHY_MODE_PCIE: -+ dev_dbg(lane->dev, "set lane %d to PCIe mode\n", lane->id); -+- fw_param = COMPHY_FW_PCIE(fw_mode, lane->port, -+- COMPHY_FW_SPEED_5G, -++ fw_param = COMPHY_FW_PCIE(fw_mode, COMPHY_FW_SPEED_5G, -+ phy->attrs.bus_width); -+ break; -+ default: -+@@ -247,17 +241,20 @@ static struct phy *mvebu_a3700_comphy_xl -+ struct of_phandle_args *args) -+ { -+ struct mvebu_a3700_comphy_lane *lane; -++ unsigned int port; -+ struct phy *phy; +++/* CDMQ Exgress Control Register */ +++#define MTK_CDMQ_EG_CTRL 0x1404 +++ ++ /* CDMP Ingress Control Register */ ++ #define MTK_CDMP_IG_CTRL 0x400 ++ #define MTK_CDMP_STAG_EN BIT(0) ++@@ -1140,6 +1146,8 @@ struct mtk_eth { + -+- if (WARN_ON(args->args[0] >= MVEBU_A3700_COMPHY_PORTS)) -+- return ERR_PTR(-EINVAL); -+- -+ phy = of_phy_simple_xlate(dev, args); -+ if (IS_ERR(phy)) -+ return phy; ++ int ip_align; + -+ lane = phy_get_drvdata(phy); -+- lane->port = args->args[0]; +++ struct metadata_dst *dsa_meta[MTK_MAX_DSA_PORTS]; ++ -++ port = args->args[0]; -++ if (port != 0 && (port != 1 || lane->id != 0)) { -++ dev_err(lane->dev, "invalid port number %u\n", port); -++ return ERR_PTR(-EINVAL); -++ } -+ -+ return phy; -+ } -+@@ -302,7 +299,6 @@ static int mvebu_a3700_comphy_probe(stru -+ lane->mode = PHY_MODE_INVALID; -+ lane->submode = PHY_INTERFACE_MODE_NA; -+ lane->id = lane_id; -+- lane->port = -1; -+ phy_set_drvdata(phy, lane); -+ } ++ struct mtk_ppe *ppe[2]; ++ struct rhashtable flow_table; + -diff --git a/target/linux/generic/pending-5.15/851-0002-phy-marvell-phy-mvebu-a3700-comphy-Add-native-kernel.patch b/target/linux/generic/pending-5.15/851-0002-phy-marvell-phy-mvebu-a3700-comphy-Add-native-kernel.patch +diff --git a/target/linux/generic/pending-5.15/732-10-net-ethernet-mtk_eth_soc-work-around-issue-with-send.patch b/target/linux/generic/pending-5.15/732-10-net-ethernet-mtk_eth_soc-work-around-issue-with-send.patch new file mode 100644 -index 0000000000..73ead1e16c +index 0000000000..ba86686eeb --- /dev/null -+++ b/target/linux/generic/pending-5.15/851-0002-phy-marvell-phy-mvebu-a3700-comphy-Add-native-kernel.patch -@@ -0,0 +1,1564 @@ -+From 9d276da259cce20b2ed7a868b6e6a6a205f7bb04 Mon Sep 17 00:00:00 2001 -+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org> -+Date: Thu, 23 Sep 2021 19:20:13 +0200 -+Subject: [PATCH] phy: marvell: phy-mvebu-a3700-comphy: Add native kernel -+ implementation -+MIME-Version: 1.0 -+Content-Type: text/plain; charset=UTF-8 -+Content-Transfer-Encoding: 8bit ++++ b/target/linux/generic/pending-5.15/732-10-net-ethernet-mtk_eth_soc-work-around-issue-with-send.patch +@@ -0,0 +1,78 @@ ++From: Felix Fietkau <nbd@nbd.name> ++Date: Thu, 3 Nov 2022 12:38:49 +0100 ++Subject: [PATCH] net: ethernet: mtk_eth_soc: work around issue with ++ sending small fragments + -+Remove old RPC implementation and add a new native kernel implementation. -+ -+The old implementation uses ARM SMC API to issue RPC calls to ARM Trusted -+Firmware which provides real implementation of PHY configuration. -+ -+But older versions of ARM Trusted Firmware do not provide this PHY -+configuration functionality, simply returning: operation not supported; or -+worse, some versions provide the configuration functionality incorrectly. -+ -+For example the firmware shipped in ESPRESSObin board has this older -+version of ARM Trusted Firmware and therefore SATA, USB 3.0 and PCIe -+functionality do not work with newer versions of Linux kernel. -+ -+Due to the above reasons, the following commits were introduced into Linux, -+to workaround these issues by ignoring -EOPNOTSUPP error code from -+phy-mvebu-a3700-comphy driver function phy_power_on(): -+ -+commit 45aefe3d2251 ("ata: ahci: mvebu: Make SATA PHY optional for Armada -+3720") -+commit 3241929b67d2 ("usb: host: xhci: mvebu: make USB 3.0 PHY optional for -+Armada 3720") -+commit b0c6ae0f8948 ("PCI: aardvark: Fix initialization with old Marvell's -+Arm Trusted Firmware") -+ -+Replace this RPC implementation with proper native kernel implementation, -+which is independent on the firmware. Never return -EOPNOTSUPP for proper -+arguments. -+ -+This should solve multiple issues with real-world boards, where it is not -+possible or really inconvenient to change the firmware. Let's eliminate -+these issues. -+ -+This implementation is ported directly from Armada 3720 comphy driver found -+in newest version of ARM Trusted Firmware source code, but with various -+fixes of register names, some added comments, some refactoring due to the -+original code not conforming to kernel standards. Also PCIe mode poweroff -+support was added here, and PHY reset support. These changes are also going -+to be sent to ARM Trusted Firmware. -+ -+Signed-off-by: Pali Rohár <pali@kernel.org> -+Acked-by: Miquel Raynal <miquel.raynal@bootlin.com> -+[ Pali did the porting from ATF. -+ I (Marek) then fixed some register names, some various other things, -+ added some comments and refactored the code to kernel standards. Also -+ fixed PHY poweroff and added PHY reset. ] -+Signed-off-by: Marek Behún <kabel@kernel.org> ++When frames are sent with very small fragments, the DMA engine appears to ++lock up and transmit attempts time out. Fix this by detecting the presence ++of small fragments and use skb_gso_segment + skb_linearize to deal with ++them ++ ++Signed-off-by: Felix Fietkau <nbd@nbd.name> +--- -+ drivers/phy/marvell/phy-mvebu-a3700-comphy.c | 1351 ++++++++++++++++-- -+ 1 file changed, 1234 insertions(+), 117 deletions(-) -+ -+--- a/drivers/phy/marvell/phy-mvebu-a3700-comphy.c -++++ b/drivers/phy/marvell/phy-mvebu-a3700-comphy.c -+@@ -5,12 +5,16 @@ -+ * Authors: -+ * Evan Wang <xswang@marvell.com> -+ * Miquèl Raynal <miquel.raynal@bootlin.com> -++ * Pali Rohár <pali@kernel.org> -++ * Marek Behún <kabel@kernel.org> -+ * -+ * Structure inspired from phy-mvebu-cp110-comphy.c written by Antoine Tenart. -+- * SMC call initial support done by Grzegorz Jaszczyk. -++ * Comphy code from ARM Trusted Firmware ported by Pali Rohár <pali@kernel.org> -++ * and Marek Behún <kabel@kernel.org>. -+ */ -+ -+-#include <linux/arm-smccc.h> -++#include <linux/bitfield.h> -++#include <linux/clk.h> -+ #include <linux/io.h> -+ #include <linux/iopoll.h> -+ #include <linux/mfd/syscon.h> -+@@ -18,103 +22,1147 @@ -+ #include <linux/phy.h> -+ #include <linux/phy/phy.h> -+ #include <linux/platform_device.h> -++#include <linux/spinlock.h> ++ ++--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++@@ -1396,12 +1396,28 @@ static void mtk_wake_queue(struct mtk_et ++ } ++ } + -+-#define MVEBU_A3700_COMPHY_LANES 3 -++#define PLL_SET_DELAY_US 600 -++#define COMPHY_PLL_SLEEP 1000 -++#define COMPHY_PLL_TIMEOUT 150000 +++static bool mtk_skb_has_small_frag(struct sk_buff *skb) +++{ +++ int min_size = 16; +++ int i; ++ -++/* Comphy lane2 indirect access register offset */ -++#define COMPHY_LANE2_INDIR_ADDR 0x0 -++#define COMPHY_LANE2_INDIR_DATA 0x4 +++ if (skb_headlen(skb) < min_size) +++ return true; ++ -++/* SATA and USB3 PHY offset compared to SATA PHY */ -++#define COMPHY_LANE2_REGS_BASE 0x200 +++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) +++ if (skb_frag_size(&skb_shinfo(skb)->frags[i]) < min_size) +++ return true; ++ -++/* -++ * When accessing common PHY lane registers directly, we need to shift by 1, -++ * since the registers are 16-bit. -++ */ -++#define COMPHY_LANE_REG_DIRECT(reg) (((reg) & 0x7FF) << 1) -++ -++/* COMPHY registers */ -++#define COMPHY_POWER_PLL_CTRL 0x01 -++#define PU_IVREF_BIT BIT(15) -++#define PU_PLL_BIT BIT(14) -++#define PU_RX_BIT BIT(13) -++#define PU_TX_BIT BIT(12) -++#define PU_TX_INTP_BIT BIT(11) -++#define PU_DFE_BIT BIT(10) -++#define RESET_DTL_RX_BIT BIT(9) -++#define PLL_LOCK_BIT BIT(8) -++#define REF_FREF_SEL_MASK GENMASK(4, 0) -++#define REF_FREF_SEL_SERDES_25MHZ FIELD_PREP(REF_FREF_SEL_MASK, 0x1) -++#define REF_FREF_SEL_SERDES_40MHZ FIELD_PREP(REF_FREF_SEL_MASK, 0x3) -++#define REF_FREF_SEL_SERDES_50MHZ FIELD_PREP(REF_FREF_SEL_MASK, 0x4) -++#define REF_FREF_SEL_PCIE_USB3_25MHZ FIELD_PREP(REF_FREF_SEL_MASK, 0x2) -++#define REF_FREF_SEL_PCIE_USB3_40MHZ FIELD_PREP(REF_FREF_SEL_MASK, 0x3) -++#define COMPHY_MODE_MASK GENMASK(7, 5) -++#define COMPHY_MODE_SATA FIELD_PREP(COMPHY_MODE_MASK, 0x0) -++#define COMPHY_MODE_PCIE FIELD_PREP(COMPHY_MODE_MASK, 0x3) -++#define COMPHY_MODE_SERDES FIELD_PREP(COMPHY_MODE_MASK, 0x4) -++#define COMPHY_MODE_USB3 FIELD_PREP(COMPHY_MODE_MASK, 0x5) -++ -++#define COMPHY_KVCO_CAL_CTRL 0x02 -++#define USE_MAX_PLL_RATE_BIT BIT(12) -++#define SPEED_PLL_MASK GENMASK(7, 2) -++#define SPEED_PLL_VALUE_16 FIELD_PREP(SPEED_PLL_MASK, 0x10) -++ -++#define COMPHY_DIG_LOOPBACK_EN 0x23 -++#define SEL_DATA_WIDTH_MASK GENMASK(11, 10) -++#define DATA_WIDTH_10BIT FIELD_PREP(SEL_DATA_WIDTH_MASK, 0x0) -++#define DATA_WIDTH_20BIT FIELD_PREP(SEL_DATA_WIDTH_MASK, 0x1) -++#define DATA_WIDTH_40BIT FIELD_PREP(SEL_DATA_WIDTH_MASK, 0x2) -++#define PLL_READY_TX_BIT BIT(4) -++ -++#define COMPHY_SYNC_PATTERN 0x24 -++#define TXD_INVERT_BIT BIT(10) -++#define RXD_INVERT_BIT BIT(11) -++ -++#define COMPHY_SYNC_MASK_GEN 0x25 -++#define PHY_GEN_MAX_MASK GENMASK(11, 10) -++#define PHY_GEN_MAX_USB3_5G FIELD_PREP(PHY_GEN_MAX_MASK, 0x1) -++ -++#define COMPHY_ISOLATION_CTRL 0x26 -++#define PHY_ISOLATE_MODE BIT(15) -++ -++#define COMPHY_GEN2_SET2 0x3e -++#define GS2_TX_SSC_AMP_MASK GENMASK(15, 9) -++#define GS2_TX_SSC_AMP_4128 FIELD_PREP(GS2_TX_SSC_AMP_MASK, 0x20) -++#define GS2_VREG_RXTX_MAS_ISET_MASK GENMASK(8, 7) -++#define GS2_VREG_RXTX_MAS_ISET_60U FIELD_PREP(GS2_VREG_RXTX_MAS_ISET_MASK,\ -++ 0x0) -++#define GS2_VREG_RXTX_MAS_ISET_80U FIELD_PREP(GS2_VREG_RXTX_MAS_ISET_MASK,\ -++ 0x1) -++#define GS2_VREG_RXTX_MAS_ISET_100U FIELD_PREP(GS2_VREG_RXTX_MAS_ISET_MASK,\ -++ 0x2) -++#define GS2_VREG_RXTX_MAS_ISET_120U FIELD_PREP(GS2_VREG_RXTX_MAS_ISET_MASK,\ -++ 0x3) -++#define GS2_RSVD_6_0_MASK GENMASK(6, 0) -++ -++#define COMPHY_GEN3_SET2 0x3f -++ -++#define COMPHY_IDLE_SYNC_EN 0x48 -++#define IDLE_SYNC_EN BIT(12) -++ -++#define COMPHY_MISC_CTRL0 0x4F -++#define CLK100M_125M_EN BIT(4) -++#define TXDCLK_2X_SEL BIT(6) -++#define CLK500M_EN BIT(7) -++#define PHY_REF_CLK_SEL BIT(10) -++ -++#define COMPHY_SFT_RESET 0x52 -++#define SFT_RST BIT(9) -++#define SFT_RST_NO_REG BIT(10) -++ -++#define COMPHY_MISC_CTRL1 0x73 -++#define SEL_BITS_PCIE_FORCE BIT(15) -++ -++#define COMPHY_GEN2_SET3 0x112 -++#define GS3_FFE_CAP_SEL_MASK GENMASK(3, 0) -++#define GS3_FFE_CAP_SEL_VALUE FIELD_PREP(GS3_FFE_CAP_SEL_MASK, 0xF) -++ -++/* PIPE registers */ -++#define COMPHY_PIPE_LANE_CFG0 0x180 -++#define PRD_TXDEEMPH0_MASK BIT(0) -++#define PRD_TXMARGIN_MASK GENMASK(3, 1) -++#define PRD_TXSWING_MASK BIT(4) -++#define CFG_TX_ALIGN_POS_MASK GENMASK(8, 5) -++ -++#define COMPHY_PIPE_LANE_CFG1 0x181 -++#define PRD_TXDEEMPH1_MASK BIT(15) -++#define USE_MAX_PLL_RATE_EN BIT(9) -++#define TX_DET_RX_MODE BIT(6) -++#define GEN2_TX_DATA_DLY_MASK GENMASK(4, 3) -++#define GEN2_TX_DATA_DLY_DEFT FIELD_PREP(GEN2_TX_DATA_DLY_MASK, 2) -++#define TX_ELEC_IDLE_MODE_EN BIT(0) -++ -++#define COMPHY_PIPE_LANE_STAT1 0x183 -++#define TXDCLK_PCLK_EN BIT(0) -++ -++#define COMPHY_PIPE_LANE_CFG4 0x188 -++#define SPREAD_SPECTRUM_CLK_EN BIT(7) -++ -++#define COMPHY_PIPE_RST_CLK_CTRL 0x1C1 -++#define PIPE_SOFT_RESET BIT(0) -++#define PIPE_REG_RESET BIT(1) -++#define MODE_CORE_CLK_FREQ_SEL BIT(9) -++#define MODE_PIPE_WIDTH_32 BIT(3) -++#define MODE_REFDIV_MASK GENMASK(5, 4) -++#define MODE_REFDIV_BY_4 FIELD_PREP(MODE_REFDIV_MASK, 0x2) -++ -++#define COMPHY_PIPE_TEST_MODE_CTRL 0x1C2 -++#define MODE_MARGIN_OVERRIDE BIT(2) -++ -++#define COMPHY_PIPE_CLK_SRC_LO 0x1C3 -++#define MODE_CLK_SRC BIT(0) -++#define BUNDLE_PERIOD_SEL BIT(1) -++#define BUNDLE_PERIOD_SCALE_MASK GENMASK(3, 2) -++#define BUNDLE_SAMPLE_CTRL BIT(4) -++#define PLL_READY_DLY_MASK GENMASK(7, 5) -++#define CFG_SEL_20B BIT(15) -++ -++#define COMPHY_PIPE_PWR_MGM_TIM1 0x1D0 -++#define CFG_PM_OSCCLK_WAIT_MASK GENMASK(15, 12) -++#define CFG_PM_RXDEN_WAIT_MASK GENMASK(11, 8) -++#define CFG_PM_RXDEN_WAIT_1_UNIT FIELD_PREP(CFG_PM_RXDEN_WAIT_MASK, 0x1) -++#define CFG_PM_RXDLOZ_WAIT_MASK GENMASK(7, 0) -++#define CFG_PM_RXDLOZ_WAIT_7_UNIT FIELD_PREP(CFG_PM_RXDLOZ_WAIT_MASK, 0x7) -++#define CFG_PM_RXDLOZ_WAIT_12_UNIT FIELD_PREP(CFG_PM_RXDLOZ_WAIT_MASK, 0xC) +++ return false; +++} ++ -++/* -++ * This register is not from PHY lane register space. It only exists in the -++ * indirect register space, before the actual PHY lane 2 registers. So the -++ * offset is absolute, not relative to COMPHY_LANE2_REGS_BASE. -++ * It is used only for SATA PHY initialization. -++ */ -++#define COMPHY_RESERVED_REG 0x0E -++#define PHYCTRL_FRM_PIN_BIT BIT(13) ++ static netdev_tx_t mtk_start_xmit(struct sk_buff *skb, struct net_device *dev) ++ { ++ struct mtk_mac *mac = netdev_priv(dev); ++ struct mtk_eth *eth = mac->hw; ++ struct mtk_tx_ring *ring = ð->tx_ring; ++ struct net_device_stats *stats = &dev->stats; +++ struct sk_buff *segs, *next; ++ bool gso = false; ++ int tx_num; ++ ++@@ -1423,6 +1439,17 @@ static netdev_tx_t mtk_start_xmit(struct ++ return NETDEV_TX_BUSY; ++ } + -+-/* COMPHY Fast SMC function identifiers */ -+-#define COMPHY_SIP_POWER_ON 0x82000001 -+-#define COMPHY_SIP_POWER_OFF 0x82000002 -+-#define COMPHY_SIP_PLL_LOCK 0x82000003 -+- -+-#define COMPHY_FW_MODE_SATA 0x1 -+-#define COMPHY_FW_MODE_SGMII 0x2 -+-#define COMPHY_FW_MODE_2500BASEX 0x3 -+-#define COMPHY_FW_MODE_USB3H 0x4 -+-#define COMPHY_FW_MODE_USB3D 0x5 -+-#define COMPHY_FW_MODE_PCIE 0x6 -+-#define COMPHY_FW_MODE_USB3 0xa -+- -+-#define COMPHY_FW_SPEED_1_25G 0 /* SGMII 1G */ -+-#define COMPHY_FW_SPEED_2_5G 1 -+-#define COMPHY_FW_SPEED_3_125G 2 /* 2500BASE-X */ -+-#define COMPHY_FW_SPEED_5G 3 -+-#define COMPHY_FW_SPEED_MAX 0x3F -+- -+-#define COMPHY_FW_MODE(mode) ((mode) << 12) -+-#define COMPHY_FW_NET(mode, idx, speed) (COMPHY_FW_MODE(mode) | \ -+- ((idx) << 8) | \ -+- ((speed) << 2)) -+-#define COMPHY_FW_PCIE(mode, speed, width) (COMPHY_FW_NET(mode, 0, speed) | \ -+- ((width) << 18)) -++/* South Bridge PHY Configuration Registers */ -++#define COMPHY_PHY_REG(lane, reg) (((1 - (lane)) * 0x28) + ((reg) & 0x3f)) +++ if (skb_is_gso(skb) && mtk_skb_has_small_frag(skb)) { +++ segs = skb_gso_segment(skb, dev->features & ~NETIF_F_ALL_TSO); +++ if (IS_ERR(segs)) +++ goto drop; ++ -++/* -++ * lane0: USB3/GbE1 PHY Configuration 1 -++ * lane1: PCIe/GbE0 PHY Configuration 1 -++ * (used only by SGMII code) -++ */ -++#define COMPHY_PHY_CFG1 0x0 -++#define PIN_PU_IVREF_BIT BIT(1) -++#define PIN_RESET_CORE_BIT BIT(11) -++#define PIN_RESET_COMPHY_BIT BIT(12) -++#define PIN_PU_PLL_BIT BIT(16) -++#define PIN_PU_RX_BIT BIT(17) -++#define PIN_PU_TX_BIT BIT(18) -++#define PIN_TX_IDLE_BIT BIT(19) -++#define GEN_RX_SEL_MASK GENMASK(25, 22) -++#define GEN_RX_SEL_VALUE(val) FIELD_PREP(GEN_RX_SEL_MASK, (val)) -++#define GEN_TX_SEL_MASK GENMASK(29, 26) -++#define GEN_TX_SEL_VALUE(val) FIELD_PREP(GEN_TX_SEL_MASK, (val)) -++#define SERDES_SPEED_1_25_G 0x6 -++#define SERDES_SPEED_3_125_G 0x8 -++#define PHY_RX_INIT_BIT BIT(30) +++ if (segs) { +++ consume_skb(skb); +++ skb = segs; +++ } +++ } ++ -++/* -++ * lane0: USB3/GbE1 PHY Status 1 -++ * lane1: PCIe/GbE0 PHY Status 1 -++ * (used only by SGMII code) -++ */ -++#define COMPHY_PHY_STAT1 0x18 -++#define PHY_RX_INIT_DONE_BIT BIT(0) -++#define PHY_PLL_READY_RX_BIT BIT(2) -++#define PHY_PLL_READY_TX_BIT BIT(3) -++ -++/* PHY Selector */ -++#define COMPHY_SELECTOR_PHY_REG 0xFC -++/* bit0: 0: Lane1 is GbE0; 1: Lane1 is PCIe */ -++#define COMPHY_SELECTOR_PCIE_GBE0_SEL_BIT BIT(0) -++/* bit4: 0: Lane0 is GbE1; 1: Lane0 is USB3 */ -++#define COMPHY_SELECTOR_USB3_GBE1_SEL_BIT BIT(4) -++/* bit8: 0: Lane0 is USB3 instead of GbE1, Lane2 is SATA; 1: Lane2 is USB3 */ -++#define COMPHY_SELECTOR_USB3_PHY_SEL_BIT BIT(8) -+ -+ struct mvebu_a3700_comphy_conf { -+ unsigned int lane; -+ enum phy_mode mode; -+ int submode; -+- u32 fw_mode; -+ }; -+ -+-#define MVEBU_A3700_COMPHY_CONF(_lane, _mode, _smode, _fw) \ -++#define MVEBU_A3700_COMPHY_CONF(_lane, _mode, _smode) \ -+ { \ -+ .lane = _lane, \ -+ .mode = _mode, \ -+ .submode = _smode, \ -+- .fw_mode = _fw, \ ++ /* TSO: fill MSS info in tcp checksum field */ ++ if (skb_is_gso(skb)) { ++ if (skb_cow_head(skb, 0)) { ++@@ -1438,8 +1465,13 @@ static netdev_tx_t mtk_start_xmit(struct ++ } + } + -+-#define MVEBU_A3700_COMPHY_CONF_GEN(_lane, _mode, _fw) \ -+- MVEBU_A3700_COMPHY_CONF(_lane, _mode, PHY_INTERFACE_MODE_NA, _fw) -++#define MVEBU_A3700_COMPHY_CONF_GEN(_lane, _mode) \ -++ MVEBU_A3700_COMPHY_CONF(_lane, _mode, PHY_INTERFACE_MODE_NA) -+ -+-#define MVEBU_A3700_COMPHY_CONF_ETH(_lane, _smode, _fw) \ -+- MVEBU_A3700_COMPHY_CONF(_lane, PHY_MODE_ETHERNET, _smode, _fw) -++#define MVEBU_A3700_COMPHY_CONF_ETH(_lane, _smode) \ -++ MVEBU_A3700_COMPHY_CONF(_lane, PHY_MODE_ETHERNET, _smode) -+ -+ static const struct mvebu_a3700_comphy_conf mvebu_a3700_comphy_modes[] = { -+ /* lane 0 */ -+- MVEBU_A3700_COMPHY_CONF_GEN(0, PHY_MODE_USB_HOST_SS, -+- COMPHY_FW_MODE_USB3H), -+- MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_SGMII, -+- COMPHY_FW_MODE_SGMII), -+- MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_2500BASEX, -+- COMPHY_FW_MODE_2500BASEX), -++ MVEBU_A3700_COMPHY_CONF_GEN(0, PHY_MODE_USB_HOST_SS), -++ MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_SGMII), -++ MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_1000BASEX), -++ MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_2500BASEX), -+ /* lane 1 */ -+- MVEBU_A3700_COMPHY_CONF_GEN(1, PHY_MODE_PCIE, COMPHY_FW_MODE_PCIE), -+- MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_SGMII, -+- COMPHY_FW_MODE_SGMII), -+- MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_2500BASEX, -+- COMPHY_FW_MODE_2500BASEX), -++ MVEBU_A3700_COMPHY_CONF_GEN(1, PHY_MODE_PCIE), -++ MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_SGMII), -++ MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_1000BASEX), -++ MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_2500BASEX), -+ /* lane 2 */ -+- MVEBU_A3700_COMPHY_CONF_GEN(2, PHY_MODE_SATA, COMPHY_FW_MODE_SATA), -+- MVEBU_A3700_COMPHY_CONF_GEN(2, PHY_MODE_USB_HOST_SS, -+- COMPHY_FW_MODE_USB3H), -++ MVEBU_A3700_COMPHY_CONF_GEN(2, PHY_MODE_SATA), -++ MVEBU_A3700_COMPHY_CONF_GEN(2, PHY_MODE_USB_HOST_SS), -++}; -++ -++struct mvebu_a3700_comphy_priv { -++ void __iomem *comphy_regs; -++ void __iomem *lane0_phy_regs; /* USB3 and GbE1 */ -++ void __iomem *lane1_phy_regs; /* PCIe and GbE0 */ -++ void __iomem *lane2_phy_indirect; /* SATA and USB3 */ -++ spinlock_t lock; /* for PHY selector access */ -++ bool xtal_is_40m; -+ }; ++- if (mtk_tx_map(skb, dev, tx_num, ring, gso) < 0) ++- goto drop; +++ skb_list_walk_safe(skb, skb, next) { +++ if ((mtk_skb_has_small_frag(skb) && skb_linearize(skb)) || +++ mtk_tx_map(skb, dev, tx_num, ring, gso) < 0) { +++ stats->tx_dropped++; +++ dev_kfree_skb_any(skb); +++ } +++ } + -+ struct mvebu_a3700_comphy_lane { -++ struct mvebu_a3700_comphy_priv *priv; -+ struct device *dev; -+ unsigned int id; -+ enum phy_mode mode; -+ int submode; -++ bool invert_tx; -++ bool invert_rx; -++ bool needs_reset; -++}; -++ -++struct gbe_phy_init_data_fix { -++ u16 addr; -++ u16 value; -++}; -++ -++/* Changes to 40M1G25 mode data required for running 40M3G125 init mode */ -++static struct gbe_phy_init_data_fix gbe_phy_init_fix[] = { -++ { 0x005, 0x07CC }, { 0x015, 0x0000 }, { 0x01B, 0x0000 }, -++ { 0x01D, 0x0000 }, { 0x01E, 0x0000 }, { 0x01F, 0x0000 }, -++ { 0x020, 0x0000 }, { 0x021, 0x0030 }, { 0x026, 0x0888 }, -++ { 0x04D, 0x0152 }, { 0x04F, 0xA020 }, { 0x050, 0x07CC }, -++ { 0x053, 0xE9CA }, { 0x055, 0xBD97 }, { 0x071, 0x3015 }, -++ { 0x076, 0x03AA }, { 0x07C, 0x0FDF }, { 0x0C2, 0x3030 }, -++ { 0x0C3, 0x8000 }, { 0x0E2, 0x5550 }, { 0x0E3, 0x12A4 }, -++ { 0x0E4, 0x7D00 }, { 0x0E6, 0x0C83 }, { 0x101, 0xFCC0 }, -++ { 0x104, 0x0C10 } -+ }; ++ if (unlikely(atomic_read(&ring->free_count) <= ring->thresh)) ++ netif_tx_stop_all_queues(dev); +diff --git a/target/linux/generic/pending-5.15/732-11-net-ethernet-mtk_eth_soc-set-NETIF_F_ALL_TSO.patch b/target/linux/generic/pending-5.15/732-11-net-ethernet-mtk_eth_soc-set-NETIF_F_ALL_TSO.patch +new file mode 100644 +index 0000000000..f89ad6adb1 +--- /dev/null ++++ b/target/linux/generic/pending-5.15/732-11-net-ethernet-mtk_eth_soc-set-NETIF_F_ALL_TSO.patch +@@ -0,0 +1,21 @@ ++From: Felix Fietkau <nbd@nbd.name> ++Date: Fri, 28 Oct 2022 12:54:48 +0200 ++Subject: [PATCH] net: ethernet: mtk_eth_soc: set NETIF_F_ALL_TSO ++ ++Significantly improves performance by avoiding unnecessary segmentation ++ ++Signed-off-by: Felix Fietkau <nbd@nbd.name> ++--- ++ ++--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++@@ -49,8 +49,7 @@ ++ NETIF_F_RXCSUM | \ ++ NETIF_F_HW_VLAN_CTAG_TX | \ ++ NETIF_F_HW_VLAN_CTAG_RX | \ ++- NETIF_F_SG | NETIF_F_TSO | \ ++- NETIF_F_TSO6 | \ +++ NETIF_F_SG | NETIF_F_ALL_TSO | \ ++ NETIF_F_IPV6_CSUM |\ ++ NETIF_F_HW_TC) ++ #define MTK_HW_FEATURES_MT7628 (NETIF_F_SG | NETIF_F_RXCSUM) +diff --git a/target/linux/generic/pending-5.15/732-12-net-ethernet-mtk_eth_soc-drop-packets-to-WDMA-if-the.patch b/target/linux/generic/pending-5.15/732-12-net-ethernet-mtk_eth_soc-drop-packets-to-WDMA-if-the.patch +new file mode 100644 +index 0000000000..9fa384e6fa +--- /dev/null ++++ b/target/linux/generic/pending-5.15/732-12-net-ethernet-mtk_eth_soc-drop-packets-to-WDMA-if-the.patch +@@ -0,0 +1,37 @@ ++From: Felix Fietkau <nbd@nbd.name> ++Date: Thu, 3 Nov 2022 17:46:25 +0100 ++Subject: [PATCH] net: ethernet: mtk_eth_soc: drop packets to WDMA if the ++ ring is full ++ ++Improves handling of DMA ring overflow. ++Clarify other WDMA drop related comment. ++ ++Signed-off-by: Felix Fietkau <nbd@nbd.name> ++--- ++ ++--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++@@ -3529,9 +3529,12 @@ static int mtk_hw_init(struct mtk_eth *e ++ mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP); ++ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { ++- /* PSE should not drop port8 and port9 packets */ +++ /* PSE should not drop port8 and port9 packets from WDMA Tx */ ++ mtk_w32(eth, 0x00000300, PSE_DROP_CFG); ++ +++ /* PSE should drop packets to port 8/9 on WDMA Rx ring full */ +++ mtk_w32(eth, 0x00000300, PSE_PPE0_DROP); +++ ++ /* PSE Free Queue Flow Control */ ++ mtk_w32(eth, 0x01fa01f4, PSE_FQFC_CFG2); ++ ++--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++@@ -127,6 +127,7 @@ ++ #define PSE_FQFC_CFG1 0x100 ++ #define PSE_FQFC_CFG2 0x104 ++ #define PSE_DROP_CFG 0x108 +++#define PSE_PPE0_DROP 0x110 ++ ++ /* PSE Input Queue Reservation Register*/ ++ #define PSE_IQ_REV(x) (0x140 + (((x) - 1) << 2)) +diff --git a/target/linux/generic/pending-5.15/732-13-net-ethernet-mtk_eth_soc-fix-flow_offload-related-re.patch b/target/linux/generic/pending-5.15/732-13-net-ethernet-mtk_eth_soc-fix-flow_offload-related-re.patch +new file mode 100644 +index 0000000000..0664e0106f +--- /dev/null ++++ b/target/linux/generic/pending-5.15/732-13-net-ethernet-mtk_eth_soc-fix-flow_offload-related-re.patch +@@ -0,0 +1,52 @@ ++From: Felix Fietkau <nbd@nbd.name> ++Date: Thu, 17 Nov 2022 11:58:21 +0100 ++Subject: [PATCH] net: ethernet: mtk_eth_soc: fix flow_offload related refcount ++ bug ++ ++Since we call flow_block_cb_decref on FLOW_BLOCK_UNBIND, we need to call ++flow_block_cb_incref unconditionally, even for a newly allocated cb. ++Fixes a use-after-free bug ++ ++Fixes: 502e84e2382d ("net: ethernet: mtk_eth_soc: add flow offloading support") ++Signed-off-by: Felix Fietkau <nbd@nbd.name> ++--- ++ ++--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++@@ -561,6 +561,7 @@ mtk_eth_setup_tc_block(struct net_device ++ struct mtk_eth *eth = mac->hw; ++ static LIST_HEAD(block_cb_list); ++ struct flow_block_cb *block_cb; +++ bool register_block = false; ++ flow_setup_cb_t *cb; ++ ++ if (!eth->soc->offload_version) ++@@ -575,16 +576,20 @@ mtk_eth_setup_tc_block(struct net_device ++ switch (f->command) { ++ case FLOW_BLOCK_BIND: ++ block_cb = flow_block_cb_lookup(f->block, cb, dev); ++- if (block_cb) { ++- flow_block_cb_incref(block_cb); ++- return 0; +++ if (!block_cb) { +++ block_cb = flow_block_cb_alloc(cb, dev, dev, NULL); +++ if (IS_ERR(block_cb)) +++ return PTR_ERR(block_cb); +++ +++ register_block = true; ++ } ++- block_cb = flow_block_cb_alloc(cb, dev, dev, NULL); ++- if (IS_ERR(block_cb)) ++- return PTR_ERR(block_cb); + -+-static int mvebu_a3700_comphy_smc(unsigned long function, unsigned long lane, -+- unsigned long mode) -++/* 40M1G25 mode init data */ -++static u16 gbe_phy_init[512] = { -++ /* 0 1 2 3 4 5 6 7 */ -++ /*-----------------------------------------------------------*/ -++ /* 8 9 A B C D E F */ -++ 0x3110, 0xFD83, 0x6430, 0x412F, 0x82C0, 0x06FA, 0x4500, 0x6D26, /* 00 */ -++ 0xAFC0, 0x8000, 0xC000, 0x0000, 0x2000, 0x49CC, 0x0BC9, 0x2A52, /* 08 */ -++ 0x0BD2, 0x0CDE, 0x13D2, 0x0CE8, 0x1149, 0x10E0, 0x0000, 0x0000, /* 10 */ -++ 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x4134, 0x0D2D, 0xFFFF, /* 18 */ -++ 0xFFE0, 0x4030, 0x1016, 0x0030, 0x0000, 0x0800, 0x0866, 0x0000, /* 20 */ -++ 0x0000, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* 28 */ -++ 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 30 */ -++ 0x0000, 0x0000, 0x000F, 0x6A62, 0x1988, 0x3100, 0x3100, 0x3100, /* 38 */ -++ 0x3100, 0xA708, 0x2430, 0x0830, 0x1030, 0x4610, 0xFF00, 0xFF00, /* 40 */ -++ 0x0060, 0x1000, 0x0400, 0x0040, 0x00F0, 0x0155, 0x1100, 0xA02A, /* 48 */ -++ 0x06FA, 0x0080, 0xB008, 0xE3ED, 0x5002, 0xB592, 0x7A80, 0x0001, /* 50 */ -++ 0x020A, 0x8820, 0x6014, 0x8054, 0xACAA, 0xFC88, 0x2A02, 0x45CF, /* 58 */ -++ 0x000F, 0x1817, 0x2860, 0x064F, 0x0000, 0x0204, 0x1800, 0x6000, /* 60 */ -++ 0x810F, 0x4F23, 0x4000, 0x4498, 0x0850, 0x0000, 0x000E, 0x1002, /* 68 */ -++ 0x9D3A, 0x3009, 0xD066, 0x0491, 0x0001, 0x6AB0, 0x0399, 0x3780, /* 70 */ -++ 0x0040, 0x5AC0, 0x4A80, 0x0000, 0x01DF, 0x0000, 0x0007, 0x0000, /* 78 */ -++ 0x2D54, 0x00A1, 0x4000, 0x0100, 0xA20A, 0x0000, 0x0000, 0x0000, /* 80 */ -++ 0x0000, 0x0000, 0x0000, 0x7400, 0x0E81, 0x1000, 0x1242, 0x0210, /* 88 */ -++ 0x80DF, 0x0F1F, 0x2F3F, 0x4F5F, 0x6F7F, 0x0F1F, 0x2F3F, 0x4F5F, /* 90 */ -++ 0x6F7F, 0x4BAD, 0x0000, 0x0000, 0x0800, 0x0000, 0x2400, 0xB651, /* 98 */ -++ 0xC9E0, 0x4247, 0x0A24, 0x0000, 0xAF19, 0x1004, 0x0000, 0x0000, /* A0 */ -++ 0x0000, 0x0013, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* A8 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* B0 */ -++ 0x0000, 0x0000, 0x0000, 0x0060, 0x0000, 0x0000, 0x0000, 0x0000, /* B8 */ -++ 0x0000, 0x0000, 0x3010, 0xFA00, 0x0000, 0x0000, 0x0000, 0x0003, /* C0 */ -++ 0x1618, 0x8200, 0x8000, 0x0400, 0x050F, 0x0000, 0x0000, 0x0000, /* C8 */ -++ 0x4C93, 0x0000, 0x1000, 0x1120, 0x0010, 0x1242, 0x1242, 0x1E00, /* D0 */ -++ 0x0000, 0x0000, 0x0000, 0x00F8, 0x0000, 0x0041, 0x0800, 0x0000, /* D8 */ -++ 0x82A0, 0x572E, 0x2490, 0x14A9, 0x4E00, 0x0000, 0x0803, 0x0541, /* E0 */ -++ 0x0C15, 0x0000, 0x0000, 0x0400, 0x2626, 0x0000, 0x0000, 0x4200, /* E8 */ -++ 0x0000, 0xAA55, 0x1020, 0x0000, 0x0000, 0x5010, 0x0000, 0x0000, /* F0 */ -++ 0x0000, 0x0000, 0x5000, 0x0000, 0x0000, 0x0000, 0x02F2, 0x0000, /* F8 */ -++ 0x101F, 0xFDC0, 0x4000, 0x8010, 0x0110, 0x0006, 0x0000, 0x0000, /*100 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*108 */ -++ 0x04CF, 0x0000, 0x04CF, 0x0000, 0x04CF, 0x0000, 0x04C6, 0x0000, /*110 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*118 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*120 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*128 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*130 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*138 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*140 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*148 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*150 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*158 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*160 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*168 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*170 */ -++ 0x0000, 0x0000, 0x0000, 0x00F0, 0x08A2, 0x3112, 0x0A14, 0x0000, /*178 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*180 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*188 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*190 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*198 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1A0 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1A8 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1B0 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1B8 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1C0 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1C8 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1D0 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1D8 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1E0 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1E8 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1F0 */ -++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 /*1F8 */ -++}; ++- flow_block_cb_add(block_cb, f); ++- list_add_tail(&block_cb->driver_list, &block_cb_list); +++ flow_block_cb_incref(block_cb); ++ -++static inline void comphy_reg_set(void __iomem *addr, u32 data, u32 mask) +++ if (register_block) { +++ flow_block_cb_add(block_cb, f); +++ list_add_tail(&block_cb->driver_list, &block_cb_list); +++ } ++ return 0; ++ case FLOW_BLOCK_UNBIND: ++ block_cb = flow_block_cb_lookup(f->block, cb, dev); +diff --git a/target/linux/generic/pending-5.15/732-14-net-ethernet-mtk_eth_soc-drop-generic-vlan-rx-offloa.patch b/target/linux/generic/pending-5.15/732-14-net-ethernet-mtk_eth_soc-drop-generic-vlan-rx-offloa.patch +new file mode 100644 +index 0000000000..42f98e6aff +--- /dev/null ++++ b/target/linux/generic/pending-5.15/732-14-net-ethernet-mtk_eth_soc-drop-generic-vlan-rx-offloa.patch +@@ -0,0 +1,181 @@ ++From: Felix Fietkau <nbd@nbd.name> ++Date: Sun, 20 Nov 2022 23:01:00 +0100 ++Subject: [PATCH] net: ethernet: mtk_eth_soc: drop generic vlan rx offload, ++ only use DSA untagging ++ ++Through testing I found out that hardware vlan rx offload support seems to ++have some hardware issues. At least when using multiple MACs and when receiving ++tagged packets on the secondary MAC, the hardware can sometimes start to emit ++wrong tags on the first MAC as well. ++ ++In order to avoid such issues, drop the feature configuration and use the ++offload feature only for DSA hardware untagging on MT7621/MT7622 devices which ++only use one MAC. ++ ++Signed-off-by: Felix Fietkau <nbd@nbd.name> ++--- ++ ++--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++@@ -1993,29 +1993,16 @@ static int mtk_poll_rx(struct napi_struc ++ if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) ++ mtk_ppe_check_skb(eth->ppe[0], skb, hash); ++ ++- if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) { ++- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { ++- if (trxd.rxd3 & RX_DMA_VTAG_V2) ++- __vlan_hwaccel_put_tag(skb, ++- htons(RX_DMA_VPID(trxd.rxd4)), ++- RX_DMA_VID(trxd.rxd4)); ++- } else if (trxd.rxd2 & RX_DMA_VTAG) { ++- __vlan_hwaccel_put_tag(skb, htons(RX_DMA_VPID(trxd.rxd3)), ++- RX_DMA_VID(trxd.rxd3)); ++- } ++- } ++- ++ /* When using VLAN untagging in combination with DSA, the ++ * hardware treats the MTK special tag as a VLAN and untags it. ++ */ ++- if (skb_vlan_tag_present(skb) && netdev_uses_dsa(netdev)) { ++- unsigned int port = ntohs(skb->vlan_proto) & GENMASK(2, 0); +++ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) && +++ (trxd.rxd2 & RX_DMA_VTAG) && netdev_uses_dsa(netdev)) { +++ unsigned int port = RX_DMA_VPID(trxd.rxd3) & GENMASK(2, 0); ++ ++ if (port < ARRAY_SIZE(eth->dsa_meta) && ++ eth->dsa_meta[port]) ++ skb_dst_set_noref(skb, ð->dsa_meta[port]->dst); ++- ++- __vlan_hwaccel_clear_tag(skb); ++ } ++ ++ skb_record_rx_queue(skb, 0); ++@@ -2832,29 +2819,11 @@ static netdev_features_t mtk_fix_feature ++ ++ static int mtk_set_features(struct net_device *dev, netdev_features_t features) + { -+- struct arm_smccc_res res; -+- s32 ret; -++ u32 val; ++- struct mtk_mac *mac = netdev_priv(dev); ++- struct mtk_eth *eth = mac->hw; ++ netdev_features_t diff = dev->features ^ features; ++- int i; + -+- arm_smccc_smc(function, lane, mode, 0, 0, 0, 0, 0, &res); -+- ret = res.a0; -++ val = readl(addr); -++ val = (val & ~mask) | (data & mask); -++ writel(val, addr); -++} ++ if ((diff & NETIF_F_LRO) && !(features & NETIF_F_LRO)) ++ mtk_hwlro_netdev_disable(dev); + -+- switch (ret) { -+- case SMCCC_RET_SUCCESS: ++- /* Set RX VLAN offloading */ ++- if (!(diff & NETIF_F_HW_VLAN_CTAG_RX)) +- return 0; -+- case SMCCC_RET_NOT_SUPPORTED: -+- return -EOPNOTSUPP; -++static inline void comphy_reg_set16(void __iomem *addr, u16 data, u16 mask) -++{ -++ u16 val; ++- ++- mtk_w32(eth, !!(features & NETIF_F_HW_VLAN_CTAG_RX), ++- MTK_CDMP_EG_CTRL); ++- ++- /* sync features with other MAC */ ++- for (i = 0; i < MTK_MAC_COUNT; i++) { ++- if (!eth->netdev[i] || eth->netdev[i] == dev) ++- continue; ++- eth->netdev[i]->features &= ~NETIF_F_HW_VLAN_CTAG_RX; ++- eth->netdev[i]->features |= features & NETIF_F_HW_VLAN_CTAG_RX; ++- } ++- ++ return 0; ++ } ++ ++@@ -3153,30 +3122,6 @@ static int mtk_open(struct net_device *d ++ struct mtk_eth *eth = mac->hw; ++ int i, err; ++ ++- if (mtk_uses_dsa(dev) && !eth->prog) { ++- for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) { ++- struct metadata_dst *md_dst = eth->dsa_meta[i]; ++- ++- if (md_dst) ++- continue; ++- ++- md_dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, ++- GFP_KERNEL); ++- if (!md_dst) ++- return -ENOMEM; ++- ++- md_dst->u.port_info.port_id = i; ++- eth->dsa_meta[i] = md_dst; ++- } ++- } else { ++- /* Hardware special tag parsing needs to be disabled if at least ++- * one MAC does not use DSA. ++- */ ++- u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL); ++- val &= ~MTK_CDMP_STAG_EN; ++- mtk_w32(eth, val, MTK_CDMP_IG_CTRL); ++- } ++- ++ err = phylink_of_phy_connect(mac->phylink, mac->of_node, 0); ++ if (err) { ++ netdev_err(dev, "%s: could not attach PHY: %d\n", __func__, ++@@ -3215,6 +3160,35 @@ static int mtk_open(struct net_device *d ++ phylink_start(mac->phylink); ++ netif_tx_start_all_queues(dev); ++ +++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) +++ return 0; ++ -++ val = readw(addr); -++ val = (val & ~mask) | (data & mask); -++ writew(val, addr); -++} +++ if (mtk_uses_dsa(dev) && !eth->prog) { +++ for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) { +++ struct metadata_dst *md_dst = eth->dsa_meta[i]; ++ -++/* Used for accessing lane 2 registers (SATA/USB3 PHY) */ -++static void comphy_set_indirect(struct mvebu_a3700_comphy_priv *priv, -++ u32 offset, u16 data, u16 mask) -++{ -++ writel(offset, -++ priv->lane2_phy_indirect + COMPHY_LANE2_INDIR_ADDR); -++ comphy_reg_set(priv->lane2_phy_indirect + COMPHY_LANE2_INDIR_DATA, -++ data, mask); -++} +++ if (md_dst) +++ continue; ++ -++static void comphy_lane_reg_set(struct mvebu_a3700_comphy_lane *lane, -++ u16 reg, u16 data, u16 mask) -++{ -++ if (lane->id == 2) { -++ /* lane 2 PHY registers are accessed indirectly */ -++ comphy_set_indirect(lane->priv, -++ reg + COMPHY_LANE2_REGS_BASE, -++ data, mask); +++ md_dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, +++ GFP_KERNEL); +++ if (!md_dst) +++ return -ENOMEM; +++ +++ md_dst->u.port_info.port_id = i; +++ eth->dsa_meta[i] = md_dst; +++ } ++ } else { -++ void __iomem *base = lane->id == 1 ? -++ lane->priv->lane1_phy_regs : -++ lane->priv->lane0_phy_regs; +++ /* Hardware special tag parsing needs to be disabled if at least +++ * one MAC does not use DSA. +++ */ +++ u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL); +++ val &= ~MTK_CDMP_STAG_EN; +++ mtk_w32(eth, val, MTK_CDMP_IG_CTRL); +++ +++ mtk_w32(eth, 0, MTK_CDMP_EG_CTRL); +++ } ++ -++ comphy_reg_set16(base + COMPHY_LANE_REG_DIRECT(reg), -++ data, mask); ++ return 0; ++ } ++ ++@@ -3508,10 +3482,9 @@ static int mtk_hw_init(struct mtk_eth *e ++ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { ++ val = mtk_r32(eth, MTK_CDMP_IG_CTRL); ++ mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL); ++- } ++ ++- /* Enable RX VLan Offloading */ ++- mtk_w32(eth, 1, MTK_CDMP_EG_CTRL); +++ mtk_w32(eth, 1, MTK_CDMP_EG_CTRL); ++ } ++ ++ /* set interrupt delays based on current Net DIM sample */ ++ mtk_dim_rx(ð->rx_dim.work); ++@@ -4132,7 +4105,7 @@ static int mtk_add_mac(struct mtk_eth *e ++ eth->netdev[id]->hw_features |= NETIF_F_LRO; ++ ++ eth->netdev[id]->vlan_features = eth->soc->hw_features & ++- ~(NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX); +++ ~NETIF_F_HW_VLAN_CTAG_TX; ++ eth->netdev[id]->features |= eth->soc->hw_features; ++ eth->netdev[id]->ethtool_ops = &mtk_ethtool_ops; ++ ++--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++@@ -48,7 +48,6 @@ ++ #define MTK_HW_FEATURES (NETIF_F_IP_CSUM | \ ++ NETIF_F_RXCSUM | \ ++ NETIF_F_HW_VLAN_CTAG_TX | \ ++- NETIF_F_HW_VLAN_CTAG_RX | \ ++ NETIF_F_SG | NETIF_F_ALL_TSO | \ ++ NETIF_F_IPV6_CSUM |\ ++ NETIF_F_HW_TC) +diff --git a/target/linux/generic/pending-5.15/733-01-net-ethernet-mtk_wed-introduce-wed-mcu-support.patch b/target/linux/generic/pending-5.15/733-01-net-ethernet-mtk_wed-introduce-wed-mcu-support.patch +new file mode 100644 +index 0000000000..c48613929d +--- /dev/null ++++ b/target/linux/generic/pending-5.15/733-01-net-ethernet-mtk_wed-introduce-wed-mcu-support.patch +@@ -0,0 +1,591 @@ ++From: Sujuan Chen <sujuan.chen@mediatek.com> ++Date: Sat, 5 Nov 2022 23:36:18 +0100 ++Subject: [PATCH] net: ethernet: mtk_wed: introduce wed mcu support ++ ++Introduce WED mcu support used to configure WED WO chip. ++This is a preliminary patch in order to add RX Wireless ++Ethernet Dispatch available on MT7986 SoC. ++ ++Tested-by: Daniel Golle <daniel@makrotopia.org> ++Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org> ++Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> ++Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com> ++Signed-off-by: David S. Miller <davem@davemloft.net> ++--- ++ create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_mcu.c ++ create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_wo.h ++ ++--- a/drivers/net/ethernet/mediatek/Makefile +++++ b/drivers/net/ethernet/mediatek/Makefile ++@@ -5,7 +5,7 @@ ++ ++ obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o ++ mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_eth_path.o mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.o ++-mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed.o +++mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed.o mtk_wed_mcu.o ++ ifdef CONFIG_DEBUG_FS ++ mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_debugfs.o ++ endif ++--- /dev/null +++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c ++@@ -0,0 +1,359 @@ +++// SPDX-License-Identifier: GPL-2.0-only +++/* Copyright (C) 2022 MediaTek Inc. +++ * +++ * Author: Lorenzo Bianconi <lorenzo@kernel.org> +++ * Sujuan Chen <sujuan.chen@mediatek.com> +++ */ +++ +++#include <linux/firmware.h> +++#include <linux/of_address.h> +++#include <linux/of_reserved_mem.h> +++#include <linux/mfd/syscon.h> +++#include <linux/soc/mediatek/mtk_wed.h> +++ +++#include "mtk_wed_regs.h" +++#include "mtk_wed_wo.h" +++#include "mtk_wed.h" +++ +++static u32 wo_r32(struct mtk_wed_wo *wo, u32 reg) +++{ +++ return readl(wo->boot.addr + reg); ++} ++ -++static int comphy_lane_reg_poll(struct mvebu_a3700_comphy_lane *lane, -++ u16 reg, u16 bits, -++ ulong sleep_us, ulong timeout_us) +++static void wo_w32(struct mtk_wed_wo *wo, u32 reg, u32 val) ++{ -++ int ret; +++ writel(val, wo->boot.addr + reg); +++} ++ -++ if (lane->id == 2) { -++ u32 data; +++static struct sk_buff * +++mtk_wed_mcu_msg_alloc(const void *data, int data_len) +++{ +++ int length = sizeof(struct mtk_wed_mcu_hdr) + data_len; +++ struct sk_buff *skb; ++ -++ /* lane 2 PHY registers are accessed indirectly */ -++ writel(reg + COMPHY_LANE2_REGS_BASE, -++ lane->priv->lane2_phy_indirect + -++ COMPHY_LANE2_INDIR_ADDR); +++ skb = alloc_skb(length, GFP_KERNEL); +++ if (!skb) +++ return NULL; ++ -++ ret = readl_poll_timeout(lane->priv->lane2_phy_indirect + -++ COMPHY_LANE2_INDIR_DATA, -++ data, (data & bits) == bits, -++ sleep_us, timeout_us); -++ } else { -++ void __iomem *base = lane->id == 1 ? -++ lane->priv->lane1_phy_regs : -++ lane->priv->lane0_phy_regs; -++ u16 data; -++ -++ ret = readw_poll_timeout(base + COMPHY_LANE_REG_DIRECT(reg), -++ data, (data & bits) == bits, -++ sleep_us, timeout_us); -++ } +++ memset(skb->head, 0, length); +++ skb_reserve(skb, sizeof(struct mtk_wed_mcu_hdr)); +++ if (data && data_len) +++ skb_put_data(skb, data, data_len); ++ -++ return ret; +++ return skb; ++} ++ -++static void comphy_periph_reg_set(struct mvebu_a3700_comphy_lane *lane, -++ u8 reg, u32 data, u32 mask) +++static struct sk_buff * +++mtk_wed_mcu_get_response(struct mtk_wed_wo *wo, unsigned long expires) ++{ -++ comphy_reg_set(lane->priv->comphy_regs + COMPHY_PHY_REG(lane->id, reg), -++ data, mask); +++ if (!time_is_after_jiffies(expires)) +++ return NULL; +++ +++ wait_event_timeout(wo->mcu.wait, !skb_queue_empty(&wo->mcu.res_q), +++ expires - jiffies); +++ return skb_dequeue(&wo->mcu.res_q); ++} ++ -++static int comphy_periph_reg_poll(struct mvebu_a3700_comphy_lane *lane, -++ u8 reg, u32 bits, -++ ulong sleep_us, ulong timeout_us) +++void mtk_wed_mcu_rx_event(struct mtk_wed_wo *wo, struct sk_buff *skb) ++{ -++ u32 data; -++ -++ return readl_poll_timeout(lane->priv->comphy_regs + -++ COMPHY_PHY_REG(lane->id, reg), -++ data, (data & bits) == bits, -++ sleep_us, timeout_us); +++ skb_queue_tail(&wo->mcu.res_q, skb); +++ wake_up(&wo->mcu.wait); ++} ++ -++/* PHY selector configures with corresponding modes */ -++static int -++mvebu_a3700_comphy_set_phy_selector(struct mvebu_a3700_comphy_lane *lane) +++void mtk_wed_mcu_rx_unsolicited_event(struct mtk_wed_wo *wo, +++ struct sk_buff *skb) ++{ -++ u32 old, new, clr = 0, set = 0; -++ unsigned long flags; +++ struct mtk_wed_mcu_hdr *hdr = (struct mtk_wed_mcu_hdr *)skb->data; ++ -++ switch (lane->mode) { -++ case PHY_MODE_SATA: -++ /* SATA must be in Lane2 */ -++ if (lane->id == 2) -++ clr = COMPHY_SELECTOR_USB3_PHY_SEL_BIT; -++ else -++ goto error; -++ break; +++ switch (hdr->cmd) { +++ case MTK_WED_WO_EVT_LOG_DUMP: { +++ const char *msg = (const char *)(skb->data + sizeof(*hdr)); ++ -++ case PHY_MODE_ETHERNET: -++ if (lane->id == 0) -++ clr = COMPHY_SELECTOR_USB3_GBE1_SEL_BIT; -++ else if (lane->id == 1) -++ clr = COMPHY_SELECTOR_PCIE_GBE0_SEL_BIT; -++ else -++ goto error; +++ dev_notice(wo->hw->dev, "%s\n", msg); ++ break; -++ -++ case PHY_MODE_USB_HOST_SS: -++ if (lane->id == 2) -++ set = COMPHY_SELECTOR_USB3_PHY_SEL_BIT; -++ else if (lane->id == 0) -++ set = COMPHY_SELECTOR_USB3_GBE1_SEL_BIT; -++ else -++ goto error; +++ } +++ case MTK_WED_WO_EVT_PROFILING: { +++ struct mtk_wed_wo_log_info *info; +++ u32 count = (skb->len - sizeof(*hdr)) / sizeof(*info); +++ int i; +++ +++ info = (struct mtk_wed_wo_log_info *)(skb->data + sizeof(*hdr)); +++ for (i = 0 ; i < count ; i++) +++ dev_notice(wo->hw->dev, +++ "SN:%u latency: total=%u, rro:%u, mod:%u\n", +++ le32_to_cpu(info[i].sn), +++ le32_to_cpu(info[i].total), +++ le32_to_cpu(info[i].rro), +++ le32_to_cpu(info[i].mod)); ++ break; -++ -++ case PHY_MODE_PCIE: -++ /* PCIE must be in Lane1 */ -++ if (lane->id == 1) -++ set = COMPHY_SELECTOR_PCIE_GBE0_SEL_BIT; -++ else -++ goto error; +++ } +++ case MTK_WED_WO_EVT_RXCNT_INFO: ++ break; -++ ++ default: -++ goto error; +++ break; ++ } ++ -++ spin_lock_irqsave(&lane->priv->lock, flags); -++ -++ old = readl(lane->priv->comphy_regs + COMPHY_SELECTOR_PHY_REG); -++ new = (old & ~clr) | set; -++ writel(new, lane->priv->comphy_regs + COMPHY_SELECTOR_PHY_REG); -++ -++ spin_unlock_irqrestore(&lane->priv->lock, flags); -++ -++ dev_dbg(lane->dev, -++ "COMPHY[%d] mode[%d] changed PHY selector 0x%08x -> 0x%08x\n", -++ lane->id, lane->mode, old, new); -++ -++ return 0; -++error: -++ dev_err(lane->dev, "COMPHY[%d] mode[%d] is invalid\n", lane->id, -++ lane->mode); -++ return -EINVAL; +++ dev_kfree_skb(skb); ++} ++ ++static int -++mvebu_a3700_comphy_sata_power_on(struct mvebu_a3700_comphy_lane *lane) +++mtk_wed_mcu_skb_send_msg(struct mtk_wed_wo *wo, struct sk_buff *skb, +++ int id, int cmd, u16 *wait_seq, bool wait_resp) ++{ -++ u32 mask, data, ref_clk; -++ int ret; +++ struct mtk_wed_mcu_hdr *hdr; ++ -++ /* Configure phy selector for SATA */ -++ ret = mvebu_a3700_comphy_set_phy_selector(lane); -++ if (ret) -++ return ret; +++ /* TODO: make it dynamic based on cmd */ +++ wo->mcu.timeout = 20 * HZ; ++ -++ /* Clear phy isolation mode to make it work in normal mode */ -++ comphy_lane_reg_set(lane, COMPHY_ISOLATION_CTRL, -++ 0x0, PHY_ISOLATE_MODE); -++ -++ /* 0. Check the Polarity invert bits */ -++ data = 0x0; -++ if (lane->invert_tx) -++ data |= TXD_INVERT_BIT; -++ if (lane->invert_rx) -++ data |= RXD_INVERT_BIT; -++ mask = TXD_INVERT_BIT | RXD_INVERT_BIT; -++ comphy_lane_reg_set(lane, COMPHY_SYNC_PATTERN, data, mask); -++ -++ /* 1. Select 40-bit data width */ -++ comphy_lane_reg_set(lane, COMPHY_DIG_LOOPBACK_EN, -++ DATA_WIDTH_40BIT, SEL_DATA_WIDTH_MASK); -++ -++ /* 2. Select reference clock(25M) and PHY mode (SATA) */ -++ if (lane->priv->xtal_is_40m) -++ ref_clk = REF_FREF_SEL_SERDES_40MHZ; -++ else -++ ref_clk = REF_FREF_SEL_SERDES_25MHZ; -++ -++ data = ref_clk | COMPHY_MODE_SATA; -++ mask = REF_FREF_SEL_MASK | COMPHY_MODE_MASK; -++ comphy_lane_reg_set(lane, COMPHY_POWER_PLL_CTRL, data, mask); -++ -++ /* 3. Use maximum PLL rate (no power save) */ -++ comphy_lane_reg_set(lane, COMPHY_KVCO_CAL_CTRL, -++ USE_MAX_PLL_RATE_BIT, USE_MAX_PLL_RATE_BIT); -++ -++ /* 4. Reset reserved bit */ -++ comphy_set_indirect(lane->priv, COMPHY_RESERVED_REG, -++ 0x0, PHYCTRL_FRM_PIN_BIT); -++ -++ /* 5. Set vendor-specific configuration (It is done in sata driver) */ -++ /* XXX: in U-Boot below sequence was executed in this place, in Linux -++ * not. Now it is done only in U-Boot before this comphy -++ * initialization - tests shows that it works ok, but in case of any -++ * future problem it is left for reference. -++ * reg_set(MVEBU_REGS_BASE + 0xe00a0, 0, 0xffffffff); -++ * reg_set(MVEBU_REGS_BASE + 0xe00a4, BIT(6), BIT(6)); -++ */ +++ hdr = (struct mtk_wed_mcu_hdr *)skb_push(skb, sizeof(*hdr)); +++ hdr->cmd = cmd; +++ hdr->length = cpu_to_le16(skb->len); ++ -++ /* Wait for > 55 us to allow PLL be enabled */ -++ udelay(PLL_SET_DELAY_US); +++ if (wait_resp && wait_seq) { +++ u16 seq = ++wo->mcu.seq; ++ -++ /* Polling status */ -++ ret = comphy_lane_reg_poll(lane, COMPHY_DIG_LOOPBACK_EN, -++ PLL_READY_TX_BIT, COMPHY_PLL_SLEEP, -++ COMPHY_PLL_TIMEOUT); -++ if (ret) { -++ dev_err(lane->dev, "Failed to lock SATA PLL\n"); -++ return ret; +++ if (!seq) +++ seq = ++wo->mcu.seq; +++ *wait_seq = seq; +++ +++ hdr->flag |= cpu_to_le16(MTK_WED_WARP_CMD_FLAG_NEED_RSP); +++ hdr->seq = cpu_to_le16(seq); ++ } +++ if (id == MTK_WED_MODULE_ID_WO) +++ hdr->flag |= cpu_to_le16(MTK_WED_WARP_CMD_FLAG_FROM_TO_WO); ++ +++ dev_kfree_skb(skb); ++ return 0; ++} ++ -++static void comphy_gbe_phy_init(struct mvebu_a3700_comphy_lane *lane, -++ bool is_1gbps) +++static int +++mtk_wed_mcu_parse_response(struct mtk_wed_wo *wo, struct sk_buff *skb, +++ int cmd, int seq) ++{ -++ int addr, fix_idx; -++ u16 val; +++ struct mtk_wed_mcu_hdr *hdr; ++ -++ fix_idx = 0; -++ for (addr = 0; addr < 512; addr++) { -++ /* -++ * All PHY register values are defined in full for 3.125Gbps -++ * SERDES speed. The values required for 1.25 Gbps are almost -++ * the same and only few registers should be "fixed" in -++ * comparison to 3.125 Gbps values. These register values are -++ * stored in "gbe_phy_init_fix" array. -++ */ -++ if (!is_1gbps && gbe_phy_init_fix[fix_idx].addr == addr) { -++ /* Use new value */ -++ val = gbe_phy_init_fix[fix_idx].value; -++ if (fix_idx < ARRAY_SIZE(gbe_phy_init_fix)) -++ fix_idx++; -++ } else { -++ val = gbe_phy_init[addr]; -++ } +++ if (!skb) { +++ dev_err(wo->hw->dev, "Message %08x (seq %d) timeout\n", +++ cmd, seq); +++ return -ETIMEDOUT; +++ } +++ +++ hdr = (struct mtk_wed_mcu_hdr *)skb->data; +++ if (le16_to_cpu(hdr->seq) != seq) +++ return -EAGAIN; ++ -++ comphy_lane_reg_set(lane, addr, val, 0xFFFF); +++ skb_pull(skb, sizeof(*hdr)); +++ switch (cmd) { +++ case MTK_WED_WO_CMD_RXCNT_INFO: +++ default: +++ break; ++ } +++ +++ return 0; ++} ++ -++static int -++mvebu_a3700_comphy_ethernet_power_on(struct mvebu_a3700_comphy_lane *lane) +++int mtk_wed_mcu_send_msg(struct mtk_wed_wo *wo, int id, int cmd, +++ const void *data, int len, bool wait_resp) ++{ -++ u32 mask, data, speed_sel; +++ unsigned long expires; +++ struct sk_buff *skb; +++ u16 seq; ++ int ret; ++ -++ /* Set selector */ -++ ret = mvebu_a3700_comphy_set_phy_selector(lane); -++ if (ret) -++ return ret; +++ skb = mtk_wed_mcu_msg_alloc(data, len); +++ if (!skb) +++ return -ENOMEM; ++ -++ /* -++ * 1. Reset PHY by setting PHY input port PIN_RESET=1. -++ * 2. Set PHY input port PIN_TX_IDLE=1, PIN_PU_IVREF=1 to keep -++ * PHY TXP/TXN output to idle state during PHY initialization -++ * 3. Set PHY input port PIN_PU_PLL=0, PIN_PU_RX=0, PIN_PU_TX=0. -++ */ -++ data = PIN_PU_IVREF_BIT | PIN_TX_IDLE_BIT | PIN_RESET_COMPHY_BIT; -++ mask = data | PIN_RESET_CORE_BIT | PIN_PU_PLL_BIT | PIN_PU_RX_BIT | -++ PIN_PU_TX_BIT | PHY_RX_INIT_BIT; -++ comphy_periph_reg_set(lane, COMPHY_PHY_CFG1, data, mask); +++ mutex_lock(&wo->mcu.mutex); ++ -++ /* 4. Release reset to the PHY by setting PIN_RESET=0. */ -++ data = 0x0; -++ mask = PIN_RESET_COMPHY_BIT; -++ comphy_periph_reg_set(lane, COMPHY_PHY_CFG1, data, mask); +++ ret = mtk_wed_mcu_skb_send_msg(wo, skb, id, cmd, &seq, wait_resp); +++ if (ret || !wait_resp) +++ goto unlock; ++ -++ /* -++ * 5. Set PIN_PHY_GEN_TX[3:0] and PIN_PHY_GEN_RX[3:0] to decide COMPHY -++ * bit rate -++ */ -++ switch (lane->submode) { -++ case PHY_INTERFACE_MODE_SGMII: -++ case PHY_INTERFACE_MODE_1000BASEX: -++ /* SGMII 1G, SerDes speed 1.25G */ -++ speed_sel = SERDES_SPEED_1_25_G; -++ break; -++ case PHY_INTERFACE_MODE_2500BASEX: -++ /* 2500Base-X, SerDes speed 3.125G */ -++ speed_sel = SERDES_SPEED_3_125_G; -++ break; -+ default: -++ /* Other rates are not supported */ -++ dev_err(lane->dev, -++ "unsupported phy speed %d on comphy lane%d\n", -++ lane->submode, lane->id); -+ return -EINVAL; -+ } -++ data = GEN_RX_SEL_VALUE(speed_sel) | GEN_TX_SEL_VALUE(speed_sel); -++ mask = GEN_RX_SEL_MASK | GEN_TX_SEL_MASK; -++ comphy_periph_reg_set(lane, COMPHY_PHY_CFG1, data, mask); +++ expires = jiffies + wo->mcu.timeout; +++ do { +++ skb = mtk_wed_mcu_get_response(wo, expires); +++ ret = mtk_wed_mcu_parse_response(wo, skb, cmd, seq); +++ dev_kfree_skb(skb); +++ } while (ret == -EAGAIN); ++ -++ /* -++ * 6. Wait 10mS for bandgap and reference clocks to stabilize; then -++ * start SW programming. -++ */ -++ mdelay(10); +++unlock: +++ mutex_unlock(&wo->mcu.mutex); ++ -++ /* 7. Program COMPHY register PHY_MODE */ -++ data = COMPHY_MODE_SERDES; -++ mask = COMPHY_MODE_MASK; -++ comphy_lane_reg_set(lane, COMPHY_POWER_PLL_CTRL, data, mask); +++ return ret; +++} ++ -++ /* -++ * 8. Set COMPHY register REFCLK_SEL to select the correct REFCLK -++ * source -++ */ -++ data = 0x0; -++ mask = PHY_REF_CLK_SEL; -++ comphy_lane_reg_set(lane, COMPHY_MISC_CTRL0, data, mask); +++static int +++mtk_wed_get_memory_region(struct mtk_wed_wo *wo, +++ struct mtk_wed_wo_memory_region *region) +++{ +++ struct reserved_mem *rmem; +++ struct device_node *np; +++ int index; ++ -++ /* -++ * 9. Set correct reference clock frequency in COMPHY register -++ * REF_FREF_SEL. -++ */ -++ if (lane->priv->xtal_is_40m) -++ data = REF_FREF_SEL_SERDES_50MHZ; -++ else -++ data = REF_FREF_SEL_SERDES_25MHZ; +++ index = of_property_match_string(wo->hw->node, "memory-region-names", +++ region->name); +++ if (index < 0) +++ return index; ++ -++ mask = REF_FREF_SEL_MASK; -++ comphy_lane_reg_set(lane, COMPHY_POWER_PLL_CTRL, data, mask); +++ np = of_parse_phandle(wo->hw->node, "memory-region", index); +++ if (!np) +++ return -ENODEV; ++ -++ /* 10. Program COMPHY register PHY_GEN_MAX[1:0] -++ * This step is mentioned in the flow received from verification team. -++ * However the PHY_GEN_MAX value is only meaningful for other interfaces -++ * (not SERDES). For instance, it selects SATA speed 1.5/3/6 Gbps or -++ * PCIe speed 2.5/5 Gbps -++ */ +++ rmem = of_reserved_mem_lookup(np); +++ of_node_put(np); ++ -++ /* -++ * 11. Program COMPHY register SEL_BITS to set correct parallel data -++ * bus width -++ */ -++ data = DATA_WIDTH_10BIT; -++ mask = SEL_DATA_WIDTH_MASK; -++ comphy_lane_reg_set(lane, COMPHY_DIG_LOOPBACK_EN, data, mask); +++ if (!rmem) +++ return -ENODEV; ++ -++ /* -++ * 12. As long as DFE function needs to be enabled in any mode, -++ * COMPHY register DFE_UPDATE_EN[5:0] shall be programmed to 0x3F -++ * for real chip during COMPHY power on. -++ * The step 14 exists (and empty) in the original initialization flow -++ * obtained from the verification team. According to the functional -++ * specification DFE_UPDATE_EN already has the default value 0x3F -++ */ +++ region->phy_addr = rmem->base; +++ region->size = rmem->size; +++ region->addr = devm_ioremap(wo->hw->dev, region->phy_addr, region->size); ++ -++ /* -++ * 13. Program COMPHY GEN registers. -++ * These registers should be programmed based on the lab testing result -++ * to achieve optimal performance. Please contact the CEA group to get -++ * the related GEN table during real chip bring-up. We only required to -++ * run though the entire registers programming flow defined by -++ * "comphy_gbe_phy_init" when the REF clock is 40 MHz. For REF clock -++ * 25 MHz the default values stored in PHY registers are OK. -++ */ -++ dev_dbg(lane->dev, "Running C-DPI phy init %s mode\n", -++ lane->submode == PHY_INTERFACE_MODE_2500BASEX ? "2G5" : "1G"); -++ if (lane->priv->xtal_is_40m) -++ comphy_gbe_phy_init(lane, -++ lane->submode != PHY_INTERFACE_MODE_2500BASEX); +++ return !region->addr ? -EINVAL : 0; +++} ++ -++ /* -++ * 14. [Simulation Only] should not be used for real chip. -++ * By pass power up calibration by programming EXT_FORCE_CAL_DONE -++ * (R02h[9]) to 1 to shorten COMPHY simulation time. -++ */ +++static int +++mtk_wed_mcu_run_firmware(struct mtk_wed_wo *wo, const struct firmware *fw, +++ struct mtk_wed_wo_memory_region *region) +++{ +++ const u8 *first_region_ptr, *region_ptr, *trailer_ptr, *ptr = fw->data; +++ const struct mtk_wed_fw_trailer *trailer; +++ const struct mtk_wed_fw_region *fw_region; ++ -++ /* -++ * 15. [Simulation Only: should not be used for real chip] -++ * Program COMPHY register FAST_DFE_TIMER_EN=1 to shorten RX training -++ * simulation time. -++ */ +++ trailer_ptr = fw->data + fw->size - sizeof(*trailer); +++ trailer = (const struct mtk_wed_fw_trailer *)trailer_ptr; +++ region_ptr = trailer_ptr - trailer->num_region * sizeof(*fw_region); +++ first_region_ptr = region_ptr; ++ -++ /* -++ * 16. Check the PHY Polarity invert bit -++ */ -++ data = 0x0; -++ if (lane->invert_tx) -++ data |= TXD_INVERT_BIT; -++ if (lane->invert_rx) -++ data |= RXD_INVERT_BIT; -++ mask = TXD_INVERT_BIT | RXD_INVERT_BIT; -++ comphy_lane_reg_set(lane, COMPHY_SYNC_PATTERN, data, mask); +++ while (region_ptr < trailer_ptr) { +++ u32 length; ++ -++ /* -++ * 17. Set PHY input ports PIN_PU_PLL, PIN_PU_TX and PIN_PU_RX to 1 to -++ * start PHY power up sequence. All the PHY register programming should -++ * be done before PIN_PU_PLL=1. There should be no register programming -++ * for normal PHY operation from this point. -++ */ -++ data = PIN_PU_PLL_BIT | PIN_PU_RX_BIT | PIN_PU_TX_BIT; -++ mask = data; -++ comphy_periph_reg_set(lane, COMPHY_PHY_CFG1, data, mask); +++ fw_region = (const struct mtk_wed_fw_region *)region_ptr; +++ length = le32_to_cpu(fw_region->len); ++ -++ /* -++ * 18. Wait for PHY power up sequence to finish by checking output ports -++ * PIN_PLL_READY_TX=1 and PIN_PLL_READY_RX=1. -++ */ -++ ret = comphy_periph_reg_poll(lane, COMPHY_PHY_STAT1, -++ PHY_PLL_READY_TX_BIT | -++ PHY_PLL_READY_RX_BIT, -++ COMPHY_PLL_SLEEP, COMPHY_PLL_TIMEOUT); -++ if (ret) { -++ dev_err(lane->dev, "Failed to lock PLL for SERDES PHY %d\n", -++ lane->id); -++ return ret; +++ if (region->phy_addr != le32_to_cpu(fw_region->addr)) +++ goto next; +++ +++ if (region->size < length) +++ goto next; +++ +++ if (first_region_ptr < ptr + length) +++ goto next; +++ +++ if (region->shared && region->consumed) +++ return 0; +++ +++ if (!region->shared || !region->consumed) { +++ memcpy_toio(region->addr, ptr, length); +++ region->consumed = true; +++ return 0; +++ } +++next: +++ region_ptr += sizeof(*fw_region); +++ ptr += length; ++ } ++ -++ /* -++ * 19. Set COMPHY input port PIN_TX_IDLE=0 -++ */ -++ comphy_periph_reg_set(lane, COMPHY_PHY_CFG1, 0x0, PIN_TX_IDLE_BIT); +++ return -EINVAL; +++} ++ -++ /* -++ * 20. After valid data appear on PIN_RXDATA bus, set PIN_RX_INIT=1. To -++ * start RX initialization. PIN_RX_INIT_DONE will be cleared to 0 by the -++ * PHY After RX initialization is done, PIN_RX_INIT_DONE will be set to -++ * 1 by COMPHY Set PIN_RX_INIT=0 after PIN_RX_INIT_DONE= 1. Please -++ * refer to RX initialization part for details. -++ */ -++ comphy_periph_reg_set(lane, COMPHY_PHY_CFG1, -++ PHY_RX_INIT_BIT, PHY_RX_INIT_BIT); -++ -++ ret = comphy_periph_reg_poll(lane, COMPHY_PHY_STAT1, -++ PHY_PLL_READY_TX_BIT | -++ PHY_PLL_READY_RX_BIT, -++ COMPHY_PLL_SLEEP, COMPHY_PLL_TIMEOUT); -++ if (ret) { -++ dev_err(lane->dev, "Failed to lock PLL for SERDES PHY %d\n", -++ lane->id); -++ return ret; +++static int +++mtk_wed_mcu_load_firmware(struct mtk_wed_wo *wo) +++{ +++ static struct mtk_wed_wo_memory_region mem_region[] = { +++ [MTK_WED_WO_REGION_EMI] = { +++ .name = "wo-emi", +++ }, +++ [MTK_WED_WO_REGION_ILM] = { +++ .name = "wo-ilm", +++ }, +++ [MTK_WED_WO_REGION_DATA] = { +++ .name = "wo-data", +++ .shared = true, +++ }, +++ }; +++ const struct mtk_wed_fw_trailer *trailer; +++ const struct firmware *fw; +++ const char *fw_name; +++ u32 val, boot_cr; +++ int ret, i; +++ +++ /* load firmware region metadata */ +++ for (i = 0; i < ARRAY_SIZE(mem_region); i++) { +++ ret = mtk_wed_get_memory_region(wo, &mem_region[i]); +++ if (ret) +++ return ret; ++ } ++ -++ ret = comphy_periph_reg_poll(lane, COMPHY_PHY_STAT1, -++ PHY_RX_INIT_DONE_BIT, -++ COMPHY_PLL_SLEEP, COMPHY_PLL_TIMEOUT); -++ if (ret) { -++ dev_err(lane->dev, "Failed to init RX of SERDES PHY %d\n", -++ lane->id); +++ wo->boot.name = "wo-boot"; +++ ret = mtk_wed_get_memory_region(wo, &wo->boot); +++ if (ret) +++ return ret; +++ +++ /* set dummy cr */ +++ wed_w32(wo->hw->wed_dev, MTK_WED_SCR0 + 4 * MTK_WED_DUMMY_CR_FWDL, +++ wo->hw->index + 1); +++ +++ /* load firmware */ +++ fw_name = wo->hw->index ? MT7986_FIRMWARE_WO1 : MT7986_FIRMWARE_WO0; +++ ret = request_firmware(&fw, fw_name, wo->hw->dev); +++ if (ret) ++ return ret; +++ +++ trailer = (void *)(fw->data + fw->size - +++ sizeof(struct mtk_wed_fw_trailer)); +++ dev_info(wo->hw->dev, +++ "MTK WED WO Firmware Version: %.10s, Build Time: %.15s\n", +++ trailer->fw_ver, trailer->build_date); +++ dev_info(wo->hw->dev, "MTK WED WO Chip ID %02x Region %d\n", +++ trailer->chip_id, trailer->num_region); +++ +++ for (i = 0; i < ARRAY_SIZE(mem_region); i++) { +++ ret = mtk_wed_mcu_run_firmware(wo, fw, &mem_region[i]); +++ if (ret) +++ goto out; ++ } ++ +++ /* set the start address */ +++ boot_cr = wo->hw->index ? MTK_WO_MCU_CFG_LS_WA_BOOT_ADDR_ADDR +++ : MTK_WO_MCU_CFG_LS_WM_BOOT_ADDR_ADDR; +++ wo_w32(wo, boot_cr, mem_region[MTK_WED_WO_REGION_EMI].phy_addr >> 16); +++ /* wo firmware reset */ +++ wo_w32(wo, MTK_WO_MCU_CFG_LS_WF_MCCR_CLR_ADDR, 0xc00); +++ +++ val = wo_r32(wo, MTK_WO_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR); +++ val |= wo->hw->index ? MTK_WO_MCU_CFG_LS_WF_WM_WA_WA_CPU_RSTB_MASK +++ : MTK_WO_MCU_CFG_LS_WF_WM_WA_WM_CPU_RSTB_MASK; +++ wo_w32(wo, MTK_WO_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR, val); +++out: +++ release_firmware(fw); +++ +++ return ret; +++} +++ +++static u32 +++mtk_wed_mcu_read_fw_dl(struct mtk_wed_wo *wo) +++{ +++ return wed_r32(wo->hw->wed_dev, +++ MTK_WED_SCR0 + 4 * MTK_WED_DUMMY_CR_FWDL); +++} +++ +++int mtk_wed_mcu_init(struct mtk_wed_wo *wo) +++{ +++ u32 val; +++ int ret; +++ +++ skb_queue_head_init(&wo->mcu.res_q); +++ init_waitqueue_head(&wo->mcu.wait); +++ mutex_init(&wo->mcu.mutex); +++ +++ ret = mtk_wed_mcu_load_firmware(wo); +++ if (ret) +++ return ret; +++ +++ return readx_poll_timeout(mtk_wed_mcu_read_fw_dl, wo, val, !val, +++ 100, MTK_FW_DL_TIMEOUT); +++} +++ +++MODULE_FIRMWARE(MT7986_FIRMWARE_WO0); +++MODULE_FIRMWARE(MT7986_FIRMWARE_WO1); ++--- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h +++++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h ++@@ -152,6 +152,7 @@ struct mtk_wdma_desc { ++ ++ #define MTK_WED_RING_RX(_n) (0x400 + (_n) * 0x10) ++ +++#define MTK_WED_SCR0 0x3c0 ++ #define MTK_WED_WPDMA_INT_TRIGGER 0x504 ++ #define MTK_WED_WPDMA_INT_TRIGGER_RX_DONE BIT(1) ++ #define MTK_WED_WPDMA_INT_TRIGGER_TX_DONE GENMASK(5, 4) ++--- /dev/null +++++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h ++@@ -0,0 +1,150 @@ +++/* SPDX-License-Identifier: GPL-2.0-only */ +++/* Copyright (C) 2022 Lorenzo Bianconi <lorenzo@kernel.org> */ +++ +++#ifndef __MTK_WED_WO_H +++#define __MTK_WED_WO_H +++ +++#include <linux/skbuff.h> +++#include <linux/netdevice.h> +++ +++struct mtk_wed_hw; +++ +++struct mtk_wed_mcu_hdr { +++ /* DW0 */ +++ u8 version; +++ u8 cmd; +++ __le16 length; +++ +++ /* DW1 */ +++ __le16 seq; +++ __le16 flag; +++ +++ /* DW2 */ +++ __le32 status; +++ +++ /* DW3 */ +++ u8 rsv[20]; +++}; +++ +++struct mtk_wed_wo_log_info { +++ __le32 sn; +++ __le32 total; +++ __le32 rro; +++ __le32 mod; +++}; +++ +++enum mtk_wed_wo_event { +++ MTK_WED_WO_EVT_LOG_DUMP = 0x1, +++ MTK_WED_WO_EVT_PROFILING = 0x2, +++ MTK_WED_WO_EVT_RXCNT_INFO = 0x3, +++}; +++ +++#define MTK_WED_MODULE_ID_WO 1 +++#define MTK_FW_DL_TIMEOUT 4000000 /* us */ +++#define MTK_WOCPU_TIMEOUT 2000000 /* us */ +++ +++enum { +++ MTK_WED_WARP_CMD_FLAG_RSP = BIT(0), +++ MTK_WED_WARP_CMD_FLAG_NEED_RSP = BIT(1), +++ MTK_WED_WARP_CMD_FLAG_FROM_TO_WO = BIT(2), +++}; +++ +++enum { +++ MTK_WED_WO_REGION_EMI, +++ MTK_WED_WO_REGION_ILM, +++ MTK_WED_WO_REGION_DATA, +++ MTK_WED_WO_REGION_BOOT, +++ __MTK_WED_WO_REGION_MAX, +++}; +++ +++enum mtk_wed_dummy_cr_idx { +++ MTK_WED_DUMMY_CR_FWDL, +++ MTK_WED_DUMMY_CR_WO_STATUS, +++}; +++ +++#define MT7986_FIRMWARE_WO0 "mediatek/mt7986_wo_0.bin" +++#define MT7986_FIRMWARE_WO1 "mediatek/mt7986_wo_1.bin" +++ +++#define MTK_WO_MCU_CFG_LS_BASE 0 +++#define MTK_WO_MCU_CFG_LS_HW_VER_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x000) +++#define MTK_WO_MCU_CFG_LS_FW_VER_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x004) +++#define MTK_WO_MCU_CFG_LS_CFG_DBG1_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x00c) +++#define MTK_WO_MCU_CFG_LS_CFG_DBG2_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x010) +++#define MTK_WO_MCU_CFG_LS_WF_MCCR_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x014) +++#define MTK_WO_MCU_CFG_LS_WF_MCCR_SET_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x018) +++#define MTK_WO_MCU_CFG_LS_WF_MCCR_CLR_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x01c) +++#define MTK_WO_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x050) +++#define MTK_WO_MCU_CFG_LS_WM_BOOT_ADDR_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x060) +++#define MTK_WO_MCU_CFG_LS_WA_BOOT_ADDR_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x064) +++ +++#define MTK_WO_MCU_CFG_LS_WF_WM_WA_WM_CPU_RSTB_MASK BIT(5) +++#define MTK_WO_MCU_CFG_LS_WF_WM_WA_WA_CPU_RSTB_MASK BIT(0) +++ +++struct mtk_wed_wo_memory_region { +++ const char *name; +++ void __iomem *addr; +++ phys_addr_t phy_addr; +++ u32 size; +++ bool shared:1; +++ bool consumed:1; +++}; +++ +++struct mtk_wed_fw_region { +++ __le32 decomp_crc; +++ __le32 decomp_len; +++ __le32 decomp_blk_sz; +++ u8 rsv0[4]; +++ __le32 addr; +++ __le32 len; +++ u8 feature_set; +++ u8 rsv1[15]; +++} __packed; +++ +++struct mtk_wed_fw_trailer { +++ u8 chip_id; +++ u8 eco_code; +++ u8 num_region; +++ u8 format_ver; +++ u8 format_flag; +++ u8 rsv[2]; +++ char fw_ver[10]; +++ char build_date[15]; +++ u32 crc; +++}; +++ +++struct mtk_wed_wo { +++ struct mtk_wed_hw *hw; +++ struct mtk_wed_wo_memory_region boot; +++ +++ struct { +++ struct mutex mutex; +++ int timeout; +++ u16 seq; +++ +++ struct sk_buff_head res_q; +++ wait_queue_head_t wait; +++ } mcu; +++}; +++ +++static inline int +++mtk_wed_mcu_check_msg(struct mtk_wed_wo *wo, struct sk_buff *skb) +++{ +++ struct mtk_wed_mcu_hdr *hdr = (struct mtk_wed_mcu_hdr *)skb->data; +++ +++ if (hdr->version) +++ return -EINVAL; +++ +++ if (skb->len < sizeof(*hdr) || skb->len != le16_to_cpu(hdr->length)) +++ return -EINVAL; +++ ++ return 0; +++} +++ +++void mtk_wed_mcu_rx_event(struct mtk_wed_wo *wo, struct sk_buff *skb); +++void mtk_wed_mcu_rx_unsolicited_event(struct mtk_wed_wo *wo, +++ struct sk_buff *skb); +++int mtk_wed_mcu_send_msg(struct mtk_wed_wo *wo, int id, int cmd, +++ const void *data, int len, bool wait_resp); +++int mtk_wed_mcu_init(struct mtk_wed_wo *wo); +++ +++#endif /* __MTK_WED_WO_H */ ++--- a/include/linux/soc/mediatek/mtk_wed.h +++++ b/include/linux/soc/mediatek/mtk_wed.h ++@@ -11,6 +11,35 @@ ++ struct mtk_wed_hw; ++ struct mtk_wdma_desc; ++ +++enum mtk_wed_wo_cmd { +++ MTK_WED_WO_CMD_WED_CFG, +++ MTK_WED_WO_CMD_WED_RX_STAT, +++ MTK_WED_WO_CMD_RRO_SER, +++ MTK_WED_WO_CMD_DBG_INFO, +++ MTK_WED_WO_CMD_DEV_INFO, +++ MTK_WED_WO_CMD_BSS_INFO, +++ MTK_WED_WO_CMD_STA_REC, +++ MTK_WED_WO_CMD_DEV_INFO_DUMP, +++ MTK_WED_WO_CMD_BSS_INFO_DUMP, +++ MTK_WED_WO_CMD_STA_REC_DUMP, +++ MTK_WED_WO_CMD_BA_INFO_DUMP, +++ MTK_WED_WO_CMD_FBCMD_Q_DUMP, +++ MTK_WED_WO_CMD_FW_LOG_CTRL, +++ MTK_WED_WO_CMD_LOG_FLUSH, +++ MTK_WED_WO_CMD_CHANGE_STATE, +++ MTK_WED_WO_CMD_CPU_STATS_ENABLE, +++ MTK_WED_WO_CMD_CPU_STATS_DUMP, +++ MTK_WED_WO_CMD_EXCEPTION_INIT, +++ MTK_WED_WO_CMD_PROF_CTRL, +++ MTK_WED_WO_CMD_STA_BA_DUMP, +++ MTK_WED_WO_CMD_BA_CTRL_DUMP, +++ MTK_WED_WO_CMD_RXCNT_CTRL, +++ MTK_WED_WO_CMD_RXCNT_INFO, +++ MTK_WED_WO_CMD_SET_CAP, +++ MTK_WED_WO_CMD_CCIF_RING_DUMP, +++ MTK_WED_WO_CMD_WED_END +++}; +++ ++ enum mtk_wed_bus_tye { ++ MTK_WED_BUS_PCIE, ++ MTK_WED_BUS_AXI, +diff --git a/target/linux/generic/pending-5.15/733-02-net-ethernet-mtk_wed-introduce-wed-wo-support.patch b/target/linux/generic/pending-5.15/733-02-net-ethernet-mtk_wed-introduce-wed-wo-support.patch +new file mode 100644 +index 0000000000..dbd7e30fbb +--- /dev/null ++++ b/target/linux/generic/pending-5.15/733-02-net-ethernet-mtk_wed-introduce-wed-wo-support.patch +@@ -0,0 +1,737 @@ ++From: Lorenzo Bianconi <lorenzo@kernel.org> ++Date: Sat, 5 Nov 2022 23:36:19 +0100 ++Subject: [PATCH] net: ethernet: mtk_wed: introduce wed wo support ++ ++Introduce WO chip support to mtk wed driver. MTK WED WO is used to ++implement RX Wireless Ethernet Dispatch and offload traffic received by ++wlan nic to the wired interface. ++ ++Tested-by: Daniel Golle <daniel@makrotopia.org> ++Co-developed-by: Sujuan Chen <sujuan.chen@mediatek.com> ++Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com> ++Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> ++Signed-off-by: David S. Miller <davem@davemloft.net> ++--- ++ create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_wo.c ++ ++--- a/drivers/net/ethernet/mediatek/Makefile +++++ b/drivers/net/ethernet/mediatek/Makefile ++@@ -5,7 +5,7 @@ ++ ++ obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o ++ mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_eth_path.o mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.o ++-mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed.o mtk_wed_mcu.o +++mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed.o mtk_wed_mcu.o mtk_wed_wo.o ++ ifdef CONFIG_DEBUG_FS ++ mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_debugfs.o ++ endif ++--- a/drivers/net/ethernet/mediatek/mtk_wed.c +++++ b/drivers/net/ethernet/mediatek/mtk_wed.c ++@@ -16,6 +16,7 @@ ++ #include "mtk_wed_regs.h" ++ #include "mtk_wed.h" ++ #include "mtk_ppe.h" +++#include "mtk_wed_wo.h" ++ ++ #define MTK_PCIE_BASE(n) (0x1a143000 + (n) * 0x2000) ++ ++@@ -355,6 +356,8 @@ mtk_wed_detach(struct mtk_wed_device *de ++ ++ mtk_wed_free_buffer(dev); ++ mtk_wed_free_tx_rings(dev); +++ if (hw->version != 1) +++ mtk_wed_wo_deinit(hw); ++ ++ if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) { ++ struct device_node *wlan_node; ++@@ -885,9 +888,11 @@ mtk_wed_attach(struct mtk_wed_device *de ++ } ++ ++ mtk_wed_hw_init_early(dev); ++- if (hw->hifsys) +++ if (hw->version == 1) ++ regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP, ++ BIT(hw->index), 0); +++ else +++ ret = mtk_wed_wo_init(hw); ++ ++ out: ++ mutex_unlock(&hw_lock); ++--- a/drivers/net/ethernet/mediatek/mtk_wed.h +++++ b/drivers/net/ethernet/mediatek/mtk_wed.h ++@@ -10,6 +10,7 @@ ++ #include <linux/netdevice.h> ++ ++ struct mtk_eth; +++struct mtk_wed_wo; ++ ++ struct mtk_wed_hw { ++ struct device_node *node; ++@@ -22,6 +23,7 @@ struct mtk_wed_hw { ++ struct regmap *mirror; ++ struct dentry *debugfs_dir; ++ struct mtk_wed_device *wed_dev; +++ struct mtk_wed_wo *wed_wo; ++ u32 debugfs_reg; ++ u32 num_flows; ++ u8 version; ++--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c +++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c ++@@ -122,8 +122,7 @@ mtk_wed_mcu_skb_send_msg(struct mtk_wed_ ++ if (id == MTK_WED_MODULE_ID_WO) ++ hdr->flag |= cpu_to_le16(MTK_WED_WARP_CMD_FLAG_FROM_TO_WO); ++ ++- dev_kfree_skb(skb); ++- return 0; +++ return mtk_wed_wo_queue_tx_skb(wo, &wo->q_tx, skb); + } + -+-static int mvebu_a3700_comphy_get_fw_mode(int lane, ++ static int ++--- /dev/null +++++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.c ++@@ -0,0 +1,508 @@ +++// SPDX-License-Identifier: GPL-2.0-only +++/* Copyright (C) 2022 MediaTek Inc. +++ * +++ * Author: Lorenzo Bianconi <lorenzo@kernel.org> +++ * Sujuan Chen <sujuan.chen@mediatek.com> +++ */ +++ +++#include <linux/kernel.h> +++#include <linux/dma-mapping.h> +++#include <linux/of_platform.h> +++#include <linux/interrupt.h> +++#include <linux/of_address.h> +++#include <linux/mfd/syscon.h> +++#include <linux/of_irq.h> +++#include <linux/bitfield.h> +++ +++#include "mtk_wed.h" +++#include "mtk_wed_regs.h" +++#include "mtk_wed_wo.h" +++ +++static u32 +++mtk_wed_mmio_r32(struct mtk_wed_wo *wo, u32 reg) +++{ +++ u32 val; +++ +++ if (regmap_read(wo->mmio.regs, reg, &val)) +++ val = ~0; +++ +++ return val; +++} +++ +++static void +++mtk_wed_mmio_w32(struct mtk_wed_wo *wo, u32 reg, u32 val) +++{ +++ regmap_write(wo->mmio.regs, reg, val); +++} +++ +++static u32 +++mtk_wed_wo_get_isr(struct mtk_wed_wo *wo) +++{ +++ u32 val = mtk_wed_mmio_r32(wo, MTK_WED_WO_CCIF_RCHNUM); +++ +++ return val & MTK_WED_WO_CCIF_RCHNUM_MASK; +++} +++ +++static void +++mtk_wed_wo_set_isr(struct mtk_wed_wo *wo, u32 mask) +++{ +++ mtk_wed_mmio_w32(wo, MTK_WED_WO_CCIF_IRQ0_MASK, mask); +++} +++ +++static void +++mtk_wed_wo_set_ack(struct mtk_wed_wo *wo, u32 mask) +++{ +++ mtk_wed_mmio_w32(wo, MTK_WED_WO_CCIF_ACK, mask); +++} +++ +++static void +++mtk_wed_wo_set_isr_mask(struct mtk_wed_wo *wo, u32 mask, u32 val, bool set) +++{ +++ unsigned long flags; +++ +++ spin_lock_irqsave(&wo->mmio.lock, flags); +++ wo->mmio.irq_mask &= ~mask; +++ wo->mmio.irq_mask |= val; +++ if (set) +++ mtk_wed_wo_set_isr(wo, wo->mmio.irq_mask); +++ spin_unlock_irqrestore(&wo->mmio.lock, flags); +++} +++ +++static void +++mtk_wed_wo_irq_enable(struct mtk_wed_wo *wo, u32 mask) +++{ +++ mtk_wed_wo_set_isr_mask(wo, 0, mask, false); +++ tasklet_schedule(&wo->mmio.irq_tasklet); +++} +++ +++static void +++mtk_wed_wo_irq_disable(struct mtk_wed_wo *wo, u32 mask) +++{ +++ mtk_wed_wo_set_isr_mask(wo, mask, 0, true); +++} +++ +++static void +++mtk_wed_wo_kickout(struct mtk_wed_wo *wo) +++{ +++ mtk_wed_mmio_w32(wo, MTK_WED_WO_CCIF_BUSY, 1 << MTK_WED_WO_TXCH_NUM); +++ mtk_wed_mmio_w32(wo, MTK_WED_WO_CCIF_TCHNUM, MTK_WED_WO_TXCH_NUM); +++} +++ +++static void +++mtk_wed_wo_queue_kick(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q, +++ u32 val) +++{ +++ wmb(); +++ mtk_wed_mmio_w32(wo, q->regs.cpu_idx, val); +++} +++ +++static void * +++mtk_wed_wo_dequeue(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q, u32 *len, +++ bool flush) +++{ +++ int buf_len = SKB_WITH_OVERHEAD(q->buf_size); +++ int index = (q->tail + 1) % q->n_desc; +++ struct mtk_wed_wo_queue_entry *entry; +++ struct mtk_wed_wo_queue_desc *desc; +++ void *buf; +++ +++ if (!q->queued) +++ return NULL; +++ +++ if (flush) +++ q->desc[index].ctrl |= cpu_to_le32(MTK_WED_WO_CTL_DMA_DONE); +++ else if (!(q->desc[index].ctrl & cpu_to_le32(MTK_WED_WO_CTL_DMA_DONE))) +++ return NULL; +++ +++ q->tail = index; +++ q->queued--; +++ +++ desc = &q->desc[index]; +++ entry = &q->entry[index]; +++ buf = entry->buf; +++ if (len) +++ *len = FIELD_GET(MTK_WED_WO_CTL_SD_LEN0, +++ le32_to_cpu(READ_ONCE(desc->ctrl))); +++ if (buf) +++ dma_unmap_single(wo->hw->dev, entry->addr, buf_len, +++ DMA_FROM_DEVICE); +++ entry->buf = NULL; +++ +++ return buf; +++} +++ ++static int -++mvebu_a3700_comphy_usb3_power_on(struct mvebu_a3700_comphy_lane *lane) +++mtk_wed_wo_queue_refill(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q, +++ gfp_t gfp, bool rx) ++{ -++ u32 mask, data, cfg, ref_clk; -++ int ret; +++ enum dma_data_direction dir = rx ? DMA_FROM_DEVICE : DMA_TO_DEVICE; +++ int n_buf = 0; ++ -++ /* Set phy seclector */ -++ ret = mvebu_a3700_comphy_set_phy_selector(lane); -++ if (ret) -++ return ret; +++ spin_lock_bh(&q->lock); +++ while (q->queued < q->n_desc) { +++ void *buf = page_frag_alloc(&q->cache, q->buf_size, gfp); +++ struct mtk_wed_wo_queue_entry *entry; +++ dma_addr_t addr; ++ -++ /* -++ * 0. Set PHY OTG Control(0x5d034), bit 4, Power up OTG module The -++ * register belong to UTMI module, so it is set in UTMI phy driver. -++ */ +++ if (!buf) +++ break; ++ -++ /* -++ * 1. Set PRD_TXDEEMPH (3.5db de-emph) -++ */ -++ data = PRD_TXDEEMPH0_MASK; -++ mask = PRD_TXDEEMPH0_MASK | PRD_TXMARGIN_MASK | PRD_TXSWING_MASK | -++ CFG_TX_ALIGN_POS_MASK; -++ comphy_lane_reg_set(lane, COMPHY_PIPE_LANE_CFG0, data, mask); +++ addr = dma_map_single(wo->hw->dev, buf, q->buf_size, dir); +++ if (unlikely(dma_mapping_error(wo->hw->dev, addr))) { +++ skb_free_frag(buf); +++ break; +++ } ++ -++ /* -++ * 2. Set BIT0: enable transmitter in high impedance mode -++ * Set BIT[3:4]: delay 2 clock cycles for HiZ off latency -++ * Set BIT6: Tx detect Rx at HiZ mode -++ * Unset BIT15: set to 0 to set USB3 De-emphasize level to -3.5db -++ * together with bit 0 of COMPHY_PIPE_LANE_CFG0 register -++ */ -++ data = TX_DET_RX_MODE | GEN2_TX_DATA_DLY_DEFT | TX_ELEC_IDLE_MODE_EN; -++ mask = PRD_TXDEEMPH1_MASK | TX_DET_RX_MODE | GEN2_TX_DATA_DLY_MASK | -++ TX_ELEC_IDLE_MODE_EN; -++ comphy_lane_reg_set(lane, COMPHY_PIPE_LANE_CFG1, data, mask); +++ q->head = (q->head + 1) % q->n_desc; +++ entry = &q->entry[q->head]; +++ entry->addr = addr; +++ entry->len = q->buf_size; +++ q->entry[q->head].buf = buf; +++ +++ if (rx) { +++ struct mtk_wed_wo_queue_desc *desc = &q->desc[q->head]; +++ u32 ctrl = MTK_WED_WO_CTL_LAST_SEC0 | +++ FIELD_PREP(MTK_WED_WO_CTL_SD_LEN0, +++ entry->len); +++ +++ WRITE_ONCE(desc->buf0, cpu_to_le32(addr)); +++ WRITE_ONCE(desc->ctrl, cpu_to_le32(ctrl)); +++ } +++ q->queued++; +++ n_buf++; +++ } +++ spin_unlock_bh(&q->lock); +++ +++ return n_buf; +++} +++ +++static void +++mtk_wed_wo_rx_complete(struct mtk_wed_wo *wo) +++{ +++ mtk_wed_wo_set_ack(wo, MTK_WED_WO_RXCH_INT_MASK); +++ mtk_wed_wo_irq_enable(wo, MTK_WED_WO_RXCH_INT_MASK); +++} +++ +++static void +++mtk_wed_wo_rx_run_queue(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q) +++{ +++ for (;;) { +++ struct mtk_wed_mcu_hdr *hdr; +++ struct sk_buff *skb; +++ void *data; +++ u32 len; +++ +++ data = mtk_wed_wo_dequeue(wo, q, &len, false); +++ if (!data) +++ break; +++ +++ skb = build_skb(data, q->buf_size); +++ if (!skb) { +++ skb_free_frag(data); +++ continue; +++ } +++ +++ __skb_put(skb, len); +++ if (mtk_wed_mcu_check_msg(wo, skb)) { +++ dev_kfree_skb(skb); +++ continue; +++ } +++ +++ hdr = (struct mtk_wed_mcu_hdr *)skb->data; +++ if (hdr->flag & cpu_to_le16(MTK_WED_WARP_CMD_FLAG_RSP)) +++ mtk_wed_mcu_rx_event(wo, skb); +++ else +++ mtk_wed_mcu_rx_unsolicited_event(wo, skb); +++ } +++ +++ if (mtk_wed_wo_queue_refill(wo, q, GFP_ATOMIC, true)) { +++ u32 index = (q->head - 1) % q->n_desc; +++ +++ mtk_wed_wo_queue_kick(wo, q, index); +++ } +++} +++ +++static irqreturn_t +++mtk_wed_wo_irq_handler(int irq, void *data) +++{ +++ struct mtk_wed_wo *wo = data; +++ +++ mtk_wed_wo_set_isr(wo, 0); +++ tasklet_schedule(&wo->mmio.irq_tasklet); +++ +++ return IRQ_HANDLED; +++} +++ +++static void mtk_wed_wo_irq_tasklet(struct tasklet_struct *t) +++{ +++ struct mtk_wed_wo *wo = from_tasklet(wo, t, mmio.irq_tasklet); +++ u32 intr, mask; +++ +++ /* disable interrupts */ +++ mtk_wed_wo_set_isr(wo, 0); +++ +++ intr = mtk_wed_wo_get_isr(wo); +++ intr &= wo->mmio.irq_mask; +++ mask = intr & (MTK_WED_WO_RXCH_INT_MASK | MTK_WED_WO_EXCEPTION_INT_MASK); +++ mtk_wed_wo_irq_disable(wo, mask); +++ +++ if (intr & MTK_WED_WO_RXCH_INT_MASK) { +++ mtk_wed_wo_rx_run_queue(wo, &wo->q_rx); +++ mtk_wed_wo_rx_complete(wo); +++ } +++} +++ +++/* mtk wed wo hw queues */ +++ +++static int +++mtk_wed_wo_queue_alloc(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q, +++ int n_desc, int buf_size, int index, +++ struct mtk_wed_wo_queue_regs *regs) +++{ +++ spin_lock_init(&q->lock); +++ q->regs = *regs; +++ q->n_desc = n_desc; +++ q->buf_size = buf_size; +++ +++ q->desc = dmam_alloc_coherent(wo->hw->dev, n_desc * sizeof(*q->desc), +++ &q->desc_dma, GFP_KERNEL); +++ if (!q->desc) +++ return -ENOMEM; +++ +++ q->entry = devm_kzalloc(wo->hw->dev, n_desc * sizeof(*q->entry), +++ GFP_KERNEL); +++ if (!q->entry) +++ return -ENOMEM; +++ +++ return 0; +++} +++ +++static void +++mtk_wed_wo_queue_free(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q) +++{ +++ mtk_wed_mmio_w32(wo, q->regs.cpu_idx, 0); +++ dma_free_coherent(wo->hw->dev, q->n_desc * sizeof(*q->desc), q->desc, +++ q->desc_dma); +++} +++ +++static void +++mtk_wed_wo_queue_tx_clean(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q) +++{ +++ struct page *page; +++ int i; +++ +++ spin_lock_bh(&q->lock); +++ for (i = 0; i < q->n_desc; i++) { +++ struct mtk_wed_wo_queue_entry *entry = &q->entry[i]; +++ +++ dma_unmap_single(wo->hw->dev, entry->addr, entry->len, +++ DMA_TO_DEVICE); +++ skb_free_frag(entry->buf); +++ entry->buf = NULL; +++ } +++ spin_unlock_bh(&q->lock); +++ +++ if (!q->cache.va) +++ return; +++ +++ page = virt_to_page(q->cache.va); +++ __page_frag_cache_drain(page, q->cache.pagecnt_bias); +++ memset(&q->cache, 0, sizeof(q->cache)); +++} +++ +++static void +++mtk_wed_wo_queue_rx_clean(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q) +++{ +++ struct page *page; +++ +++ spin_lock_bh(&q->lock); +++ for (;;) { +++ void *buf = mtk_wed_wo_dequeue(wo, q, NULL, true); +++ +++ if (!buf) +++ break; +++ +++ skb_free_frag(buf); +++ } +++ spin_unlock_bh(&q->lock); +++ +++ if (!q->cache.va) +++ return; +++ +++ page = virt_to_page(q->cache.va); +++ __page_frag_cache_drain(page, q->cache.pagecnt_bias); +++ memset(&q->cache, 0, sizeof(q->cache)); +++} +++ +++static void +++mtk_wed_wo_queue_reset(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q) +++{ +++ mtk_wed_mmio_w32(wo, q->regs.cpu_idx, 0); +++ mtk_wed_mmio_w32(wo, q->regs.desc_base, q->desc_dma); +++ mtk_wed_mmio_w32(wo, q->regs.ring_size, q->n_desc); +++} +++ +++int mtk_wed_wo_queue_tx_skb(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q, +++ struct sk_buff *skb) +++{ +++ struct mtk_wed_wo_queue_entry *entry; +++ struct mtk_wed_wo_queue_desc *desc; +++ int ret = 0, index; +++ u32 ctrl; +++ +++ spin_lock_bh(&q->lock); +++ +++ q->tail = mtk_wed_mmio_r32(wo, q->regs.dma_idx); +++ index = (q->head + 1) % q->n_desc; +++ if (q->tail == index) { +++ ret = -ENOMEM; +++ goto out; +++ } +++ +++ entry = &q->entry[index]; +++ if (skb->len > entry->len) { +++ ret = -ENOMEM; +++ goto out; +++ } +++ +++ desc = &q->desc[index]; +++ q->head = index; +++ +++ dma_sync_single_for_cpu(wo->hw->dev, entry->addr, skb->len, +++ DMA_TO_DEVICE); +++ memcpy(entry->buf, skb->data, skb->len); +++ dma_sync_single_for_device(wo->hw->dev, entry->addr, skb->len, +++ DMA_TO_DEVICE); +++ +++ ctrl = FIELD_PREP(MTK_WED_WO_CTL_SD_LEN0, skb->len) | +++ MTK_WED_WO_CTL_LAST_SEC0 | MTK_WED_WO_CTL_DMA_DONE; +++ WRITE_ONCE(desc->buf0, cpu_to_le32(entry->addr)); +++ WRITE_ONCE(desc->ctrl, cpu_to_le32(ctrl)); +++ +++ mtk_wed_wo_queue_kick(wo, q, q->head); +++ mtk_wed_wo_kickout(wo); +++out: +++ spin_unlock_bh(&q->lock); +++ +++ dev_kfree_skb(skb); +++ +++ return ret; +++} +++ +++static int +++mtk_wed_wo_exception_init(struct mtk_wed_wo *wo) +++{ +++ return 0; +++} +++ +++static int +++mtk_wed_wo_hardware_init(struct mtk_wed_wo *wo) +++{ +++ struct mtk_wed_wo_queue_regs regs; +++ struct device_node *np; +++ int ret; +++ +++ np = of_parse_phandle(wo->hw->node, "mediatek,wo-ccif", 0); +++ if (!np) +++ return -ENODEV; +++ +++ wo->mmio.regs = syscon_regmap_lookup_by_phandle(np, NULL); +++ if (IS_ERR_OR_NULL(wo->mmio.regs)) +++ return PTR_ERR(wo->mmio.regs); +++ +++ wo->mmio.irq = irq_of_parse_and_map(np, 0); +++ wo->mmio.irq_mask = MTK_WED_WO_ALL_INT_MASK; +++ spin_lock_init(&wo->mmio.lock); +++ tasklet_setup(&wo->mmio.irq_tasklet, mtk_wed_wo_irq_tasklet); +++ +++ ret = devm_request_irq(wo->hw->dev, wo->mmio.irq, +++ mtk_wed_wo_irq_handler, IRQF_TRIGGER_HIGH, +++ KBUILD_MODNAME, wo); +++ if (ret) +++ goto error; +++ +++ regs.desc_base = MTK_WED_WO_CCIF_DUMMY1; +++ regs.ring_size = MTK_WED_WO_CCIF_DUMMY2; +++ regs.dma_idx = MTK_WED_WO_CCIF_SHADOW4; +++ regs.cpu_idx = MTK_WED_WO_CCIF_DUMMY3; +++ +++ ret = mtk_wed_wo_queue_alloc(wo, &wo->q_tx, MTK_WED_WO_RING_SIZE, +++ MTK_WED_WO_CMD_LEN, MTK_WED_WO_TXCH_NUM, +++ ®s); +++ if (ret) +++ goto error; +++ +++ mtk_wed_wo_queue_refill(wo, &wo->q_tx, GFP_KERNEL, false); +++ mtk_wed_wo_queue_reset(wo, &wo->q_tx); +++ +++ regs.desc_base = MTK_WED_WO_CCIF_DUMMY5; +++ regs.ring_size = MTK_WED_WO_CCIF_DUMMY6; +++ regs.dma_idx = MTK_WED_WO_CCIF_SHADOW8; +++ regs.cpu_idx = MTK_WED_WO_CCIF_DUMMY7; +++ +++ ret = mtk_wed_wo_queue_alloc(wo, &wo->q_rx, MTK_WED_WO_RING_SIZE, +++ MTK_WED_WO_CMD_LEN, MTK_WED_WO_RXCH_NUM, +++ ®s); +++ if (ret) +++ goto error; +++ +++ mtk_wed_wo_queue_refill(wo, &wo->q_rx, GFP_KERNEL, true); +++ mtk_wed_wo_queue_reset(wo, &wo->q_rx); +++ +++ /* rx queue irqmask */ +++ mtk_wed_wo_set_isr(wo, wo->mmio.irq_mask); +++ +++ return 0; +++ +++error: +++ devm_free_irq(wo->hw->dev, wo->mmio.irq, wo); +++ +++ return ret; +++} +++ +++static void +++mtk_wed_wo_hw_deinit(struct mtk_wed_wo *wo) +++{ +++ /* disable interrupts */ +++ mtk_wed_wo_set_isr(wo, 0); +++ +++ tasklet_disable(&wo->mmio.irq_tasklet); +++ +++ disable_irq(wo->mmio.irq); +++ devm_free_irq(wo->hw->dev, wo->mmio.irq, wo); +++ +++ mtk_wed_wo_queue_tx_clean(wo, &wo->q_tx); +++ mtk_wed_wo_queue_rx_clean(wo, &wo->q_rx); +++ mtk_wed_wo_queue_free(wo, &wo->q_tx); +++ mtk_wed_wo_queue_free(wo, &wo->q_rx); +++} +++ +++int mtk_wed_wo_init(struct mtk_wed_hw *hw) +++{ +++ struct mtk_wed_wo *wo; +++ int ret; +++ +++ wo = devm_kzalloc(hw->dev, sizeof(*wo), GFP_KERNEL); +++ if (!wo) +++ return -ENOMEM; +++ +++ hw->wed_wo = wo; +++ wo->hw = hw; +++ +++ ret = mtk_wed_wo_hardware_init(wo); +++ if (ret) +++ return ret; +++ +++ ret = mtk_wed_mcu_init(wo); +++ if (ret) +++ return ret; +++ +++ return mtk_wed_wo_exception_init(wo); +++} +++ +++void mtk_wed_wo_deinit(struct mtk_wed_hw *hw) +++{ +++ struct mtk_wed_wo *wo = hw->wed_wo; +++ +++ mtk_wed_wo_hw_deinit(wo); +++} ++--- a/drivers/net/ethernet/mediatek/mtk_wed_wo.h +++++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h ++@@ -80,6 +80,54 @@ enum mtk_wed_dummy_cr_idx { ++ #define MTK_WO_MCU_CFG_LS_WF_WM_WA_WM_CPU_RSTB_MASK BIT(5) ++ #define MTK_WO_MCU_CFG_LS_WF_WM_WA_WA_CPU_RSTB_MASK BIT(0) ++ +++#define MTK_WED_WO_RING_SIZE 256 +++#define MTK_WED_WO_CMD_LEN 1504 +++ +++#define MTK_WED_WO_TXCH_NUM 0 +++#define MTK_WED_WO_RXCH_NUM 1 +++#define MTK_WED_WO_RXCH_WO_EXCEPTION 7 +++ +++#define MTK_WED_WO_TXCH_INT_MASK BIT(0) +++#define MTK_WED_WO_RXCH_INT_MASK BIT(1) +++#define MTK_WED_WO_EXCEPTION_INT_MASK BIT(7) +++#define MTK_WED_WO_ALL_INT_MASK (MTK_WED_WO_RXCH_INT_MASK | \ +++ MTK_WED_WO_EXCEPTION_INT_MASK) +++ +++#define MTK_WED_WO_CCIF_BUSY 0x004 +++#define MTK_WED_WO_CCIF_START 0x008 +++#define MTK_WED_WO_CCIF_TCHNUM 0x00c +++#define MTK_WED_WO_CCIF_RCHNUM 0x010 +++#define MTK_WED_WO_CCIF_RCHNUM_MASK GENMASK(7, 0) +++ +++#define MTK_WED_WO_CCIF_ACK 0x014 +++#define MTK_WED_WO_CCIF_IRQ0_MASK 0x018 +++#define MTK_WED_WO_CCIF_IRQ1_MASK 0x01c +++#define MTK_WED_WO_CCIF_DUMMY1 0x020 +++#define MTK_WED_WO_CCIF_DUMMY2 0x024 +++#define MTK_WED_WO_CCIF_DUMMY3 0x028 +++#define MTK_WED_WO_CCIF_DUMMY4 0x02c +++#define MTK_WED_WO_CCIF_SHADOW1 0x030 +++#define MTK_WED_WO_CCIF_SHADOW2 0x034 +++#define MTK_WED_WO_CCIF_SHADOW3 0x038 +++#define MTK_WED_WO_CCIF_SHADOW4 0x03c +++#define MTK_WED_WO_CCIF_DUMMY5 0x050 +++#define MTK_WED_WO_CCIF_DUMMY6 0x054 +++#define MTK_WED_WO_CCIF_DUMMY7 0x058 +++#define MTK_WED_WO_CCIF_DUMMY8 0x05c +++#define MTK_WED_WO_CCIF_SHADOW5 0x060 +++#define MTK_WED_WO_CCIF_SHADOW6 0x064 +++#define MTK_WED_WO_CCIF_SHADOW7 0x068 +++#define MTK_WED_WO_CCIF_SHADOW8 0x06c +++ +++#define MTK_WED_WO_CTL_SD_LEN1 GENMASK(13, 0) +++#define MTK_WED_WO_CTL_LAST_SEC1 BIT(14) +++#define MTK_WED_WO_CTL_BURST BIT(15) +++#define MTK_WED_WO_CTL_SD_LEN0_SHIFT 16 +++#define MTK_WED_WO_CTL_SD_LEN0 GENMASK(29, 16) +++#define MTK_WED_WO_CTL_LAST_SEC0 BIT(30) +++#define MTK_WED_WO_CTL_DMA_DONE BIT(31) +++#define MTK_WED_WO_INFO_WINFO GENMASK(15, 0) +++ ++ struct mtk_wed_wo_memory_region { ++ const char *name; ++ void __iomem *addr; ++@@ -112,10 +160,53 @@ struct mtk_wed_fw_trailer { ++ u32 crc; ++ }; ++ +++struct mtk_wed_wo_queue_regs { +++ u32 desc_base; +++ u32 ring_size; +++ u32 cpu_idx; +++ u32 dma_idx; +++}; +++ +++struct mtk_wed_wo_queue_desc { +++ __le32 buf0; +++ __le32 ctrl; +++ __le32 buf1; +++ __le32 info; +++ __le32 reserved[4]; +++} __packed __aligned(32); +++ +++struct mtk_wed_wo_queue_entry { +++ dma_addr_t addr; +++ void *buf; +++ u32 len; +++}; +++ +++struct mtk_wed_wo_queue { +++ struct mtk_wed_wo_queue_regs regs; +++ +++ struct page_frag_cache cache; +++ spinlock_t lock; +++ +++ struct mtk_wed_wo_queue_desc *desc; +++ dma_addr_t desc_dma; +++ +++ struct mtk_wed_wo_queue_entry *entry; +++ +++ u16 head; +++ u16 tail; +++ int n_desc; +++ int queued; +++ int buf_size; +++ +++}; +++ ++ struct mtk_wed_wo { ++ struct mtk_wed_hw *hw; ++ struct mtk_wed_wo_memory_region boot; ++ +++ struct mtk_wed_wo_queue q_tx; +++ struct mtk_wed_wo_queue q_rx; +++ ++ struct { ++ struct mutex mutex; ++ int timeout; ++@@ -124,6 +215,15 @@ struct mtk_wed_wo { ++ struct sk_buff_head res_q; ++ wait_queue_head_t wait; ++ } mcu; +++ +++ struct { +++ struct regmap *regs; +++ +++ spinlock_t lock; +++ struct tasklet_struct irq_tasklet; +++ int irq; +++ u32 irq_mask; +++ } mmio; ++ }; ++ ++ static inline int ++@@ -146,5 +246,9 @@ void mtk_wed_mcu_rx_unsolicited_event(st ++ int mtk_wed_mcu_send_msg(struct mtk_wed_wo *wo, int id, int cmd, ++ const void *data, int len, bool wait_resp); ++ int mtk_wed_mcu_init(struct mtk_wed_wo *wo); +++int mtk_wed_wo_init(struct mtk_wed_hw *hw); +++void mtk_wed_wo_deinit(struct mtk_wed_hw *hw); +++int mtk_wed_wo_queue_tx_skb(struct mtk_wed_wo *dev, struct mtk_wed_wo_queue *q, +++ struct sk_buff *skb); ++ ++ #endif /* __MTK_WED_WO_H */ +diff --git a/target/linux/generic/pending-5.15/733-03-net-ethernet-mtk_wed-rename-tx_wdma-array-in-rx_wdma.patch b/target/linux/generic/pending-5.15/733-03-net-ethernet-mtk_wed-rename-tx_wdma-array-in-rx_wdma.patch +new file mode 100644 +index 0000000000..ffd6bc3589 +--- /dev/null ++++ b/target/linux/generic/pending-5.15/733-03-net-ethernet-mtk_wed-rename-tx_wdma-array-in-rx_wdma.patch +@@ -0,0 +1,79 @@ ++From: Lorenzo Bianconi <lorenzo@kernel.org> ++Date: Sat, 5 Nov 2022 23:36:20 +0100 ++Subject: [PATCH] net: ethernet: mtk_wed: rename tx_wdma array in rx_wdma ++ ++Rename tx_wdma queue array in rx_wdma since this is rx side of wdma soc. ++Moreover rename mtk_wed_wdma_ring_setup routine in ++mtk_wed_wdma_rx_ring_setup() ++ ++Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> ++Signed-off-by: David S. Miller <davem@davemloft.net> ++--- ++ ++--- a/drivers/net/ethernet/mediatek/mtk_wed.c +++++ b/drivers/net/ethernet/mediatek/mtk_wed.c ++@@ -253,8 +253,8 @@ mtk_wed_free_tx_rings(struct mtk_wed_dev ++ ++ for (i = 0; i < ARRAY_SIZE(dev->tx_ring); i++) ++ mtk_wed_free_ring(dev, &dev->tx_ring[i]); ++- for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++) ++- mtk_wed_free_ring(dev, &dev->tx_wdma[i]); +++ for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++) +++ mtk_wed_free_ring(dev, &dev->rx_wdma[i]); ++ } ++ ++ static void ++@@ -695,10 +695,10 @@ mtk_wed_ring_alloc(struct mtk_wed_device ++ } ++ ++ static int ++-mtk_wed_wdma_ring_setup(struct mtk_wed_device *dev, int idx, int size) +++mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size) ++ { ++ u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version; ++- struct mtk_wed_ring *wdma = &dev->tx_wdma[idx]; +++ struct mtk_wed_ring *wdma = &dev->rx_wdma[idx]; ++ ++ if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size)) ++ return -ENOMEM; ++@@ -812,9 +812,9 @@ mtk_wed_start(struct mtk_wed_device *dev ++ { ++ int i; ++ ++- for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++) ++- if (!dev->tx_wdma[i].desc) ++- mtk_wed_wdma_ring_setup(dev, i, 16); +++ for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++) +++ if (!dev->rx_wdma[i].desc) +++ mtk_wed_wdma_rx_ring_setup(dev, i, 16); ++ ++ mtk_wed_hw_init(dev); ++ mtk_wed_configure_irq(dev, irq_mask); ++@@ -923,7 +923,7 @@ mtk_wed_tx_ring_setup(struct mtk_wed_dev ++ sizeof(*ring->desc))) ++ return -ENOMEM; ++ ++- if (mtk_wed_wdma_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE)) +++ if (mtk_wed_wdma_rx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE)) ++ return -ENOMEM; ++ ++ ring->reg_base = MTK_WED_RING_TX(idx); ++--- a/include/linux/soc/mediatek/mtk_wed.h +++++ b/include/linux/soc/mediatek/mtk_wed.h ++@@ -7,6 +7,7 @@ ++ #include <linux/pci.h> ++ ++ #define MTK_WED_TX_QUEUES 2 +++#define MTK_WED_RX_QUEUES 2 ++ ++ struct mtk_wed_hw; ++ struct mtk_wdma_desc; ++@@ -66,7 +67,7 @@ struct mtk_wed_device { ++ ++ struct mtk_wed_ring tx_ring[MTK_WED_TX_QUEUES]; ++ struct mtk_wed_ring txfree_ring; ++- struct mtk_wed_ring tx_wdma[MTK_WED_TX_QUEUES]; +++ struct mtk_wed_ring rx_wdma[MTK_WED_RX_QUEUES]; ++ ++ struct { ++ int size; +diff --git a/target/linux/generic/pending-5.15/733-04-net-ethernet-mtk_wed-add-configure-wed-wo-support.patch b/target/linux/generic/pending-5.15/733-04-net-ethernet-mtk_wed-add-configure-wed-wo-support.patch +new file mode 100644 +index 0000000000..4c34d0cb33 +--- /dev/null ++++ b/target/linux/generic/pending-5.15/733-04-net-ethernet-mtk_wed-add-configure-wed-wo-support.patch +@@ -0,0 +1,1521 @@ ++From: Lorenzo Bianconi <lorenzo@kernel.org> ++Date: Sat, 5 Nov 2022 23:36:21 +0100 ++Subject: [PATCH] net: ethernet: mtk_wed: add configure wed wo support ++ ++Enable RX Wireless Ethernet Dispatch available on MT7986 Soc. ++ ++Tested-by: Daniel Golle <daniel@makrotopia.org> ++Co-developed-by: Sujuan Chen <sujuan.chen@mediatek.com> ++Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com> ++Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> ++Signed-off-by: David S. Miller <davem@davemloft.net> ++--- ++ ++--- a/drivers/net/ethernet/mediatek/mtk_wed.c +++++ b/drivers/net/ethernet/mediatek/mtk_wed.c ++@@ -9,6 +9,7 @@ ++ #include <linux/skbuff.h> ++ #include <linux/of_platform.h> ++ #include <linux/of_address.h> +++#include <linux/of_reserved_mem.h> ++ #include <linux/mfd/syscon.h> ++ #include <linux/debugfs.h> ++ #include <linux/soc/mediatek/mtk_wed.h> ++@@ -23,6 +24,7 @@ ++ #define MTK_WED_PKT_SIZE 1900 ++ #define MTK_WED_BUF_SIZE 2048 ++ #define MTK_WED_BUF_PER_PAGE (PAGE_SIZE / 2048) +++#define MTK_WED_RX_RING_SIZE 1536 ++ ++ #define MTK_WED_TX_RING_SIZE 2048 ++ #define MTK_WED_WDMA_RING_SIZE 1024 ++@@ -31,6 +33,10 @@ ++ #define MTK_WED_PER_GROUP_PKT 128 ++ ++ #define MTK_WED_FBUF_SIZE 128 +++#define MTK_WED_MIOD_CNT 16 +++#define MTK_WED_FB_CMD_CNT 1024 +++#define MTK_WED_RRO_QUE_CNT 8192 +++#define MTK_WED_MIOD_ENTRY_CNT 128 ++ ++ static struct mtk_wed_hw *hw_list[2]; ++ static DEFINE_MUTEX(hw_lock); ++@@ -65,12 +71,76 @@ wdma_set(struct mtk_wed_device *dev, u32 ++ wdma_m32(dev, reg, 0, mask); ++ } ++ +++static void +++wdma_clr(struct mtk_wed_device *dev, u32 reg, u32 mask) +++{ +++ wdma_m32(dev, reg, mask, 0); +++} +++ +++static u32 +++wifi_r32(struct mtk_wed_device *dev, u32 reg) +++{ +++ return readl(dev->wlan.base + reg); +++} +++ +++static void +++wifi_w32(struct mtk_wed_device *dev, u32 reg, u32 val) +++{ +++ writel(val, dev->wlan.base + reg); +++} +++ ++ static u32 ++ mtk_wed_read_reset(struct mtk_wed_device *dev) ++ { ++ return wed_r32(dev, MTK_WED_RESET); ++ } ++ +++static u32 +++mtk_wdma_read_reset(struct mtk_wed_device *dev) +++{ +++ return wdma_r32(dev, MTK_WDMA_GLO_CFG); +++} +++ +++static void +++mtk_wdma_rx_reset(struct mtk_wed_device *dev) +++{ +++ u32 status, mask = MTK_WDMA_GLO_CFG_RX_DMA_BUSY; +++ int i; +++ +++ wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_RX_DMA_EN); +++ if (readx_poll_timeout(mtk_wdma_read_reset, dev, status, +++ !(status & mask), 0, 1000)) +++ dev_err(dev->hw->dev, "rx reset failed\n"); +++ +++ for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++) { +++ if (dev->rx_wdma[i].desc) +++ continue; +++ +++ wdma_w32(dev, +++ MTK_WDMA_RING_RX(i) + MTK_WED_RING_OFS_CPU_IDX, 0); +++ } +++} +++ +++static void +++mtk_wdma_tx_reset(struct mtk_wed_device *dev) +++{ +++ u32 status, mask = MTK_WDMA_GLO_CFG_TX_DMA_BUSY; +++ int i; +++ +++ wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN); +++ if (readx_poll_timeout(mtk_wdma_read_reset, dev, status, +++ !(status & mask), 0, 1000)) +++ dev_err(dev->hw->dev, "tx reset failed\n"); +++ +++ for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++) { +++ if (dev->tx_wdma[i].desc) +++ continue; +++ +++ wdma_w32(dev, +++ MTK_WDMA_RING_TX(i) + MTK_WED_RING_OFS_CPU_IDX, 0); +++ } +++} +++ ++ static void ++ mtk_wed_reset(struct mtk_wed_device *dev, u32 mask) ++ { ++@@ -82,6 +152,54 @@ mtk_wed_reset(struct mtk_wed_device *dev ++ WARN_ON_ONCE(1); ++ } ++ +++static u32 +++mtk_wed_wo_read_status(struct mtk_wed_device *dev) +++{ +++ return wed_r32(dev, MTK_WED_SCR0 + 4 * MTK_WED_DUMMY_CR_WO_STATUS); +++} +++ +++static void +++mtk_wed_wo_reset(struct mtk_wed_device *dev) +++{ +++ struct mtk_wed_wo *wo = dev->hw->wed_wo; +++ u8 state = MTK_WED_WO_STATE_DISABLE; +++ void __iomem *reg; +++ u32 val; +++ +++ mtk_wdma_tx_reset(dev); +++ mtk_wed_reset(dev, MTK_WED_RESET_WED); +++ +++ mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, +++ MTK_WED_WO_CMD_CHANGE_STATE, &state, +++ sizeof(state), false); +++ +++ if (readx_poll_timeout(mtk_wed_wo_read_status, dev, val, +++ val == MTK_WED_WOIF_DISABLE_DONE, +++ 100, MTK_WOCPU_TIMEOUT)) +++ dev_err(dev->hw->dev, "failed to disable wed-wo\n"); +++ +++ reg = ioremap(MTK_WED_WO_CPU_MCUSYS_RESET_ADDR, 4); +++ +++ val = readl(reg); +++ switch (dev->hw->index) { +++ case 0: +++ val |= MTK_WED_WO_CPU_WO0_MCUSYS_RESET_MASK; +++ writel(val, reg); +++ val &= ~MTK_WED_WO_CPU_WO0_MCUSYS_RESET_MASK; +++ writel(val, reg); +++ break; +++ case 1: +++ val |= MTK_WED_WO_CPU_WO1_MCUSYS_RESET_MASK; +++ writel(val, reg); +++ val &= ~MTK_WED_WO_CPU_WO1_MCUSYS_RESET_MASK; +++ writel(val, reg); +++ break; +++ default: +++ break; +++ } +++ iounmap(reg); +++} +++ ++ static struct mtk_wed_hw * ++ mtk_wed_assign(struct mtk_wed_device *dev) ++ { ++@@ -116,7 +234,7 @@ out: ++ } ++ ++ static int ++-mtk_wed_buffer_alloc(struct mtk_wed_device *dev) +++mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev) ++ { ++ struct mtk_wdma_desc *desc; ++ dma_addr_t desc_phys; ++@@ -133,16 +251,16 @@ mtk_wed_buffer_alloc(struct mtk_wed_devi ++ if (!page_list) ++ return -ENOMEM; ++ ++- dev->buf_ring.size = ring_size; ++- dev->buf_ring.pages = page_list; +++ dev->tx_buf_ring.size = ring_size; +++ dev->tx_buf_ring.pages = page_list; ++ ++ desc = dma_alloc_coherent(dev->hw->dev, ring_size * sizeof(*desc), ++ &desc_phys, GFP_KERNEL); ++ if (!desc) ++ return -ENOMEM; ++ ++- dev->buf_ring.desc = desc; ++- dev->buf_ring.desc_phys = desc_phys; +++ dev->tx_buf_ring.desc = desc; +++ dev->tx_buf_ring.desc_phys = desc_phys; ++ ++ for (i = 0, page_idx = 0; i < ring_size; i += MTK_WED_BUF_PER_PAGE) { ++ dma_addr_t page_phys, buf_phys; ++@@ -203,10 +321,10 @@ mtk_wed_buffer_alloc(struct mtk_wed_devi ++ } ++ ++ static void ++-mtk_wed_free_buffer(struct mtk_wed_device *dev) +++mtk_wed_free_tx_buffer(struct mtk_wed_device *dev) ++ { ++- struct mtk_wdma_desc *desc = dev->buf_ring.desc; ++- void **page_list = dev->buf_ring.pages; +++ struct mtk_wdma_desc *desc = dev->tx_buf_ring.desc; +++ void **page_list = dev->tx_buf_ring.pages; ++ int page_idx; ++ int i; ++ ++@@ -216,7 +334,8 @@ mtk_wed_free_buffer(struct mtk_wed_devic ++ if (!desc) ++ goto free_pagelist; ++ ++- for (i = 0, page_idx = 0; i < dev->buf_ring.size; i += MTK_WED_BUF_PER_PAGE) { +++ for (i = 0, page_idx = 0; i < dev->tx_buf_ring.size; +++ i += MTK_WED_BUF_PER_PAGE) { ++ void *page = page_list[page_idx++]; ++ dma_addr_t buf_addr; ++ ++@@ -229,13 +348,59 @@ mtk_wed_free_buffer(struct mtk_wed_devic ++ __free_page(page); ++ } ++ ++- dma_free_coherent(dev->hw->dev, dev->buf_ring.size * sizeof(*desc), ++- desc, dev->buf_ring.desc_phys); +++ dma_free_coherent(dev->hw->dev, dev->tx_buf_ring.size * sizeof(*desc), +++ desc, dev->tx_buf_ring.desc_phys); ++ ++ free_pagelist: ++ kfree(page_list); ++ } ++ +++static int +++mtk_wed_rx_buffer_alloc(struct mtk_wed_device *dev) +++{ +++ struct mtk_rxbm_desc *desc; +++ dma_addr_t desc_phys; +++ +++ dev->rx_buf_ring.size = dev->wlan.rx_nbuf; +++ desc = dma_alloc_coherent(dev->hw->dev, +++ dev->wlan.rx_nbuf * sizeof(*desc), +++ &desc_phys, GFP_KERNEL); +++ if (!desc) +++ return -ENOMEM; +++ +++ dev->rx_buf_ring.desc = desc; +++ dev->rx_buf_ring.desc_phys = desc_phys; +++ dev->wlan.init_rx_buf(dev, dev->wlan.rx_npkt); +++ +++ return 0; +++} +++ +++static void +++mtk_wed_free_rx_buffer(struct mtk_wed_device *dev) +++{ +++ struct mtk_rxbm_desc *desc = dev->rx_buf_ring.desc; +++ +++ if (!desc) +++ return; +++ +++ dev->wlan.release_rx_buf(dev); +++ dma_free_coherent(dev->hw->dev, dev->rx_buf_ring.size * sizeof(*desc), +++ desc, dev->rx_buf_ring.desc_phys); +++} +++ +++static void +++mtk_wed_rx_buffer_hw_init(struct mtk_wed_device *dev) +++{ +++ wed_w32(dev, MTK_WED_RX_BM_RX_DMAD, +++ FIELD_PREP(MTK_WED_RX_BM_RX_DMAD_SDL0, dev->wlan.rx_size)); +++ wed_w32(dev, MTK_WED_RX_BM_BASE, dev->rx_buf_ring.desc_phys); +++ wed_w32(dev, MTK_WED_RX_BM_INIT_PTR, MTK_WED_RX_BM_INIT_SW_TAIL | +++ FIELD_PREP(MTK_WED_RX_BM_SW_TAIL, dev->wlan.rx_npkt)); +++ wed_w32(dev, MTK_WED_RX_BM_DYN_ALLOC_TH, +++ FIELD_PREP(MTK_WED_RX_BM_DYN_ALLOC_TH_H, 0xffff)); +++ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN); +++} +++ ++ static void ++ mtk_wed_free_ring(struct mtk_wed_device *dev, struct mtk_wed_ring *ring) ++ { ++@@ -247,6 +412,13 @@ mtk_wed_free_ring(struct mtk_wed_device ++ } ++ ++ static void +++mtk_wed_free_rx_rings(struct mtk_wed_device *dev) +++{ +++ mtk_wed_free_rx_buffer(dev); +++ mtk_wed_free_ring(dev, &dev->rro.ring); +++} +++ +++static void ++ mtk_wed_free_tx_rings(struct mtk_wed_device *dev) ++ { ++ int i; ++@@ -291,6 +463,38 @@ mtk_wed_set_512_support(struct mtk_wed_d ++ } ++ } ++ +++#define MTK_WFMDA_RX_DMA_EN BIT(2) +++static void +++mtk_wed_check_wfdma_rx_fill(struct mtk_wed_device *dev, int idx) +++{ +++ u32 val; +++ int i; +++ +++ if (!(dev->rx_ring[idx].flags & MTK_WED_RING_CONFIGURED)) +++ return; /* queue is not configured by mt76 */ +++ +++ for (i = 0; i < 3; i++) { +++ u32 cur_idx; +++ +++ cur_idx = wed_r32(dev, +++ MTK_WED_WPDMA_RING_RX_DATA(idx) + +++ MTK_WED_RING_OFS_CPU_IDX); +++ if (cur_idx == MTK_WED_RX_RING_SIZE - 1) +++ break; +++ +++ usleep_range(100000, 200000); +++ } +++ +++ if (i == 3) { +++ dev_err(dev->hw->dev, "rx dma enable failed\n"); +++ return; +++ } +++ +++ val = wifi_r32(dev, dev->wlan.wpdma_rx_glo - dev->wlan.phy_base) | +++ MTK_WFMDA_RX_DMA_EN; +++ wifi_w32(dev, dev->wlan.wpdma_rx_glo - dev->wlan.phy_base, val); +++} +++ ++ static void ++ mtk_wed_dma_disable(struct mtk_wed_device *dev) ++ { ++@@ -304,20 +508,25 @@ mtk_wed_dma_disable(struct mtk_wed_devic ++ MTK_WED_GLO_CFG_TX_DMA_EN | ++ MTK_WED_GLO_CFG_RX_DMA_EN); ++ ++- wdma_m32(dev, MTK_WDMA_GLO_CFG, +++ wdma_clr(dev, MTK_WDMA_GLO_CFG, ++ MTK_WDMA_GLO_CFG_TX_DMA_EN | ++ MTK_WDMA_GLO_CFG_RX_INFO1_PRERES | ++- MTK_WDMA_GLO_CFG_RX_INFO2_PRERES, 0); +++ MTK_WDMA_GLO_CFG_RX_INFO2_PRERES); ++ ++ if (dev->hw->version == 1) { ++ regmap_write(dev->hw->mirror, dev->hw->index * 4, 0); ++- wdma_m32(dev, MTK_WDMA_GLO_CFG, ++- MTK_WDMA_GLO_CFG_RX_INFO3_PRERES, 0); +++ wdma_clr(dev, MTK_WDMA_GLO_CFG, +++ MTK_WDMA_GLO_CFG_RX_INFO3_PRERES); ++ } else { ++ wed_clr(dev, MTK_WED_WPDMA_GLO_CFG, ++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC | ++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC); ++ +++ wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, +++ MTK_WED_WPDMA_RX_D_RX_DRV_EN); +++ wed_clr(dev, MTK_WED_WDMA_GLO_CFG, +++ MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK); +++ ++ mtk_wed_set_512_support(dev, false); ++ } ++ } ++@@ -338,6 +547,13 @@ mtk_wed_stop(struct mtk_wed_device *dev) ++ wdma_w32(dev, MTK_WDMA_INT_MASK, 0); ++ wdma_w32(dev, MTK_WDMA_INT_GRP2, 0); ++ wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0); +++ +++ if (dev->hw->version == 1) +++ return; +++ +++ wed_w32(dev, MTK_WED_EXT_INT_MASK1, 0); +++ wed_w32(dev, MTK_WED_EXT_INT_MASK2, 0); +++ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN); ++ } ++ ++ static void ++@@ -353,11 +569,21 @@ mtk_wed_detach(struct mtk_wed_device *de ++ wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); ++ ++ mtk_wed_reset(dev, MTK_WED_RESET_WED); +++ if (mtk_wed_get_rx_capa(dev)) { +++ wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN); +++ wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX); +++ wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); +++ } ++ ++- mtk_wed_free_buffer(dev); +++ mtk_wed_free_tx_buffer(dev); ++ mtk_wed_free_tx_rings(dev); ++- if (hw->version != 1) +++ +++ if (mtk_wed_get_rx_capa(dev)) { +++ mtk_wed_wo_reset(dev); +++ mtk_wed_free_rx_rings(dev); ++ mtk_wed_wo_deinit(hw); +++ mtk_wdma_rx_reset(dev); +++ } ++ ++ if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) { ++ struct device_node *wlan_node; ++@@ -441,10 +667,12 @@ mtk_wed_set_wpdma(struct mtk_wed_device ++ } else { ++ mtk_wed_bus_init(dev); ++ ++- wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_int); ++- wed_w32(dev, MTK_WED_WPDMA_CFG_INT_MASK, dev->wlan.wpdma_mask); ++- wed_w32(dev, MTK_WED_WPDMA_CFG_TX, dev->wlan.wpdma_tx); ++- wed_w32(dev, MTK_WED_WPDMA_CFG_TX_FREE, dev->wlan.wpdma_txfree); +++ wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_int); +++ wed_w32(dev, MTK_WED_WPDMA_CFG_INT_MASK, dev->wlan.wpdma_mask); +++ wed_w32(dev, MTK_WED_WPDMA_CFG_TX, dev->wlan.wpdma_tx); +++ wed_w32(dev, MTK_WED_WPDMA_CFG_TX_FREE, dev->wlan.wpdma_txfree); +++ wed_w32(dev, MTK_WED_WPDMA_RX_GLO_CFG, dev->wlan.wpdma_rx_glo); +++ wed_w32(dev, MTK_WED_WPDMA_RX_RING, dev->wlan.wpdma_rx); ++ } ++ } ++ ++@@ -494,6 +722,132 @@ mtk_wed_hw_init_early(struct mtk_wed_dev ++ } ++ } ++ +++static int +++mtk_wed_rro_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring, +++ int size) +++{ +++ ring->desc = dma_alloc_coherent(dev->hw->dev, +++ size * sizeof(*ring->desc), +++ &ring->desc_phys, GFP_KERNEL); +++ if (!ring->desc) +++ return -ENOMEM; +++ +++ ring->desc_size = sizeof(*ring->desc); +++ ring->size = size; +++ memset(ring->desc, 0, size); +++ +++ return 0; +++} +++ +++#define MTK_WED_MIOD_COUNT (MTK_WED_MIOD_ENTRY_CNT * MTK_WED_MIOD_CNT) +++static int +++mtk_wed_rro_alloc(struct mtk_wed_device *dev) +++{ +++ struct reserved_mem *rmem; +++ struct device_node *np; +++ int index; +++ +++ index = of_property_match_string(dev->hw->node, "memory-region-names", +++ "wo-dlm"); +++ if (index < 0) +++ return index; +++ +++ np = of_parse_phandle(dev->hw->node, "memory-region", index); +++ if (!np) +++ return -ENODEV; +++ +++ rmem = of_reserved_mem_lookup(np); +++ of_node_put(np); +++ +++ if (!rmem) +++ return -ENODEV; +++ +++ dev->rro.miod_phys = rmem->base; +++ dev->rro.fdbk_phys = MTK_WED_MIOD_COUNT + dev->rro.miod_phys; +++ +++ return mtk_wed_rro_ring_alloc(dev, &dev->rro.ring, +++ MTK_WED_RRO_QUE_CNT); +++} +++ +++static int +++mtk_wed_rro_cfg(struct mtk_wed_device *dev) +++{ +++ struct mtk_wed_wo *wo = dev->hw->wed_wo; +++ struct { +++ struct { +++ __le32 base; +++ __le32 cnt; +++ __le32 unit; +++ } ring[2]; +++ __le32 wed; +++ u8 version; +++ } req = { +++ .ring[0] = { +++ .base = cpu_to_le32(MTK_WED_WOCPU_VIEW_MIOD_BASE), +++ .cnt = cpu_to_le32(MTK_WED_MIOD_CNT), +++ .unit = cpu_to_le32(MTK_WED_MIOD_ENTRY_CNT), +++ }, +++ .ring[1] = { +++ .base = cpu_to_le32(MTK_WED_WOCPU_VIEW_MIOD_BASE + +++ MTK_WED_MIOD_COUNT), +++ .cnt = cpu_to_le32(MTK_WED_FB_CMD_CNT), +++ .unit = cpu_to_le32(4), +++ }, +++ }; +++ +++ return mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, +++ MTK_WED_WO_CMD_WED_CFG, +++ &req, sizeof(req), true); +++} +++ +++static void +++mtk_wed_rro_hw_init(struct mtk_wed_device *dev) +++{ +++ wed_w32(dev, MTK_WED_RROQM_MIOD_CFG, +++ FIELD_PREP(MTK_WED_RROQM_MIOD_MID_DW, 0x70 >> 2) | +++ FIELD_PREP(MTK_WED_RROQM_MIOD_MOD_DW, 0x10 >> 2) | +++ FIELD_PREP(MTK_WED_RROQM_MIOD_ENTRY_DW, +++ MTK_WED_MIOD_ENTRY_CNT >> 2)); +++ +++ wed_w32(dev, MTK_WED_RROQM_MIOD_CTRL0, dev->rro.miod_phys); +++ wed_w32(dev, MTK_WED_RROQM_MIOD_CTRL1, +++ FIELD_PREP(MTK_WED_RROQM_MIOD_CNT, MTK_WED_MIOD_CNT)); +++ wed_w32(dev, MTK_WED_RROQM_FDBK_CTRL0, dev->rro.fdbk_phys); +++ wed_w32(dev, MTK_WED_RROQM_FDBK_CTRL1, +++ FIELD_PREP(MTK_WED_RROQM_FDBK_CNT, MTK_WED_FB_CMD_CNT)); +++ wed_w32(dev, MTK_WED_RROQM_FDBK_CTRL2, 0); +++ wed_w32(dev, MTK_WED_RROQ_BASE_L, dev->rro.ring.desc_phys); +++ +++ wed_set(dev, MTK_WED_RROQM_RST_IDX, +++ MTK_WED_RROQM_RST_IDX_MIOD | +++ MTK_WED_RROQM_RST_IDX_FDBK); +++ +++ wed_w32(dev, MTK_WED_RROQM_RST_IDX, 0); +++ wed_w32(dev, MTK_WED_RROQM_MIOD_CTRL2, MTK_WED_MIOD_CNT - 1); +++ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_RRO_QM_EN); +++} +++ +++static void +++mtk_wed_route_qm_hw_init(struct mtk_wed_device *dev) +++{ +++ wed_w32(dev, MTK_WED_RESET, MTK_WED_RESET_RX_ROUTE_QM); +++ +++ for (;;) { +++ usleep_range(100, 200); +++ if (!(wed_r32(dev, MTK_WED_RESET) & MTK_WED_RESET_RX_ROUTE_QM)) +++ break; +++ } +++ +++ /* configure RX_ROUTE_QM */ +++ wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST); +++ wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_TXDMAD_FPORT); +++ wed_set(dev, MTK_WED_RTQM_GLO_CFG, +++ FIELD_PREP(MTK_WED_RTQM_TXDMAD_FPORT, 0x3 + dev->hw->index)); +++ wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST); +++ /* enable RX_ROUTE_QM */ +++ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_ROUTE_QM_EN); +++} +++ ++ static void ++ mtk_wed_hw_init(struct mtk_wed_device *dev) ++ { ++@@ -505,11 +859,11 @@ mtk_wed_hw_init(struct mtk_wed_device *d ++ wed_w32(dev, MTK_WED_TX_BM_CTRL, ++ MTK_WED_TX_BM_CTRL_PAUSE | ++ FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM, ++- dev->buf_ring.size / 128) | +++ dev->tx_buf_ring.size / 128) | ++ FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM, ++ MTK_WED_TX_RING_SIZE / 256)); ++ ++- wed_w32(dev, MTK_WED_TX_BM_BASE, dev->buf_ring.desc_phys); +++ wed_w32(dev, MTK_WED_TX_BM_BASE, dev->tx_buf_ring.desc_phys); ++ ++ wed_w32(dev, MTK_WED_TX_BM_BUF_LEN, MTK_WED_PKT_SIZE); ++ ++@@ -536,9 +890,9 @@ mtk_wed_hw_init(struct mtk_wed_device *d ++ wed_w32(dev, MTK_WED_TX_TKID_CTRL, ++ MTK_WED_TX_TKID_CTRL_PAUSE | ++ FIELD_PREP(MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM, ++- dev->buf_ring.size / 128) | +++ dev->tx_buf_ring.size / 128) | ++ FIELD_PREP(MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM, ++- dev->buf_ring.size / 128)); +++ dev->tx_buf_ring.size / 128)); ++ wed_w32(dev, MTK_WED_TX_TKID_DYN_THR, ++ FIELD_PREP(MTK_WED_TX_TKID_DYN_THR_LO, 0) | ++ MTK_WED_TX_TKID_DYN_THR_HI); ++@@ -546,18 +900,28 @@ mtk_wed_hw_init(struct mtk_wed_device *d ++ ++ mtk_wed_reset(dev, MTK_WED_RESET_TX_BM); ++ ++- if (dev->hw->version == 1) +++ if (dev->hw->version == 1) { ++ wed_set(dev, MTK_WED_CTRL, ++ MTK_WED_CTRL_WED_TX_BM_EN | ++ MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); ++- else +++ } else { ++ wed_clr(dev, MTK_WED_TX_TKID_CTRL, MTK_WED_TX_TKID_CTRL_PAUSE); +++ /* rx hw init */ +++ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, +++ MTK_WED_WPDMA_RX_D_RST_CRX_IDX | +++ MTK_WED_WPDMA_RX_D_RST_DRV_IDX); +++ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, 0); +++ +++ mtk_wed_rx_buffer_hw_init(dev); +++ mtk_wed_rro_hw_init(dev); +++ mtk_wed_route_qm_hw_init(dev); +++ } ++ ++ wed_clr(dev, MTK_WED_TX_BM_CTRL, MTK_WED_TX_BM_CTRL_PAUSE); ++ } ++ ++ static void ++-mtk_wed_ring_reset(struct mtk_wed_ring *ring, int size) +++mtk_wed_ring_reset(struct mtk_wed_ring *ring, int size, bool tx) ++ { ++ void *head = (void *)ring->desc; ++ int i; ++@@ -567,7 +931,10 @@ mtk_wed_ring_reset(struct mtk_wed_ring * ++ ++ desc = (struct mtk_wdma_desc *)(head + i * ring->desc_size); ++ desc->buf0 = 0; ++- desc->ctrl = cpu_to_le32(MTK_WDMA_DESC_CTRL_DMA_DONE); +++ if (tx) +++ desc->ctrl = cpu_to_le32(MTK_WDMA_DESC_CTRL_DMA_DONE); +++ else +++ desc->ctrl = cpu_to_le32(MTK_WFDMA_DESC_CTRL_TO_HOST); ++ desc->buf1 = 0; ++ desc->info = 0; ++ } ++@@ -623,7 +990,8 @@ mtk_wed_reset_dma(struct mtk_wed_device ++ if (!dev->tx_ring[i].desc) ++ continue; ++ ++- mtk_wed_ring_reset(&dev->tx_ring[i], MTK_WED_TX_RING_SIZE); +++ mtk_wed_ring_reset(&dev->tx_ring[i], MTK_WED_TX_RING_SIZE, +++ true); ++ } ++ ++ if (mtk_wed_poll_busy(dev)) ++@@ -641,6 +1009,9 @@ mtk_wed_reset_dma(struct mtk_wed_device ++ wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX); ++ wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); ++ +++ if (mtk_wed_get_rx_capa(dev)) +++ mtk_wdma_rx_reset(dev); +++ ++ if (busy) { ++ mtk_wed_reset(dev, MTK_WED_RESET_WDMA_INT_AGENT); ++ mtk_wed_reset(dev, MTK_WED_RESET_WDMA_RX_DRV); ++@@ -675,12 +1046,11 @@ mtk_wed_reset_dma(struct mtk_wed_device ++ MTK_WED_WPDMA_RESET_IDX_RX); ++ wed_w32(dev, MTK_WED_WPDMA_RESET_IDX, 0); ++ } ++- ++ } ++ ++ static int ++ mtk_wed_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring, ++- int size, u32 desc_size) +++ int size, u32 desc_size, bool tx) ++ { ++ ring->desc = dma_alloc_coherent(dev->hw->dev, size * desc_size, ++ &ring->desc_phys, GFP_KERNEL); ++@@ -689,7 +1059,7 @@ mtk_wed_ring_alloc(struct mtk_wed_device ++ ++ ring->desc_size = desc_size; ++ ring->size = size; ++- mtk_wed_ring_reset(ring, size); +++ mtk_wed_ring_reset(ring, size, tx); ++ ++ return 0; ++ } ++@@ -698,9 +1068,14 @@ static int ++ mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size) ++ { ++ u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version; ++- struct mtk_wed_ring *wdma = &dev->rx_wdma[idx]; +++ struct mtk_wed_ring *wdma; ++ ++- if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size)) +++ if (idx >= ARRAY_SIZE(dev->rx_wdma)) +++ return -EINVAL; +++ +++ wdma = &dev->rx_wdma[idx]; +++ if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size, +++ true)) ++ return -ENOMEM; ++ ++ wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_BASE, ++@@ -717,6 +1092,60 @@ mtk_wed_wdma_rx_ring_setup(struct mtk_we ++ return 0; ++ } ++ +++static int +++mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size) +++{ +++ u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version; +++ struct mtk_wed_ring *wdma; +++ +++ if (idx >= ARRAY_SIZE(dev->tx_wdma)) +++ return -EINVAL; +++ +++ wdma = &dev->tx_wdma[idx]; +++ if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size, +++ true)) +++ return -ENOMEM; +++ +++ wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_BASE, +++ wdma->desc_phys); +++ wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_COUNT, +++ size); +++ wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_CPU_IDX, 0); +++ wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_DMA_IDX, 0); +++ +++ if (!idx) { +++ wed_w32(dev, MTK_WED_WDMA_RING_TX + MTK_WED_RING_OFS_BASE, +++ wdma->desc_phys); +++ wed_w32(dev, MTK_WED_WDMA_RING_TX + MTK_WED_RING_OFS_COUNT, +++ size); +++ wed_w32(dev, MTK_WED_WDMA_RING_TX + MTK_WED_RING_OFS_CPU_IDX, +++ 0); +++ wed_w32(dev, MTK_WED_WDMA_RING_TX + MTK_WED_RING_OFS_DMA_IDX, +++ 0); +++ } +++ +++ return 0; +++} +++ +++static void +++mtk_wed_ppe_check(struct mtk_wed_device *dev, struct sk_buff *skb, +++ u32 reason, u32 hash) +++{ +++ struct mtk_eth *eth = dev->hw->eth; +++ struct ethhdr *eh; +++ +++ if (!skb) +++ return; +++ +++ if (reason != MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) +++ return; +++ +++ skb_set_mac_header(skb, 0); +++ eh = eth_hdr(skb); +++ skb->protocol = eh->h_proto; +++ mtk_ppe_check_skb(eth->ppe[dev->hw->index], skb, hash); +++} +++ ++ static void ++ mtk_wed_configure_irq(struct mtk_wed_device *dev, u32 irq_mask) ++ { ++@@ -739,6 +1168,8 @@ mtk_wed_configure_irq(struct mtk_wed_dev ++ ++ wed_clr(dev, MTK_WED_WDMA_INT_CTRL, wdma_mask); ++ } else { +++ wdma_mask |= FIELD_PREP(MTK_WDMA_INT_MASK_TX_DONE, +++ GENMASK(1, 0)); ++ /* initail tx interrupt trigger */ ++ wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX, ++ MTK_WED_WPDMA_INT_CTRL_TX0_DONE_EN | ++@@ -757,6 +1188,16 @@ mtk_wed_configure_irq(struct mtk_wed_dev ++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_TRIG, ++ dev->wlan.txfree_tbit)); ++ +++ wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RX, +++ MTK_WED_WPDMA_INT_CTRL_RX0_EN | +++ MTK_WED_WPDMA_INT_CTRL_RX0_CLR | +++ MTK_WED_WPDMA_INT_CTRL_RX1_EN | +++ MTK_WED_WPDMA_INT_CTRL_RX1_CLR | +++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX0_DONE_TRIG, +++ dev->wlan.rx_tbit[0]) | +++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX1_DONE_TRIG, +++ dev->wlan.rx_tbit[1])); +++ ++ wed_w32(dev, MTK_WED_WDMA_INT_CLR, wdma_mask); ++ wed_set(dev, MTK_WED_WDMA_INT_CTRL, ++ FIELD_PREP(MTK_WED_WDMA_INT_CTRL_POLL_SRC_SEL, ++@@ -794,9 +1235,15 @@ mtk_wed_dma_enable(struct mtk_wed_device ++ wdma_set(dev, MTK_WDMA_GLO_CFG, ++ MTK_WDMA_GLO_CFG_RX_INFO3_PRERES); ++ } else { +++ int i; +++ ++ wed_set(dev, MTK_WED_WPDMA_CTRL, ++ MTK_WED_WPDMA_CTRL_SDL1_FIXED); ++ +++ wed_set(dev, MTK_WED_WDMA_GLO_CFG, +++ MTK_WED_WDMA_GLO_CFG_TX_DRV_EN | +++ MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK); +++ ++ wed_set(dev, MTK_WED_WPDMA_GLO_CFG, ++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC | ++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC); ++@@ -804,6 +1251,15 @@ mtk_wed_dma_enable(struct mtk_wed_device ++ wed_clr(dev, MTK_WED_WPDMA_GLO_CFG, ++ MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP | ++ MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV); +++ +++ wed_set(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, +++ MTK_WED_WPDMA_RX_D_RX_DRV_EN | +++ FIELD_PREP(MTK_WED_WPDMA_RX_D_RXD_READ_LEN, 0x18) | +++ FIELD_PREP(MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL, +++ 0x2)); +++ +++ for (i = 0; i < MTK_WED_RX_QUEUES; i++) +++ mtk_wed_check_wfdma_rx_fill(dev, i); ++ } ++ } ++ ++@@ -829,7 +1285,19 @@ mtk_wed_start(struct mtk_wed_device *dev ++ val |= BIT(0) | (BIT(1) * !!dev->hw->index); ++ regmap_write(dev->hw->mirror, dev->hw->index * 4, val); ++ } else { ++- mtk_wed_set_512_support(dev, true); +++ /* driver set mid ready and only once */ +++ wed_w32(dev, MTK_WED_EXT_INT_MASK1, +++ MTK_WED_EXT_INT_STATUS_WPDMA_MID_RDY); +++ wed_w32(dev, MTK_WED_EXT_INT_MASK2, +++ MTK_WED_EXT_INT_STATUS_WPDMA_MID_RDY); +++ +++ wed_r32(dev, MTK_WED_EXT_INT_MASK1); +++ wed_r32(dev, MTK_WED_EXT_INT_MASK2); +++ +++ if (mtk_wed_rro_cfg(dev)) +++ return; +++ +++ mtk_wed_set_512_support(dev, dev->wlan.wcid_512); ++ } ++ ++ mtk_wed_dma_enable(dev); ++@@ -863,7 +1331,7 @@ mtk_wed_attach(struct mtk_wed_device *de ++ if (!hw) { ++ module_put(THIS_MODULE); ++ ret = -ENODEV; ++- goto out; +++ goto unlock; ++ } ++ ++ device = dev->wlan.bus_type == MTK_WED_BUS_PCIE ++@@ -876,15 +1344,24 @@ mtk_wed_attach(struct mtk_wed_device *de ++ dev->dev = hw->dev; ++ dev->irq = hw->irq; ++ dev->wdma_idx = hw->index; +++ dev->version = hw->version; ++ ++ if (hw->eth->dma_dev == hw->eth->dev && ++ of_dma_is_coherent(hw->eth->dev->of_node)) ++ mtk_eth_set_dma_device(hw->eth, hw->dev); ++ ++- ret = mtk_wed_buffer_alloc(dev); ++- if (ret) { ++- mtk_wed_detach(dev); +++ ret = mtk_wed_tx_buffer_alloc(dev); +++ if (ret) ++ goto out; +++ +++ if (mtk_wed_get_rx_capa(dev)) { +++ ret = mtk_wed_rx_buffer_alloc(dev); +++ if (ret) +++ goto out; +++ +++ ret = mtk_wed_rro_alloc(dev); +++ if (ret) +++ goto out; ++ } ++ ++ mtk_wed_hw_init_early(dev); ++@@ -893,8 +1370,10 @@ mtk_wed_attach(struct mtk_wed_device *de ++ BIT(hw->index), 0); ++ else ++ ret = mtk_wed_wo_init(hw); ++- ++ out: +++ if (ret) +++ mtk_wed_detach(dev); +++unlock: ++ mutex_unlock(&hw_lock); ++ ++ return ret; ++@@ -917,10 +1396,11 @@ mtk_wed_tx_ring_setup(struct mtk_wed_dev ++ * WDMA RX. ++ */ ++ ++- BUG_ON(idx >= ARRAY_SIZE(dev->tx_ring)); +++ if (WARN_ON(idx >= ARRAY_SIZE(dev->tx_ring))) +++ return -EINVAL; ++ ++ if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE, ++- sizeof(*ring->desc))) +++ sizeof(*ring->desc), true)) ++ return -ENOMEM; ++ ++ if (mtk_wed_wdma_rx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE)) ++@@ -967,6 +1447,37 @@ mtk_wed_txfree_ring_setup(struct mtk_wed ++ return 0; ++ } ++ +++static int +++mtk_wed_rx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs) +++{ +++ struct mtk_wed_ring *ring = &dev->rx_ring[idx]; +++ +++ if (WARN_ON(idx >= ARRAY_SIZE(dev->rx_ring))) +++ return -EINVAL; +++ +++ if (mtk_wed_ring_alloc(dev, ring, MTK_WED_RX_RING_SIZE, +++ sizeof(*ring->desc), false)) +++ return -ENOMEM; +++ +++ if (mtk_wed_wdma_tx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE)) +++ return -ENOMEM; +++ +++ ring->reg_base = MTK_WED_RING_RX_DATA(idx); +++ ring->wpdma = regs; +++ ring->flags |= MTK_WED_RING_CONFIGURED; +++ +++ /* WPDMA -> WED */ +++ wpdma_rx_w32(dev, idx, MTK_WED_RING_OFS_BASE, ring->desc_phys); +++ wpdma_rx_w32(dev, idx, MTK_WED_RING_OFS_COUNT, MTK_WED_RX_RING_SIZE); +++ +++ wed_w32(dev, MTK_WED_WPDMA_RING_RX_DATA(idx) + MTK_WED_RING_OFS_BASE, +++ ring->desc_phys); +++ wed_w32(dev, MTK_WED_WPDMA_RING_RX_DATA(idx) + MTK_WED_RING_OFS_COUNT, +++ MTK_WED_RX_RING_SIZE); +++ +++ return 0; +++} +++ ++ static u32 ++ mtk_wed_irq_get(struct mtk_wed_device *dev, u32 mask) ++ { ++@@ -1063,7 +1574,9 @@ void mtk_wed_add_hw(struct device_node * ++ static const struct mtk_wed_ops wed_ops = { ++ .attach = mtk_wed_attach, ++ .tx_ring_setup = mtk_wed_tx_ring_setup, +++ .rx_ring_setup = mtk_wed_rx_ring_setup, ++ .txfree_ring_setup = mtk_wed_txfree_ring_setup, +++ .msg_update = mtk_wed_mcu_msg_update, ++ .start = mtk_wed_start, ++ .stop = mtk_wed_stop, ++ .reset_dma = mtk_wed_reset_dma, ++@@ -1072,6 +1585,7 @@ void mtk_wed_add_hw(struct device_node * ++ .irq_get = mtk_wed_irq_get, ++ .irq_set_mask = mtk_wed_irq_set_mask, ++ .detach = mtk_wed_detach, +++ .ppe_check = mtk_wed_ppe_check, ++ }; ++ struct device_node *eth_np = eth->dev->of_node; ++ struct platform_device *pdev; ++--- a/drivers/net/ethernet/mediatek/mtk_wed.h +++++ b/drivers/net/ethernet/mediatek/mtk_wed.h ++@@ -87,6 +87,24 @@ wpdma_tx_w32(struct mtk_wed_device *dev, ++ } ++ ++ static inline u32 +++wpdma_rx_r32(struct mtk_wed_device *dev, int ring, u32 reg) +++{ +++ if (!dev->rx_ring[ring].wpdma) +++ return 0; +++ +++ return readl(dev->rx_ring[ring].wpdma + reg); +++} +++ +++static inline void +++wpdma_rx_w32(struct mtk_wed_device *dev, int ring, u32 reg, u32 val) +++{ +++ if (!dev->rx_ring[ring].wpdma) +++ return; +++ +++ writel(val, dev->rx_ring[ring].wpdma + reg); +++} +++ +++static inline u32 ++ wpdma_txfree_r32(struct mtk_wed_device *dev, u32 reg) ++ { ++ if (!dev->txfree_ring.wpdma) ++@@ -128,6 +146,7 @@ static inline int mtk_wed_flow_add(int i ++ static inline void mtk_wed_flow_remove(int index) ++ { ++ } +++ ++ #endif ++ ++ #ifdef CONFIG_DEBUG_FS ++--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c +++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c ++@@ -10,6 +10,7 @@ ++ #include <linux/of_reserved_mem.h> ++ #include <linux/mfd/syscon.h> ++ #include <linux/soc/mediatek/mtk_wed.h> +++#include <asm/unaligned.h> ++ ++ #include "mtk_wed_regs.h" ++ #include "mtk_wed_wo.h" ++@@ -60,24 +61,37 @@ void mtk_wed_mcu_rx_event(struct mtk_wed ++ wake_up(&wo->mcu.wait); ++ } ++ +++static void +++mtk_wed_update_rx_stats(struct mtk_wed_device *wed, struct sk_buff *skb) +++{ +++ u32 count = get_unaligned_le32(skb->data); +++ struct mtk_wed_wo_rx_stats *stats; +++ int i; +++ +++ if (count * sizeof(*stats) > skb->len - sizeof(u32)) +++ return; +++ +++ stats = (struct mtk_wed_wo_rx_stats *)(skb->data + sizeof(u32)); +++ for (i = 0 ; i < count ; i++) +++ wed->wlan.update_wo_rx_stats(wed, &stats[i]); +++} +++ ++ void mtk_wed_mcu_rx_unsolicited_event(struct mtk_wed_wo *wo, ++ struct sk_buff *skb) ++ { ++ struct mtk_wed_mcu_hdr *hdr = (struct mtk_wed_mcu_hdr *)skb->data; ++ ++- switch (hdr->cmd) { ++- case MTK_WED_WO_EVT_LOG_DUMP: { ++- const char *msg = (const char *)(skb->data + sizeof(*hdr)); +++ skb_pull(skb, sizeof(*hdr)); ++ ++- dev_notice(wo->hw->dev, "%s\n", msg); +++ switch (hdr->cmd) { +++ case MTK_WED_WO_EVT_LOG_DUMP: +++ dev_notice(wo->hw->dev, "%s\n", skb->data); ++ break; ++- } ++ case MTK_WED_WO_EVT_PROFILING: { ++- struct mtk_wed_wo_log_info *info; ++- u32 count = (skb->len - sizeof(*hdr)) / sizeof(*info); +++ struct mtk_wed_wo_log_info *info = (void *)skb->data; +++ u32 count = skb->len / sizeof(*info); ++ int i; ++ ++- info = (struct mtk_wed_wo_log_info *)(skb->data + sizeof(*hdr)); ++ for (i = 0 ; i < count ; i++) ++ dev_notice(wo->hw->dev, ++ "SN:%u latency: total=%u, rro:%u, mod:%u\n", ++@@ -88,6 +102,7 @@ void mtk_wed_mcu_rx_unsolicited_event(st ++ break; ++ } ++ case MTK_WED_WO_EVT_RXCNT_INFO: +++ mtk_wed_update_rx_stats(wo->hw->wed_dev, skb); ++ break; ++ default: ++ break; ++@@ -144,6 +159,8 @@ mtk_wed_mcu_parse_response(struct mtk_we ++ skb_pull(skb, sizeof(*hdr)); ++ switch (cmd) { ++ case MTK_WED_WO_CMD_RXCNT_INFO: +++ mtk_wed_update_rx_stats(wo->hw->wed_dev, skb); +++ break; ++ default: ++ break; ++ } ++@@ -182,6 +199,18 @@ unlock: ++ return ret; ++ } ++ +++int mtk_wed_mcu_msg_update(struct mtk_wed_device *dev, int id, void *data, +++ int len) +++{ +++ struct mtk_wed_wo *wo = dev->hw->wed_wo; +++ +++ if (dev->hw->version == 1) +++ return 0; +++ +++ return mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, id, data, len, +++ true); +++} +++ ++ static int ++ mtk_wed_get_memory_region(struct mtk_wed_wo *wo, ++ struct mtk_wed_wo_memory_region *region) ++--- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h +++++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h ++@@ -4,6 +4,7 @@ ++ #ifndef __MTK_WED_REGS_H ++ #define __MTK_WED_REGS_H ++ +++#define MTK_WFDMA_DESC_CTRL_TO_HOST BIT(8) ++ #define MTK_WDMA_DESC_CTRL_LEN1 GENMASK(14, 0) ++ #define MTK_WDMA_DESC_CTRL_LEN1_V2 GENMASK(13, 0) ++ #define MTK_WDMA_DESC_CTRL_LAST_SEG1 BIT(15) ++@@ -28,6 +29,8 @@ struct mtk_wdma_desc { ++ #define MTK_WED_RESET_WED_TX_DMA BIT(12) ++ #define MTK_WED_RESET_WDMA_RX_DRV BIT(17) ++ #define MTK_WED_RESET_WDMA_INT_AGENT BIT(19) +++#define MTK_WED_RESET_RX_RRO_QM BIT(20) +++#define MTK_WED_RESET_RX_ROUTE_QM BIT(21) ++ #define MTK_WED_RESET_WED BIT(31) ++ ++ #define MTK_WED_CTRL 0x00c ++@@ -39,8 +42,12 @@ struct mtk_wdma_desc { ++ #define MTK_WED_CTRL_WED_TX_BM_BUSY BIT(9) ++ #define MTK_WED_CTRL_WED_TX_FREE_AGENT_EN BIT(10) ++ #define MTK_WED_CTRL_WED_TX_FREE_AGENT_BUSY BIT(11) ++-#define MTK_WED_CTRL_RESERVE_EN BIT(12) ++-#define MTK_WED_CTRL_RESERVE_BUSY BIT(13) +++#define MTK_WED_CTRL_WED_RX_BM_EN BIT(12) +++#define MTK_WED_CTRL_WED_RX_BM_BUSY BIT(13) +++#define MTK_WED_CTRL_RX_RRO_QM_EN BIT(14) +++#define MTK_WED_CTRL_RX_RRO_QM_BUSY BIT(15) +++#define MTK_WED_CTRL_RX_ROUTE_QM_EN BIT(16) +++#define MTK_WED_CTRL_RX_ROUTE_QM_BUSY BIT(17) ++ #define MTK_WED_CTRL_FINAL_DIDX_READ BIT(24) ++ #define MTK_WED_CTRL_ETH_DMAD_FMT BIT(25) ++ #define MTK_WED_CTRL_MIB_READ_CLEAR BIT(28) ++@@ -62,6 +69,9 @@ struct mtk_wdma_desc { ++ #define MTK_WED_EXT_INT_STATUS_TX_DMA_R_RESP_ERR BIT(22) ++ #define MTK_WED_EXT_INT_STATUS_TX_DMA_W_RESP_ERR BIT(23) ++ #define MTK_WED_EXT_INT_STATUS_RX_DRV_DMA_RECYCLE BIT(24) +++#define MTK_WED_EXT_INT_STATUS_RX_DRV_GET_BM_DMAD_SKIP BIT(25) +++#define MTK_WED_EXT_INT_STATUS_WPDMA_RX_D_DRV_ERR BIT(26) +++#define MTK_WED_EXT_INT_STATUS_WPDMA_MID_RDY BIT(27) ++ #define MTK_WED_EXT_INT_STATUS_ERROR_MASK (MTK_WED_EXT_INT_STATUS_TF_LEN_ERR | \ ++ MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD | \ ++ MTK_WED_EXT_INT_STATUS_TKID_TITO_INVALID | \ ++@@ -71,6 +81,8 @@ struct mtk_wdma_desc { ++ MTK_WED_EXT_INT_STATUS_TX_DMA_R_RESP_ERR) ++ ++ #define MTK_WED_EXT_INT_MASK 0x028 +++#define MTK_WED_EXT_INT_MASK1 0x02c +++#define MTK_WED_EXT_INT_MASK2 0x030 ++ ++ #define MTK_WED_STATUS 0x060 ++ #define MTK_WED_STATUS_TX GENMASK(15, 8) ++@@ -151,6 +163,7 @@ struct mtk_wdma_desc { ++ #define MTK_WED_RING_TX(_n) (0x300 + (_n) * 0x10) ++ ++ #define MTK_WED_RING_RX(_n) (0x400 + (_n) * 0x10) +++#define MTK_WED_RING_RX_DATA(_n) (0x420 + (_n) * 0x10) ++ ++ #define MTK_WED_SCR0 0x3c0 ++ #define MTK_WED_WPDMA_INT_TRIGGER 0x504 ++@@ -213,6 +226,12 @@ struct mtk_wdma_desc { ++ #define MTK_WED_WPDMA_INT_CTRL_TX1_DONE_TRIG GENMASK(14, 10) ++ ++ #define MTK_WED_WPDMA_INT_CTRL_RX 0x534 +++#define MTK_WED_WPDMA_INT_CTRL_RX0_EN BIT(0) +++#define MTK_WED_WPDMA_INT_CTRL_RX0_CLR BIT(1) +++#define MTK_WED_WPDMA_INT_CTRL_RX0_DONE_TRIG GENMASK(6, 2) +++#define MTK_WED_WPDMA_INT_CTRL_RX1_EN BIT(8) +++#define MTK_WED_WPDMA_INT_CTRL_RX1_CLR BIT(9) +++#define MTK_WED_WPDMA_INT_CTRL_RX1_DONE_TRIG GENMASK(14, 10) ++ ++ #define MTK_WED_WPDMA_INT_CTRL_TX_FREE 0x538 ++ #define MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_EN BIT(0) ++@@ -242,11 +261,34 @@ struct mtk_wdma_desc { ++ ++ #define MTK_WED_WPDMA_RING_TX(_n) (0x600 + (_n) * 0x10) ++ #define MTK_WED_WPDMA_RING_RX(_n) (0x700 + (_n) * 0x10) +++#define MTK_WED_WPDMA_RING_RX_DATA(_n) (0x730 + (_n) * 0x10) +++ +++#define MTK_WED_WPDMA_RX_D_GLO_CFG 0x75c +++#define MTK_WED_WPDMA_RX_D_RX_DRV_EN BIT(0) +++#define MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL GENMASK(11, 7) +++#define MTK_WED_WPDMA_RX_D_RXD_READ_LEN GENMASK(31, 24) +++ +++#define MTK_WED_WPDMA_RX_D_RST_IDX 0x760 +++#define MTK_WED_WPDMA_RX_D_RST_CRX_IDX GENMASK(17, 16) +++#define MTK_WED_WPDMA_RX_D_RST_DRV_IDX GENMASK(25, 24) +++ +++#define MTK_WED_WPDMA_RX_GLO_CFG 0x76c +++#define MTK_WED_WPDMA_RX_RING 0x770 +++ +++#define MTK_WED_WPDMA_RX_D_MIB(_n) (0x774 + (_n) * 4) +++#define MTK_WED_WPDMA_RX_D_PROCESSED_MIB(_n) (0x784 + (_n) * 4) +++#define MTK_WED_WPDMA_RX_D_COHERENT_MIB 0x78c +++ +++#define MTK_WED_WDMA_RING_TX 0x800 +++ +++#define MTK_WED_WDMA_TX_MIB 0x810 +++ ++ #define MTK_WED_WDMA_RING_RX(_n) (0x900 + (_n) * 0x10) ++ #define MTK_WED_WDMA_RX_THRES(_n) (0x940 + (_n) * 0x4) ++ ++ #define MTK_WED_WDMA_GLO_CFG 0xa04 ++ #define MTK_WED_WDMA_GLO_CFG_TX_DRV_EN BIT(0) +++#define MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK BIT(1) ++ #define MTK_WED_WDMA_GLO_CFG_RX_DRV_EN BIT(2) ++ #define MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY BIT(3) ++ #define MTK_WED_WDMA_GLO_CFG_BT_SIZE GENMASK(5, 4) ++@@ -291,6 +333,20 @@ struct mtk_wdma_desc { ++ #define MTK_WED_WDMA_RX_RECYCLE_MIB(_n) (0xae8 + (_n) * 4) ++ #define MTK_WED_WDMA_RX_PROCESSED_MIB(_n) (0xaf0 + (_n) * 4) ++ +++#define MTK_WED_RX_BM_RX_DMAD 0xd80 +++#define MTK_WED_RX_BM_RX_DMAD_SDL0 GENMASK(13, 0) +++ +++#define MTK_WED_RX_BM_BASE 0xd84 +++#define MTK_WED_RX_BM_INIT_PTR 0xd88 +++#define MTK_WED_RX_BM_SW_TAIL GENMASK(15, 0) +++#define MTK_WED_RX_BM_INIT_SW_TAIL BIT(16) +++ +++#define MTK_WED_RX_PTR 0xd8c +++ +++#define MTK_WED_RX_BM_DYN_ALLOC_TH 0xdb4 +++#define MTK_WED_RX_BM_DYN_ALLOC_TH_H GENMASK(31, 16) +++#define MTK_WED_RX_BM_DYN_ALLOC_TH_L GENMASK(15, 0) +++ ++ #define MTK_WED_RING_OFS_BASE 0x00 ++ #define MTK_WED_RING_OFS_COUNT 0x04 ++ #define MTK_WED_RING_OFS_CPU_IDX 0x08 ++@@ -301,7 +357,9 @@ struct mtk_wdma_desc { ++ ++ #define MTK_WDMA_GLO_CFG 0x204 ++ #define MTK_WDMA_GLO_CFG_TX_DMA_EN BIT(0) +++#define MTK_WDMA_GLO_CFG_TX_DMA_BUSY BIT(1) ++ #define MTK_WDMA_GLO_CFG_RX_DMA_EN BIT(2) +++#define MTK_WDMA_GLO_CFG_RX_DMA_BUSY BIT(3) ++ #define MTK_WDMA_GLO_CFG_RX_INFO3_PRERES BIT(26) ++ #define MTK_WDMA_GLO_CFG_RX_INFO2_PRERES BIT(27) ++ #define MTK_WDMA_GLO_CFG_RX_INFO1_PRERES BIT(28) ++@@ -330,4 +388,70 @@ struct mtk_wdma_desc { ++ /* DMA channel mapping */ ++ #define HIFSYS_DMA_AG_MAP 0x008 ++ +++#define MTK_WED_RTQM_GLO_CFG 0xb00 +++#define MTK_WED_RTQM_BUSY BIT(1) +++#define MTK_WED_RTQM_Q_RST BIT(2) +++#define MTK_WED_RTQM_Q_DBG_BYPASS BIT(5) +++#define MTK_WED_RTQM_TXDMAD_FPORT GENMASK(23, 20) +++ +++#define MTK_WED_RTQM_R2H_MIB(_n) (0xb70 + (_n) * 0x4) +++#define MTK_WED_RTQM_R2Q_MIB(_n) (0xb78 + (_n) * 0x4) +++#define MTK_WED_RTQM_Q2N_MIB 0xb80 +++#define MTK_WED_RTQM_Q2H_MIB(_n) (0xb84 + (_n) * 0x4) +++ +++#define MTK_WED_RTQM_Q2B_MIB 0xb8c +++#define MTK_WED_RTQM_PFDBK_MIB 0xb90 +++ +++#define MTK_WED_RROQM_GLO_CFG 0xc04 +++#define MTK_WED_RROQM_RST_IDX 0xc08 +++#define MTK_WED_RROQM_RST_IDX_MIOD BIT(0) +++#define MTK_WED_RROQM_RST_IDX_FDBK BIT(4) +++ +++#define MTK_WED_RROQM_MIOD_CTRL0 0xc40 +++#define MTK_WED_RROQM_MIOD_CTRL1 0xc44 +++#define MTK_WED_RROQM_MIOD_CNT GENMASK(11, 0) +++ +++#define MTK_WED_RROQM_MIOD_CTRL2 0xc48 +++#define MTK_WED_RROQM_MIOD_CTRL3 0xc4c +++ +++#define MTK_WED_RROQM_FDBK_CTRL0 0xc50 +++#define MTK_WED_RROQM_FDBK_CTRL1 0xc54 +++#define MTK_WED_RROQM_FDBK_CNT GENMASK(11, 0) +++ +++#define MTK_WED_RROQM_FDBK_CTRL2 0xc58 +++ +++#define MTK_WED_RROQ_BASE_L 0xc80 +++#define MTK_WED_RROQ_BASE_H 0xc84 +++ +++#define MTK_WED_RROQM_MIOD_CFG 0xc8c +++#define MTK_WED_RROQM_MIOD_MID_DW GENMASK(5, 0) +++#define MTK_WED_RROQM_MIOD_MOD_DW GENMASK(13, 8) +++#define MTK_WED_RROQM_MIOD_ENTRY_DW GENMASK(22, 16) +++ +++#define MTK_WED_RROQM_MID_MIB 0xcc0 +++#define MTK_WED_RROQM_MOD_MIB 0xcc4 +++#define MTK_WED_RROQM_MOD_COHERENT_MIB 0xcc8 +++#define MTK_WED_RROQM_FDBK_MIB 0xcd0 +++#define MTK_WED_RROQM_FDBK_COHERENT_MIB 0xcd4 +++#define MTK_WED_RROQM_FDBK_IND_MIB 0xce0 +++#define MTK_WED_RROQM_FDBK_ENQ_MIB 0xce4 +++#define MTK_WED_RROQM_FDBK_ANC_MIB 0xce8 +++#define MTK_WED_RROQM_FDBK_ANC2H_MIB 0xcec +++ +++#define MTK_WED_RX_BM_RX_DMAD 0xd80 +++#define MTK_WED_RX_BM_BASE 0xd84 +++#define MTK_WED_RX_BM_INIT_PTR 0xd88 +++#define MTK_WED_RX_BM_PTR 0xd8c +++#define MTK_WED_RX_BM_PTR_HEAD GENMASK(32, 16) +++#define MTK_WED_RX_BM_PTR_TAIL GENMASK(15, 0) +++ +++#define MTK_WED_RX_BM_BLEN 0xd90 +++#define MTK_WED_RX_BM_STS 0xd94 +++#define MTK_WED_RX_BM_INTF2 0xd98 +++#define MTK_WED_RX_BM_INTF 0xd9c +++#define MTK_WED_RX_BM_ERR_STS 0xda8 +++ +++#define MTK_WED_WOCPU_VIEW_MIOD_BASE 0x8000 +++#define MTK_WED_PCIE_INT_MASK 0x0 +++ ++ #endif ++--- a/drivers/net/ethernet/mediatek/mtk_wed_wo.h +++++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h ++@@ -49,6 +49,10 @@ enum { ++ MTK_WED_WARP_CMD_FLAG_FROM_TO_WO = BIT(2), ++ }; ++ +++#define MTK_WED_WO_CPU_MCUSYS_RESET_ADDR 0x15194050 +++#define MTK_WED_WO_CPU_WO0_MCUSYS_RESET_MASK 0x20 +++#define MTK_WED_WO_CPU_WO1_MCUSYS_RESET_MASK 0x1 +++ ++ enum { ++ MTK_WED_WO_REGION_EMI, ++ MTK_WED_WO_REGION_ILM, ++@@ -57,6 +61,28 @@ enum { ++ __MTK_WED_WO_REGION_MAX, ++ }; ++ +++enum mtk_wed_wo_state { +++ MTK_WED_WO_STATE_UNDEFINED, +++ MTK_WED_WO_STATE_INIT, +++ MTK_WED_WO_STATE_ENABLE, +++ MTK_WED_WO_STATE_DISABLE, +++ MTK_WED_WO_STATE_HALT, +++ MTK_WED_WO_STATE_GATING, +++ MTK_WED_WO_STATE_SER_RESET, +++ MTK_WED_WO_STATE_WF_RESET, +++}; +++ +++enum mtk_wed_wo_done_state { +++ MTK_WED_WOIF_UNDEFINED, +++ MTK_WED_WOIF_DISABLE_DONE, +++ MTK_WED_WOIF_TRIGGER_ENABLE, +++ MTK_WED_WOIF_ENABLE_DONE, +++ MTK_WED_WOIF_TRIGGER_GATING, +++ MTK_WED_WOIF_GATING_DONE, +++ MTK_WED_WOIF_TRIGGER_HALT, +++ MTK_WED_WOIF_HALT_DONE, +++}; +++ ++ enum mtk_wed_dummy_cr_idx { ++ MTK_WED_DUMMY_CR_FWDL, ++ MTK_WED_DUMMY_CR_WO_STATUS, ++@@ -245,6 +271,8 @@ void mtk_wed_mcu_rx_unsolicited_event(st ++ struct sk_buff *skb); ++ int mtk_wed_mcu_send_msg(struct mtk_wed_wo *wo, int id, int cmd, ++ const void *data, int len, bool wait_resp); +++int mtk_wed_mcu_msg_update(struct mtk_wed_device *dev, int id, void *data, +++ int len); ++ int mtk_wed_mcu_init(struct mtk_wed_wo *wo); ++ int mtk_wed_wo_init(struct mtk_wed_hw *hw); ++ void mtk_wed_wo_deinit(struct mtk_wed_hw *hw); ++--- a/include/linux/soc/mediatek/mtk_wed.h +++++ b/include/linux/soc/mediatek/mtk_wed.h ++@@ -5,10 +5,13 @@ ++ #include <linux/rcupdate.h> ++ #include <linux/regmap.h> ++ #include <linux/pci.h> +++#include <linux/skbuff.h> ++ ++ #define MTK_WED_TX_QUEUES 2 ++ #define MTK_WED_RX_QUEUES 2 ++ +++#define WED_WO_STA_REC 0x6 +++ ++ struct mtk_wed_hw; ++ struct mtk_wdma_desc; ++ ++@@ -41,21 +44,37 @@ enum mtk_wed_wo_cmd { ++ MTK_WED_WO_CMD_WED_END ++ }; ++ +++struct mtk_rxbm_desc { +++ __le32 buf0; +++ __le32 token; +++} __packed __aligned(4); +++ ++ enum mtk_wed_bus_tye { ++ MTK_WED_BUS_PCIE, ++ MTK_WED_BUS_AXI, ++ }; ++ +++#define MTK_WED_RING_CONFIGURED BIT(0) ++ struct mtk_wed_ring { ++ struct mtk_wdma_desc *desc; ++ dma_addr_t desc_phys; ++ u32 desc_size; ++ int size; +++ u32 flags; ++ ++ u32 reg_base; ++ void __iomem *wpdma; ++ }; ++ +++struct mtk_wed_wo_rx_stats { +++ __le16 wlan_idx; +++ __le16 tid; +++ __le32 rx_pkt_cnt; +++ __le32 rx_byte_cnt; +++ __le32 rx_err_cnt; +++ __le32 rx_drop_cnt; +++}; +++ ++ struct mtk_wed_device { ++ #ifdef CONFIG_NET_MEDIATEK_SOC_WED ++ const struct mtk_wed_ops *ops; ++@@ -64,9 +83,12 @@ struct mtk_wed_device { ++ bool init_done, running; ++ int wdma_idx; ++ int irq; +++ u8 version; ++ ++ struct mtk_wed_ring tx_ring[MTK_WED_TX_QUEUES]; +++ struct mtk_wed_ring rx_ring[MTK_WED_RX_QUEUES]; ++ struct mtk_wed_ring txfree_ring; +++ struct mtk_wed_ring tx_wdma[MTK_WED_TX_QUEUES]; ++ struct mtk_wed_ring rx_wdma[MTK_WED_RX_QUEUES]; ++ ++ struct { ++@@ -74,7 +96,20 @@ struct mtk_wed_device { ++ void **pages; ++ struct mtk_wdma_desc *desc; ++ dma_addr_t desc_phys; ++- } buf_ring; +++ } tx_buf_ring; +++ +++ struct { +++ int size; +++ struct page_frag_cache rx_page; +++ struct mtk_rxbm_desc *desc; +++ dma_addr_t desc_phys; +++ } rx_buf_ring; +++ +++ struct { +++ struct mtk_wed_ring ring; +++ dma_addr_t miod_phys; +++ dma_addr_t fdbk_phys; +++ } rro; ++ ++ /* filled by driver: */ ++ struct { ++@@ -83,22 +118,36 @@ struct mtk_wed_device { ++ struct pci_dev *pci_dev; ++ }; ++ enum mtk_wed_bus_tye bus_type; +++ void __iomem *base; +++ u32 phy_base; ++ ++ u32 wpdma_phys; ++ u32 wpdma_int; ++ u32 wpdma_mask; ++ u32 wpdma_tx; ++ u32 wpdma_txfree; +++ u32 wpdma_rx_glo; +++ u32 wpdma_rx; +++ +++ bool wcid_512; ++ ++ u16 token_start; ++ unsigned int nbuf; +++ unsigned int rx_nbuf; +++ unsigned int rx_npkt; +++ unsigned int rx_size; ++ ++ u8 tx_tbit[MTK_WED_TX_QUEUES]; +++ u8 rx_tbit[MTK_WED_RX_QUEUES]; ++ u8 txfree_tbit; ++ ++ u32 (*init_buf)(void *ptr, dma_addr_t phys, int token_id); ++ int (*offload_enable)(struct mtk_wed_device *wed); ++ void (*offload_disable)(struct mtk_wed_device *wed); +++ u32 (*init_rx_buf)(struct mtk_wed_device *wed, int size); +++ void (*release_rx_buf)(struct mtk_wed_device *wed); +++ void (*update_wo_rx_stats)(struct mtk_wed_device *wed, +++ struct mtk_wed_wo_rx_stats *stats); ++ } wlan; ++ #endif ++ }; ++@@ -107,9 +156,15 @@ struct mtk_wed_ops { ++ int (*attach)(struct mtk_wed_device *dev); ++ int (*tx_ring_setup)(struct mtk_wed_device *dev, int ring, ++ void __iomem *regs); +++ int (*rx_ring_setup)(struct mtk_wed_device *dev, int ring, +++ void __iomem *regs); ++ int (*txfree_ring_setup)(struct mtk_wed_device *dev, ++ void __iomem *regs); +++ int (*msg_update)(struct mtk_wed_device *dev, int cmd_id, +++ void *data, int len); ++ void (*detach)(struct mtk_wed_device *dev); +++ void (*ppe_check)(struct mtk_wed_device *dev, struct sk_buff *skb, +++ u32 reason, u32 hash); ++ ++ void (*stop)(struct mtk_wed_device *dev); ++ void (*start)(struct mtk_wed_device *dev, u32 irq_mask); ++@@ -144,6 +199,16 @@ mtk_wed_device_attach(struct mtk_wed_dev ++ return ret; ++ } ++ +++static inline bool +++mtk_wed_get_rx_capa(struct mtk_wed_device *dev) +++{ +++#ifdef CONFIG_NET_MEDIATEK_SOC_WED +++ return dev->version != 1; +++#else +++ return false; +++#endif +++} +++ ++ #ifdef CONFIG_NET_MEDIATEK_SOC_WED ++ #define mtk_wed_device_active(_dev) !!(_dev)->ops ++ #define mtk_wed_device_detach(_dev) (_dev)->ops->detach(_dev) ++@@ -160,6 +225,12 @@ mtk_wed_device_attach(struct mtk_wed_dev ++ (_dev)->ops->irq_get(_dev, _mask) ++ #define mtk_wed_device_irq_set_mask(_dev, _mask) \ ++ (_dev)->ops->irq_set_mask(_dev, _mask) +++#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) \ +++ (_dev)->ops->rx_ring_setup(_dev, _ring, _regs) +++#define mtk_wed_device_ppe_check(_dev, _skb, _reason, _hash) \ +++ (_dev)->ops->ppe_check(_dev, _skb, _reason, _hash) +++#define mtk_wed_device_update_msg(_dev, _id, _msg, _len) \ +++ (_dev)->ops->msg_update(_dev, _id, _msg, _len) ++ #else ++ static inline bool mtk_wed_device_active(struct mtk_wed_device *dev) ++ { ++@@ -173,6 +244,9 @@ static inline bool mtk_wed_device_active ++ #define mtk_wed_device_reg_write(_dev, _reg, _val) do {} while (0) ++ #define mtk_wed_device_irq_get(_dev, _mask) 0 ++ #define mtk_wed_device_irq_set_mask(_dev, _mask) do {} while (0) +++#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) -ENODEV +++#define mtk_wed_device_ppe_check(_dev, _skb, _reason, _hash) do {} while (0) +++#define mtk_wed_device_update_msg(_dev, _id, _msg, _len) -ENODEV ++ #endif ++ ++ #endif +diff --git a/target/linux/generic/pending-5.15/733-05-net-ethernet-mtk_wed-add-rx-mib-counters.patch b/target/linux/generic/pending-5.15/733-05-net-ethernet-mtk_wed-add-rx-mib-counters.patch +new file mode 100644 +index 0000000000..bb1066dece +--- /dev/null ++++ b/target/linux/generic/pending-5.15/733-05-net-ethernet-mtk_wed-add-rx-mib-counters.patch +@@ -0,0 +1,149 @@ ++From: Lorenzo Bianconi <lorenzo@kernel.org> ++Date: Sat, 5 Nov 2022 23:36:22 +0100 ++Subject: [PATCH] net: ethernet: mtk_wed: add rx mib counters ++ ++Introduce WED RX MIB counters support available on MT7986a SoC. ++ ++Tested-by: Daniel Golle <daniel@makrotopia.org> ++Co-developed-by: Sujuan Chen <sujuan.chen@mediatek.com> ++Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com> ++Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> ++Signed-off-by: David S. Miller <davem@davemloft.net> ++--- ++ ++--- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c +++++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c ++@@ -2,6 +2,7 @@ ++ /* Copyright (C) 2021 Felix Fietkau <nbd@nbd.name> */ ++ ++ #include <linux/seq_file.h> +++#include <linux/soc/mediatek/mtk_wed.h> ++ #include "mtk_wed.h" ++ #include "mtk_wed_regs.h" ++ ++@@ -18,6 +19,8 @@ enum { ++ DUMP_TYPE_WDMA, ++ DUMP_TYPE_WPDMA_TX, ++ DUMP_TYPE_WPDMA_TXFREE, +++ DUMP_TYPE_WPDMA_RX, +++ DUMP_TYPE_WED_RRO, ++ }; ++ ++ #define DUMP_STR(_str) { _str, 0, DUMP_TYPE_STRING } ++@@ -36,6 +39,9 @@ enum { ++ ++ #define DUMP_WPDMA_TX_RING(_n) DUMP_RING("WPDMA_TX" #_n, 0, DUMP_TYPE_WPDMA_TX, _n) ++ #define DUMP_WPDMA_TXFREE_RING DUMP_RING("WPDMA_RX1", 0, DUMP_TYPE_WPDMA_TXFREE) +++#define DUMP_WPDMA_RX_RING(_n) DUMP_RING("WPDMA_RX" #_n, 0, DUMP_TYPE_WPDMA_RX, _n) +++#define DUMP_WED_RRO_RING(_base)DUMP_RING("WED_RRO_MIOD", MTK_##_base, DUMP_TYPE_WED_RRO) +++#define DUMP_WED_RRO_FDBK(_base)DUMP_RING("WED_RRO_FDBK", MTK_##_base, DUMP_TYPE_WED_RRO) ++ ++ static void ++ print_reg_val(struct seq_file *s, const char *name, u32 val) ++@@ -57,6 +63,7 @@ dump_wed_regs(struct seq_file *s, struct ++ cur > regs ? "\n" : "", ++ cur->name); ++ continue; +++ case DUMP_TYPE_WED_RRO: ++ case DUMP_TYPE_WED: ++ val = wed_r32(dev, cur->offset); ++ break; ++@@ -69,6 +76,9 @@ dump_wed_regs(struct seq_file *s, struct ++ case DUMP_TYPE_WPDMA_TXFREE: ++ val = wpdma_txfree_r32(dev, cur->offset); ++ break; +++ case DUMP_TYPE_WPDMA_RX: +++ val = wpdma_rx_r32(dev, cur->base, cur->offset); +++ break; ++ } ++ print_reg_val(s, cur->name, val); ++ } ++@@ -132,6 +142,80 @@ wed_txinfo_show(struct seq_file *s, void ++ } ++ DEFINE_SHOW_ATTRIBUTE(wed_txinfo); ++ +++static int +++wed_rxinfo_show(struct seq_file *s, void *data) +++{ +++ static const struct reg_dump regs[] = { +++ DUMP_STR("WPDMA RX"), +++ DUMP_WPDMA_RX_RING(0), +++ DUMP_WPDMA_RX_RING(1), +++ +++ DUMP_STR("WPDMA RX"), +++ DUMP_WED(WED_WPDMA_RX_D_MIB(0)), +++ DUMP_WED_RING(WED_WPDMA_RING_RX_DATA(0)), +++ DUMP_WED(WED_WPDMA_RX_D_PROCESSED_MIB(0)), +++ DUMP_WED(WED_WPDMA_RX_D_MIB(1)), +++ DUMP_WED_RING(WED_WPDMA_RING_RX_DATA(1)), +++ DUMP_WED(WED_WPDMA_RX_D_PROCESSED_MIB(1)), +++ DUMP_WED(WED_WPDMA_RX_D_COHERENT_MIB), +++ +++ DUMP_STR("WED RX"), +++ DUMP_WED_RING(WED_RING_RX_DATA(0)), +++ DUMP_WED_RING(WED_RING_RX_DATA(1)), +++ +++ DUMP_STR("WED RRO"), +++ DUMP_WED_RRO_RING(WED_RROQM_MIOD_CTRL0), +++ DUMP_WED(WED_RROQM_MID_MIB), +++ DUMP_WED(WED_RROQM_MOD_MIB), +++ DUMP_WED(WED_RROQM_MOD_COHERENT_MIB), +++ DUMP_WED_RRO_FDBK(WED_RROQM_FDBK_CTRL0), +++ DUMP_WED(WED_RROQM_FDBK_IND_MIB), +++ DUMP_WED(WED_RROQM_FDBK_ENQ_MIB), +++ DUMP_WED(WED_RROQM_FDBK_ANC_MIB), +++ DUMP_WED(WED_RROQM_FDBK_ANC2H_MIB), +++ +++ DUMP_STR("WED Route QM"), +++ DUMP_WED(WED_RTQM_R2H_MIB(0)), +++ DUMP_WED(WED_RTQM_R2Q_MIB(0)), +++ DUMP_WED(WED_RTQM_Q2H_MIB(0)), +++ DUMP_WED(WED_RTQM_R2H_MIB(1)), +++ DUMP_WED(WED_RTQM_R2Q_MIB(1)), +++ DUMP_WED(WED_RTQM_Q2H_MIB(1)), +++ DUMP_WED(WED_RTQM_Q2N_MIB), +++ DUMP_WED(WED_RTQM_Q2B_MIB), +++ DUMP_WED(WED_RTQM_PFDBK_MIB), +++ +++ DUMP_STR("WED WDMA TX"), +++ DUMP_WED(WED_WDMA_TX_MIB), +++ DUMP_WED_RING(WED_WDMA_RING_TX), +++ +++ DUMP_STR("WDMA TX"), +++ DUMP_WDMA(WDMA_GLO_CFG), +++ DUMP_WDMA_RING(WDMA_RING_TX(0)), +++ DUMP_WDMA_RING(WDMA_RING_TX(1)), +++ +++ DUMP_STR("WED RX BM"), +++ DUMP_WED(WED_RX_BM_BASE), +++ DUMP_WED(WED_RX_BM_RX_DMAD), +++ DUMP_WED(WED_RX_BM_PTR), +++ DUMP_WED(WED_RX_BM_TKID_MIB), +++ DUMP_WED(WED_RX_BM_BLEN), +++ DUMP_WED(WED_RX_BM_STS), +++ DUMP_WED(WED_RX_BM_INTF2), +++ DUMP_WED(WED_RX_BM_INTF), +++ DUMP_WED(WED_RX_BM_ERR_STS), +++ }; +++ struct mtk_wed_hw *hw = s->private; +++ struct mtk_wed_device *dev = hw->wed_dev; +++ +++ if (!dev) +++ return 0; +++ +++ dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); +++ +++ return 0; +++} +++DEFINE_SHOW_ATTRIBUTE(wed_rxinfo); ++ ++ static int ++ mtk_wed_reg_set(void *data, u64 val) ++@@ -175,4 +259,7 @@ void mtk_wed_hw_add_debugfs(struct mtk_w ++ debugfs_create_u32("regidx", 0600, dir, &hw->debugfs_reg); ++ debugfs_create_file_unsafe("regval", 0600, dir, hw, &fops_regval); ++ debugfs_create_file_unsafe("txinfo", 0400, dir, hw, &wed_txinfo_fops); +++ if (hw->version != 1) +++ debugfs_create_file_unsafe("rxinfo", 0400, dir, hw, +++ &wed_rxinfo_fops); ++ } +diff --git a/target/linux/generic/pending-5.15/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch b/target/linux/generic/pending-5.15/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch +new file mode 100644 +index 0000000000..8a718a02f2 +--- /dev/null ++++ b/target/linux/generic/pending-5.15/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch +@@ -0,0 +1,27 @@ ++From: Tobias Waldekranz <tobias@waldekranz.com> ++Subject: [RFC net-next 7/7] net: dsa: mv88e6xxx: Request assisted learning on CPU port ++Date: Sat, 16 Jan 2021 02:25:15 +0100 ++Archived-At: <https://lore.kernel.org/netdev/20210116012515.3152-8-tobias@waldekranz.com/> ++ ++While the hardware is capable of performing learning on the CPU port, ++it requires alot of additions to the bridge's forwarding path in order ++to handle multi-destination traffic correctly. ++ ++Until that is in place, opt for the next best thing and let DSA sync ++the relevant addresses down to the hardware FDB. ++ ++Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com> ++--- ++ drivers/net/dsa/mv88e6xxx/chip.c | 1 + ++ 1 file changed, 1 insertion(+) ++ ++--- a/drivers/net/dsa/mv88e6xxx/chip.c +++++ b/drivers/net/dsa/mv88e6xxx/chip.c ++@@ -6319,6 +6319,7 @@ static int mv88e6xxx_register_switch(str ++ ds->ops = &mv88e6xxx_switch_ops; ++ ds->ageing_time_min = chip->info->age_time_coeff; ++ ds->ageing_time_max = chip->info->age_time_coeff * U8_MAX; +++ ds->assisted_learning_on_cpu_port = true; ++ ++ /* Some chips support up to 32, but that requires enabling the ++ * 5-bit port mode, which we do not support. 640k^W16 ought to +diff --git a/target/linux/generic/pending-5.15/780-ARM-kirkwood-add-missing-linux-if_ether.h-for-ETH_AL.patch b/target/linux/generic/pending-5.15/780-ARM-kirkwood-add-missing-linux-if_ether.h-for-ETH_AL.patch +new file mode 100644 +index 0000000000..fcf7892c04 +--- /dev/null ++++ b/target/linux/generic/pending-5.15/780-ARM-kirkwood-add-missing-linux-if_ether.h-for-ETH_AL.patch +@@ -0,0 +1,61 @@ ++From patchwork Thu Aug 5 22:23:30 2021 ++Content-Type: text/plain; charset="utf-8" ++MIME-Version: 1.0 ++Content-Transfer-Encoding: 7bit ++X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org> ++X-Patchwork-Id: 12422209 ++Date: Thu, 5 Aug 2021 23:23:30 +0100 ++From: Daniel Golle <daniel@makrotopia.org> ++To: linux-arm-kernel@lists.infradead.org, netdev@vger.kernel.org, ++ linux-kernel@vger.kernel.org ++Cc: "David S. Miller" <davem@davemloft.net>, Andrew Lunn <andrew@lunn.ch>, ++ Michael Walle <michael@walle.cc> ++Subject: [PATCH] ARM: kirkwood: add missing <linux/if_ether.h> for ETH_ALEN ++Message-ID: <YQxk4jrbm31NM1US@makrotopia.org> ++MIME-Version: 1.0 ++Content-Disposition: inline ++X-BeenThere: linux-arm-kernel@lists.infradead.org ++X-Mailman-Version: 2.1.34 ++Precedence: list ++List-Id: <linux-arm-kernel.lists.infradead.org> ++List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/> ++Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org> ++ ++After commit 83216e3988cd1 ("of: net: pass the dst buffer to ++of_get_mac_address()") build fails for kirkwood as ETH_ALEN is not ++defined. ++ ++arch/arm/mach-mvebu/kirkwood.c: In function 'kirkwood_dt_eth_fixup': ++arch/arm/mach-mvebu/kirkwood.c:87:13: error: 'ETH_ALEN' undeclared (first use in this function); did you mean 'ESTALE'? ++ u8 tmpmac[ETH_ALEN]; ++ ^~~~~~~~ ++ ESTALE ++arch/arm/mach-mvebu/kirkwood.c:87:13: note: each undeclared identifier is reported only once for each function it appears in ++arch/arm/mach-mvebu/kirkwood.c:87:6: warning: unused variable 'tmpmac' [-Wunused-variable] ++ u8 tmpmac[ETH_ALEN]; ++ ^~~~~~ ++make[5]: *** [scripts/Makefile.build:262: arch/arm/mach-mvebu/kirkwood.o] Error 1 ++make[5]: *** Waiting for unfinished jobs.... ++ ++Add missing #include <linux/if_ether.h> to fix this. ++ ++Cc: David S. Miller <davem@davemloft.net> ++Cc: Andrew Lunn <andrew@lunn.ch> ++Cc: Michael Walle <michael@walle.cc> ++Reported-by: https://buildbot.openwrt.org/master/images/#/builders/56/builds/220/steps/44/logs/stdio ++Fixes: 83216e3988cd1 ("of: net: pass the dst buffer to of_get_mac_address()") ++Signed-off-by: Daniel Golle <daniel@makrotopia.org> ++--- ++ arch/arm/mach-mvebu/kirkwood.c | 1 + ++ 1 file changed, 1 insertion(+) ++ ++--- a/arch/arm/mach-mvebu/kirkwood.c +++++ b/arch/arm/mach-mvebu/kirkwood.c ++@@ -14,6 +14,7 @@ ++ #include <linux/kernel.h> ++ #include <linux/init.h> ++ #include <linux/mbus.h> +++#include <linux/if_ether.h> ++ #include <linux/of.h> ++ #include <linux/of_address.h> ++ #include <linux/of_net.h> +diff --git a/target/linux/generic/pending-5.15/800-bcma-get-SoC-device-struct-copy-its-DMA-params-to-th.patch b/target/linux/generic/pending-5.15/800-bcma-get-SoC-device-struct-copy-its-DMA-params-to-th.patch +new file mode 100644 +index 0000000000..478a2cb27d +--- /dev/null ++++ b/target/linux/generic/pending-5.15/800-bcma-get-SoC-device-struct-copy-its-DMA-params-to-th.patch +@@ -0,0 +1,73 @@ ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl> ++Subject: [PATCH] bcma: get SoC device struct & copy its DMA params to the ++ subdevices ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++For bus devices to be fully usable it's required to set their DMA ++parameters. ++ ++For years it has been missing and remained unnoticed because of ++mips_dma_alloc_coherent() silently handling the empty coherent_dma_mask. ++Kernel 4.19 came with a lot of DMA changes and caused a regression on ++the bcm47xx. Starting with the commit f8c55dc6e828 ("MIPS: use generic ++dma noncoherent ops for simple noncoherent platforms") DMA coherent ++allocations just fail. Example: ++[ 1.114914] bgmac_bcma bcma0:2: Allocation of TX ring 0x200 failed ++[ 1.121215] bgmac_bcma bcma0:2: Unable to alloc memory for DMA ++[ 1.127626] bgmac_bcma: probe of bcma0:2 failed with error -12 ++[ 1.133838] bgmac_bcma: Broadcom 47xx GBit MAC driver loaded ++ ++This change fixes above regression in addition to the MIPS bcm47xx ++commit 321c46b91550 ("MIPS: BCM47XX: Setup struct device for the SoC"). ++ ++It also fixes another *old* GPIO regression caused by a parent pointing ++to the NULL: ++[ 0.157054] missing gpiochip .dev parent pointer ++[ 0.157287] bcma: bus0: Error registering GPIO driver: -22 ++introduced by the commit 74f4e0cc6108 ("bcma: switch GPIO portions to ++use GPIOLIB_IRQCHIP"). ++ ++Fixes: f8c55dc6e828 ("MIPS: use generic dma noncoherent ops for simple noncoherent platforms") ++Fixes: 74f4e0cc6108 ("bcma: switch GPIO portions to use GPIOLIB_IRQCHIP") ++Cc: linux-mips@linux-mips.org ++Cc: Christoph Hellwig <hch@lst.de> ++Cc: Linus Walleij <linus.walleij@linaro.org> ++Signed-off-by: RafaÅ‚ MiÅ‚ecki <rafal@milecki.pl> ++--- ++ ++--- a/drivers/bcma/host_soc.c +++++ b/drivers/bcma/host_soc.c ++@@ -191,6 +191,8 @@ int __init bcma_host_soc_init(struct bcm ++ struct bcma_bus *bus = &soc->bus; ++ int err; ++ +++ bus->dev = soc->dev; +++ ++ /* Scan bus and initialize it */ ++ err = bcma_bus_early_register(bus); ++ if (err) ++--- a/drivers/bcma/main.c +++++ b/drivers/bcma/main.c ++@@ -236,13 +236,17 @@ EXPORT_SYMBOL(bcma_core_irq); ++ ++ void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core) ++ { ++- device_initialize(&core->dev); +++ struct device *dev = &core->dev; +++ +++ device_initialize(dev); ++ core->dev.release = bcma_release_core_dev; ++ core->dev.bus = &bcma_bus_type; ++- dev_set_name(&core->dev, "bcma%d:%d", bus->num, core->core_index); +++ dev_set_name(dev, "bcma%d:%d", bus->num, core->core_index); ++ core->dev.parent = bus->dev; ++- if (bus->dev) +++ if (bus->dev) { ++ bcma_of_fill_device(bus->dev, core); +++ dma_coerce_mask_and_coherent(dev, bus->dev->coherent_dma_mask); +++ } ++ ++ switch (bus->hosttype) { ++ case BCMA_HOSTTYPE_PCI: +diff --git a/target/linux/generic/pending-5.15/801-gpio-gpio-cascade-add-generic-GPIO-cascade.patch b/target/linux/generic/pending-5.15/801-gpio-gpio-cascade-add-generic-GPIO-cascade.patch +new file mode 100644 +index 0000000000..c1e14b9271 +--- /dev/null ++++ b/target/linux/generic/pending-5.15/801-gpio-gpio-cascade-add-generic-GPIO-cascade.patch +@@ -0,0 +1,222 @@ ++From fc23ea48ba52c24f201fe5ca0132ee1a3de5a70a Mon Sep 17 00:00:00 2001 ++From: Mauri Sandberg <maukka@ext.kapsi.fi> ++Date: Thu, 25 Mar 2021 11:48:05 +0200 ++Subject: [PATCH 2/2] gpio: gpio-cascade: add generic GPIO cascade ++ ++Adds support for building cascades of GPIO lines. That is, it allows ++setups when there is one upstream line and multiple cascaded lines, out ++of which one can be chosen at a time. The status of the upstream line ++can be conveyed to the selected cascaded line or, vice versa, the status ++of the cascaded line can be conveyed to the upstream line. ++ ++A multiplexer is being used to select, which cascaded GPIO line is being ++used at any given time. ++ ++At the moment only input direction is supported. In future it should be ++possible to add support for output direction, too. ++ ++Signed-off-by: Mauri Sandberg <maukka@ext.kapsi.fi> ++Reviewed-by: Linus Walleij <linus.walleij@linaro.org> ++Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com> ++--- ++v7 -> v8: ++ - rearrange members in struct gpio_cascade ++ - cosmetic changes in file header and in one function declaration ++ - added Reviewed-by tags by Linus and Andy ++v6 -> v7: ++ - In Kconfig add info about module name ++ - adhere to new convention that allows lines longer than 80 chars ++ - use dev_probe_err with upstream gpio line too ++ - refactor for cleaner exit of probe function. ++v5 -> v6: ++ - In Kconfig, remove dependency to OF_GPIO and select only MULTIPLEXER ++ - refactor code preferring one-liners ++ - clean up prints, removing them from success-path. ++ - don't explicitly set gpio_chip.of_node as it's done in the GPIO library ++ - use devm_gpiochip_add_data instead of gpiochip_add ++v4 -> v5: ++ - renamed gpio-mux-input -> gpio-cascade. refactored code accordingly ++ here and there and changed to use new bindings and compatible string ++ - ambigious and vague 'pin' was rename to 'upstream_line' ++ - dropped Tested-by and Reviewed-by due to changes in bindings ++ - dropped Reported-by suggested by an automatic bot as it was not really ++ appropriate to begin with ++ - functionally it's the same as v4 ++v3 -> v4: ++ - Changed author email ++ - Included Tested-by and Reviewed-by from Drew ++v2 -> v3: ++ - use managed device resources ++ - update Kconfig description ++v1 -> v2: ++ - removed .owner from platform_driver as per test bot's instruction ++ - added MODULE_AUTHOR, MODULE_DESCRIPTION, MODULE_LICENSE ++ - added gpio_mux_input_get_direction as it's recommended for all chips ++ - removed because this is input only chip: gpio_mux_input_set_value ++ - removed because they are not needed for input/output only chips: ++ gpio_mux_input_direction_input ++ gpio_mux_input_direction_output ++ - fixed typo in an error message ++ - added info message about successful registration ++ - removed can_sleep flag as this does not sleep while getting GPIO value ++ like I2C or SPI do ++ - Updated description in Kconfig ++--- ++ drivers/gpio/Kconfig | 15 +++++ ++ drivers/gpio/Makefile | 1 + ++ drivers/gpio/gpio-cascade.c | 117 ++++++++++++++++++++++++++++++++++++ ++ 3 files changed, 133 insertions(+) ++ create mode 100644 drivers/gpio/gpio-cascade.c ++ ++--- a/drivers/gpio/Kconfig +++++ b/drivers/gpio/Kconfig ++@@ -1683,4 +1683,19 @@ config GPIO_VIRTIO ++ ++ endmenu ++ +++comment "Other GPIO expanders" ++ -++ /* -++ * 3. Set Spread Spectrum Clock Enabled -++ */ -++ comphy_lane_reg_set(lane, COMPHY_PIPE_LANE_CFG4, -++ SPREAD_SPECTRUM_CLK_EN, SPREAD_SPECTRUM_CLK_EN); +++config GPIO_CASCADE +++ tristate "General GPIO cascade" +++ select MULTIPLEXER +++ help +++ Say yes here to enable support for generic GPIO cascade. ++ -++ /* -++ * 4. Set Override Margining Controls From the MAC: -++ * Use margining signals from lane configuration -++ */ -++ comphy_lane_reg_set(lane, COMPHY_PIPE_TEST_MODE_CTRL, -++ MODE_MARGIN_OVERRIDE, 0xFFFF); +++ This allows building one-to-many cascades of GPIO lines using +++ different types of multiplexers readily available. At the +++ moment only input lines are supported. ++ -++ /* -++ * 5. Set Lane-to-Lane Bundle Clock Sampling Period = per PCLK cycles -++ * set Mode Clock Source = PCLK is generated from REFCLK -++ */ -++ data = 0x0; -++ mask = MODE_CLK_SRC | BUNDLE_PERIOD_SEL | BUNDLE_PERIOD_SCALE_MASK | -++ BUNDLE_SAMPLE_CTRL | PLL_READY_DLY_MASK; -++ comphy_lane_reg_set(lane, COMPHY_PIPE_CLK_SRC_LO, data, mask); +++ To build the driver as a module choose 'm' and the resulting module +++ will be called 'gpio-cascade'. ++ -++ /* -++ * 6. Set G2 Spread Spectrum Clock Amplitude at 4K -++ */ -++ comphy_lane_reg_set(lane, COMPHY_GEN2_SET2, -++ GS2_TX_SSC_AMP_4128, GS2_TX_SSC_AMP_MASK); ++ endif ++--- a/drivers/gpio/Makefile +++++ b/drivers/gpio/Makefile ++@@ -45,6 +45,7 @@ obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd ++ obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o ++ obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o ++ obj-$(CONFIG_GPIO_CADENCE) += gpio-cadence.o +++obj-$(CONFIG_GPIO_CASCADE) += gpio-cascade.o ++ obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o ++ obj-$(CONFIG_GPIO_SNPS_CREG) += gpio-creg-snps.o ++ obj-$(CONFIG_GPIO_CRYSTAL_COVE) += gpio-crystalcove.o ++--- /dev/null +++++ b/drivers/gpio/gpio-cascade.c ++@@ -0,0 +1,117 @@ +++// SPDX-License-Identifier: GPL-2.0-only +++/* +++ * A generic GPIO cascade driver +++ * +++ * Copyright (C) 2021 Mauri Sandberg <maukka@ext.kapsi.fi> +++ * +++ * This allows building cascades of GPIO lines in a manner illustrated +++ * below: +++ * +++ * /|---- Cascaded GPIO line 0 +++ * Upstream | |---- Cascaded GPIO line 1 +++ * GPIO line ----+ | . +++ * | | . +++ * \|---- Cascaded GPIO line n +++ * +++ * A multiplexer is being used to select, which cascaded line is being +++ * addressed at any given time. +++ * +++ * At the moment only input mode is supported due to lack of means for +++ * testing output functionality. At least theoretically output should be +++ * possible with open drain constructions. +++ */ ++ -++ /* -++ * 7. Unset G3 Spread Spectrum Clock Amplitude -++ * set G3 TX and RX Register Master Current Select -++ */ -++ data = GS2_VREG_RXTX_MAS_ISET_60U; -++ mask = GS2_TX_SSC_AMP_MASK | GS2_VREG_RXTX_MAS_ISET_MASK | -++ GS2_RSVD_6_0_MASK; -++ comphy_lane_reg_set(lane, COMPHY_GEN3_SET2, data, mask); +++#include <linux/module.h> +++#include <linux/slab.h> +++#include <linux/platform_device.h> +++#include <linux/mux/consumer.h> ++ -++ /* -++ * 8. Check crystal jumper setting and program the Power and PLL Control -++ * accordingly Change RX wait -++ */ -++ if (lane->priv->xtal_is_40m) { -++ ref_clk = REF_FREF_SEL_PCIE_USB3_40MHZ; -++ cfg = CFG_PM_RXDLOZ_WAIT_12_UNIT; -++ } else { -++ ref_clk = REF_FREF_SEL_PCIE_USB3_25MHZ; -++ cfg = CFG_PM_RXDLOZ_WAIT_7_UNIT; -++ } +++#include <linux/gpio/consumer.h> +++#include <linux/gpio/driver.h> ++ -++ data = PU_IVREF_BIT | PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT | -++ PU_TX_INTP_BIT | PU_DFE_BIT | COMPHY_MODE_USB3 | ref_clk; -++ mask = PU_IVREF_BIT | PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT | -++ PU_TX_INTP_BIT | PU_DFE_BIT | PLL_LOCK_BIT | COMPHY_MODE_MASK | -++ REF_FREF_SEL_MASK; -++ comphy_lane_reg_set(lane, COMPHY_POWER_PLL_CTRL, data, mask); +++struct gpio_cascade { +++ struct gpio_chip gpio_chip; +++ struct device *parent; +++ struct mux_control *mux_control; +++ struct gpio_desc *upstream_line; +++}; ++ -++ data = CFG_PM_RXDEN_WAIT_1_UNIT | cfg; -++ mask = CFG_PM_OSCCLK_WAIT_MASK | CFG_PM_RXDEN_WAIT_MASK | -++ CFG_PM_RXDLOZ_WAIT_MASK; -++ comphy_lane_reg_set(lane, COMPHY_PIPE_PWR_MGM_TIM1, data, mask); +++static struct gpio_cascade *chip_to_cascade(struct gpio_chip *gc) +++{ +++ return container_of(gc, struct gpio_cascade, gpio_chip); +++} ++ -++ /* -++ * 9. Enable idle sync -++ */ -++ comphy_lane_reg_set(lane, COMPHY_IDLE_SYNC_EN, -++ IDLE_SYNC_EN, IDLE_SYNC_EN); +++static int gpio_cascade_get_direction(struct gpio_chip *gc, unsigned int offset) +++{ +++ return GPIO_LINE_DIRECTION_IN; +++} ++ -++ /* -++ * 10. Enable the output of 500M clock -++ */ -++ comphy_lane_reg_set(lane, COMPHY_MISC_CTRL0, CLK500M_EN, CLK500M_EN); +++static int gpio_cascade_get_value(struct gpio_chip *gc, unsigned int offset) +++{ +++ struct gpio_cascade *cas = chip_to_cascade(gc); +++ int ret; ++ -++ /* -++ * 11. Set 20-bit data width -++ */ -++ comphy_lane_reg_set(lane, COMPHY_DIG_LOOPBACK_EN, -++ DATA_WIDTH_20BIT, 0xFFFF); +++ ret = mux_control_select(cas->mux_control, offset); +++ if (ret) +++ return ret; ++ -++ /* -++ * 12. Override Speed_PLL value and use MAC PLL -++ */ -++ data = SPEED_PLL_VALUE_16 | USE_MAX_PLL_RATE_BIT; -++ mask = 0xFFFF; -++ comphy_lane_reg_set(lane, COMPHY_KVCO_CAL_CTRL, data, mask); +++ ret = gpiod_get_value(cas->upstream_line); +++ mux_control_deselect(cas->mux_control); +++ return ret; +++} ++ -++ /* -++ * 13. Check the Polarity invert bit -++ */ -++ data = 0x0; -++ if (lane->invert_tx) -++ data |= TXD_INVERT_BIT; -++ if (lane->invert_rx) -++ data |= RXD_INVERT_BIT; -++ mask = TXD_INVERT_BIT | RXD_INVERT_BIT; -++ comphy_lane_reg_set(lane, COMPHY_SYNC_PATTERN, data, mask); +++static int gpio_cascade_probe(struct platform_device *pdev) +++{ +++ struct device *dev = &pdev->dev; +++ struct gpio_cascade *cas; +++ struct mux_control *mc; +++ struct gpio_desc *upstream; +++ struct gpio_chip *gc; ++ -++ /* -++ * 14. Set max speed generation to USB3.0 5Gbps -++ */ -++ comphy_lane_reg_set(lane, COMPHY_SYNC_MASK_GEN, -++ PHY_GEN_MAX_USB3_5G, PHY_GEN_MAX_MASK); +++ cas = devm_kzalloc(dev, sizeof(*cas), GFP_KERNEL); +++ if (!cas) +++ return -ENOMEM; ++ -++ /* -++ * 15. Set capacitor value for FFE gain peaking to 0xF -++ */ -++ comphy_lane_reg_set(lane, COMPHY_GEN2_SET3, -++ GS3_FFE_CAP_SEL_VALUE, GS3_FFE_CAP_SEL_MASK); +++ mc = devm_mux_control_get(dev, NULL); +++ if (IS_ERR(mc)) +++ return dev_err_probe(dev, PTR_ERR(mc), "unable to get mux-control\n"); ++ -++ /* -++ * 16. Release SW reset -++ */ -++ data = MODE_CORE_CLK_FREQ_SEL | MODE_PIPE_WIDTH_32 | MODE_REFDIV_BY_4; -++ mask = 0xFFFF; -++ comphy_lane_reg_set(lane, COMPHY_PIPE_RST_CLK_CTRL, data, mask); +++ cas->mux_control = mc; +++ upstream = devm_gpiod_get(dev, "upstream", GPIOD_IN); +++ if (IS_ERR(upstream)) +++ return dev_err_probe(dev, PTR_ERR(upstream), "unable to claim upstream GPIO line\n"); ++ -++ /* Wait for > 55 us to allow PCLK be enabled */ -++ udelay(PLL_SET_DELAY_US); +++ cas->upstream_line = upstream; +++ cas->parent = dev; ++ -++ ret = comphy_lane_reg_poll(lane, COMPHY_PIPE_LANE_STAT1, TXDCLK_PCLK_EN, -++ COMPHY_PLL_SLEEP, COMPHY_PLL_TIMEOUT); -++ if (ret) { -++ dev_err(lane->dev, "Failed to lock USB3 PLL\n"); -++ return ret; -++ } +++ gc = &cas->gpio_chip; +++ gc->get = gpio_cascade_get_value; +++ gc->get_direction = gpio_cascade_get_direction; +++ gc->base = -1; +++ gc->ngpio = mux_control_states(mc); +++ gc->label = dev_name(cas->parent); +++ gc->parent = cas->parent; +++ gc->owner = THIS_MODULE; ++ -++ return 0; +++ platform_set_drvdata(pdev, cas); +++ return devm_gpiochip_add_data(dev, &cas->gpio_chip, NULL); ++} ++ -++static int -++mvebu_a3700_comphy_pcie_power_on(struct mvebu_a3700_comphy_lane *lane) -++{ -++ u32 mask, data, ref_clk; -++ int ret; -++ -++ /* Configure phy selector for PCIe */ -++ ret = mvebu_a3700_comphy_set_phy_selector(lane); -++ if (ret) -++ return ret; -++ -++ /* 1. Enable max PLL. */ -++ comphy_lane_reg_set(lane, COMPHY_PIPE_LANE_CFG1, -++ USE_MAX_PLL_RATE_EN, USE_MAX_PLL_RATE_EN); +++static const struct of_device_id gpio_cascade_id[] = { +++ { .compatible = "gpio-cascade" }, +++ { /* sentinel */ } +++}; +++MODULE_DEVICE_TABLE(of, gpio_cascade_id); ++ -++ /* 2. Select 20 bit SERDES interface. */ -++ comphy_lane_reg_set(lane, COMPHY_PIPE_CLK_SRC_LO, -++ CFG_SEL_20B, CFG_SEL_20B); +++static struct platform_driver gpio_cascade_driver = { +++ .driver = { +++ .name = "gpio-cascade", +++ .of_match_table = gpio_cascade_id, +++ }, +++ .probe = gpio_cascade_probe, +++}; +++module_platform_driver(gpio_cascade_driver); ++ -++ /* 3. Force to use reg setting for PCIe mode */ -++ comphy_lane_reg_set(lane, COMPHY_MISC_CTRL1, -++ SEL_BITS_PCIE_FORCE, SEL_BITS_PCIE_FORCE); +++MODULE_AUTHOR("Mauri Sandberg <maukka@ext.kapsi.fi>"); +++MODULE_DESCRIPTION("Generic GPIO cascade"); +++MODULE_LICENSE("GPL"); +diff --git a/target/linux/generic/pending-5.15/810-pci_disable_common_quirks.patch b/target/linux/generic/pending-5.15/810-pci_disable_common_quirks.patch +new file mode 100644 +index 0000000000..7edbd94f76 +--- /dev/null ++++ b/target/linux/generic/pending-5.15/810-pci_disable_common_quirks.patch +@@ -0,0 +1,62 @@ ++From: Gabor Juhos <juhosg@openwrt.org> ++Subject: debloat: add kernel config option to disabling common PCI quirks ++ ++Signed-off-by: Gabor Juhos <juhosg@openwrt.org> ++--- ++ drivers/pci/Kconfig | 6 ++++++ ++ drivers/pci/quirks.c | 6 ++++++ ++ 2 files changed, 12 insertions(+) ++ ++--- a/drivers/pci/Kconfig +++++ b/drivers/pci/Kconfig ++@@ -118,6 +118,13 @@ config XEN_PCIDEV_FRONTEND ++ The PCI device frontend driver allows the kernel to import arbitrary ++ PCI devices from a PCI backend to support PCI driver domains. ++ +++config PCI_DISABLE_COMMON_QUIRKS +++ bool "PCI disable common quirks" +++ depends on PCI +++ help +++ If you don't know what to do here, say N. ++ -++ /* 4. Change RX wait */ -++ data = CFG_PM_RXDEN_WAIT_1_UNIT | CFG_PM_RXDLOZ_WAIT_12_UNIT; -++ mask = CFG_PM_OSCCLK_WAIT_MASK | CFG_PM_RXDEN_WAIT_MASK | -++ CFG_PM_RXDLOZ_WAIT_MASK; -++ comphy_lane_reg_set(lane, COMPHY_PIPE_PWR_MGM_TIM1, data, mask); ++ -++ /* 5. Enable idle sync */ -++ comphy_lane_reg_set(lane, COMPHY_IDLE_SYNC_EN, -++ IDLE_SYNC_EN, IDLE_SYNC_EN); ++ config PCI_ATS ++ bool ++ ++--- a/drivers/pci/quirks.c +++++ b/drivers/pci/quirks.c ++@@ -206,6 +206,7 @@ static void quirk_mmio_always_on(struct ++ DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_ANY_ID, PCI_ANY_ID, ++ PCI_CLASS_BRIDGE_HOST, 8, quirk_mmio_always_on); ++ +++#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS ++ /* ++ * The Mellanox Tavor device gives false positive parity errors. Disable ++ * parity error reporting. ++@@ -3363,6 +3364,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I ++ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65f9, quirk_intel_mc_errata); ++ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65fa, quirk_intel_mc_errata); ++ +++#endif /* !CONFIG_PCI_DISABLE_COMMON_QUIRKS */ ++ -++ /* 6. Enable the output of 100M/125M/500M clock */ -++ data = CLK500M_EN | TXDCLK_2X_SEL | CLK100M_125M_EN; -++ mask = data; -++ comphy_lane_reg_set(lane, COMPHY_MISC_CTRL0, data, mask); ++ /* ++ * Ivytown NTB BAR sizes are misreported by the hardware due to an erratum. ++ * To work around this, query the size it should be configured to by the ++@@ -3388,6 +3391,8 @@ static void quirk_intel_ntb(struct pci_d ++ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0e08, quirk_intel_ntb); ++ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0e0d, quirk_intel_ntb); ++ +++#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS ++ -++ /* -++ * 7. Enable TX, PCIE global register, 0xd0074814, it is done in -++ * PCI-E driver -++ */ ++ /* ++ * Some BIOS implementations leave the Intel GPU interrupts enabled, even ++ * though no one is handling them (e.g., if the i915 driver is never ++@@ -3426,6 +3431,8 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IN ++ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq); ++ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0152, disable_igfx_irq); ++ +++#endif /* !CONFIG_PCI_DISABLE_COMMON_QUIRKS */ ++ -++ /* -++ * 8. Check crystal jumper setting and program the Power and PLL -++ * Control accordingly -++ */ ++ /* ++ * PCI devices which are on Intel chips can skip the 10ms delay ++ * before entering D3 mode. +diff --git a/target/linux/generic/pending-5.15/811-pci_disable_usb_common_quirks.patch b/target/linux/generic/pending-5.15/811-pci_disable_usb_common_quirks.patch +new file mode 100644 +index 0000000000..b498d9f700 +--- /dev/null ++++ b/target/linux/generic/pending-5.15/811-pci_disable_usb_common_quirks.patch +@@ -0,0 +1,115 @@ ++From: Felix Fietkau <nbd@nbd.name> ++Subject: debloat: disable common USB quirks ++ ++Signed-off-by: Felix Fietkau <nbd@nbd.name> ++--- ++ drivers/usb/host/pci-quirks.c | 16 ++++++++++++++++ ++ drivers/usb/host/pci-quirks.h | 18 +++++++++++++++++- ++ include/linux/usb/hcd.h | 7 +++++++ ++ 3 files changed, 40 insertions(+), 1 deletion(-) ++ ++--- a/drivers/usb/host/pci-quirks.c +++++ b/drivers/usb/host/pci-quirks.c ++@@ -128,6 +128,8 @@ struct amd_chipset_type { ++ u8 rev; ++ }; ++ +++#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS ++ -++ if (lane->priv->xtal_is_40m) -++ ref_clk = REF_FREF_SEL_PCIE_USB3_40MHZ; -++ else -++ ref_clk = REF_FREF_SEL_PCIE_USB3_25MHZ; -++ -++ data = PU_IVREF_BIT | PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT | -++ PU_TX_INTP_BIT | PU_DFE_BIT | COMPHY_MODE_PCIE | ref_clk; -++ mask = 0xFFFF; -++ comphy_lane_reg_set(lane, COMPHY_POWER_PLL_CTRL, data, mask); -++ -++ /* 9. Override Speed_PLL value and use MAC PLL */ -++ comphy_lane_reg_set(lane, COMPHY_KVCO_CAL_CTRL, -++ SPEED_PLL_VALUE_16 | USE_MAX_PLL_RATE_BIT, -++ 0xFFFF); -++ -++ /* 10. Check the Polarity invert bit */ -++ data = 0x0; -++ if (lane->invert_tx) -++ data |= TXD_INVERT_BIT; -++ if (lane->invert_rx) -++ data |= RXD_INVERT_BIT; -++ mask = TXD_INVERT_BIT | RXD_INVERT_BIT; -++ comphy_lane_reg_set(lane, COMPHY_SYNC_PATTERN, data, mask); -++ -++ /* 11. Release SW reset */ -++ data = MODE_CORE_CLK_FREQ_SEL | MODE_PIPE_WIDTH_32; -++ mask = data | PIPE_SOFT_RESET | MODE_REFDIV_MASK; -++ comphy_lane_reg_set(lane, COMPHY_PIPE_RST_CLK_CTRL, data, mask); -++ -++ /* Wait for > 55 us to allow PCLK be enabled */ -++ udelay(PLL_SET_DELAY_US); -++ -++ ret = comphy_lane_reg_poll(lane, COMPHY_PIPE_LANE_STAT1, TXDCLK_PCLK_EN, -++ COMPHY_PLL_SLEEP, COMPHY_PLL_TIMEOUT); -++ if (ret) { -++ dev_err(lane->dev, "Failed to lock PCIE PLL\n"); -++ return ret; -++ } ++ static struct amd_chipset_info { ++ struct pci_dev *nb_dev; ++ struct pci_dev *smbus_dev; ++@@ -633,6 +635,10 @@ bool usb_amd_pt_check_port(struct device ++ } ++ EXPORT_SYMBOL_GPL(usb_amd_pt_check_port); ++ +++#endif /* CONFIG_PCI_DISABLE_COMMON_QUIRKS */ ++ -++ return 0; -++} +++#if IS_ENABLED(CONFIG_USB_UHCI_HCD) ++ -++static void -++mvebu_a3700_comphy_usb3_power_off(struct mvebu_a3700_comphy_lane *lane) ++ /* ++ * Make sure the controller is completely inactive, unable to ++ * generate interrupts or do DMA. ++@@ -712,8 +718,17 @@ reset_needed: ++ uhci_reset_hc(pdev, base); ++ return 1; ++ } +++#else +++int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base) ++{ -++ /* -++ * Currently the USB3 MAC sets the USB3 PHY to low state, so we do not -++ * need to power off USB3 PHY again. -++ */ +++ return 0; ++} ++ -++static void -++mvebu_a3700_comphy_sata_power_off(struct mvebu_a3700_comphy_lane *lane) -++{ -++ /* Set phy isolation mode */ -++ comphy_lane_reg_set(lane, COMPHY_ISOLATION_CTRL, -++ PHY_ISOLATE_MODE, PHY_ISOLATE_MODE); +++#endif ++ EXPORT_SYMBOL_GPL(uhci_check_and_reset_hc); ++ +++#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS ++ -++ /* Power off PLL, Tx, Rx */ -++ comphy_lane_reg_set(lane, COMPHY_POWER_PLL_CTRL, -++ 0x0, PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT); -++} ++ static inline int io_type_enabled(struct pci_dev *pdev, unsigned int mask) ++ { ++ u16 cmd; ++@@ -1285,3 +1300,4 @@ static void quirk_usb_early_handoff(stru ++ } ++ DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID, ++ PCI_CLASS_SERIAL_USB, 8, quirk_usb_early_handoff); +++#endif ++--- a/drivers/usb/host/pci-quirks.h +++++ b/drivers/usb/host/pci-quirks.h ++@@ -5,6 +5,9 @@ ++ #ifdef CONFIG_USB_PCI ++ void uhci_reset_hc(struct pci_dev *pdev, unsigned long base); ++ int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base); +++#endif /* CONFIG_USB_PCI */ ++ -++static void -++mvebu_a3700_comphy_ethernet_power_off(struct mvebu_a3700_comphy_lane *lane) +++#if defined(CONFIG_USB_PCI) && !defined(CONFIG_PCI_DISABLE_COMMON_QUIRKS) ++ int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *pdev); ++ bool usb_amd_hang_symptom_quirk(void); ++ bool usb_amd_prefetch_quirk(void); ++@@ -19,6 +22,18 @@ void sb800_prefetch(struct device *dev, ++ bool usb_amd_pt_check_port(struct device *device, int port); ++ #else ++ struct pci_dev; +++static inline int usb_amd_quirk_pll_check(void) ++{ -++ u32 mask, data; -++ -++ data = PIN_RESET_CORE_BIT | PIN_RESET_COMPHY_BIT | PIN_PU_IVREF_BIT | -++ PHY_RX_INIT_BIT; -++ mask = data; -++ comphy_periph_reg_set(lane, COMPHY_PHY_CFG1, data, mask); +++ return 0; ++} -++ -++static void -++mvebu_a3700_comphy_pcie_power_off(struct mvebu_a3700_comphy_lane *lane) +++static inline bool usb_amd_hang_symptom_quirk(void) ++{ -++ /* Power off PLL, Tx, Rx */ -++ comphy_lane_reg_set(lane, COMPHY_POWER_PLL_CTRL, -++ 0x0, PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT); +++ return false; ++} -++ -++static int mvebu_a3700_comphy_reset(struct phy *phy) +++static inline bool usb_amd_prefetch_quirk(void) ++{ -++ struct mvebu_a3700_comphy_lane *lane = phy_get_drvdata(phy); -++ u16 mask, data; -++ -++ dev_dbg(lane->dev, "resetting lane %d\n", lane->id); -++ -++ /* COMPHY reset for internal logic */ -++ comphy_lane_reg_set(lane, COMPHY_SFT_RESET, -++ SFT_RST_NO_REG, SFT_RST_NO_REG); -++ -++ /* COMPHY register reset (cleared automatically) */ -++ comphy_lane_reg_set(lane, COMPHY_SFT_RESET, SFT_RST, SFT_RST); -++ -++ /* PIPE soft and register reset */ -++ data = PIPE_SOFT_RESET | PIPE_REG_RESET; -++ mask = data; -++ comphy_lane_reg_set(lane, COMPHY_PIPE_RST_CLK_CTRL, data, mask); -++ -++ /* Release PIPE register reset */ -++ comphy_lane_reg_set(lane, COMPHY_PIPE_RST_CLK_CTRL, -++ 0x0, PIPE_REG_RESET); -++ -++ /* Reset SB configuration register (only for lanes 0 and 1) */ -++ if (lane->id == 0 || lane->id == 1) { -++ u32 mask, data; -++ -++ data = PIN_RESET_CORE_BIT | PIN_RESET_COMPHY_BIT | -++ PIN_PU_PLL_BIT | PIN_PU_RX_BIT | PIN_PU_TX_BIT; -++ mask = data | PIN_PU_IVREF_BIT | PIN_TX_IDLE_BIT; -++ comphy_periph_reg_set(lane, COMPHY_PHY_CFG1, data, mask); -++ } -++ -++ return 0; +++ return false; ++} -++ -++static bool mvebu_a3700_comphy_check_mode(int lane, -+ enum phy_mode mode, -+ int submode) ++ static inline void usb_amd_quirk_pll_disable(void) {} ++ static inline void usb_amd_quirk_pll_enable(void) {} ++ static inline void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev) {} ++@@ -29,6 +44,11 @@ static inline bool usb_amd_pt_check_port + { -+@@ -122,7 +1170,7 @@ static int mvebu_a3700_comphy_get_fw_mod ++ return false; ++ } +++static inline void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev) {} +++static inline bool usb_xhci_needs_pci_reset(struct pci_dev *pdev) +++{ +++ return false; +++} ++ #endif /* CONFIG_USB_PCI */ + -+ /* Unused PHY mux value is 0x0 */ -+ if (mode == PHY_MODE_INVALID) -+- return -EINVAL; -++ return false; ++ #endif /* __LINUX_USB_PCI_QUIRKS_H */ ++--- a/include/linux/usb/hcd.h +++++ b/include/linux/usb/hcd.h ++@@ -498,7 +498,14 @@ extern int usb_hcd_pci_probe(struct pci_ ++ extern void usb_hcd_pci_remove(struct pci_dev *dev); ++ extern void usb_hcd_pci_shutdown(struct pci_dev *dev); + -+ for (i = 0; i < n; i++) { -+ if (mvebu_a3700_comphy_modes[i].lane == lane && -+@@ -132,27 +1180,30 @@ static int mvebu_a3700_comphy_get_fw_mod -+ } +++#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS ++ extern int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *dev); +++#else +++static inline int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *dev) +++{ +++ return 0; +++} +++#endif + -+ if (i == n) -+- return -EINVAL; -++ return false; ++ #ifdef CONFIG_PM ++ extern const struct dev_pm_ops usb_hcd_pci_pm_ops; +diff --git a/target/linux/generic/pending-5.15/820-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch b/target/linux/generic/pending-5.15/820-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch +new file mode 100644 +index 0000000000..33eb34c913 +--- /dev/null ++++ b/target/linux/generic/pending-5.15/820-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch +@@ -0,0 +1,26 @@ ++From d9c8bc8c1408f3e8529db6e4e04017b4c579c342 Mon Sep 17 00:00:00 2001 ++From: Pawel Dembicki <paweldembicki@gmail.com> ++Date: Sun, 18 Feb 2018 17:08:04 +0100 ++Subject: [PATCH] w1: gpio: fix problem with platfom data in w1-gpio ++ ++In devices, where fdt is used, is impossible to apply platform data ++without proper fdt node. ++ ++This patch allow to use platform data in devices with fdt. ++ ++Signed-off-by: Pawel Dembicki <paweldembicki@gmail.com> ++--- ++ drivers/w1/masters/w1-gpio.c | 7 +++---- ++ 1 file changed, 3 insertions(+), 4 deletions(-) ++ ++--- a/drivers/w1/masters/w1-gpio.c +++++ b/drivers/w1/masters/w1-gpio.c ++@@ -76,7 +76,7 @@ static int w1_gpio_probe(struct platform ++ enum gpiod_flags gflags = GPIOD_OUT_LOW_OPEN_DRAIN; ++ int err; + -+- return mvebu_a3700_comphy_modes[i].fw_mode; -++ return true; -+ } ++- if (of_have_populated_dt()) { +++ if (of_have_populated_dt() && !dev_get_platdata(&pdev->dev)) { ++ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); ++ if (!pdata) ++ return -ENOMEM; +diff --git a/target/linux/generic/pending-5.15/834-ledtrig-libata.patch b/target/linux/generic/pending-5.15/834-ledtrig-libata.patch +new file mode 100644 +index 0000000000..58b837c084 +--- /dev/null ++++ b/target/linux/generic/pending-5.15/834-ledtrig-libata.patch +@@ -0,0 +1,149 @@ ++From: Daniel Golle <daniel@makrotopia.org> ++Subject: libata: add ledtrig support ++ ++This adds a LED trigger for each ATA port indicating disk activity. ++ ++As this is needed only on specific platforms (NAS SoCs and such), ++these platforms should define ARCH_WANTS_LIBATA_LEDS if there ++are boards with LED(s) intended to indicate ATA disk activity and ++need the OS to take care of that. ++In that way, if not selected, LED trigger support not will be ++included in libata-core and both, codepaths and structures remain ++untouched. ++ ++Signed-off-by: Daniel Golle <daniel@makrotopia.org> ++--- ++ drivers/ata/Kconfig | 16 ++++++++++++++++ ++ drivers/ata/libata-core.c | 41 +++++++++++++++++++++++++++++++++++++++++ ++ include/linux/libata.h | 9 +++++++++ ++ 3 files changed, 66 insertions(+) ++ ++--- a/drivers/ata/Kconfig +++++ b/drivers/ata/Kconfig ++@@ -67,6 +67,22 @@ config ATA_FORCE + -+ static int mvebu_a3700_comphy_set_mode(struct phy *phy, enum phy_mode mode, -+ int submode) -+ { -+ struct mvebu_a3700_comphy_lane *lane = phy_get_drvdata(phy); -+- int fw_mode; -+- -+- if (submode == PHY_INTERFACE_MODE_1000BASEX) -+- submode = PHY_INTERFACE_MODE_SGMII; -+ -+- fw_mode = mvebu_a3700_comphy_get_fw_mode(lane->id, mode, -+- submode); -+- if (fw_mode < 0) { -++ if (!mvebu_a3700_comphy_check_mode(lane->id, mode, submode)) { -+ dev_err(lane->dev, "invalid COMPHY mode\n"); -+- return fw_mode; -++ return -EINVAL; -+ } ++ If unsure, say Y. + -++ /* Mode cannot be changed while the PHY is powered on */ -++ if (phy->power_count && -++ (lane->mode != mode || lane->submode != submode)) -++ return -EBUSY; +++config ARCH_WANT_LIBATA_LEDS +++ bool +++ +++config ATA_LEDS +++ bool "support ATA port LED triggers" +++ depends on ARCH_WANT_LIBATA_LEDS +++ select NEW_LEDS +++ select LEDS_CLASS +++ select LEDS_TRIGGERS +++ default y +++ help +++ This option adds a LED trigger for each registered ATA port. +++ It is used to drive disk activity leds connected via GPIO. ++ -++ /* If changing mode, ensure reset is called */ -++ if (lane->mode != PHY_MODE_INVALID && lane->mode != mode) -++ lane->needs_reset = true; +++ If unsure, say N. ++ -+ /* Just remember the mode, ->power_on() will do the real setup */ -+ lane->mode = mode; -+ lane->submode = submode; -+@@ -163,76 +1214,68 @@ static int mvebu_a3700_comphy_set_mode(s -+ static int mvebu_a3700_comphy_power_on(struct phy *phy) -+ { -+ struct mvebu_a3700_comphy_lane *lane = phy_get_drvdata(phy); -+- u32 fw_param; -+- int fw_mode; -+- int fw_port; -+ int ret; ++ config ATA_ACPI ++ bool "ATA ACPI Support" ++ depends on ACPI ++--- a/drivers/ata/libata-core.c +++++ b/drivers/ata/libata-core.c ++@@ -656,6 +656,19 @@ u64 ata_tf_read_block(const struct ata_t ++ return block; ++ } + -+- fw_mode = mvebu_a3700_comphy_get_fw_mode(lane->id, -+- lane->mode, lane->submode); -+- if (fw_mode < 0) { -++ if (!mvebu_a3700_comphy_check_mode(lane->id, lane->mode, -++ lane->submode)) { -+ dev_err(lane->dev, "invalid COMPHY mode\n"); -+- return fw_mode; -++ return -EINVAL; -++ } +++#ifdef CONFIG_ATA_LEDS +++#define LIBATA_BLINK_DELAY 20 /* ms */ +++static inline void ata_led_act(struct ata_port *ap) +++{ +++ unsigned long led_delay = LIBATA_BLINK_DELAY; ++ -++ if (lane->needs_reset) { -++ ret = mvebu_a3700_comphy_reset(phy); -++ if (ret) -++ return ret; +++ if (unlikely(!ap->ledtrig)) +++ return; ++ -++ lane->needs_reset = false; -+ } -+ -+ switch (lane->mode) { -+ case PHY_MODE_USB_HOST_SS: -+ dev_dbg(lane->dev, "set lane %d to USB3 host mode\n", lane->id); -+- fw_param = COMPHY_FW_MODE(fw_mode); -+- break; -++ return mvebu_a3700_comphy_usb3_power_on(lane); -+ case PHY_MODE_SATA: -+ dev_dbg(lane->dev, "set lane %d to SATA mode\n", lane->id); -+- fw_param = COMPHY_FW_MODE(fw_mode); -+- break; -++ return mvebu_a3700_comphy_sata_power_on(lane); -+ case PHY_MODE_ETHERNET: -+- fw_port = (lane->id == 0) ? 1 : 0; -+- switch (lane->submode) { -+- case PHY_INTERFACE_MODE_SGMII: -+- dev_dbg(lane->dev, "set lane %d to SGMII mode\n", -+- lane->id); -+- fw_param = COMPHY_FW_NET(fw_mode, fw_port, -+- COMPHY_FW_SPEED_1_25G); -+- break; -+- case PHY_INTERFACE_MODE_2500BASEX: -+- dev_dbg(lane->dev, "set lane %d to 2500BASEX mode\n", -+- lane->id); -+- fw_param = COMPHY_FW_NET(fw_mode, fw_port, -+- COMPHY_FW_SPEED_3_125G); -+- break; -+- default: -+- dev_err(lane->dev, "unsupported PHY submode (%d)\n", -+- lane->submode); -+- return -ENOTSUPP; -+- } -+- break; -++ dev_dbg(lane->dev, "set lane %d to Ethernet mode\n", lane->id); -++ return mvebu_a3700_comphy_ethernet_power_on(lane); -+ case PHY_MODE_PCIE: -+ dev_dbg(lane->dev, "set lane %d to PCIe mode\n", lane->id); -+- fw_param = COMPHY_FW_PCIE(fw_mode, COMPHY_FW_SPEED_5G, -+- phy->attrs.bus_width); -+- break; -++ return mvebu_a3700_comphy_pcie_power_on(lane); -+ default: -+ dev_err(lane->dev, "unsupported PHY mode (%d)\n", lane->mode); -+- return -ENOTSUPP; -++ return -EOPNOTSUPP; +++ led_trigger_blink_oneshot(ap->ledtrig, &led_delay, &led_delay, 0); +++} +++#endif +++ ++ /** ++ * ata_build_rw_tf - Build ATA taskfile for given read/write request ++ * @tf: Target ATA taskfile ++@@ -4580,6 +4593,9 @@ struct ata_queued_cmd *ata_qc_new_init(s ++ if (tag < 0) ++ return NULL; + } -+- -+- ret = mvebu_a3700_comphy_smc(COMPHY_SIP_POWER_ON, lane->id, fw_param); -+- if (ret == -EOPNOTSUPP) -+- dev_err(lane->dev, -+- "unsupported SMC call, try updating your firmware\n"); -+- -+- return ret; -+ } -+ -+ static int mvebu_a3700_comphy_power_off(struct phy *phy) -+ { -+ struct mvebu_a3700_comphy_lane *lane = phy_get_drvdata(phy); +++#ifdef CONFIG_ATA_LEDS +++ ata_led_act(ap); +++#endif + -+- return mvebu_a3700_comphy_smc(COMPHY_SIP_POWER_OFF, lane->id, 0); -++ switch (lane->mode) { -++ case PHY_MODE_USB_HOST_SS: -++ mvebu_a3700_comphy_usb3_power_off(lane); -++ return 0; -++ case PHY_MODE_SATA: -++ mvebu_a3700_comphy_sata_power_off(lane); -++ return 0; -++ case PHY_MODE_ETHERNET: -++ mvebu_a3700_comphy_ethernet_power_off(lane); -++ return 0; -++ case PHY_MODE_PCIE: -++ mvebu_a3700_comphy_pcie_power_off(lane); -++ return 0; -++ default: -++ dev_err(lane->dev, "invalid COMPHY mode\n"); -++ return -EINVAL; -++ } -+ } ++ qc = __ata_qc_from_tag(ap, tag); ++ qc->tag = qc->hw_tag = tag; ++@@ -5358,6 +5374,9 @@ struct ata_port *ata_port_alloc(struct a ++ ap->stats.unhandled_irq = 1; ++ ap->stats.idle_irq = 1; ++ #endif +++#ifdef CONFIG_ATA_LEDS +++ ap->ledtrig = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); +++#endif ++ ata_sff_port_init(ap); + -+ static const struct phy_ops mvebu_a3700_comphy_ops = { -+ .power_on = mvebu_a3700_comphy_power_on, -+ .power_off = mvebu_a3700_comphy_power_off, -++ .reset = mvebu_a3700_comphy_reset, -+ .set_mode = mvebu_a3700_comphy_set_mode, -+ .owner = THIS_MODULE, -+ }; -+@@ -256,13 +1299,75 @@ static struct phy *mvebu_a3700_comphy_xl -+ return ERR_PTR(-EINVAL); -+ } ++ return ap; ++@@ -5393,6 +5412,12 @@ static void ata_host_release(struct kref + -++ lane->invert_tx = args->args[1] & BIT(0); -++ lane->invert_rx = args->args[1] & BIT(1); -++ -+ return phy; -+ } ++ kfree(ap->pmp_link); ++ kfree(ap->slave_link); +++#ifdef CONFIG_ATA_LEDS +++ if (ap->ledtrig) { +++ led_trigger_unregister(ap->ledtrig); +++ kfree(ap->ledtrig); +++ }; +++#endif ++ kfree(ap); ++ host->ports[i] = NULL; ++ } ++@@ -5799,7 +5824,23 @@ int ata_host_register(struct ata_host *h ++ host->ports[i]->print_id = atomic_inc_return(&ata_print_id); ++ host->ports[i]->local_port_no = i + 1; ++ } +++#ifdef CONFIG_ATA_LEDS +++ for (i = 0; i < host->n_ports; i++) { +++ if (unlikely(!host->ports[i]->ledtrig)) +++ continue; + -+ static int mvebu_a3700_comphy_probe(struct platform_device *pdev) -+ { -++ struct mvebu_a3700_comphy_priv *priv; -+ struct phy_provider *provider; -+ struct device_node *child; -++ struct resource *res; -++ struct clk *clk; -++ int ret; -++ -++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); -++ if (!priv) -++ return -ENOMEM; -++ -++ spin_lock_init(&priv->lock); -++ -++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "comphy"); -++ priv->comphy_regs = devm_ioremap_resource(&pdev->dev, res); -++ if (IS_ERR(priv->comphy_regs)) -++ return PTR_ERR(priv->comphy_regs); -++ -++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, -++ "lane1_pcie_gbe"); -++ priv->lane1_phy_regs = devm_ioremap_resource(&pdev->dev, res); -++ if (IS_ERR(priv->lane1_phy_regs)) -++ return PTR_ERR(priv->lane1_phy_regs); -++ -++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, -++ "lane0_usb3_gbe"); -++ priv->lane0_phy_regs = devm_ioremap_resource(&pdev->dev, res); -++ if (IS_ERR(priv->lane0_phy_regs)) -++ return PTR_ERR(priv->lane0_phy_regs); +++ snprintf(host->ports[i]->ledtrig_name, +++ sizeof(host->ports[i]->ledtrig_name), "ata%u", +++ host->ports[i]->print_id); ++ -++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, -++ "lane2_sata_usb3"); -++ priv->lane2_phy_indirect = devm_ioremap_resource(&pdev->dev, res); -++ if (IS_ERR(priv->lane2_phy_indirect)) -++ return PTR_ERR(priv->lane2_phy_indirect); +++ host->ports[i]->ledtrig->name = host->ports[i]->ledtrig_name; ++ -++ /* -++ * Driver needs to know if reference xtal clock is 40MHz or 25MHz. -++ * Old DT bindings do not have xtal clk present. So do not fail here -++ * and expects that default 25MHz reference clock is used. -++ */ -++ clk = clk_get(&pdev->dev, "xtal"); -++ if (IS_ERR(clk)) { -++ if (PTR_ERR(clk) == -EPROBE_DEFER) -++ return -EPROBE_DEFER; -++ dev_warn(&pdev->dev, "missing 'xtal' clk (%ld)\n", -++ PTR_ERR(clk)); -++ } else { -++ ret = clk_prepare_enable(clk); -++ if (ret) { -++ dev_warn(&pdev->dev, "enabling xtal clk failed (%d)\n", -++ ret); -++ } else { -++ if (clk_get_rate(clk) == 40000000) -++ priv->xtal_is_40m = true; -++ clk_disable_unprepare(clk); +++ if (led_trigger_register(host->ports[i]->ledtrig)) { +++ kfree(host->ports[i]->ledtrig); +++ host->ports[i]->ledtrig = NULL; ++ } -++ clk_put(clk); ++ } -++ -++ dev_set_drvdata(&pdev->dev, priv); -+ -+ for_each_available_child_of_node(pdev->dev.of_node, child) { -+ struct mvebu_a3700_comphy_lane *lane; -+@@ -277,7 +1382,7 @@ static int mvebu_a3700_comphy_probe(stru -+ continue; -+ } -+ -+- if (lane_id >= MVEBU_A3700_COMPHY_LANES) { -++ if (lane_id >= 3) { -+ dev_err(&pdev->dev, "invalid 'reg' property\n"); -+ continue; -+ } -+@@ -295,11 +1400,21 @@ static int mvebu_a3700_comphy_probe(stru -+ return PTR_ERR(phy); -+ } -+ -++ lane->priv = priv; -+ lane->dev = &pdev->dev; -+ lane->mode = PHY_MODE_INVALID; -+ lane->submode = PHY_INTERFACE_MODE_NA; -+ lane->id = lane_id; -++ lane->invert_tx = false; -++ lane->invert_rx = false; -+ phy_set_drvdata(phy, lane); -++ -++ /* -++ * To avoid relying on the bootloader/firmware configuration, -++ * power off all comphys. -++ */ -++ mvebu_a3700_comphy_reset(phy); -++ lane->needs_reset = false; -+ } -+ -+ provider = devm_of_phy_provider_register(&pdev->dev, -+@@ -323,5 +1438,7 @@ static struct platform_driver mvebu_a370 -+ module_platform_driver(mvebu_a3700_comphy_driver); +++#endif ++ /* Create associated sysfs transport objects */ ++ for (i = 0; i < host->n_ports; i++) { ++ rc = ata_tport_add(host->dev,host->ports[i]); ++--- a/include/linux/libata.h +++++ b/include/linux/libata.h ++@@ -23,6 +23,9 @@ ++ #include <linux/cdrom.h> ++ #include <linux/sched.h> ++ #include <linux/async.h> +++#ifdef CONFIG_ATA_LEDS +++#include <linux/leds.h> +++#endif + -+ MODULE_AUTHOR("Miquèl Raynal <miquel.raynal@bootlin.com>"); -++MODULE_AUTHOR("Pali Rohár <pali@kernel.org>"); -++MODULE_AUTHOR("Marek Behún <kabel@kernel.org>"); -+ MODULE_DESCRIPTION("Common PHY driver for A3700"); -+ MODULE_LICENSE("GPL v2"); -diff --git a/target/linux/generic/pending-5.15/851-0003-arm64-dts-marvell-armada-37xx-Add-xtal-clock-to-comp.patch b/target/linux/generic/pending-5.15/851-0003-arm64-dts-marvell-armada-37xx-Add-xtal-clock-to-comp.patch ++ /* ++ * Define if arch has non-standard setup. This is a _PCI_ standard ++@@ -888,6 +891,12 @@ struct ata_port { ++ #ifdef CONFIG_ATA_ACPI ++ struct ata_acpi_gtm __acpi_init_gtm; /* use ata_acpi_init_gtm() */ ++ #endif +++ +++#ifdef CONFIG_ATA_LEDS +++ struct led_trigger *ledtrig; +++ char ledtrig_name[8]; +++#endif +++ ++ /* owned by EH */ ++ u8 sector_buf[ATA_SECT_SIZE] ____cacheline_aligned; ++ }; +diff --git a/target/linux/generic/pending-5.15/840-hwrng-bcm2835-set-quality-to-1000.patch b/target/linux/generic/pending-5.15/840-hwrng-bcm2835-set-quality-to-1000.patch new file mode 100644 -index 0000000000..33203a154d +index 0000000000..5ca8933d6f --- /dev/null -+++ b/target/linux/generic/pending-5.15/851-0003-arm64-dts-marvell-armada-37xx-Add-xtal-clock-to-comp.patch -@@ -0,0 +1,31 @@ -+From 66c51c39fd4bf05e99debf0e71de5704231c57dc Mon Sep 17 00:00:00 2001 -+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org> -+Date: Thu, 23 Sep 2021 19:26:26 +0200 -+Subject: [PATCH] arm64: dts: marvell: armada-37xx: Add xtal clock to comphy -+ node ++++ b/target/linux/generic/pending-5.15/840-hwrng-bcm2835-set-quality-to-1000.patch +@@ -0,0 +1,26 @@ ++From d6988cf1d16faac56899918bb2b1be8d85155e3f Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com> ++Date: Sat, 20 Feb 2021 18:36:38 +0100 ++Subject: [PATCH] hwrng: bcm2835: set quality to 1000 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + -+Kernel driver phy-mvebu-a3700-comphy.c needs to know the rate of the -+reference xtal clock. So add missing xtal clock source into comphy device -+tree node. If the property is not present, the driver defaults to 25 MHz -+xtal rate (which, as far as we know, is used by all the existing boards). ++This allows devices without a high precission timer to reduce boot from >100s ++to <30s. + -+Signed-off-by: Pali Rohár <pali@kernel.org> -+Signed-off-by: Marek Behún <kabel@kernel.org> ++Signed-off-by: Ãlvaro Fernández Rojas <noltari@gmail.com> +--- -+ arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 2 ++ -+ 1 file changed, 2 insertions(+) -+ -+--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi -++++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi -+@@ -265,6 +265,8 @@ -+ "lane2_sata_usb3"; -+ #address-cells = <1>; -+ #size-cells = <0>; -++ clocks = <&xtalclk>; -++ clock-names = "xtal"; -+ -+ comphy0: phy@0 { -+ reg = <0>; -diff --git a/target/linux/generic/pending-5.15/851-0004-Revert-ata-ahci-mvebu-Make-SATA-PHY-optional-for-Arm.patch b/target/linux/generic/pending-5.15/851-0004-Revert-ata-ahci-mvebu-Make-SATA-PHY-optional-for-Arm.patch -new file mode 100644 -index 0000000000..3c994d2548 ---- /dev/null -+++ b/target/linux/generic/pending-5.15/851-0004-Revert-ata-ahci-mvebu-Make-SATA-PHY-optional-for-Arm.patch -@@ -0,0 +1,61 @@ -+From 750bb44dbbe9dfb4ba3e1f8a746b831b39ba3cd9 Mon Sep 17 00:00:00 2001 -+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org> -+Date: Thu, 23 Sep 2021 19:35:57 +0200 -+Subject: [PATCH] Revert "ata: ahci: mvebu: Make SATA PHY optional for Armada -+ 3720" -+MIME-Version: 1.0 -+Content-Type: text/plain; charset=UTF-8 -+Content-Transfer-Encoding: 8bit -+ -+This reverts commit 45aefe3d2251e4e229d7662052739f96ad1d08d9. -+ -+Armada 3720 PHY driver (phy-mvebu-a3700-comphy.c) does not return -+-EOPNOTSUPP from phy_power_on() callback anymore. -+ -+So remove AHCI_HFLAG_IGN_NOTSUPP_POWER_ON flag from Armada 3720 plat data. -+ -+AHCI_HFLAG_IGN_NOTSUPP_POWER_ON is not used by any other ahci driver, so -+remove this flag completely. ++ drivers/char/hw_random/bcm2835-rng.c | 1 + ++ 1 file changed, 1 insertion(+) + -+Signed-off-by: Pali Rohár <pali@kernel.org> -+Signed-off-by: Marek Behún <kabel@kernel.org> -+Acked-by: Miquel Raynal <miquel.raynal@bootlin.com> -+--- -+ drivers/ata/ahci.h | 2 -- -+ drivers/ata/ahci_mvebu.c | 2 +- -+ drivers/ata/libahci_platform.c | 2 +- -+ 3 files changed, 2 insertions(+), 4 deletions(-) -+ -+--- a/drivers/ata/ahci.h -++++ b/drivers/ata/ahci.h -+@@ -240,8 +240,6 @@ enum { -+ as default lpm_policy */ -+ AHCI_HFLAG_SUSPEND_PHYS = (1 << 26), /* handle PHYs during -+ suspend/resume */ -+- AHCI_HFLAG_IGN_NOTSUPP_POWER_ON = (1 << 27), /* ignore -EOPNOTSUPP -+- from phy_power_on() */ -+ AHCI_HFLAG_NO_SXS = (1 << 28), /* SXS not supported */ -+ -+ /* ap->flags bits */ -+--- a/drivers/ata/ahci_mvebu.c -++++ b/drivers/ata/ahci_mvebu.c -+@@ -227,7 +227,7 @@ static const struct ahci_mvebu_plat_data -+ -+ static const struct ahci_mvebu_plat_data ahci_mvebu_armada_3700_plat_data = { -+ .plat_config = ahci_mvebu_armada_3700_config, -+- .flags = AHCI_HFLAG_SUSPEND_PHYS | AHCI_HFLAG_IGN_NOTSUPP_POWER_ON, -++ .flags = AHCI_HFLAG_SUSPEND_PHYS, -+ }; -+ -+ static const struct of_device_id ahci_mvebu_of_match[] = { -+--- a/drivers/ata/libahci_platform.c -++++ b/drivers/ata/libahci_platform.c -+@@ -59,7 +59,7 @@ int ahci_platform_enable_phys(struct ahc -+ } ++--- a/drivers/char/hw_random/bcm2835-rng.c +++++ b/drivers/char/hw_random/bcm2835-rng.c ++@@ -170,6 +170,7 @@ static int bcm2835_rng_probe(struct plat ++ priv->rng.init = bcm2835_rng_init; ++ priv->rng.read = bcm2835_rng_read; ++ priv->rng.cleanup = bcm2835_rng_cleanup; +++ priv->rng.quality = 1000; + -+ rc = phy_power_on(hpriv->phys[i]); -+- if (rc && !(rc == -EOPNOTSUPP && (hpriv->flags & AHCI_HFLAG_IGN_NOTSUPP_POWER_ON))) { -++ if (rc) { -+ phy_exit(hpriv->phys[i]); -+ goto disable_phys; -+ } -diff --git a/target/linux/generic/pending-5.15/851-0005-Revert-usb-host-xhci-mvebu-make-USB-3.0-PHY-optional.patch b/target/linux/generic/pending-5.15/851-0005-Revert-usb-host-xhci-mvebu-make-USB-3.0-PHY-optional.patch ++ if (dev_of_node(dev)) { ++ rng_id = of_match_node(bcm2835_rng_of_match, dev->of_node); +diff --git a/target/linux/generic/pending-5.15/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch b/target/linux/generic/pending-5.15/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch new file mode 100644 -index 0000000000..b8a3e880ce +index 0000000000..e180a385e1 --- /dev/null -+++ b/target/linux/generic/pending-5.15/851-0005-Revert-usb-host-xhci-mvebu-make-USB-3.0-PHY-optional.patch -@@ -0,0 +1,163 @@ -+From 9f0dfb279b1dd505d5e10b10e4a78a62030978d8 Mon Sep 17 00:00:00 2001 -+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org> -+Date: Thu, 23 Sep 2021 19:40:06 +0200 -+Subject: [PATCH] Revert "usb: host: xhci: mvebu: make USB 3.0 PHY optional for -+ Armada 3720" ++++ b/target/linux/generic/pending-5.15/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch +@@ -0,0 +1,102 @@ ++From 663b9f99bb35dbc0c7b685f71ee3668a60d31320 Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?Marek=20Beh=C3=BAn?= <kabel@kernel.org> ++Date: Mon, 10 Jan 2022 02:02:00 +0100 ++Subject: [PATCH] PCI: aardvark: Make main irq_chip structure a static driver ++ structure +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + -+This reverts commit 3241929b67d28c83945d3191c6816a3271fd6b85. ++Marc Zyngier says [1] that we should use struct irq_chip as a global ++static struct in the driver. Even though the structure currently ++contains a dynamic member (parent_device), Marc says [2] that he plans ++to kill it and make the structure completely static. + -+Armada 3720 phy driver (phy-mvebu-a3700-comphy.c) does not return -+-EOPNOTSUPP from phy_power_on() callback anymore. ++We have already converted others irq_chip structures in this driver in ++this way, but we omitted this one because the .name member is ++dynamically created from device's name, and the name is displayed in ++sysfs, so changing it would break sysfs ABI. + -+So remove XHCI_SKIP_PHY_INIT flag from xhci_mvebu_a3700_plat_setup() and -+then also whole xhci_mvebu_a3700_plat_setup() function which is there just -+to handle -EOPNOTSUPP for XHCI_SKIP_PHY_INIT. ++The rationale for changing the name (to "advk-INT") in spite of sysfs ++ABI, and thus allowing to convert to a static structure, is that after ++the other changes we made in this series, the IRQ chip is basically ++something different: it no logner generates ERR and PME interrupts (they ++are generated by emulated bridge's rp_irq_chip). + -+xhci plat_setup callback is not used by any other xhci plat driver, so -+remove this callback completely. ++[1] https://lore.kernel.org/linux-pci/877dbcvngf.wl-maz@kernel.org/ ++[2] https://lore.kernel.org/linux-pci/874k6gvkhz.wl-maz@kernel.org/ + -+Signed-off-by: Pali Rohár <pali@kernel.org> +Signed-off-by: Marek Behún <kabel@kernel.org> -+Acked-by: Miquel Raynal <miquel.raynal@bootlin.com> +--- -+ drivers/usb/host/xhci-mvebu.c | 42 ----------------------------------- -+ drivers/usb/host/xhci-mvebu.h | 6 ----- -+ drivers/usb/host/xhci-plat.c | 20 +---------------- -+ drivers/usb/host/xhci-plat.h | 1 - -+ 4 files changed, 1 insertion(+), 68 deletions(-) -+ -+--- a/drivers/usb/host/xhci-mvebu.c -++++ b/drivers/usb/host/xhci-mvebu.c -+@@ -8,7 +8,6 @@ -+ #include <linux/mbus.h> -+ #include <linux/of.h> -+ #include <linux/platform_device.h> -+-#include <linux/phy/phy.h> -+ -+ #include <linux/usb.h> -+ #include <linux/usb/hcd.h> -+@@ -74,47 +73,6 @@ int xhci_mvebu_mbus_init_quirk(struct us -+ -+ return 0; -+ } -+- -+-int xhci_mvebu_a3700_plat_setup(struct usb_hcd *hcd) -+-{ -+- struct xhci_hcd *xhci = hcd_to_xhci(hcd); -+- struct device *dev = hcd->self.controller; -+- struct phy *phy; -+- int ret; -+- -+- /* Old bindings miss the PHY handle */ -+- phy = of_phy_get(dev->of_node, "usb3-phy"); -+- if (IS_ERR(phy) && PTR_ERR(phy) == -EPROBE_DEFER) -+- return -EPROBE_DEFER; -+- else if (IS_ERR(phy)) -+- goto phy_out; -+- -+- ret = phy_init(phy); -+- if (ret) -+- goto phy_put; -+- -+- ret = phy_set_mode(phy, PHY_MODE_USB_HOST_SS); -+- if (ret) -+- goto phy_exit; -+- -+- ret = phy_power_on(phy); -+- if (ret == -EOPNOTSUPP) { -+- /* Skip initializatin of XHCI PHY when it is unsupported by firmware */ -+- dev_warn(dev, "PHY unsupported by firmware\n"); -+- xhci->quirks |= XHCI_SKIP_PHY_INIT; -+- } -+- if (ret) -+- goto phy_exit; -+- -+- phy_power_off(phy); -+-phy_exit: -+- phy_exit(phy); -+-phy_put: -+- of_phy_put(phy); -+-phy_out: -+- -+- return 0; -+-} -+ -+ int xhci_mvebu_a3700_init_quirk(struct usb_hcd *hcd) -+ { -+--- a/drivers/usb/host/xhci-mvebu.h -++++ b/drivers/usb/host/xhci-mvebu.h -+@@ -12,18 +12,12 @@ struct usb_hcd; -+ -+ #if IS_ENABLED(CONFIG_USB_XHCI_MVEBU) -+ int xhci_mvebu_mbus_init_quirk(struct usb_hcd *hcd); -+-int xhci_mvebu_a3700_plat_setup(struct usb_hcd *hcd); -+ int xhci_mvebu_a3700_init_quirk(struct usb_hcd *hcd); -+ #else -+ static inline int xhci_mvebu_mbus_init_quirk(struct usb_hcd *hcd) -+ { -+ return 0; ++ drivers/pci/controller/pci-aardvark.c | 25 +++++++------------------ ++ 1 file changed, 7 insertions(+), 18 deletions(-) ++ ++--- a/drivers/pci/controller/pci-aardvark.c +++++ b/drivers/pci/controller/pci-aardvark.c ++@@ -275,7 +275,6 @@ struct advk_pcie { ++ u8 wins_count; ++ struct irq_domain *rp_irq_domain; ++ struct irq_domain *irq_domain; ++- struct irq_chip irq_chip; ++ raw_spinlock_t irq_lock; ++ struct irq_domain *msi_domain; ++ struct irq_domain *msi_inner_domain; ++@@ -1345,14 +1344,19 @@ static void advk_pcie_irq_unmask(struct ++ raw_spin_unlock_irqrestore(&pcie->irq_lock, flags); + } -+- -+-static inline int xhci_mvebu_a3700_plat_setup(struct usb_hcd *hcd) -+-{ -+- return 0; -+-} + -+ static inline int xhci_mvebu_a3700_init_quirk(struct usb_hcd *hcd) +++static struct irq_chip advk_irq_chip = { +++ .name = "advk-INT", +++ .irq_mask = advk_pcie_irq_mask, +++ .irq_unmask = advk_pcie_irq_unmask, +++}; +++ ++ static int advk_pcie_irq_map(struct irq_domain *h, ++ unsigned int virq, irq_hw_number_t hwirq) + { -+--- a/drivers/usb/host/xhci-plat.c -++++ b/drivers/usb/host/xhci-plat.c -+@@ -44,16 +44,6 @@ static void xhci_priv_plat_start(struct -+ priv->plat_start(hcd); -+ } ++ struct advk_pcie *pcie = h->host_data; + -+-static int xhci_priv_plat_setup(struct usb_hcd *hcd) -+-{ -+- struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); -+- -+- if (!priv->plat_setup) -+- return 0; -+- -+- return priv->plat_setup(hcd); -+-} -+- -+ static int xhci_priv_init_quirk(struct usb_hcd *hcd) -+ { -+ struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); -+@@ -121,7 +111,6 @@ static const struct xhci_plat_priv xhci_ -+ }; ++ irq_set_status_flags(virq, IRQ_LEVEL); ++- irq_set_chip_and_handler(virq, &pcie->irq_chip, ++- handle_level_irq); +++ irq_set_chip_and_handler(virq, &advk_irq_chip, handle_level_irq); ++ irq_set_chip_data(virq, pcie); + -+ static const struct xhci_plat_priv xhci_plat_marvell_armada3700 = { -+- .plat_setup = xhci_mvebu_a3700_plat_setup, -+ .init_quirk = xhci_mvebu_a3700_init_quirk, -+ }; ++ return 0; ++@@ -1411,7 +1415,6 @@ static int advk_pcie_init_irq_domain(str ++ struct device *dev = &pcie->pdev->dev; ++ struct device_node *node = dev->of_node; ++ struct device_node *pcie_intc_node; ++- struct irq_chip *irq_chip; ++ int ret = 0; + -+@@ -341,14 +330,7 @@ static int xhci_plat_probe(struct platfo ++ raw_spin_lock_init(&pcie->irq_lock); ++@@ -1422,28 +1425,14 @@ static int advk_pcie_init_irq_domain(str ++ return -ENODEV; ++ } + -+ hcd->tpl_support = of_usb_host_tpl_support(sysdev->of_node); -+ xhci->shared_hcd->tpl_support = hcd->tpl_support; ++- irq_chip = &pcie->irq_chip; +- -+- if (priv) { -+- ret = xhci_priv_plat_setup(hcd); -+- if (ret) -+- goto disable_usb_phy; ++- irq_chip->name = devm_kasprintf(dev, GFP_KERNEL, "%s-irq", ++- dev_name(dev)); ++- if (!irq_chip->name) { ++- ret = -ENOMEM; ++- goto out_put_node; +- } +- -+- if ((xhci->quirks & XHCI_SKIP_PHY_INIT) || (priv && (priv->quirks & XHCI_SKIP_PHY_INIT))) -++ if (priv && (priv->quirks & XHCI_SKIP_PHY_INIT)) -+ hcd->skip_phy_initialization = 1; -+ -+ if (priv && (priv->quirks & XHCI_SG_TRB_CACHE_SIZE_QUIRK)) -+--- a/drivers/usb/host/xhci-plat.h -++++ b/drivers/usb/host/xhci-plat.h -+@@ -13,7 +13,6 @@ -+ struct xhci_plat_priv { -+ const char *firmware_name; -+ unsigned long long quirks; -+- int (*plat_setup)(struct usb_hcd *); -+ void (*plat_start)(struct usb_hcd *); -+ int (*init_quirk)(struct usb_hcd *); -+ int (*suspend_quirk)(struct usb_hcd *); -diff --git a/target/linux/generic/pending-5.15/851-0006-Revert-PCI-aardvark-Fix-initialization-with-old-Marv.patch b/target/linux/generic/pending-5.15/851-0006-Revert-PCI-aardvark-Fix-initialization-with-old-Marv.patch -new file mode 100644 -index 0000000000..4425e3f86b ---- /dev/null -+++ b/target/linux/generic/pending-5.15/851-0006-Revert-PCI-aardvark-Fix-initialization-with-old-Marv.patch -@@ -0,0 +1,36 @@ -+From 9a352062b7e3857742389dff6f64393481dc755e Mon Sep 17 00:00:00 2001 -+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org> -+Date: Thu, 23 Sep 2021 19:37:05 +0200 -+Subject: [PATCH] Revert "PCI: aardvark: Fix initialization with old Marvell's -+ Arm Trusted Firmware" -+MIME-Version: 1.0 -+Content-Type: text/plain; charset=UTF-8 -+Content-Transfer-Encoding: 8bit -+ -+This reverts commit b0c6ae0f8948a2be6bf4e8b4bbab9ca1343289b6. -+ -+Armada 3720 phy driver (phy-mvebu-a3700-comphy.c) does not return -+-EOPNOTSUPP from phy_power_on() callback anymore. -+ -+So remove dead code which handles -EOPNOTSUPP return value. -+ -+Signed-off-by: Pali Rohár <pali@kernel.org> -+Signed-off-by: Marek Behún <kabel@kernel.org> -+Acked-by: Miquel Raynal <miquel.raynal@bootlin.com> -+--- -+ drivers/pci/controller/pci-aardvark.c | 4 +--- -+ 1 file changed, 1 insertion(+), 3 deletions(-) -+ -+--- a/drivers/pci/controller/pci-aardvark.c -++++ b/drivers/pci/controller/pci-aardvark.c -+@@ -1616,9 +1616,7 @@ static int advk_pcie_enable_phy(struct a ++- irq_chip->irq_mask = advk_pcie_irq_mask; ++- irq_chip->irq_unmask = advk_pcie_irq_unmask; ++- ++ pcie->irq_domain = ++ irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX, ++ &advk_pcie_irq_domain_ops, pcie); ++ if (!pcie->irq_domain) { ++ dev_err(dev, "Failed to get a INTx IRQ domain\n"); ++ ret = -ENOMEM; ++- goto out_put_node; + } + -+ ret = phy_power_on(pcie->phy); -+- if (ret == -EOPNOTSUPP) { -+- dev_warn(&pcie->pdev->dev, "PHY unsupported by firmware\n"); -+- } else if (ret) { -++ if (ret) { -+ phy_exit(pcie->phy); -+ return ret; -+ } ++-out_put_node: ++ of_node_put(pcie_intc_node); ++ return ret; ++ } diff --git a/target/linux/generic/pending-5.15/920-mangle_bootargs.patch b/target/linux/generic/pending-5.15/920-mangle_bootargs.patch new file mode 100644 -index 0000000000..dbcd6a5b32 +index 0000000000..2a02efe0aa --- /dev/null +++ b/target/linux/generic/pending-5.15/920-mangle_bootargs.patch @@ -0,0 +1,71 @@ @@ -15364,7 +18257,7 @@ index 0000000000..dbcd6a5b32 + help +--- a/init/main.c ++++ b/init/main.c -+@@ -615,6 +615,29 @@ static inline void setup_nr_cpu_ids(void ++@@ -616,6 +616,29 @@ static inline void setup_nr_cpu_ids(void + static inline void smp_prepare_cpus(unsigned int maxcpus) { } + #endif + @@ -15394,7 +18287,7 @@ index 0000000000..dbcd6a5b32 + /* + * We need to store the untouched command line for future reference. + * We also need to store the touched command line since the parameter -+@@ -955,6 +978,7 @@ asmlinkage __visible void __init __no_sa ++@@ -956,6 +979,7 @@ asmlinkage __visible void __init __no_sa + pr_notice("%s", linux_banner); + early_security_init(); + setup_arch(&command_line); -- GitLab